20static void utest_check_compare_circles(
27 struct point_2d {
double lon, lat;};
35 int contains_north_pole;
37 {{.a = {.lon = 45.0, .lat = 0.0},
38 .b = {.lon = -45.0, .lat = 0.0},
42 .contains_north_pole = 1},
43 {.a = {.lon = -45.0, .lat = 0.0},
44 .b = {.lon = 45.0, .lat = 0.0},
48 .contains_north_pole = 1},
49 {.a = {.lon = 45.0, .lat = 0.0},
50 .b = {.lon = -45.0, .lat = 0.0},
54 .contains_north_pole = 0},
55 {.a = {.lon = -45.0, .lat = 0.0},
56 .b = {.lon = 45.0, .lat = 0.0},
60 .contains_north_pole = 0},
61 {.a = {.lon = 0.0, .lat = 88.0},
62 .b = {.lon = 180.0, .lat = 88.0},
66 .contains_north_pole = 0},
67 {.a = {.lon = 180.0, .lat = 88.0},
68 .b = {.lon = 0.0, .lat = 88.0},
72 .contains_north_pole = 0},
73 {.a = {.lon = 0.0, .lat = -1.0},
74 .b = {.lon = 0.0, .lat = 1.0},
78 .contains_north_pole = 0},
79 {.a = {.lon = 10.0, .lat = 10.0},
80 .b = {.lon = 10.0, .lat = 20.0},
84 .contains_north_pole = 0},
85 {.a = {.lon = 10.0, .lat = 10.0},
86 .b = {.lon = 10.0, .lat = 20.0},
90 .contains_north_pole = 0},
91 {.a = {.lon = 45.0, .lat = 89.0},
92 .b = {.lon = 45.0+180.0, .lat = 85.0},
96 .contains_north_pole = 0},
97 {.a = {.lon = 45.0, .lat = 89.0},
98 .b = {.lon = 45.0+180.0, .lat = 85.0},
102 .contains_north_pole = 0},
103 {.a = {.lon = 10.0, .lat = 70.0},
104 .b = {.lon = 20.0, .lat = 70.0},
108 .contains_north_pole = 1},
109 {.a = {.lon = 10.0, .lat = 70.0},
110 .b = {.lon = 20.0, .lat = 70.0},
114 .contains_north_pole = 0},
115 {.a = {.lon = -5.0, .lat = 15.0},
116 .b = {.lon = 5.0, .lat = 15.0},
120 .contains_north_pole = 1}};
121 enum {
NUM_TESTS =
sizeof(test_data) /
sizeof(test_data[0])};
127 LLtoXYZ_deg(test_data[i].a.lon, test_data[i].a.lat, a);
128 LLtoXYZ_deg(test_data[i].b.lon, test_data[i].b.lat, b);
130 a, b, test_data[i].edge_type, test_data[i].edge_ordering,
135 test_data[i].contains_north_pole)
136 PUT_ERR(
"error in yac_circle_contains_north_pole");
138 utest_check_compare_circles(
141 test_data[i].circle_idx == test_data[j].circle_idx);
148 struct point_2d a, b, point;
153 {{.a = {.lon = -45.0, .lat = 0.0},
154 .b = {.lon = 45.0, .lat = 0.0},
155 .point = {.lon = 0.0, .lat = 90.0},
159 {.a = {.lon = -45.0, .lat = 0.0},
160 .b = {.lon = 45.0, .lat = 0.0},
161 .point = {.lon = 0.0, .lat = 90.0},
165 {.a = {.lon = -45.0, .lat = 0.0},
166 .b = {.lon = 45.0, .lat = 0.0},
167 .point = {.lon = 0.0, .lat = 0.0},
171 {.a = {.lon = -45.0, .lat = 0.0},
172 .b = {.lon = 45.0, .lat = 0.0},
173 .point = {.lon = 1.0, .lat = 1.0},
177 {.a = {.lon = 15.0, .lat = 25.0},
178 .b = {.lon = 15.0, .lat = 30.0},
179 .point = {.lon = 10.0, .lat = 10.0},
183 {.a = {.lon = 15.0, .lat = 25.0},
184 .b = {.lon = 15.0, .lat = 30.0},
185 .point = {.lon = 10.0, .lat = 10.0},
189 {.a = {.lon = 15.0, .lat = 25.0},
190 .b = {.lon = 15.0, .lat = 30.0},
191 .point = {.lon = 10.0, .lat = 90.0},
195 {.a = {.lon = 15.0, .lat = 25.0},
196 .b = {.lon = 15.0, .lat = 30.0},
197 .point = {.lon = 15.0, .lat = 60.0},
201 {.a = {.lon = 75.0, .lat = 75.0},
202 .b = {.lon = 80.0, .lat = 75.0},
203 .point = {.lon = 15.0, .lat = 80.0},
207 {.a = {.lon = 75.0, .lat = 75.0},
208 .b = {.lon = 80.0, .lat = 75.0},
209 .point = {.lon = 15.0, .lat = 90.0},
213 {.a = {.lon = 75.0, .lat = 75.0},
214 .b = {.lon = 80.0, .lat = 75.0},
215 .point = {.lon = 15.0, .lat = 80.0},
219 {.a = {.lon = 75.0, .lat = 75.0},
220 .b = {.lon = 80.0, .lat = 75.0},
221 .point = {.lon = 15.0, .lat = 90.0},
225 {.a = {.lon = 75.0, .lat = 75.0},
226 .b = {.lon = 80.0, .lat = 75.0},
227 .point = {.lon = 15.0, .lat = 75.0},
234 {.a = {.lon = 75.0, .lat = 90.0 - 1.0e-6 /
YAC_RAD},
235 .b = {.lon = 80.0, .lat = 90.0 - 1.0e-6 /
YAC_RAD},
236 .point = {.lon = 15.0, .lat = 90.0},
240 {.a = {.lon = 75.0, .lat = 90.0 - 1.0e-6 /
YAC_RAD},
241 .b = {.lon = 80.0, .lat = 90.0 - 1.0e-6 /
YAC_RAD},
242 .point = {.lon = 15.0, .lat = 90.0},
247 {.a = {.lon = 75.0, .lat = 90.0 - 1.0e-6 /
YAC_RAD},
248 .b = {.lon = 80.0, .lat = 90.0 - 1.0e-6 /
YAC_RAD},
249 .point = {.lon = 15.0, .lat = 90.0 - 1.0e-6 /
YAC_RAD},
254 {.a = {.lon = 75.0, .lat = 75.0},
255 .b = {.lon = 80.0, .lat = 75.0},
256 .point = {.lon = 15.0, .lat = 75.0 + 1.0e-13 /
YAC_RAD},
262 {.a = {.lon = 75.0, .lat = -90.0 + 1.0e-6 /
YAC_RAD},
263 .b = {.lon = 80.0, .lat = -90.0 + 1.0e-6 /
YAC_RAD},
264 .point = {.lon = 15.0, .lat = 90.0},
268 enum {
NUM_TESTS =
sizeof(test_data) /
sizeof(test_data[0])};
273 test_data[i].point.lat, point);
276 LLtoXYZ_deg(test_data[i].a.lon, test_data[i].a.lat, a);
277 LLtoXYZ_deg(test_data[i].b.lon, test_data[i].b.lat, b);
279 a, b, test_data[i].edge_type, test_data[i].edge_ordering,
282 if (is_inside != test_data[i].is_inside) {
284 stderr,
"test_data index %zu: is_inside %d (expected %d)\n",
285 i, is_inside, test_data[i].is_inside);
286 PUT_ERR(
"error in yac_circle_point_is_inside");
293 struct point_2d a, b, point_a, point_b;
297 {{.a = {.lon = -1.0, .lat = -1.0},
298 .b = {.lon = 1.0, .lat = 1.0},
299 .point_a = {.lon = -1.0, .lat = 1.0},
300 .point_b = {.lon = -2.0, .lat = 2.0},
303 {.a = {.lon = -1.0, .lat = -1.0},
304 .b = {.lon = 1.0, .lat = 1.0},
305 .point_a = {.lon = -2.0, .lat = 2.0},
306 .point_b = {.lon = -1.0, .lat = 1.0},
309 {.a = {.lon = -1.0, .lat = -1.0},
310 .b = {.lon = 1.0, .lat = 1.0},
311 .point_a = {.lon = -2.0, .lat = 2.0},
312 .point_b = {.lon = 2.0, .lat = -2.0},
315 {.a = {.lon = -1.0, .lat = -1.0},
316 .b = {.lon = 1.0, .lat = 1.0},
317 .point_a = {.lon = 0.0, .lat = 0.0},
318 .point_b = {.lon = 2.0, .lat = -2.0},
321 {.a = {.lon = -1.0, .lat = -1.0},
322 .b = {.lon = 1.0, .lat = 1.0},
323 .point_a = {.lon = 2.0, .lat = -2.0},
324 .point_b = {.lon = 0.0, .lat = 0.0},
327 {.a = {.lon = 2.0, .lat = -1.0},
328 .b = {.lon = 2.0, .lat = 1.0},
329 .point_a = {.lon = 1.0, .lat = 1.0},
330 .point_b = {.lon = 4.0, .lat = -1.0},
333 {.a = {.lon = 2.0, .lat = -1.0},
334 .b = {.lon = 2.0, .lat = 1.0},
335 .point_a = {.lon = 4.0, .lat = -1.0},
336 .point_b = {.lon = 1.0, .lat = 1.0},
339 {.a = {.lon = 2.0, .lat = -1.0},
340 .b = {.lon = 2.0, .lat = 1.0},
341 .point_a = {.lon = 3.0, .lat = -1.0},
342 .point_b = {.lon = 1.0, .lat = 1.0},
345 {.a = {.lon = -1.0, .lat = 60.0},
346 .b = {.lon = 1.0, .lat = 60.0},
347 .point_a = {.lon = 7.0, .lat = 59.0},
348 .point_b = {.lon = -13.0, .lat = 62.0},
351 {.a = {.lon = -1.0, .lat = 60.0},
352 .b = {.lon = 1.0, .lat = 60.0},
353 .point_a = {.lon = -13.0, .lat = 62.0},
354 .point_b = {.lon = 7.0, .lat = 59.0},
357 {.a = {.lon = -1.0, .lat = 60.0},
358 .b = {.lon = 1.0, .lat = 60.0},
359 .point_a = {.lon = 7.0, .lat = 59.0},
360 .point_b = {.lon = -13.0, .lat = 61.0},
363 {.a = {.lon = 45.0, .lat = 45.0},
364 .b = {.lon = 45.0, .lat = 45.0},
365 .point_a = {.lon = 46.0, .lat = 46.0},
366 .point_b = {.lon = 47.0, .lat = 47.0},
369 {.a = {.lon = 45.0, .lat = 45.0},
370 .b = {.lon = 45.0, .lat = 45.0},
371 .point_a = {.lon = 47.0, .lat = 47.0},
372 .point_b = {.lon = 46.0, .lat = 46.0},
375 {.a = {.lon = 45.0, .lat = 45.0},
376 .b = {.lon = 45.0, .lat = 45.0},
377 .point_a = {.lon = 40.0, .lat = 40.0},
378 .point_b = {.lon = -45.0, .lat = -45.0},
381 {.a = {.lon = 45.0, .lat = 45.0},
382 .b = {.lon = 45.0, .lat = 45.0},
383 .point_a = {.lon = -45.0, .lat = -45.0},
384 .point_b = {.lon = 40.0, .lat = 40.0},
387 {.a = {.lon = 45.0, .lat = 45.0},
388 .b = {.lon = 45.0, .lat = 45.0},
389 .point_a = {.lon = 45.0, .lat = 90.0},
390 .point_b = {.lon = 45.0, .lat = 0.0},
393 enum {
NUM_TESTS =
sizeof(test_data) /
sizeof(test_data[0])};
396 double point_a[3], point_b[3];
398 test_data[i].point_a.lat, point_a);
400 test_data[i].point_b.lat, point_b);
403 LLtoXYZ_deg(test_data[i].a.lon, test_data[i].a.lat, a);
404 LLtoXYZ_deg(test_data[i].b.lon, test_data[i].b.lat, b);
406 a, b, test_data[i].edge_type, 1, &test_circle);
408 test_data[i].compare)
409 PUT_ERR(
"error in yac_circle_compare_distances");
416 struct point_2d
points[2];
419 struct point_2d
p, q;
422 {{.circles = {{.points = {{.lon = -1.0, .lat = -1.0},
423 {.lon = 1.0, .lat = 1.0}},
425 {.points = {{.lon = -1.0, .lat = 1.0},
426 {.lon = 1.0, .lat = -1.0}},
428 .p = {.lon = 0.0, .lat = 0.0},
429 .q = {.lon = 180.0, .lat = 0.0},
431 {.circles = {{.points = {{.lon = 0.0, .lat = -1.0},
432 {.lon = 0.0, .lat = 1.0}},
434 {.points = {{.lon = 180.0, .lat = -2.0},
435 {.lon = 180.0, .lat = 2.0}},
437 .p = {.lon = 0.0, .lat = 0.0},
438 .q = {.lon = 0.0, .lat = 0.0},
440 {.circles = {{.points = {{.lon = 0.0, .lat = -1.0},
441 {.lon = 0.0, .lat = 1.0}},
443 {.points = {{.lon = 6.0, .lat = 45.0},
444 {.lon = 9.0, .lat = 45.0}},
446 .p = {.lon = 0.0, .lat = 45.0},
447 .q = {.lon = 180.0, .lat = 45.0},
449 {.circles = {{.points = {{.lon = 0.0, .lat = -1.0},
450 {.lon = 0.0, .lat = 1.0}},
452 {.points = {{.lon = 6.0, .lat = 90.0},
453 {.lon = 9.0, .lat = 90.0}},
455 .p = {.lon = 0.0, .lat = 90.0},
456 .q = {.lon = 180.0, .lat = -90.0},
458 {.circles = {{.points = {{.lon = 1.0, .lat = 0.0},
459 {.lon = 2.0, .lat = 0.0}},
461 {.points = {{.lon = 6.0, .lat = 45.0},
462 {.lon = 9.0, .lat = 45.0}},
464 .p = {.lon = 0.0, .lat = 0.0},
465 .q = {.lon = 0.0, .lat = 0.0},
467 {.circles = {{.points = {{.lon = 0.0, .lat = -1.0},
468 {.lon = 0.0, .lat = 1.0}},
470 {.points = {{.lon = 17.0, .lat = -1.0},
471 {.lon = 17.0, .lat = 1.0}},
473 .p = {.lon = 0.0, .lat = 90.0},
474 .q = {.lon = 0.0, .lat = -90.0},
476 {.circles = {{.points = {{.lon = 0.0, .lat = -1.0},
477 {.lon = 0.0, .lat = 1.0}},
479 {.points = {{.lon = 0.0, .lat = 45.0},
480 {.lon = 0.0, .lat = 50.0}},
482 .p = {.lon = 0.0, .lat = 90.0},
483 .q = {.lon = 0.0, .lat = -90.0},
485 {.circles = {{.points = {{.lon = 0.0, .lat = -1.0},
486 {.lon = 0.0, .lat = 1.0}},
488 {.points = {{.lon = -1.0, .lat = 45.0},
489 {.lon = 1.0, .lat = 45.0}},
491 .p = {.lon = 0.0, .lat = 45.0},
492 .q = {.lon = 180.0, .lat = 45.0},
494 {.circles = {{.points = {{.lon = 0.0, .lat = -1.0},
495 {.lon = 0.0, .lat = 1.0}},
497 {.points = {{.lon = -1.0, .lat = -90.0},
498 {.lon = 1.0, .lat = -90.0}},
500 .p = {.lon = 0.0, .lat = -90.0},
501 .q = {.lon = 180.0, .lat = 90.0},
503 {.circles = {{.points = {{.lon = 0.0, .lat = 0.0},
504 {.lon = 0.0, .lat = 0.0}},
506 {.points = {{.lon = -1.0, .lat = 0.0},
507 {.lon = 1.0, .lat = 0.0}},
509 .p = {.lon = 0.0, .lat = 0.0},
510 .q = {.lon = 180.0, .lat = 0.0},
512 {.circles = {{.points = {{.lon = 0.0, .lat = 1.0},
513 {.lon = 0.0, .lat = 1.0}},
515 {.points = {{.lon = -1.0, .lat = 0.0},
516 {.lon = 1.0, .lat = 0.0}},
518 .p = {.lon = 0.0, .lat = 0.0},
519 .q = {.lon = 180.0, .lat = 0.0},
521 {.circles = {{.points = {{.lon = 0.0, .lat = 45.0},
522 {.lon = 0.0, .lat = 45.0}},
524 {.points = {{.lon = -1.0, .lat = 45.0},
525 {.lon = 1.0, .lat = 45.0}},
527 .p = {.lon = 0.0, .lat = 45.0},
528 .q = {.lon = 180.0, .lat = 45.0},
530 {.circles = {{.points = {{.lon = 0.0, .lat = 0.0},
531 {.lon = 0.0, .lat = 0.0}},
533 {.points = {{.lon = -1.0, .lat = 45.0},
534 {.lon = 1.0, .lat = 45.0}},
536 .p = {.lon = 0.0, .lat = 45.0},
537 .q = {.lon = 180.0, .lat = 45.0},
539 {.circles = {{.points = {{.lon = 5.0, .lat = 5.0},
540 {.lon = 5.0, .lat = 5.0}},
542 {.points = {{.lon = 5.0, .lat = 5.0},
543 {.lon = 5.0, .lat = 5.0}},
545 .p = {.lon = 5.0, .lat = 5.0},
546 .q = {.lon = 185.0, .lat = -5.0},
549 {.circles = {{.points = {{.lon = 0.0, .lat = 45.0},
550 {.lon = 10.0, .lat = 45.0}},
552 {.points = {{.lon = 20.0, .lat = 45.0},
553 {.lon = 30.0, .lat = 45.0}},
555 .p = {.lon = 0.0, .lat = 0.0},
556 .q = {.lon = 0.0, .lat = 0.0},
559 {.circles = {{.points = {{.lon = 0.0, .lat = 0.0},
560 {.lon = 10.0, .lat = 0.0}},
562 {.points = {{.lon = 20.0, .lat = 0.0},
563 {.lon = 30.0, .lat = 0.0}},
565 .p = {.lon = 0.0, .lat = 0.0},
566 .q = {.lon = 0.0, .lat = 0.0},
569 {.circles = {{.points = {{.lon = 0.0, .lat = 30.0},
570 {.lon = 10.0, .lat = 30.0}},
572 {.points = {{.lon = 20.0, .lat = 60.0},
573 {.lon = 30.0, .lat = 60.0}},
575 .p = {.lon = 0.0, .lat = 0.0},
576 .q = {.lon = 0.0, .lat = 0.0},
579 {.circles = {{.points = {{.lon = 0.0, .lat = -45.0},
580 {.lon = 10.0, .lat = -45.0}},
582 {.points = {{.lon = 20.0, .lat = 45.0},
583 {.lon = 30.0, .lat = 45.0}},
585 .p = {.lon = 0.0, .lat = 0.0},
586 .q = {.lon = 0.0, .lat = 0.0},
589 {.circles = {{.points = {{.lon = 0.0, .lat = 10.0},
590 {.lon = 10.0, .lat = 10.0}},
592 {.points = {{.lon = 20.0, .lat = 20.0},
593 {.lon = 30.0, .lat = 20.0}},
595 .p = {.lon = 0.0, .lat = 0.0},
596 .q = {.lon = 0.0, .lat = 0.0},
600 {.circles = {{.points = {{.lon = 0.0, .lat = 45.0},
601 {.lon = 10.0, .lat = 45.0}},
603 {.points = {{.lon = 20.0,
604 .lat = 45.0 + 1.0e-7 /
YAC_RAD},
606 .lat = 45.0 + 1.0e-7 /
YAC_RAD}},
608 .p = {.lon = 0.0, .lat = 0.0},
609 .q = {.lon = 0.0, .lat = 0.0},
612 {.circles = {{.points = {{.lon = 0.0, .lat = 45.0},
613 {.lon = 10.0, .lat = 45.0}},
615 {.points = {{.lon = 20.0,
616 .lat = 45.0 + 1.0e-11 /
YAC_RAD},
618 .lat = 45.0 + 1.0e-11 /
YAC_RAD}},
620 .p = {.lon = 0.0, .lat = 0.0},
621 .q = {.lon = 0.0, .lat = 0.0},
623 enum {
NUM_TESTS =
sizeof(test_data) /
sizeof(test_data[0])};
627 for (
int j = 0; j < 2; ++j) {
628 double points_3d[2][3];
629 for (
int k = 0; k < 2; ++k)
631 test_data[i].circles[j].points[k].
lon,
632 test_data[i].circles[j].points[k].
lat, points_3d[k]);
634 points_3d[0], points_3d[1], test_data[i].circles[j].edge_type,
635 1, &test_circles[j]);
637 double ref_p[3], ref_q[3],
p[3], q[3];
638 LLtoXYZ_deg(test_data[i].
p.lon, test_data[i].p.lat, ref_p);
639 LLtoXYZ_deg(test_data[i].q.lon, test_data[i].q.lat, ref_q);
640 for (
int j = 0; j < 2; ++j) {
642 test_circles[j], test_circles[j^1],
p, q) !=
643 test_data[i].ret_value)
644 PUT_ERR(
"error in yac_circle_intersect");
645 if (test_data[i].ret_value > 0)
650 PUT_ERR(
"error in yac_circle_intersect");
658static void utest_check_compare_circles(
struct yac_circle * circle_a,
int a_is_lat,
664 if ((are_identical && (ret_a || ret_b)) ||
666 ((!ret_a || !ret_b) ||
667 (ret_a != - ret_b) ||
668 ((a_is_lat != b_is_lat) &&
669 ((ret_a > ret_b) ^ a_is_lat)))))
670 PUT_ERR(
"error in yac_circle_compare");
int yac_circle_compare(void const *a, void const *b)
int yac_circle_contains_north_pole(struct yac_circle const *circle)
int yac_circle_point_is_inside(double const point[3], struct yac_circle const *circle)
void yac_circle_generate(double const *a, double const *b, enum yac_edge_type type, int edge_ordering, struct yac_circle *circle)
int yac_circle_compare_distances(double const a[3], double const b[3], struct yac_circle const *circle)
int yac_circle_intersect(struct yac_circle a, struct yac_circle b, double p[3], double q[3])
static void LLtoXYZ_deg(double lon, double lat, double p_out[])
static double get_vector_angle(double const a[3], double const b[3])
@ YAC_GREAT_CIRCLE_EDGE
great circle
@ YAC_LAT_CIRCLE_EDGE
latitude circle
@ YAC_LON_CIRCLE_EDGE
longitude circle
struct yac_circle::@8::@10 lat
struct yac_circle::@8::@11 p
struct yac_circle::@8::@9 lon
double(* p)(double lon, double lat)