Class: SGS::Location
- Inherits:
-
Object
- Object
- SGS::Location
- Defined in:
- lib/sgs/location.rb
Overview
Class for dealing with latitude/longitude. Includes methods for parsing, converting to a printable string, and so forth.
Note that for convenience, we retain latitude and longitude in Radians rather than degrees.
Instance Attribute Summary collapse
-
#latitude ⇒ Object
Returns the value of attribute latitude.
-
#longitude ⇒ Object
Returns the value of attribute longitude.
Class Method Summary collapse
-
.parse(data) ⇒ Object
Create a new location from a lat/long hash.
Instance Method Summary collapse
-
#+(bearing) ⇒ Object
Calculate a new position from the current position given a bearing (angle and distance).
-
#-(loc) ⇒ Object
Subtract one location from another, returning a bearing.
-
#initialize(lat = nil, long = nil) ⇒ Location
constructor
Create the Location instance.
-
#latitude_array(fmt = nil) ⇒ Object
Produce a latitude array for NMEA output.
-
#latitude_d ⇒ Object
Return the latitude in degrees.
-
#latitude_d=(val) ⇒ Object
Set the latitude using a value in degrees.
-
#longitude_array(fmt = nil) ⇒ Object
Produce a longitude array for NMEA output.
-
#longitude_d ⇒ Object
Return the longitude in degrees.
-
#longitude_d=(val) ⇒ Object
Set the longitude using a value in degrees.
-
#move!(bearing) ⇒ Object
Move to the new location.
-
#parse(data) ⇒ Object
Parse the lat/long values passed as a string.
-
#parse_hash(data = {}) ⇒ Object
Parse the lat/long from a hash object.
-
#to_hash ⇒ Object
Convert the lat/long to a hash.
-
#to_kml(sep = ',') ⇒ Object
Display the lat/long as it would appear in a KML file.
-
#to_s(opts = {}) ⇒ Object
Display the lat/long as a useful string (in degrees).
-
#valid? ⇒ Boolean
Is this location valid?.
Constructor Details
#initialize(lat = nil, long = nil) ⇒ Location
Create the Location instance. Latitude and longitude passed in radians.
60 61 62 63 |
# File 'lib/sgs/location.rb', line 60 def initialize(lat = nil, long = nil) @latitude = lat.to_f if lat @longitude = long.to_f if long end |
Instance Attribute Details
#latitude ⇒ Object
Returns the value of attribute latitude.
56 57 58 |
# File 'lib/sgs/location.rb', line 56 def latitude @latitude end |
#longitude ⇒ Object
Returns the value of attribute longitude.
56 57 58 |
# File 'lib/sgs/location.rb', line 56 def longitude @longitude end |
Class Method Details
.parse(data) ⇒ Object
Create a new location from a lat/long hash. Uses the instance method to parse.
108 109 110 111 112 |
# File 'lib/sgs/location.rb', line 108 def self.parse(data) loc = new loc.parse(data) loc end |
Instance Method Details
#+(bearing) ⇒ Object
Calculate a new position from the current position given a bearing (angle and distance)
This code was derived from formulae on the Movable Type site: www.movable-type.co.uk/scripts/latlong.html
var lat2 = Math.asin( Math.sin(lat1)*Math.cos(d/R) +
Math.cos(lat1)*Math.sin(d/R)*Math.cos(angle) );
var lon2 = lon1 + Math.atan2(Math.sin(angle)*Math.sin(d/R)*Math.cos(lat1),
Math.cos(d/R)-Math.sin(lat1)*Math.sin(lat2));
82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/sgs/location.rb', line 82 def +(bearing) loc = Location.new sin_angle = Math.sin(bearing.angle) cos_angle = Math.cos(bearing.angle) sin_dstr = Math.sin(bearing.distance / EARTH_RADIUS) cos_dstr = Math.cos(bearing.distance / EARTH_RADIUS) sin_lat1 = Math.sin(@latitude) cos_lat1 = Math.cos(@latitude) loc.latitude = Math.asin(sin_lat1*cos_dstr + cos_lat1*sin_dstr*cos_angle) sin_lat2 = Math.sin(@latitude) loc.longitude = @longitude + Math.atan2(sin_angle*sin_dstr*cos_lat1, cos_dstr - sin_lat1*sin_lat2) loc end |
#-(loc) ⇒ Object
Subtract one location from another, returning a bearing
67 68 69 |
# File 'lib/sgs/location.rb', line 67 def -(loc) Bearing.compute(self, loc) end |
#latitude_array(fmt = nil) ⇒ Object
Produce a latitude array for NMEA output.
195 196 197 |
# File 'lib/sgs/location.rb', line 195 def latitude_array(fmt = nil) _make_ll_array latitude_d, "NS", fmt end |
#latitude_d ⇒ Object
Return the latitude in degrees.
183 184 185 |
# File 'lib/sgs/location.rb', line 183 def latitude_d Bearing.rtod @latitude end |
#latitude_d=(val) ⇒ Object
Set the latitude using a value in degrees.
189 190 191 |
# File 'lib/sgs/location.rb', line 189 def latitude_d=(val) @latitude = Bearing.dtor val end |
#longitude_array(fmt = nil) ⇒ Object
Produce a longitude array for NMEA output.
213 214 215 |
# File 'lib/sgs/location.rb', line 213 def longitude_array(fmt = nil) _make_ll_array longitude_d, "EW", fmt end |
#longitude_d ⇒ Object
Return the longitude in degrees.
201 202 203 |
# File 'lib/sgs/location.rb', line 201 def longitude_d Bearing.rtod @longitude end |
#longitude_d=(val) ⇒ Object
Set the longitude using a value in degrees.
207 208 209 |
# File 'lib/sgs/location.rb', line 207 def longitude_d=(val) @longitude = Bearing.dtor val end |
#move!(bearing) ⇒ Object
Move to the new location
99 100 101 102 103 |
# File 'lib/sgs/location.rb', line 99 def move!(bearing) loc = calculate(bearing) self.latitude = loc.latitude self.longitude = loc.longitude end |
#parse(data) ⇒ Object
Parse the lat/long values passed as a string. This function should be able to handle any type of lat/long string, in most general formats. See :to_s for examples.
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/sgs/location.rb', line 118 def parse(data) llvals = data.split /,/ if llvals.count == 1 # # Must be space-separated. Try that... llvals = data.split(/ /) if llvals.count != 2 raise ArgumentError.new "Cannot split lat/long values" end elsif llvals.count != 2 # # Too many comma separators. raise ArgumentError.new "Invalid lat/long values" end self.latitude_d = _ll_parse(llvals[0], "NS") self.longitude_d = _ll_parse(llvals[1], "EW") true end |
#parse_hash(data = {}) ⇒ Object
Parse the lat/long from a hash object.
139 140 141 142 |
# File 'lib/sgs/location.rb', line 139 def parse_hash(data = {}) self.latitude_d = _ll_parse(data["latitude"], "NS") self.longitude_d = _ll_parse(data["longitude"], "EW") end |
#to_hash ⇒ Object
Convert the lat/long to a hash.
152 153 154 |
# File 'lib/sgs/location.rb', line 152 def to_hash {"latitude" => latitude_d.round(6), "longitude" => longitude_d.round(6)} end |
#to_kml(sep = ',') ⇒ Object
Display the lat/long as it would appear in a KML file.
175 176 177 178 179 |
# File 'lib/sgs/location.rb', line 175 def to_kml(sep = ',') vals = [@longitude, @latitude, 0.0] str_vals = vals.map {|val| "%.8f" % Bearing.rtod(val)} str_vals.join(sep) end |
#to_s(opts = {}) ⇒ Object
Display the lat/long as a useful string (in degrees). Output formats are as follows (default is :d): :d “48.104051, -7.282614” :dd “48.104051N, 7.282614W” :dmm “48 6.243060N, 7 16.956840W” :dms “48 6 14.583600N, 7 16 57.410400W”
163 164 165 166 167 168 169 170 171 |
# File 'lib/sgs/location.rb', line 163 def to_s(opts = {}) if valid? lat_str = _ll_conv(latitude_d.round(6), "NS", opts) lon_str = _ll_conv(longitude_d.round(6), "EW", opts) "#{lat_str}, #{lon_str}" else "unknown" end end |
#valid? ⇒ Boolean
Is this location valid?
146 147 148 |
# File 'lib/sgs/location.rb', line 146 def valid? @latitude and @longitude end |