1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package s2
16
17 import (
18 "math"
19 "testing"
20
21 "github.com/golang/geo/r3"
22 "github.com/golang/geo/s1"
23 )
24
25 func TestEdgeDistancesCheckDistance(t *testing.T) {
26 tests := []struct {
27 x, a, b r3.Vector
28 distRad float64
29 want r3.Vector
30 }{
31 {
32 x: r3.Vector{1, 0, 0},
33 a: r3.Vector{1, 0, 0},
34 b: r3.Vector{0, 1, 0},
35 distRad: 0,
36 want: r3.Vector{1, 0, 0},
37 },
38 {
39 x: r3.Vector{0, 1, 0},
40 a: r3.Vector{1, 0, 0},
41 b: r3.Vector{0, 1, 0},
42 distRad: 0,
43 want: r3.Vector{0, 1, 0},
44 },
45 {
46 x: r3.Vector{1, 3, 0},
47 a: r3.Vector{1, 0, 0},
48 b: r3.Vector{0, 1, 0},
49 distRad: 0,
50 want: r3.Vector{1, 3, 0},
51 },
52 {
53 x: r3.Vector{0, 0, 1},
54 a: r3.Vector{1, 0, 0},
55 b: r3.Vector{0, 1, 0},
56 distRad: math.Pi / 2,
57 want: r3.Vector{1, 0, 0},
58 },
59 {
60 x: r3.Vector{0, 0, -1},
61 a: r3.Vector{1, 0, 0},
62 b: r3.Vector{0, 1, 0},
63 distRad: math.Pi / 2,
64 want: r3.Vector{1, 0, 0},
65 },
66 {
67 x: r3.Vector{-1, -1, 0},
68 a: r3.Vector{1, 0, 0},
69 b: r3.Vector{0, 1, 0},
70 distRad: 0.75 * math.Pi,
71 want: r3.Vector{1, 0, 0},
72 },
73 {
74 x: r3.Vector{0, 1, 0},
75 a: r3.Vector{1, 0, 0},
76 b: r3.Vector{1, 1, 0},
77 distRad: math.Pi / 4,
78 want: r3.Vector{1, 1, 0},
79 },
80 {
81 x: r3.Vector{0, -1, 0},
82 a: r3.Vector{1, 0, 0},
83 b: r3.Vector{1, 1, 0},
84 distRad: math.Pi / 2,
85 want: r3.Vector{1, 0, 0},
86 },
87 {
88 x: r3.Vector{0, -1, 0},
89 a: r3.Vector{1, 0, 0},
90 b: r3.Vector{-1, 1, 0},
91 distRad: math.Pi / 2,
92 want: r3.Vector{1, 0, 0},
93 },
94 {
95 x: r3.Vector{-1, -1, 0},
96 a: r3.Vector{1, 0, 0},
97 b: r3.Vector{-1, 1, 0},
98 distRad: math.Pi / 2,
99 want: r3.Vector{-1, 1, 0},
100 },
101 {
102 x: r3.Vector{1, 1, 1},
103 a: r3.Vector{1, 0, 0},
104 b: r3.Vector{0, 1, 0},
105 distRad: math.Asin(math.Sqrt(1.0 / 3.0)),
106 want: r3.Vector{1, 1, 0},
107 },
108 {
109 x: r3.Vector{1, 1, -1},
110 a: r3.Vector{1, 0, 0},
111 b: r3.Vector{0, 1, 0},
112 distRad: math.Asin(math.Sqrt(1.0 / 3.0)),
113 want: r3.Vector{1, 1, 0}},
114 {
115 x: r3.Vector{-1, 0, 0},
116 a: r3.Vector{1, 1, 0},
117 b: r3.Vector{1, 1, 0},
118 distRad: 0.75 * math.Pi,
119 want: r3.Vector{1, 1, 0},
120 },
121 {
122 x: r3.Vector{0, 0, -1},
123 a: r3.Vector{1, 1, 0},
124 b: r3.Vector{1, 1, 0},
125 distRad: math.Pi / 2,
126 want: r3.Vector{1, 1, 0},
127 },
128 {
129 x: r3.Vector{-1, 0, 0},
130 a: r3.Vector{1, 0, 0},
131 b: r3.Vector{1, 0, 0},
132 distRad: math.Pi,
133 want: r3.Vector{1, 0, 0},
134 },
135 }
136
137 for _, test := range tests {
138 x := Point{test.x.Normalize()}
139 a := Point{test.a.Normalize()}
140 b := Point{test.b.Normalize()}
141 want := Point{test.want.Normalize()}
142
143 if d := DistanceFromSegment(x, a, b).Radians(); !float64Near(d, test.distRad, 1e-15) {
144 t.Errorf("DistanceFromSegment(%v, %v, %v) = %v, want %v", x, a, b, d, test.distRad)
145 }
146
147 closest := Project(x, a, b)
148 if !closest.ApproxEqual(want) {
149 t.Errorf("ClosestPoint(%v, %v, %v) = %v, want %v", x, a, b, closest, want)
150 }
151
152 if minDistance, ok := UpdateMinDistance(x, a, b, 0); ok {
153 t.Errorf("UpdateMinDistance(%v, %v, %v, %v) = %v, want %v", x, a, b, 0, minDistance, 0)
154 }
155
156 minDistance, ok := UpdateMinDistance(x, a, b, s1.InfChordAngle())
157 if !ok {
158 t.Errorf("UpdateMinDistance(%v, %v, %v, %v) = %v, want %v", x, a, b, s1.InfChordAngle(), minDistance, s1.InfChordAngle())
159 }
160
161 if !float64Near(test.distRad, minDistance.Angle().Radians(), 1e-15) {
162 t.Errorf("MinDistance between %v and %v,%v = %v, want %v within %v", x, a, b, minDistance.Angle().Radians(), test.distRad, 1e-15)
163 }
164 }
165 }
166
167 func TestEdgeDistancesUpdateMinInteriorDistanceLowerBoundOptimizationIsConservative(t *testing.T) {
168
169
170 x := PointFromCoords(-0.017952729194524016, -0.30232422079175203, 0.95303607751077712)
171 a := PointFromCoords(-0.017894725505830295, -0.30229974986194175, 0.95304493075220664)
172 b := PointFromCoords(-0.017986591360900289, -0.30233851195954353, 0.95303090543659963)
173
174 minDistance, ok := UpdateMinDistance(x, a, b, s1.InfChordAngle())
175 if !ok {
176 t.Errorf("UpdateMinDistance(%v, %v, %v, %v) = %v, want %v", x, a, b, s1.InfChordAngle(), minDistance, s1.InfChordAngle())
177 }
178 minDistance = minDistance.Successor()
179 minDistance, ok = UpdateMinDistance(x, a, b, minDistance)
180 if !ok {
181 t.Errorf("UpdateMinDistance(%v, %v, %v, %v) = %v, want %v", x, a, b, s1.InfChordAngle(), minDistance, minDistance)
182 }
183
184 }
185
186 func TestEdgeDistancesUpdateMinInteriorDistanceRejectionTestIsConservative(t *testing.T) {
187
188
189
190
191
192 minDist := s1.ChordAngleFromSquaredLength(6.3897233584120815e-26)
193
194 tests := []struct {
195 x, a, b Point
196 minDist s1.ChordAngle
197 want bool
198 }{
199 {
200
201 x: Point{r3.Vector{1, -4.6547732744037044e-11, -5.6374428459823598e-89}},
202 a: Point{r3.Vector{1, -8.9031850507928352e-11, 0}},
203 b: Point{r3.Vector{-0.99999999999996347, 2.7030110029169596e-07, 1.555092348806121e-99}},
204 minDist: minDist,
205 want: false,
206 },
207 {
208 x: Point{r3.Vector{1, -4.7617930898495072e-13, 0}},
209 a: Point{r3.Vector{-1, -1.6065916409055676e-10, 0}},
210 b: Point{r3.Vector{1, 0, 9.9964883247706732e-35}},
211 minDist: minDist,
212 want: false,
213 },
214 {
215 x: Point{r3.Vector{1, 0, 0}},
216 a: Point{r3.Vector{1, -8.4965026896454536e-11, 0}},
217 b: Point{r3.Vector{-0.99999999999966138, 8.2297529603339328e-07, 9.6070344113320997e-21}},
218 minDist: minDist,
219 want: false,
220 },
221 }
222
223 for _, test := range tests {
224 if _, ok := UpdateMinDistance(test.x, test.a, test.b, test.minDist); !ok {
225 t.Errorf("UpdateMinDistance(%v, %v, %v, %v) = %v, want %v", test.x, test.a, test.b, test.minDist, ok, test.want)
226 }
227 }
228 }
229
230 func TestEdgeDistancesCheckMaxDistance(t *testing.T) {
231 tests := []struct {
232 x, a, b r3.Vector
233 distRad float64
234 }{
235 {
236 x: r3.Vector{1, 0, 1},
237 a: r3.Vector{1, 0, 0},
238 b: r3.Vector{0, 1, 0},
239 distRad: math.Pi / 2,
240 },
241 {
242 x: r3.Vector{1, 0, -1},
243 a: r3.Vector{1, 0, 0},
244 b: r3.Vector{0, 1, 0},
245 distRad: math.Pi / 2,
246 },
247 {
248 x: r3.Vector{0, 1, 1},
249 a: r3.Vector{1, 0, 0},
250 b: r3.Vector{0, 1, 0},
251 distRad: math.Pi / 2,
252 },
253 {
254 x: r3.Vector{0, 1, -1},
255 a: r3.Vector{1, 0, 0},
256 b: r3.Vector{0, 1, 0},
257 distRad: math.Pi / 2,
258 },
259 {
260 x: r3.Vector{1, 1, 1},
261 a: r3.Vector{1, 0, 0},
262 b: r3.Vector{0, 1, 0},
263 distRad: math.Asin(math.Sqrt(2. / 3)),
264 },
265 {
266 x: r3.Vector{1, 1, -1},
267 a: r3.Vector{1, 0, 0},
268 b: r3.Vector{0, 1, 0},
269 distRad: math.Asin(math.Sqrt(2. / 3)),
270 },
271 {
272 x: r3.Vector{1, 0, 0},
273 a: r3.Vector{1, 1, 0},
274 b: r3.Vector{1, -1, 0},
275 distRad: math.Pi / 4,
276 },
277 {
278 x: r3.Vector{0, 1, 0},
279 a: r3.Vector{1, 1, 0},
280 b: r3.Vector{1, 1, 0},
281 distRad: math.Pi / 4,
282 },
283 {
284 x: r3.Vector{0, 0, 1},
285 a: r3.Vector{0, 1, 1},
286 b: r3.Vector{0, -1, 1},
287 distRad: math.Pi / 4,
288 },
289 {
290 x: r3.Vector{0, 0, 1},
291 a: r3.Vector{1, 0, 0},
292 b: r3.Vector{1, 0, -1},
293 distRad: 3 * math.Pi / 4,
294 },
295 {
296 x: r3.Vector{0, 0, 1},
297 a: r3.Vector{1, 0, 0},
298 b: r3.Vector{1, 1, -math.Sqrt2},
299 distRad: 3 * math.Pi / 4,
300 },
301 {
302 x: r3.Vector{0, 0, 1},
303 a: r3.Vector{0, 0, -1},
304 b: r3.Vector{0, 0, -1},
305 distRad: math.Pi,
306 },
307 }
308
309 for _, test := range tests {
310 x := Point{test.x.Normalize()}
311 a := Point{test.a.Normalize()}
312 b := Point{test.b.Normalize()}
313
314 var ok bool
315 maxDistance := s1.StraightChordAngle
316 if maxDistance, ok = UpdateMaxDistance(x, a, b, maxDistance); ok {
317 t.Errorf("UpdateMaxDistance(%v, %v, %v, %v) = %v, want %v", x, a, b, s1.StraightChordAngle, maxDistance, s1.StraightChordAngle)
318 }
319
320 maxDistance = s1.NegativeChordAngle
321 if maxDistance, ok = UpdateMaxDistance(x, a, b, maxDistance); !ok {
322 t.Errorf("UpdateMaxDistance(%v, %v, %v, %v) = %v, want > %v", x, a, b, s1.NegativeChordAngle, maxDistance, s1.NegativeChordAngle)
323 }
324
325 if !float64Near(test.distRad, maxDistance.Angle().Radians(), 1e-15) {
326 t.Errorf("MaxDistance between %v and %v, %v = %v, want %v within %v", x, a, b, maxDistance.Angle().Radians(), test.distRad, 1e-15)
327 }
328 }
329 }
330
331 func TestEdgeDistancesInterpolate(t *testing.T) {
332
333 p1 := PointFromCoords(0.1, 1e-30, 0.3)
334 p2 := PointFromCoords(-0.7, -0.55, -1e30)
335 i := PointFromCoords(1, 0, 0)
336 j := PointFromCoords(0, 1, 0)
337
338
339 p := Interpolate(0.001, i, j)
340
341 tests := []struct {
342 a, b Point
343 dist float64
344 want Point
345 }{
346
347 {p1, p1, 0, p1},
348 {p1, p1, 1, p1},
349
350 {p1, p2, 0, p1},
351 {p1, p2, 1, p2},
352 {p1, p2, 0.5, Point{(p1.Add(p2.Vector)).Mul(0.5)}},
353
354
355
356 {
357 Point{r3.Vector{1, 0, 0}},
358 Point{r3.Vector{0, 1, 0}},
359 1.0 / 3.0,
360 Point{r3.Vector{math.Sqrt(3), 1, 0}},
361 },
362 {
363 Point{r3.Vector{1, 0, 0}},
364 Point{r3.Vector{0, 1, 0}},
365 2.0 / 3.0,
366 Point{r3.Vector{1, math.Sqrt(3), 0}},
367 },
368
369
370
371
372 {i, j, 0, Point{r3.Vector{1, 0, 0}}},
373 {i, j, 1, Point{r3.Vector{0, 1, 0}}},
374 {i, j, 1.5, Point{r3.Vector{-1, 1, 0}}},
375 {i, j, 2, Point{r3.Vector{-1, 0, 0}}},
376 {i, j, 3, Point{r3.Vector{0, -1, 0}}},
377 {i, j, 4, Point{r3.Vector{1, 0, 0}}},
378
379
380 {i, j, -1, Point{r3.Vector{0, -1, 0}}},
381 {i, j, -2, Point{r3.Vector{-1, 0, 0}}},
382 {i, j, -3, Point{r3.Vector{0, 1, 0}}},
383 {i, j, -4, Point{r3.Vector{1, 0, 0}}},
384
385
386 {i, Point{r3.Vector{1, 1, 0}}, 2, Point{r3.Vector{0, 1, 0}}},
387 {i, Point{r3.Vector{1, 1, 0}}, 3, Point{r3.Vector{-1, 1, 0}}},
388 {i, Point{r3.Vector{1, 1, 0}}, 4, Point{r3.Vector{-1, 0, 0}}},
389
390
391 {i, Point{r3.Vector{-1, 1, 0}}, 2, Point{r3.Vector{0, -1, 0}}},
392
393
394
395 {i, p, 1000, j},
396 }
397
398 for _, test := range tests {
399 test.a = Point{test.a.Normalize()}
400 test.b = Point{test.b.Normalize()}
401 test.want = Point{test.want.Normalize()}
402
403
404
405 if got := Interpolate(test.dist, test.a, test.b); !pointsApproxEqual(got, test.want, 3e-15) {
406 t.Errorf("Interpolate(%v, %v, %v) = %v, want %v", test.dist, test.a, test.b, got, test.want)
407 }
408 }
409 }
410
411 func TestEdgeDistancesInterpolateOverLongEdge(t *testing.T) {
412 lng := math.Pi - 1e-2
413 a := Point{PointFromLatLng(LatLng{0, 0}).Normalize()}
414 b := Point{PointFromLatLng(LatLng{0, s1.Angle(lng)}).Normalize()}
415
416 for f := 0.4; f > 1e-15; f *= 0.1 {
417
418
419 want := Point{PointFromLatLng(LatLng{0, s1.Angle(f * lng)}).Normalize()}
420 if got := Interpolate(f, a, b); !pointsApproxEqual(got, want, 3e-15) {
421 t.Errorf("long edge Interpolate(%v, %v, %v) = %v, want %v", f, a, b, got, want)
422 }
423
424
425 wantRem := Point{PointFromLatLng(LatLng{0, s1.Angle((1 - f) * lng)}).Normalize()}
426 if got := Interpolate(1-f, a, b); !pointsApproxEqual(got, wantRem, 3e-15) {
427 t.Errorf("long edge Interpolate(%v, %v, %v) = %v, want %v", 1-f, a, b, got, wantRem)
428 }
429 }
430 }
431
432 func TestEdgeDistancesInterpolateAntipodal(t *testing.T) {
433 p1 := PointFromCoords(0.1, 1e-30, 0.3)
434
435
436
437 for dist := 0.0; dist <= 1.0; dist += 0.125 {
438 actual := Interpolate(dist, p1, Point{p1.Mul(-1)})
439 if !float64Near(actual.Distance(p1).Radians(), dist*math.Pi, 3e-15) {
440 t.Errorf("antipodal points Interpolate(%v, %v, %v) = %v, want %v", dist, p1, Point{p1.Mul(-1)}, actual, dist*math.Pi)
441 }
442 }
443 }
444
445 func TestEdgeDistancesRepeatedInterpolation(t *testing.T) {
446
447
448 for i := 0; i < 100; i++ {
449 a := randomPoint()
450 b := randomPoint()
451 for j := 0; j < 1000; j++ {
452 a = Interpolate(0.01, a, b)
453 }
454 if !a.Vector.IsUnit() {
455 t.Errorf("repeated Interpolate(%v, %v, %v) calls did not stay unit length for", 0.01, a, b)
456 }
457 }
458 }
459
460 func TestEdgeDistanceMinUpdateDistanceMaxError(t *testing.T) {
461 tests := []struct {
462 actual s1.Angle
463 maxErr s1.Angle
464 }{
465 {0, 1.5e-15},
466 {1e-8, 1e-15},
467 {1e-5, 1e-15},
468 {0.05, 1e-15},
469 {math.Pi/2 - 1e-8, 2e-15},
470 {math.Pi / 2, 2e-15},
471 {math.Pi/2 + 1e-8, 2e-15},
472 {math.Pi - 1e-5, 2e-10},
473 {math.Pi, 0},
474 }
475
476
477
478
479
480
481
482
483 for _, test := range tests {
484 ca := s1.ChordAngleFromAngle(test.actual)
485 bound := ca.Expanded(minUpdateDistanceMaxError(ca)).Angle()
486
487 if got := s1.Angle(bound.Radians()) - test.actual; got > test.maxErr {
488 t.Errorf("minUpdateDistanceMaxError(%v)-%v = %v> %v, want <=", ca, got, test.actual, test.maxErr)
489 }
490 }
491 }
492
493
494
495
496 func TestEdgeDistancesEdgePairMinDistance(t *testing.T) {
497 var zero Point
498 tests := []struct {
499 a0, a1 Point
500 b0, b1 Point
501 distRads float64
502 wantA Point
503 wantB Point
504 }{
505 {
506
507 a0: PointFromCoords(1, 0, 1),
508 a1: PointFromCoords(1, 0, 1),
509 b0: PointFromCoords(1, -1, 0),
510 b1: PointFromCoords(1, 1, 0),
511 distRads: math.Pi / 4,
512 wantA: PointFromCoords(1, 0, 1),
513 wantB: PointFromCoords(1, 0, 0),
514 },
515 {
516
517 a0: PointFromCoords(1, -1, 0),
518 a1: PointFromCoords(1, 1, 0),
519 b0: PointFromCoords(1, 0, 1),
520 b1: PointFromCoords(1, 0, 1),
521 distRads: math.Pi / 4,
522 wantA: PointFromCoords(1, 0, 0),
523 wantB: PointFromCoords(1, 0, 1),
524 },
525 {
526
527 a0: PointFromCoords(1, 0, 0),
528 a1: PointFromCoords(1, 0, 0),
529 b0: PointFromCoords(0, 1, 0),
530 b1: PointFromCoords(0, 1, 0),
531 distRads: math.Pi / 2,
532 wantA: PointFromCoords(1, 0, 0),
533 wantB: PointFromCoords(0, 1, 0),
534 },
535 {
536
537 a0: PointFromCoords(1, 0, 0),
538 a1: PointFromCoords(1, 0, 0),
539 b0: PointFromCoords(-1, 0, 0),
540 b1: PointFromCoords(-1, 0, 0),
541 distRads: math.Pi,
542 wantA: PointFromCoords(1, 0, 0),
543 wantB: PointFromCoords(-1, 0, 0),
544 },
545 {
546
547 a0: PointFromCoords(1, 0, 0),
548 a1: PointFromCoords(0, 1, 0),
549 b0: PointFromCoords(1, 0, 0),
550 b1: PointFromCoords(0, 1, 0),
551 distRads: 0,
552 wantA: zero,
553 wantB: zero,
554 },
555 {
556
557 a0: PointFromCoords(1, 0, 0),
558 a1: PointFromCoords(1, 0, 0),
559 b0: PointFromCoords(1, 0, 0),
560 b1: PointFromCoords(1, 0, 0),
561 distRads: 0,
562 wantA: PointFromCoords(1, 0, 0),
563 wantB: PointFromCoords(1, 0, 0),
564 },
565
566 {
567 a0: PointFromCoords(1, 0, 0),
568 a1: PointFromCoords(0, 1, 0),
569 b0: PointFromCoords(0, 1, 0),
570 b1: PointFromCoords(0, 1, 1),
571 distRads: 0,
572 wantA: PointFromCoords(0, 1, 0),
573 wantB: PointFromCoords(0, 1, 0),
574 },
575 {
576 a0: PointFromCoords(0, 1, 0),
577 a1: PointFromCoords(1, 0, 0),
578 b0: PointFromCoords(0, 1, 0),
579 b1: PointFromCoords(0, 1, 1),
580 distRads: 0,
581 wantA: PointFromCoords(0, 1, 0),
582 wantB: PointFromCoords(0, 1, 0),
583 },
584 {
585 a0: PointFromCoords(1, 0, 0),
586 a1: PointFromCoords(0, 1, 0),
587 b0: PointFromCoords(0, 1, 1),
588 b1: PointFromCoords(0, 1, 0),
589 distRads: 0,
590 wantA: PointFromCoords(0, 1, 0),
591 wantB: PointFromCoords(0, 1, 0),
592 },
593 {
594 a0: PointFromCoords(0, 1, 0),
595 a1: PointFromCoords(1, 0, 0),
596 b0: PointFromCoords(0, 1, 1),
597 b1: PointFromCoords(0, 1, 0),
598 distRads: 0,
599 wantA: PointFromCoords(0, 1, 0),
600 wantB: PointFromCoords(0, 1, 0),
601 },
602 {
603
604 a0: PointFromCoords(1, -1, 0),
605 a1: PointFromCoords(1, 1, 0),
606 b0: PointFromCoords(1, 0, -1),
607 b1: PointFromCoords(1, 0, 1),
608 distRads: 0,
609 wantA: PointFromCoords(1, 0, 0),
610 wantB: PointFromCoords(1, 0, 0),
611 },
612
613
614 {
615 a0: PointFromCoords(1, -1, 0),
616 a1: PointFromCoords(1, 1, 0),
617 b0: PointFromCoords(-1, 0, 0),
618 b1: PointFromCoords(-1, 0, 1),
619 distRads: math.Acos(-0.5),
620 wantA: zero,
621 wantB: PointFromCoords(-1, 0, 1),
622 },
623 {
624 a0: PointFromCoords(-1, 0, 0),
625 a1: PointFromCoords(-1, 0, 1),
626 b0: PointFromCoords(1, -1, 0),
627 b1: PointFromCoords(1, 1, 0),
628 distRads: math.Acos(-0.5),
629 wantA: PointFromCoords(-1, 0, 1),
630 wantB: zero,
631 },
632 {
633 a0: PointFromCoords(1, -1, 0),
634 a1: PointFromCoords(1, 1, 0),
635 b0: PointFromCoords(-1, 0, -1),
636 b1: PointFromCoords(-1, 0, 1),
637 distRads: math.Acos(-0.5),
638 wantA: zero,
639 wantB: zero,
640 },
641 }
642
643
644
645
646
647
648
649 for _, test := range tests {
650 actualA, actualB := EdgePairClosestPoints(test.a0, test.a1, test.b0, test.b1)
651 if test.wantA == zero {
652
653 if !(actualA == test.a0 || actualA == test.a1) {
654 t.Errorf("EdgePairClosestPoints(%v, %v, %v, %v) = %v, want %v or %v", test.a0, test.a1, test.b0, test.b1, actualA, test.a0, test.a1)
655 }
656 } else {
657 if !actualA.ApproxEqual(test.wantA) {
658 t.Errorf("EdgePairClosestPoints(%v, %v, %v, %v) = %v, want %v", test.a0, test.a1, test.b0, test.b1, actualA, test.wantA)
659 }
660 }
661
662 if test.wantB == zero {
663
664 if !(actualB == test.b0 || actualB == test.b1) {
665 t.Errorf("EdgePairClosestPoints(%v, %v, %v, %v) = %v, want %v or %v", test.a0, test.a1, test.b0, test.b1, actualB, test.b0, test.b1)
666 }
667 } else {
668 if !actualB.ApproxEqual(test.wantB) {
669 t.Errorf("EdgePairClosestPoints(%v, %v, %v, %v) = %v, want %v", test.a0, test.a1, test.b0, test.b1, actualB, test.wantB)
670 }
671 }
672
673 var minDist s1.ChordAngle
674 var ok bool
675 minDist, ok = updateEdgePairMinDistance(test.a0, test.a1, test.b0, test.b1, minDist)
676 if ok {
677 t.Errorf("updateEdgePairMinDistance(%v, %v, %v, %v, %v) = %v, want updated to be false", test.a0, test.a1, test.b0, test.b1, 0, minDist)
678 }
679
680 minDist = s1.InfChordAngle()
681 minDist, ok = updateEdgePairMinDistance(test.a0, test.a1, test.b0, test.b1, minDist)
682 if !ok {
683 t.Errorf("updateEdgePairMinDistance(%v, %v, %v, %v, %v) = %v, want updated to be true", test.a0, test.a1, test.b0, test.b1, s1.InfChordAngle(), minDist)
684 }
685
686 if !float64Near(test.distRads, minDist.Angle().Radians(), epsilon) {
687 t.Errorf("minDist %v - %v = %v, want < %v", test.distRads, minDist.Angle().Radians(), (test.distRads - minDist.Angle().Radians()), epsilon)
688 }
689 }
690 }
691
692 func TestEdgeDistancesEdgePairMaxDistance(t *testing.T) {
693 tests := []struct {
694 a0, a1 Point
695 b0, b1 Point
696 distRads float64
697 }{
698 {
699
700 a0: PointFromCoords(1, 0, 0),
701 a1: PointFromCoords(0, 1, 0),
702 b0: PointFromCoords(1, 1, 0),
703 b1: PointFromCoords(1, 1, 1),
704 distRads: math.Acos(1 / math.Sqrt(3)),
705 },
706 {
707
708
709 a0: PointFromCoords(1, 0, 1),
710 a1: PointFromCoords(1, 0, 1),
711 b0: PointFromCoords(1, -1, 0),
712 b1: PointFromCoords(1, 1, 0),
713 distRads: math.Acos(0.5),
714 },
715 {
716 a0: PointFromCoords(1, -1, 0),
717 a1: PointFromCoords(1, 1, 0),
718 b0: PointFromCoords(1, 0, 1),
719 b1: PointFromCoords(1, 0, 1),
720 distRads: math.Acos(0.5),
721 },
722 {
723
724 a0: PointFromCoords(1, 0, 0),
725 a1: PointFromCoords(1, 0, 0),
726 b0: PointFromCoords(0, 1, 0),
727 b1: PointFromCoords(0, 1, 0),
728 distRads: math.Pi / 2,
729 },
730 {
731
732 a0: PointFromCoords(1, 0, 0),
733 a1: PointFromCoords(1, 0, 0),
734 b0: PointFromCoords(-1, 0, 0),
735 b1: PointFromCoords(-1, 0, 0),
736 distRads: math.Pi,
737 },
738 {
739
740 a0: PointFromCoords(1, 0, 0),
741 a1: PointFromCoords(0, 1, 0),
742 b0: PointFromCoords(1, 0, 0),
743 b1: PointFromCoords(0, 1, 0),
744 distRads: math.Pi / 2,
745 },
746 {
747
748 a0: PointFromCoords(1, 0, 0),
749 a1: PointFromCoords(1, 0, 0),
750 b0: PointFromCoords(1, 0, 0),
751 b1: PointFromCoords(1, 0, 0),
752 distRads: 0,
753 },
754 {
755
756 a0: PointFromCoords(1, 0, 1),
757 a1: PointFromCoords(1, 0, -1),
758 b0: PointFromCoords(-1, -1, 0),
759 b1: PointFromCoords(-1, 1, 0),
760 distRads: math.Pi,
761 },
762 {
763
764
765 a0: PointFromCoords(1, 0, 1),
766 a1: PointFromCoords(1, 0, 0),
767 b0: PointFromCoords(-1, -1, 0),
768 b1: PointFromCoords(-1, 1, 0),
769 distRads: math.Pi,
770 },
771 }
772
773 for _, test := range tests {
774
775
776 if maxDist, ok := updateEdgePairMaxDistance(test.a0, test.a1, test.b0, test.b1, s1.StraightChordAngle); ok {
777 t.Errorf("updateEdgePairMaxDistance(%v, %v, %v, %v, %v) = %v, want updated to be false", test.a0, test.a1, test.b0, test.b1, s1.StraightChordAngle, maxDist)
778 }
779
780 maxDist, ok := updateEdgePairMaxDistance(test.a0, test.a1, test.b0, test.b1, s1.NegativeChordAngle)
781 if !ok {
782 t.Errorf("updateEdgePairMaxDistance(%v, %v, %v, %v, %v) = %v, want updated to be false", test.a0, test.a1, test.b0, test.b1, s1.NegativeChordAngle, maxDist)
783 }
784 if !float64Near(test.distRads, maxDist.Angle().Radians(), epsilon) {
785 t.Errorf("maxDist %v - %v = %v, want < %v", test.distRads, maxDist.Angle().Radians(), (test.distRads - maxDist.Angle().Radians()), epsilon)
786
787 }
788 }
789 }
790
791
792
View as plain text