geo_calc 0.5.3 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geo_calc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-05-22 00:00:00.000000000Z
12
+ date: 2011-05-23 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &2161529760 !ruby/object:Gem::Requirement
16
+ requirement: &2163339360 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 2.5.0
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *2161529760
24
+ version_requirements: *2163339360
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bundler
27
- requirement: &2161528940 !ruby/object:Gem::Requirement
27
+ requirement: &2163338880 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '1'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *2161528940
35
+ version_requirements: *2163338880
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: jeweler
38
- requirement: &2161528040 !ruby/object:Gem::Requirement
38
+ requirement: &2163338380 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.5.2
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2161528040
46
+ version_requirements: *2163338380
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rcov
49
- requirement: &2161524740 !ruby/object:Gem::Requirement
49
+ requirement: &2163337860 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *2161524740
57
+ version_requirements: *2163337860
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rake
60
- requirement: &2161524140 !ruby/object:Gem::Requirement
60
+ requirement: &2163337360 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: '0.9'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *2161524140
68
+ version_requirements: *2163337360
69
69
  description: Geo calculations in ruby and javascript
70
70
  email: kmandrup@gmail.com
71
71
  executables: []
@@ -76,6 +76,7 @@ extra_rdoc_files:
76
76
  files:
77
77
  - .document
78
78
  - .rspec
79
+ - Changelog.textile
79
80
  - Gemfile
80
81
  - LICENSE.txt
81
82
  - README.textile
@@ -83,16 +84,27 @@ files:
83
84
  - VERSION
84
85
  - geo_calc.gemspec
85
86
  - lib/geo_calc.rb
86
- - lib/geo_calc/calculations.rb
87
+ - lib/geo_calc/calc.rb
88
+ - lib/geo_calc/calc/bearing.rb
89
+ - lib/geo_calc/calc/destination.rb
90
+ - lib/geo_calc/calc/distance.rb
91
+ - lib/geo_calc/calc/intersection.rb
92
+ - lib/geo_calc/calc/midpoint.rb
93
+ - lib/geo_calc/calc/rhumb.rb
87
94
  - lib/geo_calc/core_ext.rb
88
95
  - lib/geo_calc/geo.rb
89
96
  - lib/geo_calc/geo_point.rb
90
- - lib/geo_calc/js/geo_calc.js
97
+ - lib/geo_calc/pretty_print.rb
91
98
  - spec/geo_calc/calculations_spec.rb
99
+ - spec/geo_calc/core_ext/array_ext_spec.rb
100
+ - spec/geo_calc/core_ext/hash_ext_spec.rb
101
+ - spec/geo_calc/core_ext/numeric_geo_ext_spec.rb
102
+ - spec/geo_calc/core_ext/string_ext_spec.rb
92
103
  - spec/geo_calc/core_ext_spec.rb
93
104
  - spec/geo_calc/geo_point_spec.rb
94
105
  - spec/geo_calc/geo_spec.rb
95
106
  - spec/spec_helper.rb
107
+ - vendor/assets/javascript/geo_calc.js
96
108
  homepage: http://github.com/kristianmandrup/geo_calc
97
109
  licenses:
98
110
  - MIT
@@ -108,7 +120,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
108
120
  version: '0'
109
121
  segments:
110
122
  - 0
111
- hash: -3503624259360642159
123
+ hash: 1099117799658716810
112
124
  required_rubygems_version: !ruby/object:Gem::Requirement
113
125
  none: false
114
126
  requirements:
@@ -117,7 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
129
  version: '0'
118
130
  requirements: []
119
131
  rubyforge_project:
120
- rubygems_version: 1.8.0
132
+ rubygems_version: 1.8.3
121
133
  signing_key:
122
134
  specification_version: 3
123
135
  summary: Geo calculation library
