class Geospatial::Location
This location is specifically relating to a WGS84 coordinate on Earth.
Attributes
latitude[R]
longitude[R]
Public Class Methods
from_ecef(x, y, z)
click to toggle source
# File lib/geospatial/location.rb, line 50 def from_ecef(x, y, z) # Constants (WGS ellipsoid) a = WGS84_A e = WGS84_E b = Math::sqrt((a*a) * (1.0-(e*e))) ep = Math::sqrt(((a*a)-(b*b))/(b*b)) p = Math::sqrt((x*x)+(y*y)) th = Math::atan2(a*z, b*p) lon = Math::atan2(y, x) lat = Math::atan2((z+ep*ep*b*(Math::sin(th) ** 3)), (p-e*e*a*(Math::cos(th)**3))) # n = a / Math::sqrt(1.0-e*e*(Math::sin(lat) ** 2)) # alt = p / Math::cos(lat)-n return self.new(lat*R2D, lon*R2D) end
new(longitude, latitude)
click to toggle source
# File lib/geospatial/location.rb, line 73 def initialize(longitude, latitude) @longitude = longitude @latitude = latitude end
Public Instance Methods
-(other)
click to toggle source
# File lib/geospatial/location.rb, line 202 def - other Distance.new(self.distance_from(other)) end
<=>(other)
click to toggle source
# File lib/geospatial/location.rb, line 100 def <=> other to_a <=> other.to_a end
bearing_from(other)
click to toggle source
@return [Numeric] bearing in degrees.
# File lib/geospatial/location.rb, line 177 def bearing_from(other) lon1 = other.longitude * D2R lat1 = other.latitude * D2R lon2 = self.longitude * D2R lat2 = self.latitude * D2R return Math::atan2( Math::sin(lon2 - lon1) * Math::cos(lat2), Math::cos(lat1) * Math::sin(lat2) - Math::sin(lat1) * Math::cos(lat2) * Math::cos(lon2-lon1) ) * R2D end
bounding_box(distance, radius = R)
click to toggle source
janmatuschek.de/LatitudeLongitudeBoundingCoordinates
# File lib/geospatial/location.rb, line 110 def bounding_box(distance, radius = R) raise ArgumentError.new("Invalid distance or radius") if distance < 0 or radius < 0 # angular distance in radians on a great circle angular_distance = distance / radius min_latitude = (self.latitude * D2R) - angular_distance max_latitude = (self.latitude * D2R) + angular_distance if min_latitude > MIN_LATITUDE and max_latitude < MAX_LATITUDE longitude_delta = Math::asin(Math::sin(angular_distance) / Math::cos(self.latitude * D2R)) min_longitude = (self.longitude * D2R) - longitude_delta min_longitude += 2.0 * Math::PI if (min_longitude < MIN_LONGITUDE) max_longitude = (self.longitude * D2R) + longitude_delta; max_longitude -= 2.0 * Math::PI if (max_longitude > MAX_LONGITUDE) else # a pole is within the distance min_latitude = [min_latitude, MIN_LATITUDE].max max_latitude = [max_latitude, MAX_LATITUDE].min min_longitude = MIN_LONGITUDE max_longitude = MAX_LONGITUDE end return { :latitude => Range.new(min_latitude * R2D, max_latitude * R2D), :longitude => Range.new(min_longitude * R2D, max_longitude * R2D), } end
distance_from(other)
click to toggle source
calculate distance in metres between us and something else ref: codingandweb.blogspot.co.nz/2012/04/calculating-distance-between-two-points.html
# File lib/geospatial/location.rb, line 160 def distance_from(other) rlong1 = self.longitude * D2R rlat1 = self.latitude * D2R rlong2 = other.longitude * D2R rlat2 = other.latitude * D2R dlon = rlong1 - rlong2 dlat = rlat1 - rlat2 a = Math::sin(dlat/2) ** 2 + Math::cos(rlat1) * Math::cos(rlat2) * Math::sin(dlon/2) ** 2 c = 2 * Math::atan2(Math::sqrt(a), Math::sqrt(1-a)) d = R * c return d end
location_by(bearing, distance)
click to toggle source
@param distance [Numeric] distance in meters. @param bearing [Numeric] bearing in degrees.
# File lib/geospatial/location.rb, line 191 def location_by(bearing, distance) lon1 = self.longitude * D2R lat1 = self.latitude * D2R lat2 = Math::asin(Math::sin(lat1)*Math::cos(distance/R) + Math::cos(lat1)*Math::sin(distance/R)*Math::cos(bearing * D2R)) lon2 = lon1 + Math::atan2(Math::sin(bearing * D2R)*Math::sin(distance/R)*Math::cos(lat1), Math::cos(distance/R)-Math::sin(lat1)*Math::sin(lat2)) return self.class.new(lon2 * R2D, lat2 * R2D) end
midpoints_to(other, count) { |location_by(bearing, step * i)| ... }
click to toggle source
Compute count midpoints between self and other. @param count [Integer] the number of segments to generate.
# File lib/geospatial/location.rb, line 208 def midpoints_to(other, count) return to_enum(:midpoints_to, other, count) unless block_given? distance = other.distance_from(self) bearing = other.bearing_from(self) step = distance / count (1...count).each do |i| yield self.location_by(bearing, step * i) end end
to_a()
click to toggle source
# File lib/geospatial/location.rb, line 82 def to_a [@longitude, @latitude] end
to_ary()
click to toggle source
# File lib/geospatial/location.rb, line 86 def to_ary to_a end
to_ecef()
click to toggle source
Converts latitude, longitude to ECEF coordinate system
# File lib/geospatial/location.rb, line 143 def to_ecef clon = Math::cos(lon * D2R) slon = Math::sin(lon * D2R) clat = Math::cos(lat * D2R) slat = Math::sin(lat * D2R) n = WGS84_A / Math::sqrt(1.0 - WGS84_E * WGS84_E * slat * slat) x = n * clat * clon y = n * clat * slon z = n * (1.0 - WGS84_E * WGS84_E) * slat return x, y, z end
to_h()
click to toggle source
# File lib/geospatial/location.rb, line 90 def to_h {latitude: @latitude, longitude: @longitude} end
to_s()
click to toggle source
# File lib/geospatial/location.rb, line 94 def to_s "#{self.class}[#{self.longitude.to_f}, #{self.latitude.to_f}]" end
Also aliased as: inspect
valid?()
click to toggle source
# File lib/geospatial/location.rb, line 78 def valid? VALID_LONGITUDE.include?(longitude) and VALID_LATITUDE.include?(latitude) end