1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package s2
16
17 import (
18 "reflect"
19 "sort"
20 "testing"
21
22 "github.com/golang/geo/s1"
23 )
24
25 func TestDistanceTargetMaxCellTargetCapBound(t *testing.T) {
26 var md maxDistance
27 zero := md.zero()
28
29 for i := 0; i < 100; i++ {
30 cell := CellFromCellID(randomCellID())
31 target := NewMaxDistanceToCellTarget(cell)
32 c := target.capBound()
33
34 for j := 0; j < 100; j++ {
35 pTest := randomPoint()
36
37 if !c.ContainsPoint(pTest) {
38 if got := cell.MaxDistance(pTest); !zero.less(maxDistance(got)) {
39 t.Errorf("%v.MaxDistance(%v) = %v, want < %v", cell, pTest, got, zero)
40 }
41 }
42 }
43 }
44 }
45
46 func TestDistanceTargetMaxCellTargetUpdateDistance(t *testing.T) {
47 var ok bool
48
49 targetCell := CellFromCellID(cellIDFromPoint(parsePoint("0:1")))
50 target := NewMaxDistanceToCellTarget(targetCell)
51
52 dist0 := maxDistance(0)
53 dist10 := maxDistance(s1.ChordAngleFromAngle(s1.Angle(10) * s1.Degree))
54
55
56 p := parsePoint("0:0")
57 if _, ok = target.updateDistanceToPoint(p, dist0); !ok {
58 t.Errorf("target.updateDistanceToPoint(%v, %v) should have succeeded", p, dist0)
59 }
60 if _, ok = target.updateDistanceToPoint(p, dist10); ok {
61 t.Errorf("target.updateDistanceToPoint(%v, %v) should have failed", p, dist10)
62 }
63
64
65 dist0 = maxDistance(0)
66
67 pts := parsePoints("0:2, 0:3")
68 edge := Edge{pts[0], pts[1]}
69 if _, ok := target.updateDistanceToEdge(edge, dist0); !ok {
70 t.Errorf("target.updateDistanceToEdge(%v, %v) should have succeeded", edge, dist0)
71 }
72
73 if _, ok := target.updateDistanceToEdge(edge, dist10); ok {
74 t.Errorf("target.updateDistanceToEdge(%v, %v) should have failed", edge, dist10)
75 }
76
77
78 dist0 = maxDistance(0)
79
80 cell := CellFromCellID(cellIDFromPoint(parsePoint("0:0")))
81 if _, ok = target.updateDistanceToCell(cell, dist0); !ok {
82 t.Errorf("target.updateDistanceToCell(%v, %v) should have succeeded", cell, dist0)
83 }
84
85 if _, ok = target.updateDistanceToCell(cell, dist10); ok {
86 t.Errorf("target.updateDistanceToCell(%v, %v) should have failed", cell, dist10)
87 }
88 }
89
90 func TestDistanceTargetMaxCellTargetUpdateDistanceToCellAntipodal(t *testing.T) {
91 var maxDist maxDistance
92
93 p := parsePoint("0:0")
94 targetCell := CellFromCellID(cellIDFromPoint(p))
95 target := NewMaxDistanceToCellTarget(targetCell)
96 dist := maxDist.infinity()
97 cell := CellFromCellID(cellIDFromPoint(Point{p.Mul(-1)}))
98
99
100 dist0, ok := target.updateDistanceToCell(cell, dist)
101 if !ok {
102 t.Errorf("target.updateDistanceToCell(%v, %v) should have succeeded", cell, dist)
103 }
104 if dist0.chordAngle() != s1.StraightChordAngle {
105 t.Errorf("target.updateDistanceToCell() = %v, want %v", dist0.chordAngle(), s1.StraightChordAngle)
106 }
107
108 if _, ok := target.updateDistanceToCell(cell, dist0); ok {
109 t.Errorf("target.updateDistanceToCell(%v, %v) should have failed", cell, dist0)
110 }
111 }
112
113 func TestDistanceTargetMaxCellTargetUpdateDistanceToCellWhenEqual(t *testing.T) {
114 var maxDist maxDistance
115
116 targetCell := CellFromCellID(cellIDFromPoint(parsePoint("0:1")))
117 target := NewMaxDistanceToCellTarget(targetCell)
118 dist := maxDist.infinity()
119 cell := CellFromCellID(cellIDFromPoint(parsePoint("0:0")))
120
121
122 dist0, ok := target.updateDistanceToCell(cell, dist)
123 if !ok {
124 t.Errorf("target.updateDistanceToCell(%v, %v) should have succeeded", cell, dist)
125 }
126
127 if _, ok := target.updateDistanceToCell(cell, dist0); ok {
128 t.Errorf("target.updateDistanceToCell(%v, %v) should have failed", cell, dist0)
129 }
130 }
131
132 func TestDistanceTargetMaxCellTargetUpdateDistanceToEdgeWhenEqual(t *testing.T) {
133 var maxDist maxDistance
134
135 targetCell := CellFromCellID(cellIDFromPoint(parsePoint("0:1")))
136 target := NewMaxDistanceToCellTarget(targetCell)
137 dist := maxDist.infinity()
138 pts := parsePoints("0:-1, 0:1")
139 edge := Edge{pts[0], pts[1]}
140
141
142 dist0, ok := target.updateDistanceToEdge(edge, dist)
143 if !ok {
144 t.Errorf("target.updateDistanceToEdge(%v, %v) should have succeeded", edge, dist)
145 }
146
147 if _, ok := target.updateDistanceToEdge(edge, dist0); ok {
148 t.Errorf("target.updateDistanceToEdge(%v, %v) should have failed", edge, dist0)
149 }
150 }
151
152 func TestDistanceTargetMaxCellTargetVisitContainingShapes(t *testing.T) {
153 index := makeShapeIndex("1:1 # 1:1, 2:2 # 0:0, 0:3, 3:0 | 6:6, 6:9, 9:6 | -1:-1, -1:5, 5:-1")
154
155
156 targetCell := CellFromCellID(cellIDFromPoint(Point{parsePoint("1:1").Mul(-1)}))
157 target := NewMaxDistanceToCellTarget(targetCell)
158
159 if got, want := containingShapesForTarget(target, index, 1), []int{2}; !reflect.DeepEqual(got, want) {
160 t.Errorf("containingShapesForTarget(%v, %q, 1) = %+v, want %+v", target, shapeIndexDebugString(index), got, want)
161 }
162 if got, want := containingShapesForTarget(target, index, 5), []int{2, 4}; !reflect.DeepEqual(got, want) {
163 t.Errorf("containingShapesForTarget(%v, %q, 5) = %+v, want %+v", target, shapeIndexDebugString(index), got, want)
164 }
165
166
167
168
169
170 target2 := NewMaxDistanceToCellTarget(CellFromCellID(targetCell.ID().Parent(5)))
171 if got, want := containingShapesForTarget(target2, index, 5), []int{2, 4}; !reflect.DeepEqual(got, want) {
172 t.Errorf("containingShapesForTarget(%v, %q, 5) = %+v, want %+v", target2, shapeIndexDebugString(index), got, want)
173 }
174 }
175
176 func TestDistanceTargetMaxPointTargetUpdateDistance(t *testing.T) {
177 var ok bool
178 var dist0, dist10 distance
179 target := NewMaxDistanceToPointTarget(parsePoint("0:0"))
180 dist0 = maxDistance(0)
181 dist10 = maxDistance(s1.ChordAngleFromAngle(s1.Angle(10) * s1.Degree))
182
183
184 p := parsePoint("1:0")
185 if dist0, ok = target.updateDistanceToPoint(p, dist0); !ok {
186 t.Errorf("target.updateDistanceToPoint(%v, %v) should have succeeded", p, dist0)
187 }
188 if got, want := dist0.chordAngle().Angle().Degrees(), 1.0; !float64Near(got, want, epsilon) {
189 t.Errorf("target.updateDistanceToPoint(%v, %v) = %v, want ~%v", p, dist0.chordAngle(), got, want)
190 }
191 if _, ok = target.updateDistanceToPoint(p, dist10); ok {
192 t.Errorf("target.updateDistanceToPoint(%v, %v) should have failed", p, dist0)
193
194 }
195
196
197 dist0 = maxDistance(0)
198
199 pts := parsePoints("0:-1, 0:1")
200 edge := Edge{pts[0], pts[1]}
201 if dist0, ok = target.updateDistanceToEdge(edge, dist0); !ok {
202 t.Errorf("target.updateDistanceToEdge(%v, %v) should have succeeded", edge, dist0)
203 }
204 if got, want := dist0.chordAngle().Angle().Degrees(), 1.0; !float64Near(got, want, epsilon) {
205 t.Errorf("target.updateDistanceToEdge(%v, %v) = %v, want ~%v", edge, dist0.chordAngle(), got, want)
206 }
207 if _, ok = target.updateDistanceToEdge(edge, dist10); ok {
208 t.Errorf("target.updateDistanceToEdge(%v, %v) should have failed", edge, dist10)
209 }
210
211
212 dist0 = maxDistance(0)
213
214 cell := CellFromCellID(cellIDFromPoint(parsePoint("0:0")))
215 if _, ok = target.updateDistanceToCell(cell, dist0); !ok {
216 t.Errorf("target.updateDistanceToCell(%v, %v) should have succeeded", cell, dist0)
217 }
218
219 if _, ok = target.updateDistanceToCell(cell, dist10); ok {
220 t.Errorf("target.updateDistanceToCell(%v, %v) should have failed", cell, dist10)
221 }
222 }
223
224 func TestDistanceTargetMaxPointTargetUpdateDistanceToCellWhenEqual(t *testing.T) {
225 var maxDist maxDistance
226
227 target := NewMaxDistanceToPointTarget(parsePoint("1:0"))
228 dist := maxDist.infinity()
229 cell := CellFromCellID(cellIDFromPoint(parsePoint("0:0")))
230
231
232 dist0, ok := target.updateDistanceToCell(cell, dist)
233 if !ok {
234 t.Errorf("target.updateDistanceToCell(%v, %v) should have succeeded", cell, dist)
235 }
236
237 if _, ok := target.updateDistanceToCell(cell, dist0); ok {
238 t.Errorf("target.updateDistanceToCell(%v, %v) should have failed", cell, dist0)
239 }
240 }
241
242 func TestDistanceTargetMaxPointTargetUpdateDistanceToEdgeWhenEqual(t *testing.T) {
243 var maxDist maxDistance
244
245
246
247 target := NewMaxDistanceToPointTarget(parsePoint("1:0"))
248 dist := maxDist.infinity()
249 pts := parsePoints("0:-1, 0:1")
250 edge := Edge{pts[0], pts[1]}
251
252
253 dist0, ok := target.updateDistanceToEdge(edge, dist)
254 if !ok {
255 t.Errorf("target.updateDistanceToEdge(%v, %v) should have succeeded", edge, dist)
256 }
257
258 if _, ok := target.updateDistanceToEdge(edge, dist0); ok {
259 t.Errorf("target.updateDistanceToEdge(%v, %v) should have failed", edge, dist0)
260 }
261 }
262
263 func containingShapesForTarget(target distanceTarget, index *ShapeIndex, maxShapes int) []int {
264 shapeIDs := map[int32]bool{}
265 target.visitContainingShapes(index,
266 func(containingShape Shape, targetPoint Point) bool {
267
268 shapeIDs[index.idForShape(containingShape)] = true
269 return len(shapeIDs) < maxShapes
270 })
271 var ids []int
272 for k := range shapeIDs {
273 ids = append(ids, int(k))
274 }
275 sort.Ints(ids)
276 return ids
277 }
278
279 func TestDistanceTargetMaxPointTargetVisitContainingShapes(t *testing.T) {
280
281 index := makeShapeIndex("1:1 # 1:1, 2:2 # 0:0, 0:3, 3:0 | 6:6, 6:9, 9:6 | 0:0, 0:4, 4:0")
282
283
284 point := Point{parsePoint("1:1").Mul(-1)}
285 target := NewMaxDistanceToPointTarget(point)
286
287 if got, want := containingShapesForTarget(target, index, 1), []int{2}; !reflect.DeepEqual(got, want) {
288 t.Errorf("containingShapesForTarget(%v, %q, 1) = %+v, want %+v", point, shapeIndexDebugString(index), got, want)
289 }
290 if got, want := containingShapesForTarget(target, index, 5), []int{2, 4}; !reflect.DeepEqual(got, want) {
291 t.Errorf("containingShapesForTarget(%v, %q, 5) = %+v, want %+v", point, shapeIndexDebugString(index), got, want)
292 }
293 }
294
295 func TestDistanceTargetMaxEdgeTargetUpdateDistance(t *testing.T) {
296 var ok bool
297 var dist0, dist10 distance
298
299 targetPts := parsePoints("0:-1, 0:1")
300 targetEdge := Edge{targetPts[0], targetPts[1]}
301 target := NewMaxDistanceToEdgeTarget(targetEdge)
302
303 dist0 = maxDistance(0)
304 dist10 = maxDistance(s1.ChordAngleFromAngle(s1.Angle(10) * s1.Degree))
305
306
307 p := parsePoint("0:2")
308 if dist0, ok = target.updateDistanceToPoint(p, dist0); !ok {
309 t.Errorf("target.updateDistanceToPoint(%v, %v) should have succeeded", p, dist0)
310 }
311 if got, want := dist0.chordAngle().Angle().Degrees(), 3.0; !float64Near(got, want, epsilon) {
312 t.Errorf("target.updateDistanceToPoint(%v, %v) = %v, want ~%v", p, dist0.chordAngle(), got, want)
313 }
314 if _, ok = target.updateDistanceToPoint(p, dist10); ok {
315 t.Errorf("target.updateDistanceToPoint(%v, %v) should have failed", p, dist10)
316 }
317
318
319 dist0 = maxDistance(0)
320
321 pts := parsePoints("0:2, 0:3")
322 edge := Edge{pts[0], pts[1]}
323 if dist0, ok = target.updateDistanceToEdge(edge, dist0); !ok {
324 t.Errorf("target.updateDistanceToEdge(%v, %v) should have succeeded", edge, dist0)
325 }
326 if got, want := dist0.chordAngle().Angle().Degrees(), 4.0; !float64Near(got, want, epsilon) {
327 t.Errorf("target.updateDistanceToEdge(%v, %v) = %v, want ~%v", p, dist0.chordAngle(), got, want)
328 }
329 if _, ok = target.updateDistanceToEdge(edge, dist10); ok {
330 t.Errorf("target.updateDistanceToEdge(%v, %v) should have failed", edge, dist10)
331 }
332
333
334 dist0 = maxDistance(0)
335
336 cell := CellFromCellID(cellIDFromPoint(parsePoint("0:0")))
337 if _, ok = target.updateDistanceToCell(cell, dist0); !ok {
338 t.Errorf("target.updateDistanceToCell(%v, %v) should have succeeded", cell, dist0)
339 }
340
341 if _, ok = target.updateDistanceToCell(cell, dist10); ok {
342 t.Errorf("target.updateDistanceToCell(%v, %v) should have failed", cell, dist10)
343 }
344 }
345
346 func TestDistanceTargetMaxEdgeTargetUpdateDistanceToCellWhenEqual(t *testing.T) {
347 var maxDist maxDistance
348
349 targetEdge := parsePoints("1:0, 1:1")
350 target := NewMaxDistanceToEdgeTarget(Edge{targetEdge[0], targetEdge[1]})
351 dist := maxDist.infinity()
352 cell := CellFromCellID(cellIDFromPoint(parsePoint("0:0")))
353
354
355 dist0, ok := target.updateDistanceToCell(cell, dist)
356 if !ok {
357 t.Errorf("target.updateDistanceToCell(%v, %v) should have succeeded", cell, dist)
358 }
359
360 if _, ok := target.updateDistanceToCell(cell, dist0); ok {
361 t.Errorf("target.updateDistanceToCell(%v, %v) should have failed", cell, dist0)
362 }
363 }
364
365 func TestDistanceTargetMaxEdgeTargetUpdateDistanceToEdgeAntipodal(t *testing.T) {
366 var maxDist maxDistance
367
368 targetPts := parsePoints("0:89, 0:91")
369 targetEdge := Edge{targetPts[0], targetPts[1]}
370 target := NewMaxDistanceToEdgeTarget(targetEdge)
371 dist := maxDist.infinity()
372 pts := parsePoints("1:-90, -1:-90")
373 edge := Edge{pts[0], pts[1]}
374
375
376 dist0, ok := target.updateDistanceToEdge(edge, dist)
377 if !ok {
378 t.Errorf("target.updateDistanceToEdge(%v, %v) should have succeeded", edge, dist)
379 }
380
381 if dist0.chordAngle() != s1.StraightChordAngle {
382 t.Errorf("target.updateDistanceToPoint(%v, %v) = %v, want %v", edge, dist0, dist0, s1.StraightChordAngle)
383 }
384 }
385
386 func TestDistanceTargetMaxEdgeTargetUpdateDistanceToEdgeWhenEqual(t *testing.T) {
387 var maxDist maxDistance
388
389 targetEdge := parsePoints("1:0, 1:1")
390 target := NewMaxDistanceToEdgeTarget(Edge{targetEdge[0], targetEdge[1]})
391 dist := maxDist.infinity()
392 pts := parsePoints("0:-1, 0:1")
393 edge := Edge{pts[0], pts[1]}
394
395
396 dist0, ok := target.updateDistanceToEdge(edge, dist)
397 if !ok {
398 t.Errorf("target.updateDistanceToEdge(%v, %v) should have succeeded", edge, dist)
399 }
400
401 if _, ok := target.updateDistanceToEdge(edge, dist0); ok {
402 t.Errorf("target.updateDistanceToEdge(%v, %v) should have failed", edge, dist0)
403 }
404 }
405
406 func TestDistanceTargetMaxEdgeTargetVisitContainingShapes(t *testing.T) {
407
408 index := makeShapeIndex("1:1 # 1:1, 2:2 # 0:0, 0:3, 3:0 | 6:6, 6:9, 9:6 | 0:0, 0:4, 4:0")
409
410
411 pts := parsePoints("1:2, 2:1")
412 edge := Edge{Point{pts[0].Mul(-1)}, Point{pts[1].Mul(-1)}}
413 target := NewMaxDistanceToEdgeTarget(edge)
414
415 if got, want := containingShapesForTarget(target, index, 1), []int{2}; !reflect.DeepEqual(got, want) {
416 t.Errorf("containingShapesForTarget(%v, %q, 1) = %+v, want %+v", target, shapeIndexDebugString(index), got, want)
417 }
418 if got, want := containingShapesForTarget(target, index, 5), []int{2, 4}; !reflect.DeepEqual(got, want) {
419 t.Errorf("containingShapesForTarget(%v, %q, 5) = %+v, want %+v", target, shapeIndexDebugString(index), got, want)
420 }
421 }
422
423 func TestDistanceTargetMaxShapeIndexTargetCapBound(t *testing.T) {
424 var md maxDistance
425 zero := md.zero()
426 inf := md.infinity()
427
428 index := NewShapeIndex()
429 index.Add(PolygonFromCell(CellFromCellID(randomCellID())))
430 pv := PointVector([]Point{randomPoint()})
431 index.Add(Shape(&pv))
432 target := NewMaxDistanceToShapeIndexTarget(index)
433 c := target.capBound()
434
435 for j := 0; j < 100; j++ {
436 pTest := randomPoint()
437
438 if !c.ContainsPoint(pTest) {
439 var curDist distance = inf
440 var ok bool
441 if curDist, ok = target.updateDistanceToPoint(pTest, curDist); !ok {
442 t.Errorf("updateDistanceToPoint failed, but should have succeeded")
443 continue
444 }
445 if !zero.less(curDist) {
446 t.Errorf("point %v outside of cap should be less than %v distance, but were %v", pTest, zero, curDist)
447 }
448 }
449 }
450 }
451
452 func TestDistanceTargetMaxShapeIndexTargetUpdateDistanceToCellWhenEqual(t *testing.T) {
453 var maxDist maxDistance
454
455 index := makeShapeIndex("1:0 # #")
456 target := NewMaxDistanceToShapeIndexTarget(index)
457 dist := maxDist.infinity()
458 cell := CellFromCellID(cellIDFromPoint(parsePoint("0:0")))
459
460
461 dist0, ok := target.updateDistanceToCell(cell, dist)
462 if !ok {
463 t.Errorf("target.updateDistanceToCell(%v, %v) should have succeeded", cell, dist)
464 }
465
466 if _, ok := target.updateDistanceToCell(cell, dist0); ok {
467 t.Errorf("target.updateDistanceToCell(%v, %v) should have failed", cell, dist0)
468 }
469 }
470
471 func TestDistanceTargetMaxShapeIndexTargetUpdateDistanceToEdgeWhenEqual(t *testing.T) {
472 var maxDist maxDistance
473
474 index := makeShapeIndex("1:0 # #")
475 target := NewMaxDistanceToShapeIndexTarget(index)
476 dist := maxDist.infinity()
477 pts := parsePoints("0:-1, 0:1")
478 edge := Edge{pts[0], pts[1]}
479
480
481 dist0, ok := target.updateDistanceToEdge(edge, dist)
482 if !ok {
483 t.Errorf("target.updateDistanceToEdge(%v, %v) should have succeeded", edge, dist)
484 }
485
486 if _, ok := target.updateDistanceToEdge(edge, dist0); ok {
487 t.Errorf("target.updateDistanceToEdge(%v, %v) should have failed", edge, dist0)
488 }
489 }
490
491
492 func reflectPoints(pts []Point) []Point {
493 var negativePts []Point
494 for _, p := range pts {
495 negativePts = append(negativePts, Point{p.Mul(-1)})
496 }
497 return negativePts
498 }
499
500 func TestDistanceTargetMaxShapeIndexTargetVisitContainingShapes(t *testing.T) {
501
502
503 index := makeShapeIndex("1:1 | 4:4 | 7:7 | 10:10 # " +
504 "1:1, 1:2 | 4:4, 4:5 | 7:7, 7:8 | 10:10, 10:11 # " +
505 "0:0, 0:3, 3:0 | 3:3, 3:6, 6:3 | 6:6, 6:9, 9:6 | 9:9, 9:12, 12:9")
506
507
508
509
510 targetIndex := NewShapeIndex()
511
512 pts := PointVector(reflectPoints(parsePoints("1:1")))
513 targetIndex.Add(&pts)
514
515 line := Polyline(reflectPoints(parsePoints("4:5, 5:4")))
516 targetIndex.Add(&line)
517
518 loops := [][]Point{
519 reflectPoints(parsePoints("20:20, 20:21, 21:20")),
520 reflectPoints(parsePoints("10:10, 10:11, 11:10")),
521 }
522 laxPoly := LaxPolygonFromPoints(loops)
523 targetIndex.Add(laxPoly)
524
525 target := NewMaxDistanceToShapeIndexTarget(targetIndex)
526
527
528
529 if got, want := containingShapesForTarget(target, index, 5), []int{5, 6, 8}; !reflect.DeepEqual(got, want) {
530 t.Errorf("containingShapesForTarget(%v, %q, 5) = %+v, want %+v", target, shapeIndexDebugString(index), got, want)
531 }
532 }
533
534 func TestDistanceTargetMaxShapeIndexTargetVisitContainingShapesEmptyAndFull(t *testing.T) {
535
536
537
538
539 index := makeShapeIndex("# # empty | full")
540
541
542 pointIndex := makeShapeIndex("1:1 # #")
543 pointTarget := NewMinDistanceToShapeIndexTarget(pointIndex)
544 if got, want := containingShapesForTarget(pointTarget, index, 5), []int{1}; !reflect.DeepEqual(got, want) {
545 t.Errorf("containingShapesForTarget(%v, %q, 5) = %+v, want %+v", pointTarget, shapeIndexDebugString(index), got, want)
546 }
547
548
549 fullPolygonIndex := makeShapeIndex("# # full")
550 fullTarget := NewMinDistanceToShapeIndexTarget(fullPolygonIndex)
551 if got, want := containingShapesForTarget(fullTarget, index, 5), []int{1}; !reflect.DeepEqual(got, want) {
552 t.Errorf("containingShapesForTarget(%v, %q, 5) = %+v, want %+v", fullTarget, shapeIndexDebugString(index), got, want)
553 }
554
555
556
557
558 emptyPolygonIndex := makeShapeIndex("# # empty")
559 emptyTarget := NewMinDistanceToShapeIndexTarget(emptyPolygonIndex)
560 if got, want := containingShapesForTarget(emptyTarget, index, 5), []int(nil); !reflect.DeepEqual(got, want) {
561 t.Errorf("containingShapesForTarget(%v, %q, 5) = %+v, want %+v", emptyTarget, shapeIndexDebugString(index), got, want)
562 }
563 }
564
View as plain text