1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package s2
16
17 import (
18 "math"
19 "reflect"
20 "testing"
21
22 "github.com/golang/geo/r1"
23 "github.com/golang/geo/s1"
24 )
25
26 func TestCellUnionDuplicateCellsNotValid(t *testing.T) {
27 id := cellIDFromPoint(PointFromCoords(1, 0, 0))
28 cu := CellUnion([]CellID{id, id})
29 if cu.IsValid() {
30 t.Errorf("%v.IsValid() = true, want false", cu)
31 }
32 }
33
34 func TestCellUnionUnsortedCellsNotValid(t *testing.T) {
35 id := cellIDFromPoint(PointFromCoords(1, 0, 0)).Parent(10)
36 cu := CellUnion([]CellID{id, id.Prev()})
37 if cu.IsValid() {
38 t.Errorf("%v.IsValid() = true, want false", cu)
39 }
40 }
41
42 func TestCellUnionIsNormalized(t *testing.T) {
43 id := cellIDFromPoint(PointFromCoords(1, 0, 0)).Parent(10)
44 children := id.Children()
45 cu := CellUnion([]CellID{children[0], children[1], children[2], children[3]})
46 if !(cu.IsValid()) {
47 t.Errorf("%v.IsValid() = false, want true", cu)
48 }
49 if cu.IsNormalized() {
50 t.Errorf("%v.IsNormalized() = true, want false", cu)
51 }
52 }
53
54 func TestCellUnionInvalidCellIdNotValid(t *testing.T) {
55 cu := CellUnion([]CellID{CellID(0)})
56 if cu.IsValid() {
57 t.Error("CellUnion containing an invalid CellID should not be valid")
58 }
59 }
60
61 func TestCellUnionAreSiblings(t *testing.T) {
62 id := cellIDFromPoint(PointFromCoords(1, 0, 0)).Parent(10)
63 children := id.Children()
64 if siblings := areSiblings(children[0], children[1], children[2], children[3]); !siblings {
65 t.Errorf("areSiblings(%v, %v, %v, %v) = false, want true", children[0], children[1], children[2], children[3])
66 }
67
68 if siblings := areSiblings(id, children[1], children[2], children[3]); siblings {
69 t.Errorf("areSiblings(%v, %v, %v, %v) = true, want false", id, children[1], children[2], children[3])
70 }
71 }
72
73 func TestCellUnionNormalization(t *testing.T) {
74 cu := CellUnion{
75 0x80855c0000000000,
76 0x80855d0000000000,
77 0x8085634000000000,
78 0x808563c000000000,
79 0x80855dc000000000,
80 0x808562c000000000,
81 0x8085624000000000,
82 0x80855d0000000000,
83 }
84 exp := CellUnion{
85 0x80855c0000000000,
86 0x8085630000000000,
87 }
88 cu.Normalize()
89 if !reflect.DeepEqual(cu, exp) {
90 t.Errorf("got %v, want %v", cu, exp)
91 }
92
93
94
100 }
101
102 func TestCellUnionBasic(t *testing.T) {
103 empty := CellUnion{}
104 empty.Normalize()
105 if len(empty) != 0 {
106 t.Errorf("empty CellUnion had %d cells, want 0", len(empty))
107 }
108
109 face1ID := CellIDFromFace(1)
110 face1Cell := CellFromCellID(face1ID)
111 face1Union := CellUnion{face1ID}
112 face1Union.Normalize()
113 if len(face1Union) != 1 {
114 t.Errorf("%v had %d cells, want 1", face1Union, len(face1Union))
115 }
116 if face1ID != face1Union[0] {
117 t.Errorf("%v[0] = %v, want %v", face1Union, face1Union[0], face1ID)
118 }
119 if got := face1Union.ContainsCell(face1Cell); !got {
120 t.Errorf("%v.ContainsCell(%v) = %t, want %t", face1Union, face1Cell, got, true)
121 }
122
123 face2ID := CellIDFromFace(2)
124 face2Cell := CellFromCellID(face2ID)
125 face2Union := CellUnion{face2ID}
126 face2Union.Normalize()
127 if len(face2Union) != 1 {
128 t.Errorf("%v had %d cells, want 1", face2Union, len(face2Union))
129 }
130 if face2ID != face2Union[0] {
131 t.Errorf("%v[0] = %v, want %v", face2Union, face2Union[0], face2ID)
132 }
133
134 if got := face1Union.ContainsCell(face2Cell); got {
135 t.Errorf("%v.ContainsCell(%v) = %t, want %t", face1Union, face2Cell, got, false)
136 }
137
138 }
139
140 func TestCellUnion(t *testing.T) {
141 tests := []struct {
142 cells []CellID
143 contained []CellID
144 overlaps []CellID
145 disjoint []CellID
146 }{
147 {
148
149 cells: []CellID{0x89c25c0000000000},
150 contained: []CellID{
151 CellID(0x89c25c0000000000).ChildBegin(),
152 CellID(0x89c25c0000000000).ChildBeginAtLevel(28),
153 },
154 overlaps: []CellID{
155 CellID(0x89c25c0000000000).immediateParent(),
156 CellIDFromFace(CellID(0x89c25c0000000000).Face()),
157 },
158 disjoint: []CellID{
159 CellID(0x89c25c0000000000).Next(),
160 CellID(0x89c25c0000000000).Next().ChildBeginAtLevel(28),
161 0x89c2700000000000,
162 0x89e9000000000000,
163 0x89c1000000000000,
164 },
165 },
166
167 {
168
169 cells: []CellID{
170 0x89c25b0000000000,
171 0x89c2590000000000,
172 0x89c2f70000000000,
173 0x89c2f50000000000,
174 0x8085870000000000,
175 0x8085810000000000,
176 0x808f7d0000000000,
177 0x808f7f0000000000,
178 },
179 contained: []CellID{
180 0x808f7ef300000000,
181 0x808f7e5cf0000000,
182 0x808587f000000000,
183 0x89c25ac000000000,
184 0x89c259a400000000,
185 0x89c258fa10000000,
186 0x89c258f174007000,
187 },
188 overlaps: []CellID{
189 0x808c000000000000,
190 0x89c4000000000000,
191 },
192 disjoint: []CellID{
193 0x89c15a4fcb1bb000,
194 0x89c15a4e4aa95000,
195 0x8094000000000000,
196 0x8096f10000000000,
197
198 0x87c0000000000000,
199 },
200 },
201 {
202
203 cells: []CellID{
204 0x8100000000000000,
205 0x8740000000000000,
206 0x8790000000000000,
207 0x87f4000000000000,
208 0x87f9000000000000,
209 0x87ff400000000000,
210 0x87ff900000000000,
211 0x87fff40000000000,
212 0x87fff90000000000,
213 0x87ffff4000000000,
214 0x87ffff9000000000,
215 0x87fffff400000000,
216 0x87fffff900000000,
217 0x87ffffff40000000,
218 0x87ffffff90000000,
219 0x87fffffff4000000,
220 0x87fffffff9000000,
221 0x87ffffffff400000,
222 },
223 contained: []CellID{
224 0x808f400000000000,
225 0x80eb118b00000000,
226 0x8136a7a11d000000,
227 0x8136a7a11dac0000,
228 0x876c7c0000000000,
229 0x87f96d0000000000,
230 0x87ffffffff400000,
231 },
232 overlaps: []CellID{
233 CellID(0x8100000000000000).immediateParent(),
234 CellID(0x8740000000000000).immediateParent(),
235 },
236 disjoint: []CellID{
237 0x52aaaaaaab300000,
238 0x52aaaaaaacd00000,
239 0x87fffffffa100000,
240 0x87ffffffed500000,
241 0x87ffffffa0100000,
242 0x87fffffed5540000,
243 0x87fffffed6240000,
244 0x52aaaacccb340000,
245 0x87a0000400000000,
246 0x87a000001f000000,
247 0x87a0000029d00000,
248 0x9500000000000000,
249 },
250 },
251 }
252 for _, test := range tests {
253 union := CellUnion(test.cells)
254 union.Normalize()
255
256
257 for _, id := range test.cells {
258 if !union.IntersectsCellID(id) {
259 t.Errorf("CellUnion %v should self-intersect %v but does not", union, id)
260 }
261 if !union.ContainsCellID(id) {
262 t.Errorf("CellUnion %v should self-contain %v but does not", union, id)
263 }
264 }
265
266 for _, id := range test.contained {
267 if !union.IntersectsCellID(id) {
268 t.Errorf("CellUnion %v should intersect %v but does not", union, id)
269 }
270 if !union.ContainsCellID(id) {
271 t.Errorf("CellUnion %v should contain %v but does not", union, id)
272 }
273 }
274
275 for _, id := range test.overlaps {
276 if !union.IntersectsCellID(id) {
277 t.Errorf("CellUnion %v should intersect %v but does not", union, id)
278 }
279 if union.ContainsCellID(id) {
280 t.Errorf("CellUnion %v should not contain %v but does", union, id)
281 }
282 }
283
284 for _, id := range test.disjoint {
285 if union.IntersectsCellID(id) {
286 t.Errorf("CellUnion %v should not intersect %v but does", union, id)
287 }
288 if union.ContainsCellID(id) {
289 t.Errorf("CellUnion %v should not contain %v but does", union, id)
290 }
291 }
292 }
293 }
294
295 func addCells(id CellID, selected bool, input *[]CellID, expected *[]CellID, t *testing.T) {
296
297
298
299
300
301
302 if id == 0 {
303
304 for face := 0; face < 6; face++ {
305 addCells(CellIDFromFace(face), false, input, expected, t)
306 }
307 return
308 }
309
310 if id.IsLeaf() {
311
312
313 if selected != true {
314 t.Errorf("id IsLeaf() and not selected")
315 }
316 *input = append(*input, id)
317 return
318 }
319
320
321
322 if !selected && oneIn(MaxLevel-id.Level()) {
323
324
325 *expected = append(*expected, id)
326 selected = true
327
328 }
329
330
331
332
333
334
335
336
337 added := false
338 if selected && !oneIn(6) {
339 *input = append(*input, id)
340 added = true
341 }
342 numChildren := 0
343 for child := id.ChildBegin(); child != id.ChildEnd(); child = child.Next() {
344
345
346
347
348
349
350
351
352 recurse := false
353 if selected {
354 recurse = oneIn(12)
355 } else {
356 recurse = oneIn(4)
357 }
358 if recurse && numChildren < 3 {
359 addCells(child, selected, input, expected, t)
360 numChildren++
361 }
362
363
364
365
366 if selected && !added {
367 addCells(child, selected, input, expected, t)
368 }
369 }
370 }
371
372 func TestCellUnionNormalizePseudoRandom(t *testing.T) {
373
374
375
376 inSum := 0
377 outSum := 0
378 iters := 2000
379
380 for i := 0; i < iters; i++ {
381 input := []CellID{}
382 expected := []CellID{}
383 addCells(CellID(0), false, &input, &expected, t)
384 inSum += len(input)
385 outSum += len(expected)
386 cellunion := CellUnion(input)
387 cellunion.Normalize()
388
389 if len(expected) != len(cellunion) {
390 t.Errorf("Expected size of union to be %d, but got %d.",
391 len(expected), len(cellunion))
392 }
393
394
395 cb := cellunion.CapBound()
396 for _, ci := range cellunion {
397 if !cb.ContainsCell(CellFromCellID(ci)) {
398 t.Errorf("CapBound %v of union %v should contain cellID %v", cb, cellunion, ci)
399 }
400 }
401
402 for _, j := range input {
403 if !cellunion.ContainsCellID(j) {
404 t.Errorf("Expected containment of CellID %v", j)
405 }
406
407 if cellunion.IntersectsCellID(j) == false {
408 t.Errorf("Expected intersection with %v.", j)
409 }
410
411 if !j.isFace() {
412 if cellunion.IntersectsCellID(j.immediateParent()) == false {
413 t.Errorf("Expected intersection with parent cell %v.", j.immediateParent())
414 if j.Level() > 1 {
415 if cellunion.IntersectsCellID(j.immediateParent().immediateParent()) == false {
416 t.Errorf("Expected intersection with parent's parent %v.",
417 j.immediateParent().immediateParent())
418 }
419 if cellunion.IntersectsCellID(j.Parent(0)) == false {
420 t.Errorf("Expected intersection with parent %v at level 0.", j.Parent(0))
421 }
422 }
423 }
424 }
425
426 if !j.IsLeaf() {
427 if cellunion.ContainsCellID(j.ChildBegin()) == false {
428 t.Errorf("Expected containment of %v.", j.ChildBegin())
429 }
430 if cellunion.IntersectsCellID(j.ChildBegin()) == false {
431 t.Errorf("Expected intersection with %v.", j.ChildBegin())
432 }
433 if cellunion.ContainsCellID(j.ChildEnd().Prev()) == false {
434 t.Errorf("Expected containment of %v.", j.ChildEnd().Prev())
435 }
436 if cellunion.IntersectsCellID(j.ChildEnd().Prev()) == false {
437 t.Errorf("Expected intersection with %v.", j.ChildEnd().Prev())
438 }
439 if cellunion.ContainsCellID(j.ChildBeginAtLevel(MaxLevel)) == false {
440 t.Errorf("Expected containment of %v.", j.ChildBeginAtLevel(MaxLevel))
441 }
442 if cellunion.IntersectsCellID(j.ChildBeginAtLevel(MaxLevel)) == false {
443 t.Errorf("Expected intersection with %v.", j.ChildBeginAtLevel(MaxLevel))
444 }
445 }
446 }
447
448 for _, exp := range expected {
449 if !exp.isFace() {
450 if cellunion.ContainsCellID(exp.Parent(exp.Level() - 1)) {
451 t.Errorf("cellunion should not contain its parent %v", exp.Parent(exp.Level()-1))
452 }
453 if cellunion.ContainsCellID(exp.Parent(0)) {
454 t.Errorf("cellunion should not contain the top level parent %v", exp.Parent(0))
455 }
456 }
457 }
458
459 var test []CellID
460 var dummy []CellID
461 addCells(CellID(0), false, &test, &dummy, t)
462 for _, j := range test {
463 intersects := false
464 contains := false
465 for _, k := range expected {
466 if k.Contains(j) {
467 contains = true
468 }
469 if k.Intersects(j) {
470 intersects = true
471 }
472 }
473 if cellunion.ContainsCellID(j) != contains {
474 t.Errorf("Expected contains with %v.", (uint64)(j))
475 }
476 if cellunion.IntersectsCellID(j) != intersects {
477 t.Errorf("Expected intersection with %v.", (uint64)(j))
478 }
479 }
480 }
481 t.Logf("avg in %.2f, avg out %.2f\n", (float64)(inSum)/(float64)(iters), (float64)(outSum)/(float64)(iters))
482 }
483
484 func TestCellUnionDenormalize(t *testing.T) {
485 tests := []struct {
486 name string
487 minL int
488 lMod int
489 cu *CellUnion
490 exp *CellUnion
491 }{
492 {
493 "not expanded, level mod == 1",
494 10,
495 1,
496 &CellUnion{
497 CellIDFromFace(2).ChildBeginAtLevel(11),
498 CellIDFromFace(2).ChildBeginAtLevel(11),
499 CellIDFromFace(3).ChildBeginAtLevel(14),
500 CellIDFromFace(0).ChildBeginAtLevel(10),
501 },
502 &CellUnion{
503 CellIDFromFace(2).ChildBeginAtLevel(11),
504 CellIDFromFace(2).ChildBeginAtLevel(11),
505 CellIDFromFace(3).ChildBeginAtLevel(14),
506 CellIDFromFace(0).ChildBeginAtLevel(10),
507 },
508 },
509 {
510 "not expanded, level mod > 1",
511 10,
512 2,
513 &CellUnion{
514 CellIDFromFace(2).ChildBeginAtLevel(12),
515 CellIDFromFace(2).ChildBeginAtLevel(12),
516 CellIDFromFace(3).ChildBeginAtLevel(14),
517 CellIDFromFace(0).ChildBeginAtLevel(10),
518 },
519 &CellUnion{
520 CellIDFromFace(2).ChildBeginAtLevel(12),
521 CellIDFromFace(2).ChildBeginAtLevel(12),
522 CellIDFromFace(3).ChildBeginAtLevel(14),
523 CellIDFromFace(0).ChildBeginAtLevel(10),
524 },
525 },
526 {
527 "expended, (level - min_level) is not multiple of level mod",
528 10,
529 3,
530 &CellUnion{
531 CellIDFromFace(2).ChildBeginAtLevel(12),
532 CellIDFromFace(5).ChildBeginAtLevel(11),
533 },
534 &CellUnion{
535 CellIDFromFace(2).ChildBeginAtLevel(12).Children()[0],
536 CellIDFromFace(2).ChildBeginAtLevel(12).Children()[1],
537 CellIDFromFace(2).ChildBeginAtLevel(12).Children()[2],
538 CellIDFromFace(2).ChildBeginAtLevel(12).Children()[3],
539 CellIDFromFace(5).ChildBeginAtLevel(11).Children()[0].Children()[0],
540 CellIDFromFace(5).ChildBeginAtLevel(11).Children()[0].Children()[1],
541 CellIDFromFace(5).ChildBeginAtLevel(11).Children()[0].Children()[2],
542 CellIDFromFace(5).ChildBeginAtLevel(11).Children()[0].Children()[3],
543 CellIDFromFace(5).ChildBeginAtLevel(11).Children()[1].Children()[0],
544 CellIDFromFace(5).ChildBeginAtLevel(11).Children()[1].Children()[1],
545 CellIDFromFace(5).ChildBeginAtLevel(11).Children()[1].Children()[2],
546 CellIDFromFace(5).ChildBeginAtLevel(11).Children()[1].Children()[3],
547 CellIDFromFace(5).ChildBeginAtLevel(11).Children()[2].Children()[0],
548 CellIDFromFace(5).ChildBeginAtLevel(11).Children()[2].Children()[1],
549 CellIDFromFace(5).ChildBeginAtLevel(11).Children()[2].Children()[2],
550 CellIDFromFace(5).ChildBeginAtLevel(11).Children()[2].Children()[3],
551 CellIDFromFace(5).ChildBeginAtLevel(11).Children()[3].Children()[0],
552 CellIDFromFace(5).ChildBeginAtLevel(11).Children()[3].Children()[1],
553 CellIDFromFace(5).ChildBeginAtLevel(11).Children()[3].Children()[2],
554 CellIDFromFace(5).ChildBeginAtLevel(11).Children()[3].Children()[3],
555 },
556 },
557 {
558 "expended, level < min_level",
559 10,
560 3,
561 &CellUnion{
562 CellIDFromFace(2).ChildBeginAtLevel(9),
563 },
564 &CellUnion{
565 CellIDFromFace(2).ChildBeginAtLevel(9).Children()[0],
566 CellIDFromFace(2).ChildBeginAtLevel(9).Children()[1],
567 CellIDFromFace(2).ChildBeginAtLevel(9).Children()[2],
568 CellIDFromFace(2).ChildBeginAtLevel(9).Children()[3],
569 },
570 },
571 }
572 for _, test := range tests {
573 if test.cu.Denormalize(test.minL, test.lMod); !reflect.DeepEqual(test.cu, test.exp) {
574 t.Errorf("test: %s; got %v, want %v", test.name, test.cu, test.exp)
575 }
576 }
577 }
578
579 func TestCellUnionRectBound(t *testing.T) {
580 tests := []struct {
581 cu *CellUnion
582 want Rect
583 }{
584 {&CellUnion{}, EmptyRect()},
585 {
586 &CellUnion{CellIDFromFace(1)},
587 Rect{
588 r1.Interval{-math.Pi / 4, math.Pi / 4},
589 s1.Interval{math.Pi / 4, 3 * math.Pi / 4},
590 },
591 },
592 {
593 &CellUnion{
594 0x808c000000000000,
595 },
596 Rect{
597 r1.Interval{
598 float64(s1.Degree * 34.644220547108482),
599 float64(s1.Degree * 38.011928357226651),
600 },
601 s1.Interval{
602 float64(s1.Degree * -124.508522987668428),
603 float64(s1.Degree * -121.628309835221216),
604 },
605 },
606 },
607 {
608 &CellUnion{
609 0x89c4000000000000,
610 },
611 Rect{
612 r1.Interval{
613 float64(s1.Degree * 38.794595155857657),
614 float64(s1.Degree * 41.747046884651063),
615 },
616 s1.Interval{
617 float64(s1.Degree * -76.456308667788633),
618 float64(s1.Degree * -73.465162142654819),
619 },
620 },
621 },
622 {
623 &CellUnion{
624 0x89c4000000000000,
625 0x808c000000000000,
626 },
627 Rect{
628 r1.Interval{
629 float64(s1.Degree * 34.644220547108482),
630 float64(s1.Degree * 41.747046884651063),
631 },
632 s1.Interval{
633 float64(s1.Degree * -124.508522987668428),
634 float64(s1.Degree * -73.465162142654819),
635 },
636 },
637 },
638 }
639
640 for _, test := range tests {
641 if got := test.cu.RectBound(); !rectsApproxEqual(got, test.want, epsilon, epsilon) {
642 t.Errorf("%v.RectBound() = %v, want %v", test.cu, got, test.want)
643 }
644 }
645 }
646
647 func TestCellUnionLeafCellsCovered(t *testing.T) {
648 fiveFaces := CellUnion{CellIDFromFace(0)}
649 fiveFaces.ExpandAtLevel(0)
650 wholeWorld := CellUnion{CellIDFromFace(0)}
651 wholeWorld.ExpandAtLevel(0)
652 wholeWorld.ExpandAtLevel(0)
653
654 tests := []struct {
655 have []CellID
656 want int64
657 }{
658 {},
659 {
660 have: []CellID{},
661 want: 0,
662 },
663 {
664
665 have: []CellID{
666 CellIDFromFace(0).ChildBeginAtLevel(MaxLevel),
667 },
668 want: 1,
669 },
670 {
671
672 have: []CellID{
673 CellIDFromFace(0).ChildBeginAtLevel(MaxLevel),
674 CellIDFromFace(0),
675 },
676 want: 1 << 60,
677 },
678 {
679 have: fiveFaces,
680 want: 5 << 60,
681 },
682 {
683 have: wholeWorld,
684 want: 6 << 60,
685 },
686 {
687
688 have: []CellID{
689 CellIDFromFace(0).ChildBeginAtLevel(MaxLevel),
690 CellIDFromFace(0),
691 CellIDFromFace(1).ChildBeginAtLevel(1),
692 CellIDFromFace(2).ChildBeginAtLevel(2),
693 CellIDFromFace(2).ChildEndAtLevel(2).Prev(),
694 CellIDFromFace(3).ChildBeginAtLevel(14),
695 CellIDFromFace(4).ChildBeginAtLevel(27),
696 CellIDFromFace(4).ChildEndAtLevel(15).Prev(),
697 CellIDFromFace(5).ChildBeginAtLevel(30),
698 },
699 want: 1 + (1 << 6) + (1 << 30) + (1 << 32) +
700 (2 << 56) + (1 << 58) + (1 << 60),
701 },
702 }
703
704 for _, test := range tests {
705 cu := CellUnion(test.have)
706 cu.Normalize()
707 if got := cu.LeafCellsCovered(); got != test.want {
708 t.Errorf("CellUnion(%v).LeafCellsCovered() = %v, want %v", cu, got, test.want)
709 }
710 }
711 }
712
713 func TestCellUnionFromRange(t *testing.T) {
714 for iter := 0; iter < 2000; iter++ {
715 min := randomCellIDForLevel(MaxLevel)
716 max := randomCellIDForLevel(MaxLevel)
717 if min > max {
718 min, max = max, min
719 }
720
721 cu := CellUnionFromRange(min, max.Next())
722 if len(cu) <= 0 {
723 t.Errorf("len(CellUnionFromRange(%v, %v)) = %d, want > 0", min, max.Next(), len(cu))
724 }
725 if min != cu[0].RangeMin() {
726 t.Errorf("%v.RangeMin of CellUnion should not be below the minimum value it was created from %v", cu[0], min)
727 }
728 if max != cu[len(cu)-1].RangeMax() {
729 t.Errorf("%v.RangeMax of CellUnion should not be above the maximum value it was created from %v", cu[len(cu)-1], max)
730 }
731 for i := 1; i < len(cu); i++ {
732 if got, want := cu[i].RangeMin(), cu[i-1].RangeMax().Next(); got != want {
733 t.Errorf("%v.RangeMin() = %v, want %v", cu[i], got, want)
734 }
735 }
736 }
737
738
739
740
741 idBegin := CellIDFromFace(0).ChildBeginAtLevel(MaxLevel)
742 cu := CellUnionFromRange(idBegin, idBegin)
743 if len(cu) != 0 {
744 t.Errorf("CellUnionFromRange with begin and end as the first CellID should be empty, got %d", len(cu))
745 }
746
747
748 idEnd := CellIDFromFace(5).ChildEndAtLevel(MaxLevel)
749 cu = CellUnionFromRange(idEnd, idEnd)
750 if len(cu) != 0 {
751 t.Errorf("CellUnionFromRange with begin and end as the last CellID should be empty, got %d", len(cu))
752 }
753
754
755 cu = CellUnionFromRange(idBegin, idEnd)
756 if len(cu) != 6 {
757 t.Errorf("CellUnionFromRange from first CellID to last CellID should have 6 cells, got %d", len(cu))
758 }
759
760 for i := 0; i < len(cu); i++ {
761 if !cu[i].isFace() {
762 t.Errorf("CellUnionFromRange for full sphere cu[%d].isFace() = %t, want %t", i, cu[i].isFace(), true)
763 }
764 }
765 }
766
767 func TestCellUnionFromUnionDiffIntersection(t *testing.T) {
768 const iters = 2000
769 for i := 0; i < iters; i++ {
770 input := []CellID{}
771 expected := []CellID{}
772 addCells(CellID(0), false, &input, &expected, t)
773
774 var x, y, xOrY, xAndY []CellID
775 for _, id := range input {
776 inX := oneIn(2)
777 inY := oneIn(2)
778
779 if inX {
780 x = append(x, id)
781 }
782 if inY {
783 y = append(y, id)
784 }
785 if inX || inY {
786 xOrY = append(xOrY, id)
787 }
788 }
789
790 xcells := CellUnion(x)
791 xcells.Normalize()
792 ycells := CellUnion(y)
793 ycells.Normalize()
794 xOrYExpected := CellUnion(xOrY)
795 xOrYExpected.Normalize()
796
797 xOrYCells := CellUnionFromUnion(xcells, ycells)
798
799 if !xOrYCells.Equal(xOrYExpected) {
800 t.Errorf("CellUnionFromUnion(%v, %v) = %v, want %v", xcells, ycells, xOrYCells, xOrYExpected)
801 }
802
803
804
805
806 for _, yid := range ycells {
807 u := CellUnionFromIntersectionWithCellID(xcells, yid)
808 for _, xid := range xcells {
809 if xid.Contains(yid) {
810 if !(len(u) == 1 && u[0] == yid) {
811 t.Errorf("CellUnionFromIntersectionWithCellID(%v, %v) = %v with len: %d, want len of 1.", xcells, yid, u, len(u))
812 }
813 } else if yid.Contains(xid) {
814 if !u.ContainsCellID(xid) {
815 t.Errorf("%v.ContainsCellID(%v) = false, want true", u, xid)
816 }
817 }
818 }
819 for _, uCellID := range u {
820 if !xcells.ContainsCellID(uCellID) {
821 t.Errorf("%v.ContainsCellID(%v) = false, but should contain CellID that was used to create CellUnion", xcells, uCellID)
822 }
823 if !yid.Contains(uCellID) {
824 t.Errorf("%v.Contains(%v) = false, but should contain CellID that was used to create CellUnion", yid, uCellID)
825 }
826 }
827
828 xAndY = append(xAndY, u...)
829 }
830
831 xAndYExpected := CellUnion(xAndY)
832 xAndYExpected.Normalize()
833
834 xAndYCells := CellUnionFromIntersection(xcells, ycells)
835 if !xAndYCells.Equal(xAndYExpected) {
836 t.Errorf("CellUnionFromIntersection(%v, %v) = %v, want %v", xcells, ycells, xAndYCells, xAndYExpected)
837 }
838
839 xMinusYCells := CellUnionFromDifference(xcells, ycells)
840 yMinusXCells := CellUnionFromDifference(ycells, xcells)
841 if !xcells.Contains(xMinusYCells) {
842 t.Errorf("%v.Contains(%v) = false, want true", xcells, xMinusYCells)
843 }
844 if xMinusYCells.Intersects(ycells) {
845 t.Errorf("%v.Intersects(%v) = true, want false", xMinusYCells, ycells)
846 }
847 if !ycells.Contains(yMinusXCells) {
848 t.Errorf("%v.Contains(%v) = false, want true", ycells, yMinusXCells)
849 }
850 if yMinusXCells.Intersects(xcells) {
851 t.Errorf("%v.Intersects(%v) = true, want false", yMinusXCells, xcells)
852 }
853 if xMinusYCells.Intersects(yMinusXCells) {
854 t.Errorf("%v.Intersects(%v) = true, want false", xMinusYCells, yMinusXCells)
855 }
856
857 diffUnion := CellUnionFromUnion(xMinusYCells, yMinusXCells)
858 diffIntersectionUnion := CellUnionFromUnion(diffUnion, xAndYCells)
859 if !diffIntersectionUnion.Equal(xOrYCells) {
860 t.Errorf("Union(%v, %v).Union(%v) = %v, want %v", xMinusYCells, yMinusXCells, xAndYCells, diffIntersectionUnion, xOrYCells)
861 }
862 }
863 }
864
865
866
867 func cellUnionDistanceFromAxis(cu CellUnion, axis Point) float64 {
868 var maxDist float64
869 for _, cid := range cu {
870 cell := CellFromCellID(cid)
871 for j := 0; j < 4; j++ {
872 a := cell.Vertex(j)
873 b := cell.Vertex((j + 1) & 3)
874 var dist float64
875
876
877
878
879
880
881
882
883 if a.Angle(axis.Vector) > math.Pi/2 || b.Angle(axis.Vector) > math.Pi/2 {
884 dist = math.Pi - DistanceFromSegment(Point{axis.Mul(-1)}, a, b).Radians()
885 } else {
886 dist = float64(a.Angle(axis.Vector))
887 }
888 maxDist = math.Max(maxDist, dist)
889 }
890 }
891 return maxDist
892 }
893
894 func TestCellUnionExpand(t *testing.T) {
895
896
897
898
899 for i := 0; i < 5000; i++ {
900 rndCap := randomCap(AvgAreaMetric.Value(MaxLevel), 4*math.Pi)
901
902
903
904 expandedCap := CapFromCenterHeight(
905 rndCap.center, math.Min(2.0, math.Pow(1e2, randomFloat64())*rndCap.Height()))
906
907 radius := (expandedCap.Radius() - rndCap.Radius()).Radians()
908 maxLevelDiff := randomUniformInt(8)
909
910
911
912 coverer := &RegionCoverer{
913 MaxLevel: MaxLevel,
914 MaxCells: 1 + skewedInt(10),
915 LevelMod: 1,
916 }
917 covering := coverer.CellUnion(rndCap)
918 checkCellUnionCovering(t, rndCap, covering, true, 0)
919 coveringRadius := cellUnionDistanceFromAxis(covering, rndCap.center)
920
921
922
923 minLevel := MaxLevel
924 for _, cid := range covering {
925 minLevel = minInt(minLevel, cid.Level())
926 }
927 expandLevel := minInt(minLevel+maxLevelDiff, MinWidthMetric.MaxLevel(radius))
928
929
930
931 covering.ExpandByRadius(s1.Angle(radius), maxLevelDiff)
932 checkCellUnionCovering(t, expandedCap, covering, false, 0)
933 expandedCoveringRadius := cellUnionDistanceFromAxis(covering, rndCap.center)
934
935
936
937
938 if expandedCoveringRadius-coveringRadius >= 2*MaxDiagMetric.Value(expandLevel) {
939 t.Errorf("covering.ExpandByRadius(%v, %v) distance from center = %v want < %v", radius, maxLevelDiff, expandedCoveringRadius-coveringRadius, 2*MaxDiagMetric.Value(expandLevel))
940 }
941 }
942 }
943
944
945
946
947
948 func checkCellUnionCovering(t *testing.T, r Region, covering CellUnion, checkTight bool, id CellID) {
949 if !id.IsValid() {
950 for face := 0; face < 6; face++ {
951 checkCellUnionCovering(t, r, covering, checkTight, CellIDFromFace(face))
952 }
953 return
954 }
955
956 if !r.IntersectsCell(CellFromCellID(id)) {
957
958 if checkTight {
959 if covering.IntersectsCellID(id) {
960 t.Errorf("%v.IntersectsCellID(%v) = true, want false", covering, id)
961 }
962 }
963 return
964 }
965 if !covering.ContainsCellID(id) {
966
967
968
969 if r.ContainsCell(CellFromCellID(id)) {
970 t.Errorf("%v.ContainsCell(%v) = true, want false", r, id)
971 return
972 }
973 if id.IsLeaf() {
974 t.Errorf("%v.IsLeaf() = true, want false", id)
975 return
976 }
977 for child := id.ChildBegin(); child != id.ChildEnd(); child = child.Next() {
978 checkCellUnionCovering(t, r, covering, checkTight, child)
979 }
980 }
981 }
982
983 func TestCellUnionEmpty(t *testing.T) {
984 var empty CellUnion
985
986
987 empty.Normalize()
988 if len(empty) != 0 {
989 t.Errorf("len(empty.Normalize()) = %d, want 0", len(empty))
990 }
991
992
993 empty.Denormalize(0, 2)
994 if len(empty) != 0 {
995 t.Errorf("len(empty.Denormalize(0, 2)) = %d, want 0", len(empty))
996 }
997
998 face1ID := CellIDFromFace(1)
999
1000 if empty.ContainsCellID(face1ID) {
1001 t.Errorf("empty.ContainsCellID(%v) = true, want false", face1ID)
1002 }
1003 if !empty.Contains(empty) {
1004 t.Errorf("empty.Contains(%v) = false, want true", empty)
1005 }
1006
1007
1008 if empty.IntersectsCellID(face1ID) {
1009 t.Errorf("empty.IntersectsCellID(%v) = true, want false", face1ID)
1010 }
1011 if empty.Intersects(empty) {
1012 t.Errorf("empty.Intersects(%v) = true, want false", empty)
1013 }
1014
1015
1016 cellUnion := CellUnionFromUnion(empty, empty)
1017 if len(cellUnion) != 0 {
1018 t.Errorf("CellUnionFromUnion(empty, empty) has %v cells, want 0", len(cellUnion))
1019 }
1020
1021
1022 intersection := CellUnionFromIntersectionWithCellID(empty, face1ID)
1023 if len(intersection) != 0 {
1024 t.Errorf("CellUnionFromIntersectionWithCellID(%v, %v) = %v cells, want 0", empty, face1ID, len(intersection))
1025 }
1026
1027 intersection = CellUnionFromIntersection(empty, empty)
1028 if len(intersection) != 0 {
1029 t.Errorf("CellUnionFromIntersection(%v, %v) = %v cells, want 0", empty, empty, len(intersection))
1030 }
1031
1032
1033 difference := CellUnionFromDifference(empty, empty)
1034 if len(difference) != 0 {
1035 t.Errorf("CellUnionFromDifference(%v, %v) = %v cells, want 0", empty, empty, len(difference))
1036 }
1037
1038
1039 empty.ExpandByRadius(s1.Angle(1), 20)
1040 if len(empty) != 0 {
1041 t.Errorf("empty.ExpandByRadius(1, 20) = %v cells, want 0", len(empty))
1042 }
1043
1044 empty.ExpandAtLevel(10)
1045 if len(empty) != 0 {
1046 t.Errorf("empty.ExpandAtLevel(10) = %v cells, want 0", len(empty))
1047 }
1048 }
1049
1050 func BenchmarkCellUnionFromRange(b *testing.B) {
1051 x := CellIDFromFace(0).ChildBeginAtLevel(MaxLevel)
1052 y := CellIDFromFace(5).ChildEndAtLevel(MaxLevel)
1053 for i := 0; i < b.N; i++ {
1054 CellUnionFromRange(x, y)
1055 }
1056 }
1057
View as plain text