class GIS::Distance

The Distance class encapsulates methods related to geographic distance.

Constants

VERSION

The version of the gis-distance library

Attributes

formula[R]

Returns the formula used to calculate the distance. The default formula is ‘haversine’.

radius[R]

Returns the radius of the Earth in kilometers. The default is 6367.45.

Public Class Methods

new(latitude1, longitude1, latitude2, longitude2) click to toggle source

Create a new GIS::Distance object using the two sets of coordinates that are provided.

If invalid coordinates are provided a GIS::Distance::Error is raised.

# File lib/gis/distance.rb, line 18
def initialize(latitude1, longitude1, latitude2, longitude2)
  validate(latitude1, longitude1, latitude2, longitude2)

  @latitude1  = latitude1
  @longitude1 = longitude1
  @latitude2  = latitude2
  @longitude2 = longitude2

  @radius   = 6367.45
  @formula  = 'haversine'
  @distance = nil
end

Public Instance Methods

distance() click to toggle source

Returns the distance (in kilometers) between the two coordinates provided in the constructor.

# File lib/gis/distance.rb, line 79
def distance
  @distance =
    case @formula.to_s.downcase
      when 'haversine'
        haversine_formula
      when 'cosines'
        law_of_cosines_formula
      when 'vincenty'
        vincenty_formula
    end
end
formula=(formula) click to toggle source

Sets the formula to be used internally for calculating the distance. The default is ‘haversine’. Your other option is ‘cosines’ (i.e. the Law of Cosines).

If an unsupported formula is provided a GIS::Distance::Error is raised.

# File lib/gis/distance.rb, line 63
def formula=(formula)
  case formula.to_s.downcase
    when 'haversine'
      @formula = 'haversine'
    when 'cosines'
      @formula = 'cosines'
    when 'vincenty'
      @formula = 'vincenty'
    else
      raise Error, "Formula '#{formula}' not supported"
  end
end
radius=(kms) click to toggle source

Sets the radius of the Earth in kilometers. This is variable because the Earth is not perfectly spherical, and you may wish to adjust it.

However, the possible range of values is limited from 6357.0 to 6378.0. If a value outside of this range is provided a GIS::Distance::Error is raised.

The default value is 6367.45.

See en.wikipedia.org/wiki/Earth_radius for more information.

# File lib/gis/distance.rb, line 46
def radius=(kms)
  raise Error, "Proposed radius '#{kms}' is out of range" if kms < 6357.0 || kms > 6378.0
  @radius = kms
end

Private Instance Methods

haversine_formula() click to toggle source

See en.wikipedia.org/wiki/Haversine_formula

# File lib/gis/distance.rb, line 126
def haversine_formula
  lat1 = @latitude1  * Math::PI / 180
  lon1 = @longitude1 * Math::PI / 180
  lat2 = @latitude2  * Math::PI / 180
  lon2 = @longitude2 * Math::PI / 180

  dlat = lat2 - lat1
  dlon = lon2 - lon1

  a = (Math.sin(dlat / 2)**2) + (Math.cos(lat1) * Math.cos(lat2) * (Math.sin(dlon / 2)**2))
  c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))

  radius * c
end
law_of_cosines_formula() click to toggle source

See en.wikipedia.org/wiki/Law_of_cosines

# File lib/gis/distance.rb, line 114
def law_of_cosines_formula
  sin1 = Math.sin(@latitude1 * Math::PI / 180)
  sin2 = Math.sin(@latitude2 * Math::PI / 180)
  cos1 = Math.cos(@latitude1 * Math::PI / 180)
  cos2 = Math.cos(@latitude2 * Math::PI / 180)
  cos3 = Math.cos((@longitude2 * Math::PI / 180) - (@longitude1 * Math::PI / 180))

  Math.acos((sin1 * sin2) + (cos1 * cos2 * cos3)) * radius
end
validate(lat1, lon1, lat2, lon2) click to toggle source

Validate the latitude and longitude values. Latitudes must be between 90.0 and -90.0 while longitudes must be between 180.0 and -180.0.

# File lib/gis/distance.rb, line 96
def validate(lat1, lon1, lat2, lon2)
  [lat1, lat2].each do |lat|
    if lat > 90 || lat < -90
      msg = "Latitude '#{lat}' is invalid - must be between -90 and 90"
      raise Error, msg
    end
  end

  [lon1, lon2].each do |lon|
    if lon > 180 || lon < -180
      msg = "Longitude '#{lon}' is invalid - must be between -180 and 180"
      raise Error, msg
    end
  end
end
vincenty_formula() click to toggle source

See en.wikipedia.org/wiki/Vincenty’s_formulae

# File lib/gis/distance.rb, line 142
def vincenty_formula
  require 'rvincenty'
  RVincenty.distance([@latitude1, @longitude1], [@latitude2, @longitude2]) / 1000.0
end