@@ -177,6 +177,102 @@ func TestEdgeQuerySortAndUnique(t *testing.T) {
177177 }
178178}
179179
180+ func TestEdgeQueryOptimized (t * testing.T ) {
181+ tests := []struct {
182+ name string
183+ locs []struct { latitude , longitude float64 }
184+ }{
185+ {
186+ // 0 intermediate faces: first and last handled directly
187+ "faces 0,4" ,
188+ []struct { latitude , longitude float64 }{{20 , 20 }, {40 , - 100 }},
189+ },
190+
191+ {
192+ "faces 0,4 (3+1 shapes)" ,
193+ []struct { latitude , longitude float64 }{{20 , 20 }, {25 , 25 }, {15 , 15 }, {40 , - 100 }},
194+ },
195+
196+ {
197+ // 1 intermediate face with 1 shape each
198+ "faces 0,1,4" ,
199+ []struct { latitude , longitude float64 }{{20 , 20 }, {40 , 90 }, {40 , - 100 }},
200+ },
201+
202+ {
203+ // 1 intermediate face but multiple shapes on first face
204+ "faces 0,1,4 (3+1+1 shapes)" ,
205+ []struct { latitude , longitude float64 }{{20 , 20 }, {25 , 25 }, {15 , 15 }, {40 , 90 }, {40 , - 100 }},
206+ },
207+
208+ {
209+ // 2 intermediate faces
210+ "faces 0,1,3,4" ,
211+ []struct { latitude , longitude float64 }{{20 , 20 }, {40 , 90 }, {0 , 170 }, {40 , - 100 }},
212+ },
213+
214+ {
215+ // All 6 faces: extreme case with 4 intermediate faces
216+ "all 6 faces" ,
217+ []struct { latitude , longitude float64 }{
218+ {20 , 20 }, {40 , 90 }, {90 , 0 }, {0 , 170 }, {40 , - 100 }, {- 90 , 0 },
219+ },
220+ },
221+
222+ {
223+ // Non-zero starting face with 1 intermediate
224+ "faces 1,3,4" ,
225+ []struct { latitude , longitude float64 }{{40 , 90 }, {0 , 170 }, {40 , - 100 }},
226+ },
227+
228+ {
229+ // Non-zero starting face with 2 intermediate faces
230+ "faces 1,2,3,4" ,
231+ []struct { latitude , longitude float64 }{{40 , 90 }, {90 , 0 }, {0 , 170 }, {40 , - 100 }},
232+ },
233+ }
234+
235+ for _ , test := range tests {
236+ t .Run (test .name , func (t * testing.T ) {
237+ index := NewShapeIndex ()
238+ for _ , location := range test .locs {
239+ center := PointFromLatLng (LatLngFromDegrees (location .latitude , location .longitude ))
240+ loop := RegularLoop (center , s1 .Degree , 8 )
241+ index .Add (PolygonFromLoops ([]* Loop {loop }))
242+ }
243+
244+ queryPoint := PointFromLatLng (LatLngFromDegrees (0 , 10 ))
245+
246+ optimized := NewClosestEdgeQueryOptions ().IncludeInteriors (true )
247+ got := NewClosestEdgeQuery (index , optimized ).FindEdges (
248+ NewMinDistanceToPointTarget (queryPoint ),
249+ )
250+
251+ bruteForce := NewClosestEdgeQueryOptions ().IncludeInteriors (true ).UseBruteForce (true )
252+ want := NewClosestEdgeQuery (index , bruteForce ).FindEdges (
253+ NewMinDistanceToPointTarget (queryPoint ),
254+ )
255+
256+ shapesGot , shapesWant := make (map [int32 ]bool ), make (map [int32 ]bool )
257+ for _ , r := range got {
258+ shapesGot [r .ShapeID ()] = true
259+ }
260+ for _ , r := range want {
261+ shapesWant [r .ShapeID ()] = true
262+ }
263+
264+ if len (shapesGot ) != len (shapesWant ) {
265+ t .Errorf (
266+ "%s: optimized found %d shapes, brute force found %d" ,
267+ test .name ,
268+ len (shapesGot ),
269+ len (shapesWant ),
270+ )
271+ }
272+ })
273+ }
274+ }
275+
180276// For various tests and benchmarks on the edge query code, there are a number of
181277// ShapeIndex generators that can be used.
182278type shapeIndexGeneratorFunc func (c Cap , numEdges int , index * ShapeIndex )
0 commit comments