122 double * overlap_areas,
123 double (*overlap_barycenters)[3]) {
127 "ERROR(yac_compute_overlap_info): "
128 "target cell has too few corners")
134 if (overlap_barycenters != NULL)
135 for (
size_t i = 0; i <
N; ++i)
136 for (
int j = 0; j < 3; ++j)
137 overlap_barycenters[i][j] = 0.0;
147 for (
size_t i = 0; i <
N; ++i) {
149 if (overlap_barycenters == NULL)
154 overlap_buffer[i], overlap_barycenters[i], 1.0);
155 if (overlap_areas[i] < 0.0) {
156 overlap_areas[i] = -overlap_areas[i];
157 overlap_barycenters[i][0] = -overlap_barycenters[i][0];
158 overlap_barycenters[i][1] = -overlap_barycenters[i][1];
159 overlap_barycenters[i][2] = -overlap_barycenters[i][2];
161 if (overlap_areas[i] > 0.0) {
163 (overlap_barycenters[i][0] != 0.0) ||
164 (overlap_barycenters[i][1] != 0.0) ||
165 (overlap_barycenters[i][2] != 0.0),
166 "ERROR(yac_compute_overlap_info): "
167 "overlap was computed, still barycenter is sphere origin");
172 overlap_areas[i] = 0.0;
184 "ERROR(yac_compute_overlap_info): invalid target cell type")
200 for (
size_t n = 0; n <
N; n++) overlap_areas[n] = 0.0;
206 for (
size_t corner_idx = 1;
207 corner_idx < target_cell.
num_corners - 1; ++corner_idx ) {
229 for (
size_t n = 0; n <
N; n++) {
233 if (overlap_barycenters == NULL)
243 for (
size_t n = 0; n <
N; n++) {
245 if (overlap_areas[n] < 0.0) {
247 overlap_areas[n] = -overlap_areas[n];
249 if (overlap_barycenters != NULL) {
250 overlap_barycenters[n][0] = -overlap_barycenters[n][0];
251 overlap_barycenters[n][1] = -overlap_barycenters[n][1];
252 overlap_barycenters[n][2] = -overlap_barycenters[n][2];
257 if (overlap_barycenters != NULL)
258 for (
size_t n = 0; n <
N; n++)
259 if ((overlap_areas[n] > 0.0) &&
260 ((overlap_barycenters[n][0] != 0.0) ||
261 (overlap_barycenters[n][1] != 0.0) ||
262 (overlap_barycenters[n][2] != 0.0)))
265#ifdef YAC_VERBOSE_CLIPPING
266 for (
size_t n = 0; n <
N; n++)
267 printf(
"overlap area %zu: %lf \n", n, overlap_areas[n]);
589 struct point_list * cell,
size_t num_cell_edges,
590 struct yac_circle ** clipping_circles,
size_t num_clipping_circles) {
594 qsort(clipping_circles, num_clipping_circles,
sizeof(*clipping_circles),
598 for (
size_t i = 0; (i < num_clipping_circles) && (num_cell_edges > 1); ++i) {
603 struct yac_circle * clipping_circle = clipping_circles[i];
605 int start_is_inside, first_start_is_inside;
609 cell_edge_start->
vec_coords, clipping_circle);
610 first_start_is_inside = start_is_inside;
613 for (
size_t cell_edge_idx = 0; cell_edge_idx < num_cell_edges;
617 (cell_edge_idx != num_cell_edges - 1)?
619 cell_edge_end->
vec_coords, clipping_circle)):first_start_is_inside;
621 double * cell_edge_coords[2] =
625 double intersection[2][3];
626 int num_edge_intersections = -1;
636 int one_intersect_expected = (end_is_inside + start_is_inside == 1);
637 int two_intersect_possible =
640 (end_is_inside + start_is_inside != 1) &&
641 (end_is_inside + start_is_inside != 4);
644 if (one_intersect_expected || two_intersect_possible) {
648 int num_circle_intersections =
650 *clipping_circle, *cell_edge_circle,
651 intersection[0], intersection[1]);
655 switch (num_circle_intersections) {
657 "ERROR(circle_clipping): Unexpected number of intersections");
660 YAC_UNREACHABLE(
"Unexpected case: both circles are on the same plane");
679 num_edge_intersections = 0;
691 int is_on_edge[2] = {
693 intersection[0], cell_edge_coords[0], cell_edge_coords[1],
694 cell_edge_circle->
type),
695 (num_circle_intersections == 2)?
697 intersection[1], cell_edge_coords[0], cell_edge_coords[1],
698 cell_edge_circle->
type):0};
701 if (is_on_edge[0] && is_on_edge[1]) {
705 !one_intersect_expected,
706 "ERROR: two intersections found, even "
707 "though no circle of latitude involed and "
708 "both edge vertices on different sides of "
709 "the cutting plane.\n"
710 "cell edge (%lf %lf %lf) (%lf %lf %lf) (edge type %d)\n"
711 "circle (gc: norm_vec %lf %lf %lf\n"
712 " lon: norm_vec %lf %lf %lf\n"
713 " lat: z %lf north_is_out %d\n"
714 " point: vec %lf %lf %lf) (circle type %d)\n"
715 "intersections points (%lf %lf %lf) (%lf %lf %lf)\n",
716 cell_edge_coords[0][0],
717 cell_edge_coords[0][1],
718 cell_edge_coords[0][2],
719 cell_edge_coords[1][0],
720 cell_edge_coords[1][1],
721 cell_edge_coords[1][2], (
int)cell_edge_circle->
type,
732 clipping_circle->
data.
p.
vec[2], (
int)(clipping_circle->
type),
733 intersection[0][0], intersection[0][1], intersection[0][2],
734 intersection[1][0], intersection[1][1], intersection[1][2])
738 if (end_is_inside == start_is_inside) {
743 num_edge_intersections = 1;
753 double temp_intersection[3];
754 temp_intersection[0] = intersection[1][0];
755 temp_intersection[1] = intersection[1][1];
756 temp_intersection[2] = intersection[1][2];
757 intersection[1][0] = intersection[0][0];
758 intersection[1][1] = intersection[0][1];
759 intersection[1][2] = intersection[0][2];
760 intersection[0][0] = temp_intersection[0];
761 intersection[0][1] = temp_intersection[1];
762 intersection[0][2] = temp_intersection[2];
765 num_edge_intersections = 2;
773 double * cell_edge_coord = cell_edge_coords[end_is_inside == 2];
774 double distances[2] = {
783 num_edge_intersections = 0;
787 num_edge_intersections = 1;
790 if (distances[0] < distances[1]) {
791 intersection[0][0] = intersection[1][0];
792 intersection[0][1] = intersection[1][1];
793 intersection[0][2] = intersection[1][2];
798 }
else if (is_on_edge[0] || is_on_edge[1]) {
801 if ((end_is_inside == 2) || (start_is_inside == 2)) {
806 num_edge_intersections = 0;
812 intersection[0][0] = intersection[1][0];
813 intersection[0][1] = intersection[1][1];
814 intersection[0][2] = intersection[1][2];
817 num_edge_intersections = 1;
822 num_edge_intersections = 0;
831 if ((one_intersect_expected) && (num_edge_intersections == 0)) {
834 cell_edge_coords[0], cell_edge_coords[1],
835 clipping_circle) <= 0)
840 one_intersect_expected = 0;
843 if (cell_edge_idx == 0) first_start_is_inside = start_is_inside;
847 num_edge_intersections = 0;
851 num_edge_intersections != -1,
852 "ERROR(circle_clipping): internal error");
863 if (one_intersect_expected) {
869 cell_edge_start->
next = intersect_point;
870 intersect_point->
next = cell_edge_end;
872 intersect_point->
vec_coords[0] = intersection[0][0];
873 intersect_point->
vec_coords[1] = intersection[0][1];
874 intersect_point->
vec_coords[2] = intersection[0][2];
877 (start_is_inside)?clipping_circle:cell_edge_circle;
880 }
else if ((start_is_inside == 2) && (end_is_inside == 2)) {
888 int clipping_circle_contains_north =
890 int same_inside_direction =
891 clipping_circle_contains_north ==
893 int cell_edge_is_on_south_hemisphere =
901 if (same_inside_direction &&
902 (cell_edge_is_on_south_hemisphere ^
903 clipping_circle_contains_north ^
904 clipping_circle_is_lat))
911 }
else if ((num_edge_intersections == 0) && (start_is_inside == 2)) {
914 if (end_is_inside == 0)
919 }
else if (num_edge_intersections == 2) {
926 cell_edge_start->
next = intersect_points[0];
927 intersect_points[0]->
next = intersect_points[1];
928 intersect_points[1]->
next = cell_edge_end;
930 intersect_points[0]->
vec_coords[0] = intersection[0][0];
931 intersect_points[0]->
vec_coords[1] = intersection[0][1];
932 intersect_points[0]->
vec_coords[2] = intersection[0][2];
933 intersect_points[1]->
vec_coords[0] = intersection[1][0];
934 intersect_points[1]->
vec_coords[1] = intersection[1][1];
935 intersect_points[1]->
vec_coords[2] = intersection[1][2];
938 ((start_is_inside == 0) && (end_is_inside == 0)) ||
939 ((start_is_inside == 1) && (end_is_inside == 1)),
940 "ERROR: one cell edge vertex is on the clipping edge, therefore we "
941 "should not have two intersections.")
944 if ((start_is_inside == 0) && (end_is_inside == 0)) {
945 intersect_points[0]->
edge_circle = cell_edge_circle;
946 intersect_points[1]->
edge_circle = clipping_circle;
950 intersect_points[0]->
edge_circle = clipping_circle;
951 intersect_points[1]->
edge_circle = cell_edge_circle;
956 }
else if (two_intersect_possible && (num_edge_intersections == 1)) {
962 (start_is_inside == end_is_inside) ||
963 ((start_is_inside == 2) || (end_is_inside == 2)),
964 "ERROR: unhandled intersection case")
966 switch (
MAX(start_is_inside, end_is_inside)) {
976 cell_edge_start->
next = intersect_point;
977 intersect_point->
next = cell_edge_end;
979 intersect_point->
vec_coords[0] = intersection[0][0];
980 intersect_point->
vec_coords[1] = intersection[0][1];
981 intersect_point->
vec_coords[2] = intersection[0][2];
997 cell_edge_start->
next = intersect_point;
998 intersect_point->
next = cell_edge_end;
1000 intersect_point->
vec_coords[0] = intersection[0][0];
1001 intersect_point->
vec_coords[1] = intersection[0][1];
1002 intersect_point->
vec_coords[2] = intersection[0][2];
1005 if (start_is_inside == 2) {
1007 if (end_is_inside == 0) {
1017 if (start_is_inside == 0) {
1029 cell_edge_start = cell_edge_end;
1030 cell_edge_end = cell_edge_end->
next;
1031 start_is_inside = end_is_inside;
1094 for (
size_t n = 0; n <
N; n++ ) overlap_buffer[n].num_corners = 0;
1102 "invalid target cell type (cell contains edges consisting "
1103 "of great circles and circles of latitude)")
1108 if (!target_ordering) {
1109 for (
size_t n = 0; n <
N; n++ ) overlap_buffer[n].num_corners = 0;
1113 size_t max_num_src_cell_corners = 0;
1114 for (
size_t n = 0; n <
N; ++n)
1115 if (source_cell[n].num_corners > max_num_src_cell_corners)
1116 max_num_src_cell_corners = source_cell[n].
num_corners;
1119 (target_cell.
num_corners + max_num_src_cell_corners) *
1120 sizeof(*circle_buffer));
1129 &target_list, target_cell, target_ordering, circle_buffer);
1136 for (
size_t n = 0; n <
N; n++ ) {
1144 "invalid source cell type (cell contains edges consisting "
1145 "of great circles and circles of latitude)")
1147 if (source_cell[n].num_corners < 2)
continue;
1153 if (!source_ordering)
continue;
1158 &source_list, source_cell[n], source_ordering, src_circle_buffer);
1161 double fabs_tgt_coordinate_z = fabs(target_cell.
coordinates_xyz[0][2]);
1162 double fabs_src_coordinate_z = fabs(source_cell[n].coordinates_xyz[0][2]);
1171 (fabs_tgt_coordinate_z > fabs_src_coordinate_z))) {
1177 overlap = &temp_list;
1183 overlap = &source_list;
1189 free(circle_buffer);
1327 double lat_bounds[2],
1330 double z_bounds[2] = {sin(lat_bounds[0]), sin(lat_bounds[1])};
1331 int upper_bound_idx = lat_bounds[0] < lat_bounds[1];
1332 int lower_bound_idx = upper_bound_idx ^ 1;
1333 int is_pole[2] = {fabs(fabs(lat_bounds[0]) - M_PI_2) <
yac_angle_tol,
1335 int upper_is_north_pole =
1336 is_pole[upper_bound_idx] && (lat_bounds[upper_bound_idx] > 0.0);
1337 int lower_is_south_pole =
1338 is_pole[lower_bound_idx] && (lat_bounds[lower_bound_idx] < 0.0);
1343 if ((fabs(lat_bounds[0] - lat_bounds[1]) <
yac_angle_tol) ||
1344 (is_pole[upper_bound_idx] ^ upper_is_north_pole) ||
1345 (is_pole[lower_bound_idx] ^ lower_is_south_pole)) {
1347 for (
size_t n = 0; n <
N; ++n)
1348 overlap_buffer[n].num_corners = 0;
1354 {&(lat_circle_buffer[0]), &(lat_circle_buffer[1])};
1355 size_t num_lat_circles = 0;
1356 if (!lower_is_south_pole)
1357 lat_circle_buffer[num_lat_circles++] =
1359 if (!upper_is_north_pole)
1360 lat_circle_buffer[num_lat_circles++] =
1363 size_t max_num_cell_corners = 0;
1364 for (
size_t n = 0; n <
N; ++n)
1365 if (cells[n].num_corners > max_num_cell_corners)
1368 xmalloc(max_num_cell_corners *
sizeof(*circle_buffer));
1374 for (
size_t n = 0; n <
N; n++) {
1376 if (cells[n].num_corners < 2)
continue;
1384 "invalid source cell type (cell contains edges consisting "
1385 "of great circles and circles of latitude)\n")
1390 cells + n, z_bounds[upper_bound_idx], z_bounds[lower_bound_idx],
1391 overlap_buffer + n);
1398 size_t num_corners =
1400 &cell_list, cells[n], cell_ordering, circle_buffer);
1405 (
double[3]){0.0, 0.0, pole}, cells[n])) {
1412 double z_bound = z_bounds[upper_bound_idx ^ upper_is_north_pole];
1414 for (
size_t i = 0; i < num_corners; ++i) {
1419 double z_bound = z_bounds[lower_bound_idx ^ lower_is_south_pole];
1421 for (
size_t i = 0; i < num_corners; ++i) {
1428 "ERROR(yac_cell_lat_clipping): Latitude bounds are within a cell "
1429 "covering a pole, this is not supported. Increased grid resolution "
1430 "or widen lat bounds may help.")
1433 circle_clipping(&cell_list, num_corners, lat_circles, num_lat_circles);
1439 free(circle_buffer);