32static void utest_check_overlap(
33 double * lon_a,
double * lat_a,
enum yac_edge_type * edges_a,
int count_a,
34 double * lon_b,
double * lat_b,
enum yac_edge_type * edges_b,
int count_b,
35 double ref_area,
double const * ref_barycenter);
36static void utest_check_overlap_polygons(
38 double const * ref_barycenter);
69 double ref_barycenter[3] = {0, 0, 0};
71 double intersection[2][3], intersection_lon[2], intersection_lat[2];
80 for (
int i = 0;
i < 2; ++
i) {
81 XYZtoLL(intersection[i], &intersection_lon[i], &intersection_lat[i]);
88 (
double[]){10.5, intersection_lon[0], 10.5, intersection_lon[1]},
89 (
double[]){31.0, intersection_lat[0], 31.5, intersection_lat[1]},
97 (
double[]){10.0, 11.0, 11.5, 10.5, 9.5},
98 (
double[]){32.0, 32.0, 30.0, 31.0, 30.0},
gc_edges, 5,
99 (
double[]){10.5, 11.0, 10.0},
100 (
double[]){31.5, 29.5, 29.5},
gc_edges, 3,
101 ref_area, ref_barycenter);
125 double ref_barycenter[3] = {0, 0, 0};
127 double intersection[2][3], intersection_lon[2], intersection_lat[2];
136 for (
int i = 0;
i < 2; ++
i) {
137 XYZtoLL(intersection[i], &intersection_lon[i], &intersection_lat[i]);
144 (
double[]){-4, 4, intersection_lon[0], intersection_lon[1]},
145 (
double[]){-4, -4, intersection_lat[0], intersection_lat[1]},
gc_edges, 4);
152 (
double[]){-5, 5, 5, -5}, (
double[]){-5, -5, 5, 5},
gc_edges, 4,
153 (
double[]){-4, 4, 0}, (
double[]){-4, -4, 6},
gc_edges, 3,
154 ref_area, ref_barycenter);
180 double ref_area = 0.0;
181 double ref_barycenter[] = {0.0, 0.0, 0.0};
182 for (
int i = 0;
i < 3; ++
i) {
183 double tri_lon[3][3] = {{0,0,90},{90,90,180},{180,180,270}};
184 double tri_lat[3] = {90,89,89};
193 (
double[]){0,0,90,180,270}, (
double[]){90,88,88,88,88},
gc_edges, 5,
194 (
double[]){0,90,180,270}, (
double[]){89,89,89,89},
gc_edges, 4,
195 ref_area, ref_barycenter);
214 double ref_area = 0.0;
215 double * ref_barycenter = NULL;
218 (
double[]){2,3,3,-3,-3,-2,-2,2},
219 (
double[]){3,3,-3,-3,3,3,-2,-2},
gc_edges, 8,
220 (
double[]){1,1,-1,-1},
222 ref_area, ref_barycenter);
243 double ref_area = 0.0;
244 double * ref_barycenter = NULL;
247 (
double[]){0,3,3,-3,-3,0,0,-2,-2,2,2,0},
248 (
double[]){3,3,-3,-3,3,3,2,2,-2,-2,2,2},
gc_edges, 12,
249 (
double[]){1,1,-1,-1}, (
double[]){1,-1,-1,1},
gc_edges, 4,
250 ref_area, ref_barycenter);
274 double ref_barycenter[3] = {0.0, 0.0, 0.0};
278 (
double[]){90,180,90},
279 (
double[]){90,87.5,87.5},
gc_edges, 3);
282 (
double[]){90,180,90},
286 if (ref_area < 0.0) {
287 ref_area = -ref_area;
288 ref_barycenter[0] = -ref_barycenter[0];
289 ref_barycenter[1] = -ref_barycenter[1];
290 ref_barycenter[2] = -ref_barycenter[2];
298 (
double[]){0,90,180,270,270,180,90,0},
299 (
double[]){88,88,88,88,87,87,87,87},
gc_edges, 8,
300 (
double[]){90,180,90},
301 (
double[]){90,87.5,87.5},
gc_edges, 3,
302 ref_area, ref_barycenter);
325 double ref_area = 0.0;
326 double ref_barycenter[3] = {0.0, 0.0, 0.0};
330 (
double[]){90,180,180,90},
331 (
double[]){87.5,87.5,89,89},
gc_edges, 4);
338 (
double[]){315,270,180,90,0,315,
339 315,0,90,180,270,315},
340 (
double[]){89,89,89,89,89,89,
342 (
double[]){90,90,180},
343 (
double[]){90,87.5,87.5},
gc_edges, 3,
344 ref_area, ref_barycenter);
367 for (
int i = 0;
i < 4; ++
i) {
369 double tri_rotation = (double)i * 90.0;
371 double ref_area = 0.0;
372 double ref_barycenter[3] = {0.0, 0.0, 0.0};
376 (
double[]){0+tri_rotation,90+tri_rotation,180+tri_rotation,
377 180+tri_rotation,135+tri_rotation,90+tri_rotation,
378 45+tri_rotation,0+tri_rotation},
379 (
double[]){87.5,87.5,87.5,89,89,89,89,89},
gc_edges, 8);
386 (
double[]){315,270,225,180,135,90,45,0,315,
387 315,0,45,90,135,180,225,270,315},
388 (
double[]){89,89,89,89,89,89,89,89,89,
389 86,86,86,86,86,86,86,86,86},
gc_edges, 18,
390 (
double[]){0+tri_rotation,90+tri_rotation,180+tri_rotation},
391 (
double[]){87.5,87.5,87.5},
gc_edges, 3,
392 ref_area, ref_barycenter);
416 double ref_area = 0.0;
417 double ref_barycenter[3];
421 (
double[]){0,90,180,270},
422 (
double[]){87.5,87.5,87.5,87.5},
gc_edges, 4);
425 (
double[]){0,45,90,135,180,225,270,315},
426 (
double[]){89,89,89,89,89,89,89,89},
gc_edges, 8);
434 (
double[]){315,270,225,180,135,90,45,0,315,
435 315,0,45,90,135,180,225,270,315},
436 (
double[]){89,89,89,89,89,89,89,89,89,
437 86,86,86,86,86,86,86,86,86},
gc_edges, 18,
438 (
double[]){0,90,180,270},
439 (
double[]){87.5,87.5,87.5,87.5},
gc_edges, 4,
440 ref_area, ref_barycenter);
474 double ref_barycenter[3];
478 (
double[]){315,270,225,180,135,90,45,0,315,
479 315,0,45,90,135,180,225,270,315},
480 (
double[]){88,88,88,88,88,88,88,88,88,
481 87,87,87,87,87,87,87,87,87},
gc_edges, 18);
488 (
double[]){135,90,45,0,315,270,225,180,135,
489 135,180,225,270,315,0,45,90,135},
490 (
double[]){88,88,88,88,88,88,88,88,88,
491 86,86,86,86,86,86,86,86,86},
gc_edges, 18,
492 (
double[]){315,270,225,180,135,90,45,0,315,
493 315,0,45,90,135,180,225,270,315},
494 (
double[]){89,89,89,89,89,89,89,89,89,
495 87,87,87,87,87,87,87,87,87},
gc_edges, 18,
496 ref_area, ref_barycenter);
519 double ref_area = 0.0;
520 double ref_barycenter[3] = {0.0, 0.0, 0.0};
523 (
double[]){-5.0,5.0,5.0,-5.0},
525 (
double[]){-5.0,5.0,0.0},
526 (
double[]){0.0,0.0,5.0},
gc_edges, 3,
527 ref_area, ref_barycenter);
534 {{-0.11609962857526578,
536 -0.98472697932740894},
537 {-0.1873171704582404,
539 -0.97350351685504954},
540 {-0.16162842294547278,
541 0.064722709158966607,
542 -0.98472697932740894}},
552 {{-0.10626911810438046,
554 -0.98917650996478101},
555 {-0.10872011017156734,
556 0.098538164069449888,
557 -0.98917650996478101},
558 {-0.12667440386975459,
560 -0.98527764238894122},
561 {-0.12381864923052141,
563 -0.98527764238894122}},
574 double ref_overlap_barycenters[3] = {0.0, 0.0, 0.0};
575 utest_check_overlap_polygons(cells, ref_overlap_areas, ref_overlap_barycenters);
583 {{0.12226322617998441,
584 0.0060064071448744901,
585 0.99247953459870997},
586 {0.12207899817177321,
587 0.0090050879009709785,
588 0.99247953459870997},
589 {0.097751558641606923,
590 0.0072105881536315003,
591 0.99518472667219682},
592 {0.097899074391390048,
593 0.0048094731201957178,
594 0.99518472667219682}},
600 {{ 0.13173419827179747,
601 -0.0024316641355669943,
602 0.99128209305687476},
603 { 0.12602575200455376,
604 0.0081957056315718202,
605 0.99199311501687715},
606 { 0.11521731465958367,
607 0.0019341931455107773,
608 0.99333842636812875},
609 { 0.12147807203778695,
610 -0.0083897691028181811,
611 0.99255865810962707}},
627 double ref_overlap_barycenters[3] = {0.0, 0.0, 0.0};
629 utest_check_overlap_polygons(cells, ref_overlap_areas, ref_overlap_barycenters);
636 {{-0.67635734277981696,
637 -0.34044967630401168,
638 0.65317284295377664},
639 {-0.66779858328675834,
640 -0.35694577933893479,
641 0.65317284295377664},
642 {-0.65346055329338182,
643 -0.34928194263987855,
644 0.67155895484701855},
645 {-0.66183555116521386,
646 -0.33314002067992043,
647 0.67155895484701855}},
653 {{-0.659061024045835,
654 -0.36232186404812883,
655 0.65906102404583489},
656 {-0.66524659712730871,
657 -0.33896007142593126,
658 0.66524659712730871},
659 {-0.64171186251713952,
660 -0.34818611452313608,
661 0.68335372623412638},
662 {-0.63542071129861122,
663 -0.37199386619312252,
664 0.67665433063526625}},
680 double ref_overlap_barycenters[3] = {0.0, 0.0, 0.0};
682 utest_check_overlap_polygons(cells, ref_overlap_areas, ref_overlap_barycenters);
703 double ref_area = 0.0;
704 double ref_barycenter[3];
708 (
double[]){0.0,0.5,2.0,0.5,0.0,-0.5,-2.0,-0.5},
709 (
double[]){2.0,0.5,0.0,-0.5,-2.0,-0.5,0.0,0.5},
gc_edges, 8);
715 (
double[]){0.0,0.5,2.0,0.5,0.0,-0.5,-2.0,-0.5},
716 (
double[]){2.0,0.5,0.0,-0.5,-2.0,-0.5,0.0,0.5},
gc_edges, 8,
717 (
double[]){-3.0,3.0,3.0,-3.0},
718 (
double[]){3.0,3.0,-3.0,-3.0},
gc_edges, 4,
719 ref_area, ref_barycenter);
740 double ref_area = 0.0;
741 double ref_barycenter[3];
745 (
double[]){-0.5,0.5,0.5,-0.5},
746 (
double[]){0.5,0.5,-0.5,-0.5},
gc_edges, 4);
752 (
double[]){0.0,0.5,2.0,0.5,0.0,-0.5,-2.0,-0.5},
753 (
double[]){2.0,0.5,0.0,-0.5,-2.0,-0.5,0.0,0.5},
gc_edges, 8,
754 (
double[]){-0.5,0.5,0.5,-0.5},
755 (
double[]){0.5,0.5,-0.5,-0.5},
gc_edges, 4,
756 ref_area, ref_barycenter);
763 {{5.06731853971386536628e-01,
764 5.06731853971386536628e-01,
765 6.97456562333055085645e-01},
766 {4.56966311668627278575e-01,
767 6.28960169645094047119e-01,
768 6.28960169645094047119e-01},
769 {5.77350269189625842081e-01,
770 5.77350269189625731059e-01,
771 5.77350269189625842081e-01},
772 {6.28960169645094047119e-01,
773 4.56966311668627389597e-01,
774 6.28960169645094047119e-01}},
786 {{5.26518818746262273756e-01,
787 4.92120108892697694092e-01,
788 6.93250122199397744716e-01},
789 {5.28392100138220688343e-01,
790 4.99031313570251600087e-01,
791 6.86854814781020395209e-01},
792 {5.20491669253990818511e-01,
793 4.99252122636297701597e-01,
794 6.92701768642426274347e-01}},
804 double barycenter[3];
806 1, &src_cell, tgt_cell, &areas[0], NULL);
808 1, &src_cell, tgt_cell, &areas[1], &barycenter);
810 if (fabs(areas[0] - areas[1]) > (areas[0] * 1e-6))
811 PUT_ERR(
"error in yac_compute_overlap_info");
835 double lat_edge_middle[3];
836 double gc_edge_middle[3];
837 double overlap_intersections[2][3];
845 overlap_intersections[0]) ||
848 overlap_intersections[1]))
860 double ref_barycenter[3] = {lat_edge_middle[0] + gc_edge_middle[0],
861 lat_edge_middle[1] + gc_edge_middle[1],
862 lat_edge_middle[2] + gc_edge_middle[2]};
866 (
double[]){-5.0,5.0,5.0,-5.0},
868 (
double[]){-5.0,5.0,5.0,-5.0},
869 (
double[]){84.99,84.99,80.0,80.0},
gc_edges, 4,
870 ref_area, ref_barycenter);
879static void utest_check_overlap_polygons(
881 double const * ref_barycenter) {
883 double area_tolerance =
MAX(ref_area * 1e-6, 1e-10);
885 for (
int test_order = 0; test_order < 2; ++test_order) {
887 if (ref_barycenter) {
888 double barycenter[3] = {0.0,0.0,0.0};
890 1, &Polygons[test_order], Polygons[test_order^1],
892 if (fabs(ref_area-area) > area_tolerance)
893 PUT_ERR(
"error in yac_compute_overlap_info "
894 "area difference is too large.\n");
895 if ((barycenter[0] != barycenter[0]) ||
896 (barycenter[1] != barycenter[1]) ||
897 (barycenter[2] != barycenter[2]))
898 PUT_ERR(
"error in yac_compute_overlap_info "
899 "barycenter contains nan's.\n");
900 if ((ref_barycenter[0] != 0.0) ||
901 (ref_barycenter[1] != 0.0) ||
902 (ref_barycenter[2] != 0.0)) {
904 if (fabs(angle_diff) > 1e-9)
905 PUT_ERR(
"error in yac_compute_overlap_info "
906 "barycenter difference is too large.\n");
910 1, &Polygons[test_order], Polygons[test_order^1], &area);
911 if (fabs(ref_area-area) > area_tolerance)
912 PUT_ERR(
"error in yac_compute_overlap_areas "
913 "area difference is too large.\n");
917static void utest_check_overlap(
918 double * lon_a,
double * lat_a,
enum yac_edge_type * edges_a,
int count_a,
919 double * lon_b,
double * lat_b,
enum yac_edge_type * edges_b,
int count_b,
920 double ref_area,
double const * ref_barycenter) {
922 for (
int order_a = -1; order_a <=1; order_a += 2) {
923 for (
int order_b = -1; order_b <=1; order_b += 2) {
924 for (
int start_idx_a = 0; start_idx_a < count_a; ++start_idx_a) {
925 for (
int start_idx_b = 0; start_idx_b < count_b; ++start_idx_b) {
927 double curr_lon_a[count_a], curr_lat_a[count_a];
928 double curr_lon_b[count_b], curr_lat_b[count_b];
932 for (
int i = 0;
i < count_a; ++
i) {
933 int idx = (start_idx_a + order_a *
i + count_a) % count_a;
934 curr_lon_a[
i] = lon_a[idx];
935 curr_lat_a[
i] = lat_a[idx];
936 idx = (idx - (order_a < 0) + count_a) % count_a;
937 curr_edges_a[
i] = edges_a[idx];
939 for (
int i = 0;
i < count_b; ++
i) {
940 int idx = (start_idx_b + order_b *
i + count_b) % count_b;
941 curr_lon_b[
i] = lon_b[idx];
942 curr_lat_b[
i] = lat_b[idx];
943 idx = (idx - (order_b < 0) + count_b) % count_b;
944 curr_edges_b[
i] = edges_b[idx];
951 utest_check_overlap_polygons(Polygons, ref_area, ref_barycenter);
double yac_huiliers_area(struct yac_grid_cell cell)
Area calculation on a unit sphere taken from ESMF based on L'Huilier's Theorem.
double yac_huiliers_area_info(struct yac_grid_cell cell, double *barycenter, double sign)
Structs and interfaces for area calculations.
void yac_cell_clipping(size_t N, struct yac_grid_cell *source_cell, struct yac_grid_cell target_cell, struct yac_grid_cell *overlap_buffer)
cell clipping to get the cells describing the intersections
void yac_compute_overlap_info(size_t N, struct yac_grid_cell *source_cell, struct yac_grid_cell target_cell, double *overlap_areas, double(*overlap_barycenters)[3])
calculates partial areas for all overlapping parts of the source cells with arbitrary target cells,...
void yac_compute_overlap_areas(size_t N, struct yac_grid_cell *source_cell, struct yac_grid_cell target_cell, double *partial_areas)
calculates partial areas for all overlapping parts of the source cells with arbitrary target cells,...
void yac_compute_overlap_buf_free()
static void LLtoXYZ_deg(double lon, double lat, double p_out[])
static void normalise_vector(double v[])
static double get_vector_angle(double const a[3], double const b[3])
void yac_free_grid_cell(struct yac_grid_cell *cell)
@ YAC_GREAT_CIRCLE_EDGE
great circle
@ YAC_LAT_CIRCLE_EDGE
latitude circle
@ YAC_LON_CIRCLE_EDGE
longitude circle
static void XYZtoLL(double const p_in[], double *lon, double *lat)
double(* coordinates_xyz)[3]
struct yac_grid_cell generate_cell_deg(double *lon, double *lat, enum yac_edge_type *edge_type, size_t num_corners)
int intersect(enum yac_edge_type edge_type_a, double lon_a, double lat_a, double lon_b, double lat_b, enum yac_edge_type edge_type_b, double lon_c, double lat_c, double lon_d, double lat_d, double *intersection)
static enum yac_edge_type gc_edges[]
static enum yac_edge_type latlon_edges[4]