@@ -96,6 +96,7 @@ func TestLengthFromLatLngs(t *testing.T) {
96
96
{- 37 , 25 , - 66 , - 155 , 8562022.790666264 * unit .Meter },
97
97
{0 , 165 , 0 , - 80 , 12787436.635410652 * unit .Meter },
98
98
{47 , - 127 , - 47 , 53 , 20015118.077688109 * unit .Meter },
99
+ {51.961951 , - 180.227156 , 51.782383 , 181.126878 , 95.0783566198074 * unit .Kilometer },
99
100
}
100
101
for _ , test := range tests {
101
102
ll1 := s2 .LatLngFromDegrees (test .lat1 , test .lng1 )
@@ -106,13 +107,14 @@ func TestLengthFromLatLngs(t *testing.T) {
106
107
}
107
108
}
108
109
109
- func TestAreaFromSteradians ( t * testing. T ) {
110
- const earthArea = 6371.01 * 6371.01 * math .Pi * 4 * unit . SquareKilometer
111
- tests : = []struct {
110
+ var (
111
+ earthArea = unit . Area ( Radius . Meters () * Radius . Meters ()) * math .Pi * 4
112
+ steradiansToArea = []struct {
112
113
steradians float64
113
114
area unit.Area
114
115
}{
115
116
{1 , earthArea / 4 / math .Pi },
117
+ {4 * math .Pi , earthArea },
116
118
{s2 .PolygonFromLoops ([]* s2.Loop {s2 .FullLoop ()}).Area (), earthArea },
117
119
{s2 .PolygonFromLoops ([]* s2.Loop {s2 .LoopFromPoints ([]s2.Point {
118
120
s2 .PointFromLatLng (s2 .LatLngFromDegrees (- 90 , 0 )),
@@ -126,34 +128,18 @@ func TestAreaFromSteradians(t *testing.T) {
126
128
{s2 .AvgAreaMetric .Value (30 ), 73.73529927808979 * unit .SquareMillimeter }, // average area of level 30 cells
127
129
{s2 .PolygonFromLoops ([]* s2.Loop {s2 .EmptyLoop ()}).Area (), 0 * unit .SquareMeter },
128
130
}
129
- for _ , test := range tests {
131
+ )
132
+
133
+ func TestAreaFromSteradians (t * testing.T ) {
134
+ for _ , test := range steradiansToArea {
130
135
if got , want := AreaFromSteradians (test .steradians ), test .area ; ! float64Eq (got .SquareMeters (), want .SquareMeters ()) {
131
136
t .Errorf ("AreaFromSteradians(%v) = %v, want %v" , test .steradians , got , want )
132
137
}
133
138
}
134
139
}
135
140
136
141
func TestSteradiansFromArea (t * testing.T ) {
137
- const earthArea = 6371.01 * 6371.01 * math .Pi * 4 * unit .SquareKilometer
138
- tests := []struct {
139
- steradians float64
140
- area unit.Area
141
- }{
142
- {1 , earthArea / 4 / math .Pi },
143
- {s2 .PolygonFromLoops ([]* s2.Loop {s2 .FullLoop ()}).Area (), earthArea },
144
- {s2 .PolygonFromLoops ([]* s2.Loop {s2 .LoopFromPoints ([]s2.Point {
145
- s2 .PointFromLatLng (s2 .LatLngFromDegrees (- 90 , 0 )),
146
- s2 .PointFromLatLng (s2 .LatLngFromDegrees (0 , 0 )),
147
- s2 .PointFromLatLng (s2 .LatLngFromDegrees (90 , 0 )),
148
- s2 .PointFromLatLng (s2 .LatLngFromDegrees (0 , - 90 )),
149
- })}).Area (), earthArea / 4 },
150
- {s2 .CellFromCellID (s2 .CellIDFromFace (2 )).ExactArea (), earthArea / 6 },
151
- {s2 .AvgAreaMetric .Value (10 ), 81.07281893380302 * unit .SquareKilometer }, // average area of level 10 cells
152
- {s2 .AvgAreaMetric .Value (20 ), 77.31706517582228 * unit .SquareMeter }, // average area of level 20 cells
153
- {s2 .AvgAreaMetric .Value (30 ), 73.73529927808979 * unit .SquareMillimeter }, // average area of level 30 cells
154
- {s2 .PolygonFromLoops ([]* s2.Loop {s2 .EmptyLoop ()}).Area (), 0 * unit .SquareMeter },
155
- }
156
- for _ , test := range tests {
142
+ for _ , test := range steradiansToArea {
157
143
if got , want := SteradiansFromArea (test .area ), test .steradians ; ! float64Eq (got , want ) {
158
144
t .Errorf ("SteradiansFromArea(%v) = %v, want %v" , test .area , got , want )
159
145
}
@@ -186,7 +172,37 @@ func TestInitialBearingFromLatLngs(t *testing.T) {
186
172
t .Run (tc .name , func (t * testing.T ) {
187
173
got := InitialBearingFromLatLngs (tc .a , tc .b )
188
174
if diff := (got - tc .want ).Abs (); diff > 0.01 {
189
- t .Errorf ("InitialBearingsFromLatLngs(%s, %s): got %s, want %s, diff %s" , tc .a , tc .b , got , tc .want , diff )
175
+ t .Errorf ("InitialBearingFromLatLngs(%s, %s): got %s, want %s, diff %s" , tc .a , tc .b , got , tc .want , diff )
176
+ }
177
+ })
178
+ }
179
+ }
180
+
181
+ func TestInitialBearingFromLatLngsUndefinedResultDoesNotCrash (t * testing.T ) {
182
+ // InitialBearingFromLatLngs says if a == b, a == -b, or a is one of Earth's
183
+ // poles, the return value is undefined. Make sure it returns a real value
184
+ // (but don't assert what it is) rather than panicking or NaN.
185
+ // Bearing from a pole is undefined because 0° is north, but the observer
186
+ // can't face north from the north pole, so the calculation depends on the
187
+ // latitude value at the pole, even though 90°N 123°E and 90°N 45°W represent
188
+ // the same point. Bearing is undefined when a == b because the observer can
189
+ // point any direction and still be present. Bearing is undefined when
190
+ // a == -b (two antipodal points) because there are two possible paths.
191
+ for _ , tc := range []struct {
192
+ name string
193
+ a , b s2.LatLng
194
+ }{
195
+ {"North pole prime meridian to Null Island" , s2 .LatLngFromDegrees (90 , 0 ), s2 .LatLngFromDegrees (0 , 0 )},
196
+ {"North pole facing east to Guatemala" , s2 .LatLngFromDegrees (90 , 90 ), s2 .LatLngFromDegrees (15 , - 90 )},
197
+ {"South pole facing west to McMurdo" , s2 .LatLngFromDegrees (- 90 , - 90 ), s2 .LatLngFromDegrees (- 78 , 166 )},
198
+ {"South pole anti-prime meridian to Null Island" , s2 .LatLngFromDegrees (- 90 , - 180 ), s2 .LatLngFromDegrees (0 , 0 )},
199
+ {"Jakarta and antipode" , s2 .LatLngFromDegrees (- 6.109 , 106.668 ), s2 .LatLngFromDegrees (6.109 , - 180 + 106.668 )},
200
+ {"Alert and antipode" , s2 .LatLngFromDegrees (82.499 , - 62.350 ), s2 .LatLngFromDegrees (- 82.499 , 180 - 62.350 )},
201
+ } {
202
+ t .Run (tc .name , func (t * testing.T ) {
203
+ got := InitialBearingFromLatLngs (tc .a , tc .b )
204
+ if math .IsNaN (got .Radians ()) || math .IsInf (got .Radians (), 0 ) {
205
+ t .Errorf ("InitialBearingFromLatLngs(%s, %s): got %s, want a real value" , tc .a , tc .b , got )
190
206
}
191
207
})
192
208
}
0 commit comments