@@ -1,333 +0,0 @@
1
- require 'geo_calc/geo'
2
- require 'geo_calc/core_ext'
3
-
4
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5
- # Latitude/longitude spherical geodesy formulae & scripts (c) Chris Veness 2002-2010
6
- # - www.movable-type.co.uk/scripts/latlong.html
7
- #
8
-
9
- module GeoCalc
10
- # Returns the distance from this point to the supplied point, in km
11
- # (using Haversine formula)
12
- #
13
- # from: Haversine formula - R. W. Sinnott, "Virtues of the Haversine",
14
- # Sky and Telescope, vol 68, no 2, 1984
15
- #
16
- # GeoPoint point: Latitude/longitude of destination point
17
- # - Numeric precision=4: number of significant digits to use for returned value
18
- #
19
- # Returns - Numeric distance in km between this point and destination point
20
-
21
- def distance_to point, precision = 4
22
- # default 4 sig figs reflects typical 0.3% accuracy of spherical model
23
- precision ||= 4
24
-
25
- lat1 = lat.to_rad
26
- lon1 = lon.to_rad
27
-
28
- lat2 = point.lat.to_rad
29
- lon2 = point.lon.to_rad
30
-
31
- dlat = lat2 - lat1
32
- dlon = lon2 - lon1
33
-
34
- a = Math.sin(dlat/2) * Math.sin(dlat/2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(dlon/2) * Math.sin(dlon/2)
35
- c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
36
- d = radius * c
37
- d.round(precision)
38
- end
39
-
40
-
41
- # Returns the (initial) bearing from this point to the supplied point, in degrees
42
- # see http:#williams.best.vwh.net/avform.htm#Crs
43
- #
44
- # - Point point: Latitude/longitude of destination point
45
- #
46
- # Returns - Numeric: Initial bearing in degrees from North
47
-
48
- def bearing_to point
49
- lat1 = lat.to_rad
50
- lat2 = point.lat.to_rad
51
- dlon = (point.lon - lon).to_rad
52
-
53
- y = Math.sin(dlon) * Math.cos(lat2)
54
- x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dlon)
55
- bearing = Math.atan2(y, x)
56
-
57
- (bearing.to_deg + 360) % 360
58
- end
59
-
60
-
61
- # Returns final bearing arriving at supplied destination point from this point; the final bearing
62
- # will differ from the initial bearing by varying degrees according to distance and latitude
63
- #
64
- # - GeoPoint point: Latitude/longitude of destination point
65
- #
66
- # Returns Numeric: Final bearing in degrees from North
67
-
68
- def final_bearing_to point
69
- # get initial bearing from supplied point back to this point...
70
- lat1 = point.lat.to_rad
71
- lat2 = lat.to_rad
72
- dlon = (lon - point.lon).to_rad
73
-
74
- y = Math.sin(dlon) * Math.cos(lat2)
75
- x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dlon)
76
- bearing = Math.atan2(y, x)
77
-
78
- # ... & reverse it by adding 180°
79
- (bearing.to_deg+180) % 360
80
- end
81
-
82
-
83
- # Returns the midpoint between this point and the supplied point.
84
- # see http:#mathforum.org/library/drmath/view/51822.html for derivation
85
- #
86
- # - GeoPoint point: Latitude/longitude of destination point
87
- # Returns GeoPoint: Midpoint between this point and the supplied point
88
-
89
- def midpoint_to point
90
- lat1 = lat.to_rad
91
- lon1 = lon.to_rad;
92
- lat2 = point.lat.to_rad
93
- dlon = (point.lon - lon).to_rad
94
-
95
- bx = Math.cos(lat2) * Math.cos(dlon)
96
- by = Math.cos(lat2) * Math.sin(dlon)
97
-
98
- lat3 = Math.atan2(Math.sin(lat1)+Math.sin(lat2), Math.sqrt( (Math.cos(lat1)+bx)*(Math.cos(lat1)+bx) + by*by) )
99
-
100
- lon3 = lon1 + Math.atan2(by, Math.cos(lat1) + bx)
101
-
102
- GeoPoint.new lat3.to_deg, lon3.to_deg
103
- end
104
-
105
-
106
- # Returns the destination point from this point having travelled the given distance (in km) on the
107
- # given initial bearing (bearing may vary before destination is reached)
108
- #
109
- # see http:#williams.best.vwh.net/avform.htm#LL
110
- #
111
- # - Numeric bearing: Initial bearing in degrees
112
- # - Numeric dist: Distance in km
113
- # Returns GeoPoint: Destination point
114
-
115
- def destination_point brng, dist
116
- dist = dist / radius # convert dist to angular distance in radians
117
- brng = brng.to_rad
118
- lat1 = lat.to_rad
119
- lon1 = lon.to_rad
120
-
121
- lat2 = Math.asin( Math.sin(lat1) * Math.cos(dist) + Math.cos(lat1) * Math.sin(dist) * Math.cos(brng) )
122
- lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(dist) * Math.cos(lat1), Math.cos(dist) - Math.sin(lat1) * Math.sin(lat2))
123
-
124
- lon2 = (lon2 + 3*Math::PI) % (2*Math::PI) - Math::PI # normalise to -180...+180
125
-
126
- GeoPoint.new lat2.to_deg, lon2.to_deg
127
- end
128
-
129
-
130
- # Returns the point of intersection of two paths defined by point and bearing
131
- #
132
- # see http:#williams.best.vwh.net/avform.htm#Intersection
133
- #
134
- # @param {LatLon} p1: First point
135
- # @param {Number} brng1: Initial bearing from first point
136
- # @param {LatLon} p2: Second point
137
- # @param {Number} brng2: Initial bearing from second point
138
- # @returns {LatLon} Destination point (null if no unique intersection defined)
139
-
140
- def self.intersection p1, brng1, p2, brng2
141
- lat1 = p1.lat.to_rad
142
- lon1 = p1.lon.to_rad
143
-
144
- lat2 = p2.lat.to_rad
145
- lon2 = p2.lon.to_rad
146
-
147
- brng13 = brng1.to_rad
148
- brng23 = brng2.to_rad
149
-
150
- dlat = lat2-lat1
151
- dlon = lon2-lon1;
152
-
153
- dist12 = 2*Math.asin( Math.sqrt( Math.sin(dlat/2)*Math.sin(dlat/2) + Math.cos(lat1)*Math.cos(lat2)*Math.sin(dlon/2)*Math.sin(dlon/2) ) )
154
- return nil if dist12 == 0
155
-
156
- # initial/final bearings between points
157
- brng_a = begin
158
- Math.acos( ( Math.sin(lat2) - Math.sin(lat1)*Math.cos(dist12) ) / ( Math.sin(dist12)*Math.cos(lat1) ) )
159
- rescue # protect against rounding
160
- 0
161
- end
162
-
163
- brng_b = Math.acos( ( Math.sin(lat1) - Math.sin(lat2)*Math.cos(dist12) ) / ( Math.sin(dist12)*Math.cos(lat2) ) )
164
-
165
- brng12, brng21 = if Math.sin(lon2-lon1) > 0
166
- [brng_a, 2*Math::PI - brng_b]
167
- else
168
- [2*Math::PI - brng_a, brng_b]
169
- end
170
-
171
- alpha1 = (brng13 - brng12 + Math::PI) % (2*Math::PI) - Math::PI # angle 2-1-3
172
- alpha2 = (brng21 - brng23 + Math::PI) % (2*Math::PI) - Math::PI # angle 1-2-3
173
-
174
- return nil if (Math.sin(alpha1)==0 && Math.sin(alpha2)==0) # infinite intersections
175
- return nil if (Math.sin(alpha1)*Math.sin(alpha2) < 0) # ambiguous intersection
176
-
177
- # alpha1 = Math.abs(alpha1);
178
- # alpha2 = Math.abs(alpha2);
179
- # ... Ed Williams takes abs of alpha1/alpha2, but seems to break calculation?
180
-
181
- alpha3 = Math.acos( -Math.cos(alpha1)*Math.cos(alpha2) + Math.sin(alpha1)*Math.sin(alpha2)*Math.cos(dist12) )
182
-
183
- dist13 = Math.atan2( Math.sin(dist12)*Math.sin(alpha1)*Math.sin(alpha2), Math.cos(alpha2)+Math.cos(alpha1)*Math.cos(alpha3) )
184
-
185
- lat3 = Math.asin( Math.sin(lat1)*Math.cos(dist13) + Math.cos(lat1)*Math.sin(dist13)*Math.cos(brng13) )
186
-
187
- dlon13 = Math.atan2( Math.sin(brng13)*Math.sin(dist13)*Math.cos(lat1), Math.cos(dist13)-Math.sin(lat1)*Math.sin(lat3) )
188
-
189
- lon3 = lon1 + dlon13;
190
- lon3 = (lon3 + Math::PI) % (2*Math::PI) - Math::PI # normalise to -180..180º
191
-
192
- GeoPoint.new lat3.to_deg, lon3.to_deg
193
- end
194
-
195
-
196
- # Returns the distance from this point to the supplied point, in km, travelling along a rhumb line
197
- #
198
- # see http:#williams.best.vwh.net/avform.htm#Rhumb
199
- #
200
- # - GeoPoint point: Latitude/longitude of destination point
201
- # Returns Numeric: Distance in km between this point and destination point
202
-
203
- def rhumb_distance_to point
204
- lat1 = lat.to_rad
205
- lat2 = point.lat.to_rad
206
-
207
- dlat = (point.lat-lat).to_rad
208
- dlon = (point.lon-lon).abs.to_rad
209
-
210
- dphi = Math.log(Math.tan(lat2/2 + Math::PI/4) / Math.tan(lat1/2 + Math::PI/4))
211
-
212
- q = begin
213
- dlat / dphi
214
- rescue
215
- Math.cos(lat1) # E-W line gives dPhi=0
216
- end
217
-
218
- # if dlon over 180° take shorter rhumb across 180° meridian:
219
- dlon = 2*Math::PI - dlon if (dlon > Math::PI)
220
-
221
- dist = Math.sqrt(dlat*dlat + q*q*dlon*dlon) * radius;
222
-
223
- dist.round(4) # 4 sig figures reflects typical 0.3% accuracy of spherical model
224
- end
225
-
226
-
227
- # Returns the bearing from this point to the supplied point along a rhumb line, in degrees
228
- #
229
- # - GeoPoint point: Latitude/longitude of destination point
230
- # Returns Numeric: Bearing in degrees from North
231
-
232
- def rhumb_bearing_to point
233
- lat1 = lat.to_rad
234
- lat2 = point.lat.to_rad
235
-
236
- dlon = (point.lon - lon).to_rad
237
-
238
- dphi = Math.log(Math.tan(lat2/2+Math::PI/4) / Math.tan(lat1/2+Math::PI/4))
239
- if dlon.abs > Math::PI
240
- dlon = dlon>0 ? -(2*Math::PI-dlon) : (2*Math::PI+dlon);
241
- end
242
-
243
- brng = Math.atan2(dlon, dphi);
244
-
245
- (brng.to_deg+360) % 360
246
- end
247
-
248
-
249
- # Returns the destination point from this point having travelled the given distance (in km) on the
250
- # given bearing along a rhumb line
251
- #
252
- # @param {Number} brng: Bearing in degrees from North
253
- # @param {Number} dist: Distance in km
254
- # @returns {LatLon} Destination point
255
-
256
- def rhumb_destination_point brng, dist
257
- d = dist / radius # d = angular distance covered on earth's surface
258
- lat1 = lat.to_rad
259
- lon1 = lon.to_rad
260
- brng = brng.to_rad
261
-
262
- lat2 = lat1 + d*Math.cos(brng);
263
- dlat = lat2-lat1;
264
- dphi = Math.log(Math.tan(lat2/2+Math::PI/4)/Math.tan(lat1/2+Math::PI/4))
265
-
266
- q = begin
267
- dlat/dphi
268
- rescue
269
- Math.cos(lat1) # E-W line gives dPhi=0
270
- end
271
-
272
- dlon = d*Math.sin(brng)/q
273
- # check for some daft bugger going past the pole
274
-
275
- if lat2.abs > Math::PI/2
276
- lat2 = lat2>0 ? Math::PI-lat2 : -(Math::PI-lat2)
277
- end
278
- lon2 = (lon1+dlon+3*Math::PI) % (2*Math::PI) - Math::PI
279
-
280
- GeoPoint.new lat2.to_deg, lon2.to_deg
281
- end
282
-
283
-
284
- # Returns the latitude of this point; signed numeric degrees if no format, otherwise format & dp
285
- # as per Geo.to_lat
286
- #
287
- # - String [format]: Return value as 'd', 'dm', 'dms'
288
- # - Numeric [dp=0|2|4]: No of decimal places to display
289
- #
290
- # Returns {Numeric|String}: Numeric degrees if no format specified, otherwise deg/min/sec
291
- #
292
-
293
- def to_lat format = :dms, dp = 0
294
- return lat if !format
295
- Geo.to_lat lat, format, dp
296
- end
297
-
298
-
299
- # Returns the longitude of this point; signed numeric degrees if no format, otherwise format & dp
300
- # as per Geo.toLon()
301
- #
302
- # @param {String} [format]: Return value as 'd', 'dm', 'dms'
303
- # @param {Number} [dp=0|2|4]: No of decimal places to display
304
- # @returns {Number|String} Numeric degrees if no format specified, otherwise deg/min/sec
305
- #
306
- # @requires Geo
307
-
308
- def to_lon format, dp
309
- return lon if !format
310
- Geo.to_lon lon, format, dp
311
- end
312
-
313
-
314
- # Returns a string representation of this point; format and dp as per lat()/lon()
315
- #
316
- # @param {String} [format]: Return value as 'd', 'dm', 'dms'
317
- # @param {Number} [dp=0|2|4]: No of decimal places to display
318
-
319
- # @returns {String} Comma-separated latitude/longitude
320
- #
321
-
322
- def to_s format = :dms, dp = 0
323
- format ||= :dms
324
-
325
- return '-,-' if !lat || !lon
326
-
327
- _lat = Geo.to_lat lat, format, dp
328
- _lon = Geo.to_lon lon, format, dp
329
-
330
- "#{_lat}, #{_lon}"
331
- end
332
- end
333
-