Class: Osgb::Point

Inherits:
Object
  • Object
show all
Defined in:
lib/osgb/point.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(lat, lng, datum = nil, precision = nil) ⇒ Point

Usage:

Osgb::Point.new(lat[float], lng[float], datum[symbol], precision[integer])

Default datum is :osgb36. For most web use you will be using WGS84 points, since that’s the standard for most GPS applications and used by google maps:

Osgb::Point.new(54.196915, -3.094684, :wgs84)
Osgb::Point.new(54.196763, -3.093320).transform_to(:wgs84)


20
21
22
23
24
25
# File 'lib/osgb/point.rb', line 20

def initialize(lat, lng, datum=nil, precision=nil)
  @lat = lat.to_f
  @lng = lng.to_f
  @datum = datum || :osgb36
  @precision = precision || 6
end

Instance Attribute Details

#datumObject

Returns the value of attribute datum.



9
10
11
# File 'lib/osgb/point.rb', line 9

def datum
  @datum
end

#latObject

Returns the latitude of the point, rounded to the specified precision



29
30
31
# File 'lib/osgb/point.rb', line 29

def lat
  round(@lat)
end

#lngObject

Returns the longitude of the point, rounded to the specified precision



35
36
37
# File 'lib/osgb/point.rb', line 35

def lng
  round(@lng)
end

#precisionObject

Returns the value of attribute precision.



9
10
11
# File 'lib/osgb/point.rb', line 9

def precision
  @precision
end

Instance Method Details

#==(other) ⇒ Object

Tests the equivalence of two points, however they are specified. If given two Point objects, they can lie on different datums:

Osgb::Point.new(54.196763, -3.093320, :osgb36) == Osgb::Point.new(54.196915, -3.094684, :wgs84)  # -> true

When comparing a point with a string or array representation they are assumed to lie on the same datum:

Osgb::Point.new(54.196763, -3.093320) == "54.196763, -3.093320"   # -> true
Osgb::Point.new(54.196763, -3.093320) == [54.196763, -3.093320]   # -> true
Osgb::Point.new(54.196763, -3.093320) == "SD28687846"             # -> true

Two points with different precisions will not be considered equivalent.



90
91
92
93
94
95
96
97
98
99
100
# File 'lib/osgb/point.rb', line 90

def ==(other)
  case other
  when Osgb::Point
    other = other.transform_to(self.datum) unless other.datum == self.datum
    self.lat == other.lat && self.lng == other.lng && self.datum == other.datum
  when Array
    self.to_a == other
  when String
    self == other.to_latlng(:datum => self.datum) # serves to normalise string representation
  end
end

#to_aObject

Returns the point as a [lat,lng] array.



51
52
53
# File 'lib/osgb/point.rb', line 51

def to_a
  [lat, lng]
end

#to_sObject

Returns the point as a “lat,lng” string.



46
47
48
# File 'lib/osgb/point.rb', line 46

def to_s
  "#{lat},#{lng}"
end

#transform_to(target_datum) ⇒ Object

Remaps the point onto another datum. If you’re turning OS grid references into GPS coordinates you have to remap from OSGB36 to WGS84:

point = "SD28687846".to_latlng.transform_to(:wgs84)

or more concisely:

point = "SD28687846".to_wgs84


64
65
66
67
68
69
70
71
72
73
74
# File 'lib/osgb/point.rb', line 64

def transform_to(target_datum)
  return self if datum == target_datum
  if helmert = Osgb::Helmert[:"#{self.datum}_to_#{target_datum}"]
    cartesian_coordinates = Osgb::Ellipsoid[self.datum].polar_to_cartesian(@lat.to_radians,@lng.to_radians)
    transformed = helmert.transform(*cartesian_coordinates)
    phi, lambda = Osgb::Ellipsoid[target_datum].cartesian_to_polar(*transformed)
    self.class.new(phi.to_degrees, lambda.to_degrees, target_datum, precision)
  else
    raise Osgb::TransformationError, "Missing helmert transformation for #{self.datum} to #{target_datum}"
  end
end

#valid?Boolean

Returns true if the coordinates are both specified and within the acceptable range.

Returns:

  • (Boolean)


41
42
43
# File 'lib/osgb/point.rb', line 41

def valid?
  lat && lng && lat >= -90 && lat <= 90 && lng >= -180 && lng <= 180
end