1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package r2
19
20 import (
21 "math"
22 "reflect"
23 "testing"
24
25 "github.com/golang/geo/r1"
26 )
27
28 var (
29 sw = Point{0, 0.25}
30 se = Point{0.5, 0.25}
31 ne = Point{0.5, 0.75}
32 nw = Point{0, 0.75}
33
34 empty = EmptyRect()
35 rect = RectFromPoints(sw, ne)
36 rectMid = RectFromPoints(Point{0.25, 0.5}, Point{0.25, 0.5})
37 rectSW = RectFromPoints(sw, sw)
38 rectNE = RectFromPoints(ne, ne)
39 )
40
41 func float64Eq(x, y float64) bool { return math.Abs(x-y) < 1e-14 }
42
43 func pointsApproxEqual(a, b Point) bool {
44 return float64Eq(a.X, b.X) && float64Eq(a.Y, b.Y)
45 }
46
47 func TestOrtho(t *testing.T) {
48 tests := []struct {
49 p Point
50 want Point
51 }{
52 {Point{0, 0}, Point{0, 0}},
53 {Point{0, 1}, Point{-1, 0}},
54 {Point{1, 1}, Point{-1, 1}},
55 {Point{-4, 7}, Point{-7, -4}},
56 {Point{1, math.Sqrt(3)}, Point{-math.Sqrt(3), 1}},
57 }
58 for _, test := range tests {
59 if got := test.p.Ortho(); !pointsApproxEqual(got, test.want) {
60 t.Errorf("%v.Ortho() = %v, want %v", test.p, got, test.want)
61 }
62 }
63 }
64
65 func TestDot(t *testing.T) {
66 tests := []struct {
67 p Point
68 op Point
69 want float64
70 }{
71 {Point{0, 0}, Point{0, 0}, 0},
72 {Point{0, 1}, Point{0, 0}, 0},
73 {Point{1, 1}, Point{4, 3}, 7},
74 {Point{-4, 7}, Point{1, 5}, 31},
75 }
76 for _, test := range tests {
77 if got := test.p.Dot(test.op); !float64Eq(got, test.want) {
78 t.Errorf("%v.Dot(%v) = %v, want %v", test.p, test.op, got, test.want)
79 }
80 }
81 }
82
83 func TestCross(t *testing.T) {
84 tests := []struct {
85 p Point
86 op Point
87 want float64
88 }{
89 {Point{0, 0}, Point{0, 0}, 0},
90 {Point{0, 1}, Point{0, 0}, 0},
91 {Point{1, 1}, Point{-1, -1}, 0},
92 {Point{1, 1}, Point{4, 3}, -1},
93 {Point{1, 5}, Point{-2, 3}, 13},
94 }
95
96 for _, test := range tests {
97 if got := test.p.Cross(test.op); !float64Eq(got, test.want) {
98 t.Errorf("%v.Cross(%v) = %v, want %v", test.p, test.op, got, test.want)
99 }
100 }
101 }
102
103 func TestNorm(t *testing.T) {
104 tests := []struct {
105 p Point
106 want float64
107 }{
108 {Point{0, 0}, 0},
109 {Point{0, 1}, 1},
110 {Point{-1, 0}, 1},
111 {Point{3, 4}, 5},
112 {Point{3, -4}, 5},
113 {Point{2, 2}, 2 * math.Sqrt(2)},
114 {Point{1, math.Sqrt(3)}, 2},
115 {Point{29, 29 * math.Sqrt(3)}, 29 * 2},
116 {Point{1, 1e15}, 1e15},
117 {Point{1e14, math.MaxFloat32 - 1}, math.MaxFloat32},
118 }
119
120 for _, test := range tests {
121 if !float64Eq(test.p.Norm(), test.want) {
122 t.Errorf("%v.Norm() = %v, want %v", test.p, test.p.Norm(), test.want)
123 }
124 }
125 }
126
127 func TestNormalize(t *testing.T) {
128 tests := []struct {
129 have Point
130 want Point
131 }{
132 {Point{}, Point{}},
133 {Point{0, 0}, Point{0, 0}},
134 {Point{0, 1}, Point{0, 1}},
135 {Point{-1, 0}, Point{-1, 0}},
136 {Point{3, 4}, Point{0.6, 0.8}},
137 {Point{3, -4}, Point{0.6, -0.8}},
138 {Point{2, 2}, Point{math.Sqrt(2) / 2, math.Sqrt(2) / 2}},
139 {Point{7, 7 * math.Sqrt(3)}, Point{0.5, math.Sqrt(3) / 2}},
140 {Point{1e21, 1e21 * math.Sqrt(3)}, Point{0.5, math.Sqrt(3) / 2}},
141 {Point{1, 1e16}, Point{0, 1}},
142 {Point{1e4, math.MaxFloat32 - 1}, Point{0, 1}},
143 }
144
145 for _, test := range tests {
146 if got := test.have.Normalize(); !pointsApproxEqual(got, test.want) {
147 t.Errorf("%v.Normalize() = %v, want %v", test.have, got, test.want)
148 }
149 }
150
151 }
152
153 func TestEmptyRect(t *testing.T) {
154 if !empty.IsValid() {
155 t.Errorf("empty Rect should be valid: %v", empty)
156 }
157 if !empty.IsEmpty() {
158 t.Errorf("empty Rect should be empty: %v", empty)
159 }
160 }
161
162 func TestFromVariousTypes(t *testing.T) {
163 d1 := RectFromPoints(Point{0.1, 0}, Point{0.25, 1})
164 tests := []struct {
165 r1, r2 Rect
166 }{
167 {
168 RectFromCenterSize(Point{0.3, 0.5}, Point{0.2, 0.4}),
169 RectFromPoints(Point{0.2, 0.3}, Point{0.4, 0.7}),
170 },
171 {
172 RectFromCenterSize(Point{1, 0.1}, Point{0, 2}),
173 RectFromPoints(Point{1, -0.9}, Point{1, 1.1}),
174 },
175 {
176 d1,
177 Rect{d1.X, d1.Y},
178 },
179 {
180 RectFromPoints(Point{0.15, 0.3}, Point{0.35, 0.9}),
181 RectFromPoints(Point{0.15, 0.9}, Point{0.35, 0.3}),
182 },
183 {
184 RectFromPoints(Point{0.12, 0}, Point{0.83, 0.5}),
185 RectFromPoints(Point{0.83, 0}, Point{0.12, 0.5}),
186 },
187 }
188
189 for _, test := range tests {
190 if got := test.r1.ApproxEqual(test.r2); !got {
191 t.Errorf("%v.ApproxEqual(%v); got %v want true", test.r1, test.r2, got)
192 }
193 }
194 }
195
196 func TestCenter(t *testing.T) {
197 tests := []struct {
198 rect Rect
199 want Point
200 }{
201 {empty, Point{0.5, 0.5}},
202 {rect, Point{0.25, 0.5}},
203 }
204 for _, test := range tests {
205 if got := test.rect.Center(); got != test.want {
206 t.Errorf("%v.Center(); got %v want %v", test.rect, got, test.want)
207 }
208 }
209 }
210
211 func TestVertices(t *testing.T) {
212 want := [4]Point{sw, se, ne, nw}
213 got := rect.Vertices()
214 if !reflect.DeepEqual(got, want) {
215 t.Errorf("%v.Vertices(); got %v want %v", rect, got, want)
216 }
217 }
218
219 func TestContainsPoint(t *testing.T) {
220 tests := []struct {
221 rect Rect
222 p Point
223 want bool
224 }{
225 {rect, Point{0.2, 0.4}, true},
226 {rect, Point{0.2, 0.8}, false},
227 {rect, Point{-0.1, 0.4}, false},
228 {rect, Point{0.6, 0.1}, false},
229 {rect, Point{rect.X.Lo, rect.Y.Lo}, true},
230 {rect, Point{rect.X.Hi, rect.Y.Hi}, true},
231 }
232 for _, test := range tests {
233 if got := test.rect.ContainsPoint(test.p); got != test.want {
234 t.Errorf("%v.ContainsPoint(%v); got %v want %v", test.rect, test.p, got, test.want)
235 }
236 }
237 }
238
239 func TestInteriorContainsPoint(t *testing.T) {
240 tests := []struct {
241 rect Rect
242 p Point
243 want bool
244 }{
245
246 {rect, sw, false},
247 {rect, ne, false},
248
249 {rect, Point{0, 0.5}, false},
250 {rect, Point{0.25, 0.25}, false},
251 {rect, Point{0.5, 0.5}, false},
252
253 {rect, Point{0.125, 0.6}, true},
254 }
255 for _, test := range tests {
256 if got := test.rect.InteriorContainsPoint(test.p); got != test.want {
257 t.Errorf("%v.InteriorContainsPoint(%v); got %v want %v",
258 test.rect, test.p, got, test.want)
259 }
260 }
261 }
262
263 func TestIntervalOps(t *testing.T) {
264 tests := []struct {
265 r1, r2 Rect
266 contains, intContains, intersects, intIntersects bool
267 wantUnion, wantIntersection Rect
268 }{
269 {
270 rect, rectMid,
271 true, true, true, true,
272 rect, rectMid,
273 },
274 {
275 rect, rectSW,
276 true, false, true, false,
277 rect, rectSW,
278 },
279 {
280 rect, rectNE,
281 true, false, true, false,
282 rect, rectNE,
283 },
284 {
285 rect,
286 RectFromPoints(Point{0.45, 0.1}, Point{0.75, 0.3}),
287 false, false, true, true,
288 RectFromPoints(Point{0, 0.1}, Point{0.75, 0.75}),
289 RectFromPoints(Point{0.45, 0.25}, Point{0.5, 0.3}),
290 },
291 {
292 rect,
293 RectFromPoints(Point{0.5, 0.1}, Point{0.7, 0.3}),
294 false, false, true, false,
295 RectFromPoints(Point{0, 0.1}, Point{0.7, 0.75}),
296 RectFromPoints(Point{0.5, 0.25}, Point{0.5, 0.3}),
297 },
298 {
299 rect,
300 RectFromPoints(Point{0.45, 0.1}, Point{0.7, 0.25}),
301 false, false, true, false,
302 RectFromPoints(Point{0, 0.1}, Point{0.7, 0.75}),
303 RectFromPoints(Point{0.45, 0.25}, Point{0.5, 0.25}),
304 },
305 {
306 RectFromPoints(Point{0.1, 0.2}, Point{0.1, 0.3}),
307 RectFromPoints(Point{0.15, 0.7}, Point{0.2, 0.8}),
308 false, false, false, false,
309 RectFromPoints(Point{0.1, 0.2}, Point{0.2, 0.8}),
310 EmptyRect(),
311 },
312
313
314 {
315 RectFromPoints(Point{0.1, 0.2}, Point{0.4, 0.5}),
316 RectFromPoints(Point{0, 0}, Point{0.2, 0.1}),
317 false, false, false, false,
318 RectFromPoints(Point{0, 0}, Point{0.4, 0.5}),
319 EmptyRect(),
320 },
321 {
322 RectFromPoints(Point{0, 0}, Point{0.1, 0.3}),
323 RectFromPoints(Point{0.2, 0.1}, Point{0.3, 0.4}),
324 false, false, false, false,
325 RectFromPoints(Point{0, 0}, Point{0.3, 0.4}),
326 EmptyRect(),
327 },
328 }
329 for _, test := range tests {
330 if got := test.r1.Contains(test.r2); got != test.contains {
331 t.Errorf("%v.Contains(%v); got %v want %v",
332 test.r1, test.r2, got, test.contains)
333 }
334
335 if got := test.r1.InteriorContains(test.r2); got != test.intContains {
336 t.Errorf("%v.InteriorContains(%v); got %v want %v",
337 test.r1, test.r2, got, test.contains)
338 }
339
340 if got := test.r1.Intersects(test.r2); got != test.intersects {
341 t.Errorf("%v.Intersects(%v); got %v want %v",
342 test.r1, test.r2, got, test.intersects)
343 }
344
345 if got := test.r1.InteriorIntersects(test.r2); got != test.intIntersects {
346 t.Errorf("%v.InteriorIntersects(%v); got %v want %v",
347 test.r1, test.r2, got, test.intIntersects)
348 }
349
350 tCon := test.r1.Contains(test.r2)
351 if got := test.r1.Union(test.r2).ApproxEqual(test.r1); got != tCon {
352 t.Errorf("%v.Union(%v) == %v.Contains(%v); got %v want %v",
353 test.r1, test.r2, test.r1, test.r2, got, tCon)
354 }
355
356 tInter := test.r1.Intersects(test.r2)
357 if got := !test.r1.Intersection(test.r2).IsEmpty(); got != tInter {
358 t.Errorf("%v.Intersection(%v).IsEmpty() == %v.Intersects(%v); got %v want %v",
359 test.r1, test.r2, test.r1, test.r2, got, tInter)
360 }
361
362 if got := test.r1.Union(test.r2); got != test.wantUnion {
363 t.Errorf("%v.Union(%v); got %v want %v",
364 test.r1, test.r2, got, test.wantUnion)
365 }
366
367 if got := test.r1.Intersection(test.r2); got != test.wantIntersection {
368 t.Errorf("%v.Intersection(%v); got %v want %v",
369 test.r1, test.r2, got, test.wantIntersection)
370 }
371
372 r := test.r1.AddRect(test.r2)
373
374 if r != test.wantUnion {
375 t.Errorf("%v.AddRect(%v); got %v want %v", test.r1, test.r2, r, test.wantUnion)
376 }
377 }
378 }
379
380 func TestAddPoint(t *testing.T) {
381 r1 := rect
382 r2 := EmptyRect()
383
384 r2 = r2.AddPoint(sw)
385 r2 = r2.AddPoint(se)
386 r2 = r2.AddPoint(nw)
387 r2 = r2.AddPoint(Point{0.1, 0.4})
388
389 if !r1.ApproxEqual(r2) {
390 t.Errorf("%v.AddPoint(%v); got false want true", r1, r2)
391 }
392 }
393
394 func TestClampPoint(t *testing.T) {
395 r := Rect{r1.Interval{Lo: 0, Hi: 0.5}, r1.Interval{Lo: 0.25, Hi: 0.75}}
396 tests := []struct {
397 p Point
398 want Point
399 }{
400 {Point{-0.01, 0.24}, Point{0, 0.25}},
401 {Point{-5.0, 0.48}, Point{0, 0.48}},
402 {Point{-5.0, 2.48}, Point{0, 0.75}},
403 {Point{0.19, 2.48}, Point{0.19, 0.75}},
404
405 {Point{6.19, 2.48}, Point{0.5, 0.75}},
406 {Point{6.19, 0.53}, Point{0.5, 0.53}},
407 {Point{6.19, -2.53}, Point{0.5, 0.25}},
408 {Point{0.33, -2.53}, Point{0.33, 0.25}},
409 {Point{0.33, 0.37}, Point{0.33, 0.37}},
410 }
411 for _, test := range tests {
412 if got := r.ClampPoint(test.p); got != test.want {
413 t.Errorf("%v.ClampPoint(%v); got %v want %v", r, test.p, got, test.want)
414 }
415 }
416 }
417
418 func TestExpandedEmpty(t *testing.T) {
419 tests := []struct {
420 rect Rect
421 p Point
422 }{
423 {
424 EmptyRect(),
425 Point{0.1, 0.3},
426 },
427 {
428 EmptyRect(),
429 Point{-0.1, -0.3},
430 },
431 {
432 RectFromPoints(Point{0.2, 0.4}, Point{0.3, 0.7}),
433 Point{-0.1, 0.3},
434 },
435 {
436 RectFromPoints(Point{0.2, 0.4}, Point{0.3, 0.7}),
437 Point{0.1, -0.2},
438 },
439 }
440 for _, test := range tests {
441 if got := test.rect.Expanded(test.p); !got.IsEmpty() {
442 t.Errorf("%v.Expanded(%v); got %v want true", test.rect, test.p, got.IsEmpty())
443 }
444 }
445 }
446
447 func TestExpandedEqual(t *testing.T) {
448 tests := []struct {
449 rect Rect
450 p Point
451 want Rect
452 }{
453 {
454 RectFromPoints(Point{0.2, 0.4}, Point{0.3, 0.7}),
455 Point{0.1, 0.3},
456 RectFromPoints(Point{0.1, 0.1}, Point{0.4, 1.0}),
457 },
458 {
459 RectFromPoints(Point{0.2, 0.4}, Point{0.3, 0.7}),
460 Point{0.1, -0.1},
461 RectFromPoints(Point{0.1, 0.5}, Point{0.4, 0.6}),
462 },
463 {
464 RectFromPoints(Point{0.2, 0.4}, Point{0.3, 0.7}),
465 Point{0.1, 0.1},
466 RectFromPoints(Point{0.1, 0.3}, Point{0.4, 0.8}),
467 },
468 }
469 for _, test := range tests {
470 if got := test.rect.Expanded(test.p); !got.ApproxEqual(test.want) {
471 t.Errorf("%v.Expanded(%v); got %v want %v", test.rect, test.p, got, test.want)
472 }
473 }
474 }
475
View as plain text