geo_calc 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,174 @@
1
+ require 'spec_helper'
2
+
3
+ # - www.movable-type.co.uk/scripts/latlong.html
4
+
5
+ # Accuracy: since the earth is not quite a sphere, there are small errors in using spherical geometry; the earth is actually roughly ellipsoidal (or more precisely, oblate spheroidal) with a radius varying between about 6,378km (equatorial) and 6,357km (polar), and local radius of curvature varying from 6,336km (equatorial meridian) to 6,399km (polar). 6,371 km is the generally accepted value for the Earth’s mean radius. This means that errors from assuming spherical geometry might be up to 0.55% crossing the equator, though generally below 0.3%, depending on latitude and direction of travel. An accuracy of better than 3m in 1km is mostly good enough for me, but if you want greater accuracy, you could use the Vincenty formula for calculating geodesic distances on ellipsoids, which gives results accurate to within 1mm. (Out of sheer perversity – I’ve never needed such accuracy – I looked up this formula and discovered the JavaScript implementation was simpler than I expected).
6
+ # Trig functions take arguments in radians, so latitude, longitude, and bearings in degrees (either decimal or degrees/minutes/seconds) need to be converted to radians, rad = π.deg/180. When converting radians back to degrees (deg = 180.rad/π), West is negative if using signed decimal degrees. For bearings, values in the range -π to +π [-180° to +180°] need to be converted to 0 to +2π [0°–360°]; this can be done by (brng+2.π)%2.π [or brng+360)%360] where % is the modulo operator.
7
+ #
8
+ # The atan2() function widely used here takes two arguments, atan2(y, x), and computes the arc tangent of the ratio y/x. It is more flexible than atan(y/x), since it handles x=0, and it also returns values in all 4 quadrants -π to +π (the atan function returns values in the range -π/2 to +π/2).
9
+ # All bearings are with respect to true north, 0°=N, 90°=E, etc; if you are working from a compass, magnetic north varies from true north in a complex way around the earth, and the difference has to be compensated for by variances indicated on local maps.
10
+ #
11
+ # If you implement any formula involving atan2 in Microsoft Excel, you will need to reverse the arguments, as Excel has them the opposite way around from JavaScript – conventional order is atan2(y, x), but Excel uses atan2(x, y). To use atan2 in a (VBA) macro, you can use WorksheetFunction.Atan2().
12
+ # If you are using Google Maps, several of these functions are now provided in the Google Maps API V3 ‘spherical’ library (computeDistanceBetween(), computeHeading(), computeOffset(), interpolate(), etc;
13
+ # note they use a default Earth radius of 6,378,137 meters).
14
+ #
15
+ # I learned a lot from the US Census Bureau GIS FAQ which is no longer available, so I’ve made a copy.
16
+ # Thanks to Ed Williams’ Aviation Formulary for many of the formulæ.
17
+ # For miles, divide km by 1.609344
18
+ # For nautical miles, divide km by 1.852
19
+
20
+ describe GeoCalc do
21
+
22
+ # Point 1: 50 03 59N, 005 42 53W
23
+ # Point 2: 58 38 38N, 003 04 12W
24
+ context 'p1= (50 03 59N, 005 42 53W) .. p2= (58 38 38N, 003 04 12W)' do
25
+ before do
26
+ @p1 = GeoPoint.new "50 03 59N", "005 42 53W"
27
+ @p2 = GeoPoint.new "58 38 38N, 003 04 12W"
28
+ end
29
+
30
+ # Distance: 968.9 km
31
+ describe '#distance_to' do
32
+ it 'should return the distance from p1 to p2 as 968.9 km' do
33
+ @p1.distance_to(@p2).should be_within(0.5).of(968.9)
34
+ end
35
+ end
36
+
37
+ # Initial bearing: 009°07′11″
38
+ describe '#bearing_to' do
39
+ it 'should return the initial bearing from p1 to p2 as 009 07 11' do
40
+ @p1.bearing_to(@p2).to_dms.should match /009.+07.+11/
41
+ end
42
+ end
43
+
44
+ # Final bearing: 011°16′31″
45
+ describe '#final_bearing_to' do
46
+ it 'should return the initial bearing from p1 to p2 as 011 16 31' do
47
+ @p1.final_bearing_to(@p2).to_dms.should match /011.+16.+31/
48
+ end
49
+ end
50
+ #
51
+ # Midpoint: 54°21′44″N, 004°31′50″W
52
+ describe '#midpoint_to' do
53
+ it 'should return the initial bearing from p1 to p2 as 011 16 31' do
54
+ @p1.midpoint_to(@p2).to_dms.should match /54.+21.+44.+N, 004.+31.+50.+W/
55
+ end
56
+ end
57
+ end # context
58
+
59
+ # Start Point: 53°19′14″N, 001°43′47″W
60
+ # Bearing: 096°01′18″
61
+ # Distance: 124.8
62
+
63
+ context 'Start Point: (53 19 14 N, 001 43 47 W)' do
64
+ before do
65
+ @p1 = GeoPoint.new "53 19 14 N, 001 43 47 W"
66
+ end
67
+
68
+ # Destination point: 53°11′18″N, 000°08′00″E
69
+ # Final bearing: 097°30′52″
70
+ describe '#destination_point' do
71
+ it 'should return the destination_point as (53 11 18 N, 000 08 00 E)' do
72
+ # Bearing: 096°01′18″
73
+ # Distance: 124.8
74
+ @p2 = @p1.destination_point("096 01 18", 124.8)
75
+ @p2.to_dms.should match /53.+11.+18.+N, 000.+08.+00.+E/
76
+
77
+ # @p1.final_bearing_to(@p2).to_dms.should == "097°30′52″"
78
+ end
79
+ end
80
+ end
81
+
82
+ # Intersection:
83
+ # Point 1: 51.885 N, 0.235 E; Brng 108.63°
84
+ # Point 2: 49.008 N, 2.549 E; Brng 32.72°
85
+ # Distance: 124.8 km
86
+ context 'Points: (51.885 N, 0.235 E) Brng 108.63 .. (49.008 N, 2.549 E) Brng 32.72' do
87
+ before do
88
+ @p1 = GeoPoint.new "51.885 N, 0.235 E"
89
+ @brng1 = "108.63"
90
+ @p2 = GeoPoint.new "49.008 N, 2.549 E"
91
+ @brng2 = "32.72"
92
+ end
93
+
94
+ # Intersection point: 50°54′06″N, 004°29′39″E
95
+ describe '#intersection' do
96
+ it 'should return the intersection between p1 and p2 as (50 54 06 N, 004 29 39 E)' do
97
+ GeoCalc.intersection(@p1, @brng1, @p2, @brng2).to_dms.should match /50.+54.+06.+N, 004.+29.+39.+E/
98
+ end
99
+ end
100
+ end
101
+
102
+ # Rhumb lines:
103
+ # Point 1: (50 21 50 N, 004 09 25 W)
104
+ # Point 2: (42 21 04 N, 071 02 27 W)
105
+ context 'Points: (50 21 50N, 004 09 25W ) (42 21 04N, 071 02 27 W)' do
106
+ before do
107
+ @p1 = GeoPoint.new "50 21 50N, 004 09 25 W"
108
+ @p2 = GeoPoint.new "42 21 04N, 071 02 27 W"
109
+ end
110
+
111
+ # Distance: 5196 km
112
+ describe '#rhumb_distance_to' do
113
+ it 'should return the distance from p1 to p2 as 5196 km' do
114
+ @p1.rhumb_distance_to(@p2).should be_within(1).of(5196)
115
+ end
116
+ end
117
+
118
+ # Bearing: 260°07′38″
119
+ describe '#rhumb_bearing_to' do
120
+ it 'should return the initial bearing from p1 to p2 as 260 07 38' do
121
+ @p1.rhumb_bearing_to(@p2).to_dms.should match /260.+07.+38/
122
+ end
123
+ end
124
+ end
125
+
126
+ # Start Point: (51 07 32N, 001 20 17E)
127
+ # Bearing: 116°38′10
128
+ # Distance: 40.23 km
129
+ context 'Start Point: (51 07 32N, 001 20 17E), Bearing: 116 38 10, Distance: 40.23 km' do
130
+ before do
131
+ @p1 = GeoPoint.new "51 07 32N, 001 20 17E"
132
+ @brng = "116 38 10"
133
+ @dist = 40.23
134
+ end
135
+
136
+ # Destination point: 50°57′48″N, 001°51′09″E
137
+ describe '#rhumb_destination_point' do
138
+ it 'should return the destination_point as (50 57 48 N, 001 51 09 E)' do
139
+ @p2 = @p1.rhumb_destination_point(@brng, @dist)
140
+ @p2.to_dms.should match /50.+57.+48.+N, 001.+51.+09.+E/
141
+ end
142
+ end
143
+ end
144
+
145
+ # Conversion
146
+ # Point: (52°12′17.0″N, 000°08′26.0″E)
147
+ # 52.20472 numeric deg (lat)
148
+ # 0.14056 numeric deg (lon)
149
+ context 'Point: (52 12 17.0 N, 000 08 26.0 E)' do
150
+ before do
151
+ @p = GeoPoint.new "52 12 17.0 N", "000 08 26.0 E"
152
+ @lat = 52.20472
153
+ @lon = 0.14056
154
+ end
155
+
156
+ # 1° ≈ 111 km (110.57 eq’l — 111.70 polar)
157
+ # 1′ ≈ 1.85 km (= 1 nm) 0.01° ≈ 1.11 km
158
+ # 1″ ≈ 30.9 m 0.0001° ≈ 11.1 m
159
+
160
+ # Convert numeric degrees to deg/min/sec longitude (suffixed with E/W)
161
+ describe '#to_lon' do
162
+ it 'should Convert numeric degrees to deg/min/sec longitude (suffixed with E/W)' do
163
+ @lon.to_lon_dms.should match /000.+08.+26.+E/
164
+ end
165
+ end
166
+
167
+ # Convert numeric degrees to deg/min/sec latitude (suffixed with N/S)
168
+ describe '#to_lat' do
169
+ it 'should convert numeric degrees to deg/min/sec latitude (suffixed with N/S)' do
170
+ @lat.to_lat_dms.should match /52.+12.+17.+N/
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,272 @@
1
+ require 'spec_helper'
2
+
3
+ # - www.movable-type.co.uk/scripts/latlong.html
4
+ describe GeoPoint do
5
+ describe 'ruby core Class extensions' do
6
+ describe NumericGeoExt do
7
+ describe '#to_rad' do
8
+ it 'should convert 0 degrees to 0 radians' do
9
+ 0.to_rad.should == 0
10
+ end
11
+
12
+ it 'should convert 180 degrees to PI radians' do
13
+ 180.to_rad.should == Math::PI
14
+ end
15
+
16
+ it 'should convert 360 degrees to 6.28 radians' do
17
+ 360.to_rad.should == Math::PI*2
18
+ end
19
+ end
20
+
21
+ describe '#to_radians' do
22
+ it 'should alias to_rad' do
23
+ 360.to_rad.should == 360.to_radians
24
+ end
25
+ end
26
+
27
+ describe '#to_deg' do
28
+ it 'should convert 0 radians to 0 degrees' do
29
+ 0.to_deg.should == 0
30
+ end
31
+
32
+ it 'should convert PI radians to 180 degrees' do
33
+ 180.to_rad.to_deg.should be_within(0.01).of(180)
34
+ end
35
+
36
+ it 'should convert 6.28 radians to 360 degrees' do
37
+ 360.to_rad.to_deg.should be_within(0.01).of(360)
38
+ end
39
+ end
40
+
41
+ describe '#to_degrees' do
42
+ it 'should alias to_deg' do
43
+ 360.to_deg.should == 360.to_degrees
44
+ end
45
+ end
46
+
47
+ describe '#to_fixed' do
48
+ it 'should make precision 4' do
49
+ 1.123456.to_fixed(2).should == '1.12'
50
+ end
51
+ end
52
+
53
+ describe '#to_precision' do
54
+ it 'should alis to_fixed' do
55
+ 1.123456.to_precision(4).should == '1.1235'
56
+ end
57
+ end
58
+
59
+ describe '#normalize' do
60
+ it 'should turn 180 deg and normalize' do
61
+ 361.normalize_deg(180).should == 181
62
+ end
63
+ it 'should normalize deg' do
64
+ 361.normalize_deg.should == 1
65
+ end
66
+
67
+ it 'should alias with #normalize_degrees' do
68
+ 362.normalize_degrees.should == 2
69
+ end
70
+ end
71
+ end # NumericGeoExt
72
+
73
+ describe NumericLatLngExt do
74
+ describe 'Fixnum extension' do
75
+ describe '#to_lat' do
76
+ it 'should return latitude degree value for 360' do
77
+ 360.to_lat.should == 0
78
+ end
79
+
80
+ it 'should normalize degrees before converting to latitude, so 361 becomes 1' do
81
+ 361.to_lat.should == 1
82
+ end
83
+ end
84
+
85
+ describe '#to_lng' do
86
+ it 'should return latitude degree value for 360' do
87
+ 90.to_lng.should == 90
88
+ end
89
+
90
+ it 'should normalize degrees before converting to latitude, so 361 becomes 1' do
91
+ 91.to_lng.should == 91
92
+ end
93
+ end
94
+ end
95
+
96
+ describe 'Float extension' do
97
+ describe '#to_lat' do
98
+ it 'should return latitude degree value for 360' do
99
+ (360.0).to_lat.should == 0
100
+ end
101
+
102
+ it 'should normalize degrees before converting to latitude, so 361 becomes 1' do
103
+ (361.1).to_lat.should be_within(0.01).of(1.1)
104
+ end
105
+ end
106
+
107
+ describe '#to_lng' do
108
+ it 'should return latitude degree value for 360' do
109
+ (360.0).to_lng.should == 0
110
+ end
111
+
112
+ it 'should normalize degrees before converting to latitude, so 361 becomes 1' do
113
+ (361.1).to_lng.should be_within(0.01).of(1.1)
114
+ end
115
+ end
116
+ end
117
+
118
+ describe 'Array extension' do
119
+ describe '#to_lat' do
120
+ it 'should return latitude as first element' do
121
+ @arr = [4, 27]
122
+ @arr.to_lat.should == 4
123
+ end
124
+
125
+ it 'should return latitude as #to_lng of first element' do
126
+ @arr = ["4.1", 27]
127
+ @arr.to_lat.should == 4.1
128
+ end
129
+ end
130
+
131
+ describe '#to_lng' do
132
+ it 'should return latitude degree value for 360' do
133
+ @arr = [4, 27]
134
+ @arr.to_lng.should == 27
135
+ end
136
+
137
+ it 'should return latitude as #to_lng of first element' do
138
+ @arr = [4, "27.2"]
139
+ @arr.to_lng.should == 27.2
140
+ end
141
+ end
142
+
143
+ describe '#to_lat_lng' do
144
+ it 'should return Array with lat, lng' do
145
+ @arr = ["3", {:lng => "2"}]
146
+ @arr.to_lat_lng.should == [3, 2]
147
+ end
148
+ end
149
+
150
+ describe '#geo_point' do
151
+ it 'should return a GeoPoint' do
152
+ @p = [3, 2].geo_point
153
+ @p.should be_a(GeoPoint)
154
+ @p.to_lat_lng.should == [3, 2]
155
+ end
156
+ end
157
+ end # Array
158
+
159
+ describe 'Hash extension' do
160
+ describe '#to_lat' do
161
+ it 'should return latitude as #to_lat on the value for key :lat' do
162
+ @hash = {:lat => 4}
163
+ @hash.to_lat.should == 4
164
+ end
165
+
166
+ it 'should return latitude as #to_lat on the value for key :latitude' do
167
+ @hash = {:latitude => "7"}
168
+ @hash.to_lat.should == 7
169
+ end
170
+ end
171
+
172
+ describe '#to_lng' do
173
+ it 'should return latitude as #to_lng on the value for key :lng' do
174
+ @hash = {:lng => 2}
175
+ @hash.to_lng.should == 2
176
+ end
177
+
178
+ it 'should return latitude as #to_lng on the value for key :longitude' do
179
+ @hash = {:longitude => "3.1"}
180
+ @hash.to_lng.should == 3.1
181
+ end
182
+ end
183
+
184
+ describe '#to_lat_lng' do
185
+ it 'should return Array with lat, lng' do
186
+ @hash = {:lng => 2, :lat => "3"}
187
+ @hash.to_lat_lng.should == [3, 2]
188
+ end
189
+ end
190
+
191
+ describe '#geo_point' do
192
+ it 'should return a GeoPoint' do
193
+ @p = {:lng => 2, :lat => "3"}.geo_point
194
+ @p.should be_a(GeoPoint)
195
+ @p.to_lat_lng.should == [3, 2]
196
+ end
197
+ end
198
+ end # Hash
199
+
200
+ describe 'String extension' do
201
+ describe '#to_lat' do
202
+ it 'should not return latitude on empty String' do
203
+ @str = ""
204
+ lambda { @str.to_lat}.should raise_error
205
+ end
206
+
207
+ it 'should return latitude' do
208
+ @str = "4"
209
+ @str.to_lat.should == 4
210
+ end
211
+
212
+ it 'should convert to latitude' do
213
+ @str = "50 03 59N"
214
+ @str.to_lat.should be_within(0.4).of(50)
215
+ end
216
+ end
217
+
218
+ describe '#to_lng' do
219
+ it 'should not return longitude on empty String' do
220
+ @str = ""
221
+ lambda { @str.to_lng}.should raise_error
222
+ end
223
+
224
+ it 'should return latitude' do
225
+ @str = "4"
226
+ @str.to_lat.should == 4
227
+ end
228
+
229
+ it 'should convert to latitude' do
230
+ @str = "50 03 59E"
231
+ @str.to_lat.should be_within(0.4).of(50)
232
+ end
233
+ end
234
+
235
+ describe '#to_lat_lng' do
236
+ it 'should return Array with lat, lng' do
237
+ @str = "4, 3"
238
+ @str.to_lat_lng.should == [4, 3]
239
+ end
240
+
241
+ it 'should raise error if only latitude' do
242
+ @str = "4"
243
+ lambda { @str.to_lat_lng}.should raise_error
244
+ end
245
+
246
+ it 'should raise error if "," but only latitude' do
247
+ @str = "4,"
248
+ lambda { @str.to_lat_lng}.should raise_error
249
+ end
250
+
251
+ it 'should raise error if "," in bad position' do
252
+ @str = ", 4 3"
253
+ lambda { @str.to_lat_lng}.should raise_error
254
+ end
255
+
256
+ it 'should raise error if not using "," as seperator' do
257
+ @str = "4; 3"
258
+ lambda { @str.to_lat_lng}.should raise_error
259
+ end
260
+ end
261
+
262
+ describe '#geo_point' do
263
+ it 'should return a GeoPoint' do
264
+ @p = "3, 2".geo_point
265
+ @p.should be_a(GeoPoint)
266
+ @p.to_lat_lng.should == [3, 2]
267
+ end
268
+ end
269
+ end # String
270
+ end
271
+ end
272
+ end
@@ -0,0 +1,228 @@
1
+ require 'spec_helper'
2
+
3
+ # - www.movable-type.co.uk/scripts/latlong.html
4
+ describe GeoPoint do
5
+ describe '#initializer' do
6
+ describe '1 argument' do
7
+ describe 'single String' do
8
+ describe '50.1, 5.0 ' do
9
+ it 'should create a GeoPoint' do
10
+ p1 = GeoPoint.new "50.1, 5.0"
11
+ p1.should be_a(GeoPoint)
12
+ p1.lat.should == 50.1
13
+ p1.lon.should == 5.0
14
+ p1.unit.should == :degrees
15
+ p1.radius.should == 6371
16
+ end
17
+ end
18
+
19
+ describe '(50.1, 5.0)' do
20
+ it 'should create a GeoPoint' do
21
+ p1 = GeoPoint.new "(50.1, 5.2)"
22
+ p1.should be_a(GeoPoint)
23
+ p1.lat.should == 50.1
24
+ p1.lon.should == 5.2
25
+ p1.unit.should == :degrees
26
+ p1.radius.should == 6371
27
+ end
28
+ end
29
+
30
+ describe '58 38 38N, 003 04 12W' do
31
+ it 'should create a GeoPoint' do
32
+ p1 = GeoPoint.new "58 38 38N, 003 04 12W"
33
+ p1.should be_a(GeoPoint)
34
+ p1.lat.should be_within(0.5).of(58.38)
35
+ p1.lon.should be_within(0.5).of(356.5)
36
+ p1.unit.should == :degrees
37
+ p1.radius.should == 6371
38
+ end
39
+ end
40
+
41
+ describe '(58 38 38N, 003 04 12W)' do
42
+ it 'should create a GeoPoint' do
43
+ p1 = GeoPoint.new "(58 38 38N, 003 04 12W)"
44
+ p1.should be_a(GeoPoint)
45
+ p1.lat.should be_within(0.5).of(58.38)
46
+ p1.lon.should be_within(0.5).of(356.5) # W is negative, then normalize
47
+ p1.unit.should == :degrees
48
+ p1.radius.should == 6371
49
+ end
50
+ end
51
+ end
52
+
53
+ describe 'single Array' do
54
+ describe '2 Fixed numbers: 50,5 ' do
55
+ it 'should create a GeoPoint' do
56
+ p1 = GeoPoint.new [50, 5]
57
+ p1.should be_a(GeoPoint)
58
+ p1.lat.should == 50
59
+ p1.lon.should == 5
60
+ p1.unit.should == :degrees
61
+ p1.radius.should == 6371
62
+ end
63
+ end
64
+
65
+ describe '2 Float numbers: 50.1, 5.0 ' do
66
+ it 'should create a GeoPoint' do
67
+ p1 = GeoPoint.new [50.1, 5.0]
68
+ p1.should be_a(GeoPoint)
69
+ p1.lat.should == 50.1
70
+ p1.lon.should == 5.0
71
+ p1.unit.should == :degrees
72
+ p1.radius.should == 6371
73
+ end
74
+ end
75
+
76
+ describe 'single Hash' do
77
+ describe 'with: {:lat => 50.1, :lng => 5.1}' do
78
+ it 'should create a GeoPoint' do
79
+ p1 = GeoPoint.new :lat => 50.1, :lng => 5.1
80
+ p1.should be_a(GeoPoint)
81
+ p1.lat.should == 50.1
82
+ p1.lon.should == 5.1
83
+ p1.unit.should == :degrees
84
+ p1.radius.should == 6371
85
+ end
86
+ end
87
+
88
+ describe 'with: {:lat => 50.1, :long => 5.1}' do
89
+ it 'should create a GeoPoint' do
90
+ p1 = GeoPoint.new :lat => 50.1, :long => 5.1
91
+ p1.should be_a(GeoPoint)
92
+ p1.lat.should == 50.1
93
+ p1.lon.should == 5.1
94
+ p1.unit.should == :degrees
95
+ p1.radius.should == 6371
96
+ end
97
+ end
98
+
99
+ describe 'with: {:latitude => 50.1, :longitude => 5.1}' do
100
+ it 'should create a GeoPoint' do
101
+ p1 = GeoPoint.new :latitude => 50.1, :longitude => 5.1
102
+ p1.should be_a(GeoPoint)
103
+ p1.lat.should == 50.1
104
+ p1.lon.should == 5.1
105
+ p1.unit.should == :degrees
106
+ p1.radius.should == 6371
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ describe 'with 2 arguments' do
114
+ describe '2 Fixed numbers (Fixnum)' do
115
+ it 'should create a GeoPoint' do
116
+ p1 = GeoPoint.new 50, 5
117
+ p1.should be_a(GeoPoint)
118
+ p1.lat.should == 50
119
+ p1.lon.should == 5
120
+ p1.unit.should == :degrees
121
+ p1.radius.should == 6371
122
+ end
123
+ end
124
+
125
+ describe '2 Float numbers' do
126
+ it 'should create a GeoPoint' do
127
+ p1 = GeoPoint.new 50.1, 5.0
128
+ p1.should be_a(GeoPoint)
129
+ p1.lat.should == 50.1
130
+ p1.lon.should == 5.0
131
+ p1.unit.should == :degrees
132
+ p1.radius.should == 6371
133
+ end
134
+ end
135
+
136
+ describe '2 Strings: "58 38 38N", "003 04 12W"' do
137
+ it 'should create a GeoPoint' do
138
+ p1 = GeoPoint.new "58 38 38N", "003 04 12W"
139
+ p1.should be_a(GeoPoint)
140
+ p1.lat.should be_within(0.5).of(58.38)
141
+ p1.lon.should be_within(0.5).of(356.5)
142
+ p1.unit.should == :degrees
143
+ p1.radius.should == 6371
144
+ end
145
+ end
146
+ end
147
+ end # initializer
148
+
149
+ describe '#to_s' do
150
+ before :each do
151
+ @p1 = GeoPoint.new 50.1, 5
152
+ end
153
+
154
+ it 'should return GeoPoint as a dms formatted String' do
155
+ @p1.to_s.should match /50.+5/
156
+ end
157
+
158
+ it 'should return GeoPoint as a dms formatted String' do
159
+ @p1.to_s(:dm, 2).should match /50.+5/
160
+ end
161
+ end
162
+
163
+ describe '#lat' do
164
+ before :each do
165
+ @p1 = GeoPoint.new 50, 5
166
+ end
167
+
168
+ it 'should return latitude' do
169
+ @p1.lat.should == 50
170
+ end
171
+
172
+ describe '#latitude (alias)' do
173
+ it 'should return latitude' do
174
+ @p1.latitude.should == 50
175
+ end
176
+ end
177
+ end
178
+
179
+ describe '#[]' do
180
+ before :each do
181
+ @p1 = GeoPoint.new 50, 5
182
+ end
183
+
184
+ it 'index of 0 should return latitude' do
185
+ @p1[0].should == 50
186
+ end
187
+
188
+ it 'index of 1 should return longitude' do
189
+ @p1[1].should == 5
190
+ end
191
+
192
+ it 'index of 2 should raise error' do
193
+ lambda {@p1[2]}.should raise_error
194
+ end
195
+
196
+ it ':lat should return latitude' do
197
+ @p1[:lat].should == 50
198
+ end
199
+
200
+ it ':long should return longitude' do
201
+ @p1[:long].should == 5
202
+ end
203
+ end
204
+
205
+ describe '#to_arr' do
206
+ before :each do
207
+ @p1 = GeoPoint.new 50, 5
208
+ end
209
+
210
+ it 'should return GeoPoint as an array depending on state of reverse_arr' do
211
+ @p1.to_arr.should == [50, 5]
212
+ end
213
+
214
+ describe '#reverse_arr!' do
215
+ it 'should reverse the array returned by #to_arr to [lng, lat]' do
216
+ @p1.reverse_arr!
217
+ @p1.to_arr.should == [5, 50]
218
+ end
219
+ end
220
+
221
+ describe '#reverse_arr!' do
222
+ it 'should turn effect of #to_arr back to normal [lat, lng]' do
223
+ @p1.normal_arr!
224
+ @p1.to_arr.should == [50, 5]
225
+ end
226
+ end
227
+ end
228
+ end