112 double * overlap_areas,
113 double (*overlap_barycenters)[3]) {
117 "ERROR(yac_compute_overlap_info): "
118 "target cell has too few corners")
124 if (overlap_barycenters != NULL)
125 for (
size_t i = 0; i < N; ++i)
126 for (
int j = 0; j < 3; ++j)
127 overlap_barycenters[i][j] = 0.0;
137 for (
size_t i = 0; i < N; ++i) {
139 if (overlap_barycenters == NULL)
144 overlap_buffer[i], overlap_barycenters[i], 1.0);
145 if ((overlap_barycenters[i][0] != 0.0) ||
146 (overlap_barycenters[i][1] != 0.0) ||
147 (overlap_barycenters[i][2] != 0.0))
149 if (overlap_areas[i] < 0.0) {
150 overlap_areas[i] = -overlap_areas[i];
151 overlap_barycenters[i][0] = -overlap_barycenters[i][0];
152 overlap_barycenters[i][1] = -overlap_barycenters[i][1];
153 overlap_barycenters[i][2] = -overlap_barycenters[i][2];
157 overlap_areas[i] = 0.0;
169 "ERROR(yac_compute_overlap_info): invalid target cell type")
185 for (
size_t n = 0; n < N; n++) overlap_areas[n] = 0.0;
191 for (
size_t corner_idx = 1;
192 corner_idx < target_cell.
num_corners - 1; ++corner_idx ) {
214 for (
size_t n = 0; n < N; n++) {
218 if (overlap_barycenters == NULL)
228 for (
size_t n = 0; n < N; n++) {
230 if (overlap_areas[n] < 0.0) {
232 overlap_areas[n] = -overlap_areas[n];
234 if (overlap_barycenters != NULL) {
235 overlap_barycenters[n][0] = -overlap_barycenters[n][0];
236 overlap_barycenters[n][1] = -overlap_barycenters[n][1];
237 overlap_barycenters[n][2] = -overlap_barycenters[n][2];
242 if (overlap_barycenters != NULL)
243 for (
size_t n = 0; n < N; n++)
244 if ((overlap_areas[n] > 0.0) &&
245 ((overlap_barycenters[n][0] != 0.0) ||
246 (overlap_barycenters[n][1] != 0.0) ||
247 (overlap_barycenters[n][2] != 0.0)))
250#ifdef YAC_VERBOSE_CLIPPING
251 for (
size_t n = 0; n < N; n++)
252 printf(
"overlap area %zu: %lf \n", n, overlap_areas[n]);
575 struct point_list * cell,
size_t num_cell_edges,
576 struct yac_circle ** clipping_circles,
size_t num_clipping_circles) {
580 qsort(clipping_circles, num_clipping_circles,
sizeof(*clipping_circles),
584 for (
size_t i = 0; (i < num_clipping_circles) && (num_cell_edges > 1); ++i) {
589 struct yac_circle * clipping_circle = clipping_circles[i];
591 int start_is_inside, first_start_is_inside;
595 cell_edge_start->
vec_coords, clipping_circle);
596 first_start_is_inside = start_is_inside;
599 for (
size_t cell_edge_idx = 0; cell_edge_idx < num_cell_edges;
603 (cell_edge_idx != num_cell_edges - 1)?
605 cell_edge_end->
vec_coords, clipping_circle)):first_start_is_inside;
607 double * cell_edge_coords[2] =
611 double intersection[2][3];
612 int num_edge_intersections = -1;
622 int one_intersect_expected = (end_is_inside + start_is_inside == 1);
623 int two_intersect_possible =
626 (end_is_inside + start_is_inside != 1) &&
627 (end_is_inside + start_is_inside != 4);
630 if (one_intersect_expected || two_intersect_possible) {
634 int num_circle_intersections =
636 *clipping_circle, *cell_edge_circle,
637 intersection[0], intersection[1]);
640 (num_circle_intersections >= -1) && (num_circle_intersections <= 2),
641 "ERROR(circle_clipping): invalid number of intersections")
645 switch (num_circle_intersections) {
655 num_edge_intersections = 0;
657 one_intersect_expected = 0;
660 if (cell_edge_idx == 0) first_start_is_inside = 2;
668 num_edge_intersections = 0;
681 int is_on_edge[2] = {
683 intersection[0], cell_edge_coords[0], cell_edge_coords[1],
684 cell_edge_circle->
type),
685 (num_circle_intersections == 2)?
687 intersection[1], cell_edge_coords[0], cell_edge_coords[1],
688 cell_edge_circle->
type):0};
691 if (is_on_edge[0] && is_on_edge[1]) {
695 !one_intersect_expected,
696 "ERROR: two intersections found, even "
697 "though no circle of latitude involed and "
698 "both edge vertices on different sides of "
699 "the cutting plane.\n"
700 "cell edge (%lf %lf %lf) (%lf %lf %lf) (edge type %d)\n"
701 "circle (gc: norm_vec %lf %lf %lf\n"
702 " lon: norm_vec %lf %lf %lf\n"
703 " lat: z %lf north_is_out %d\n"
704 " point: vec %lf %lf %lf) (circle type %d)\n"
705 "intersections points (%lf %lf %lf) (%lf %lf %lf)\n",
706 cell_edge_coords[0][0],
707 cell_edge_coords[0][1],
708 cell_edge_coords[0][2],
709 cell_edge_coords[1][0],
710 cell_edge_coords[1][1],
711 cell_edge_coords[1][2], (
int)cell_edge_circle->
type,
722 clipping_circle->
data.
p.
vec[2], (
int)(clipping_circle->
type),
723 intersection[0][0], intersection[0][1], intersection[0][2],
724 intersection[1][0], intersection[1][1], intersection[1][2])
728 if (end_is_inside == start_is_inside) {
733 num_edge_intersections = 1;
743 double temp_intersection[3];
744 temp_intersection[0] = intersection[1][0];
745 temp_intersection[1] = intersection[1][1];
746 temp_intersection[2] = intersection[1][2];
747 intersection[1][0] = intersection[0][0];
748 intersection[1][1] = intersection[0][1];
749 intersection[1][2] = intersection[0][2];
750 intersection[0][0] = temp_intersection[0];
751 intersection[0][1] = temp_intersection[1];
752 intersection[0][2] = temp_intersection[2];
755 num_edge_intersections = 2;
763 double * cell_edge_coord = cell_edge_coords[end_is_inside == 2];
764 double distances[2] = {
773 num_edge_intersections = 0;
777 num_edge_intersections = 1;
780 if (distances[0] < distances[1]) {
781 intersection[0][0] = intersection[1][0];
782 intersection[0][1] = intersection[1][1];
783 intersection[0][2] = intersection[1][2];
788 }
else if (is_on_edge[0] || is_on_edge[1]) {
791 if ((end_is_inside == 2) || (start_is_inside == 2)) {
796 num_edge_intersections = 0;
802 intersection[0][0] = intersection[1][0];
803 intersection[0][1] = intersection[1][1];
804 intersection[0][2] = intersection[1][2];
807 num_edge_intersections = 1;
812 num_edge_intersections = 0;
821 if ((one_intersect_expected) && (num_edge_intersections == 0)) {
824 cell_edge_coords[0], cell_edge_coords[1],
825 clipping_circle) <= 0)
830 one_intersect_expected = 0;
833 if (cell_edge_idx == 0) first_start_is_inside = start_is_inside;
837 num_edge_intersections = 0;
841 num_edge_intersections != -1,
842 "ERROR(circle_clipping): internal error");
853 if (one_intersect_expected) {
859 cell_edge_start->
next = intersect_point;
860 intersect_point->
next = cell_edge_end;
862 intersect_point->
vec_coords[0] = intersection[0][0];
863 intersect_point->
vec_coords[1] = intersection[0][1];
864 intersect_point->
vec_coords[2] = intersection[0][2];
867 (start_is_inside)?clipping_circle:cell_edge_circle;
870 }
else if ((start_is_inside == 2) && (end_is_inside == 2)) {
878 int clipping_circle_contains_north =
880 int same_inside_direction =
881 clipping_circle_contains_north ==
883 int cell_edge_is_on_south_hemisphere =
891 if (same_inside_direction &&
892 (cell_edge_is_on_south_hemisphere ^
893 clipping_circle_contains_north ^
894 clipping_circle_is_lat))
901 }
else if ((num_edge_intersections == 0) && (start_is_inside == 2)) {
904 if (end_is_inside == 0)
909 }
else if (num_edge_intersections == 2) {
916 cell_edge_start->
next = intersect_points[0];
917 intersect_points[0]->
next = intersect_points[1];
918 intersect_points[1]->
next = cell_edge_end;
920 intersect_points[0]->
vec_coords[0] = intersection[0][0];
921 intersect_points[0]->
vec_coords[1] = intersection[0][1];
922 intersect_points[0]->
vec_coords[2] = intersection[0][2];
923 intersect_points[1]->
vec_coords[0] = intersection[1][0];
924 intersect_points[1]->
vec_coords[1] = intersection[1][1];
925 intersect_points[1]->
vec_coords[2] = intersection[1][2];
928 ((start_is_inside == 0) && (end_is_inside == 0)) ||
929 ((start_is_inside == 1) && (end_is_inside == 1)),
930 "ERROR: one cell edge vertex is on the clipping edge, therefore we "
931 "should not have two intersections.")
934 if ((start_is_inside == 0) && (end_is_inside == 0)) {
935 intersect_points[0]->
edge_circle = cell_edge_circle;
936 intersect_points[1]->
edge_circle = clipping_circle;
940 intersect_points[0]->
edge_circle = clipping_circle;
941 intersect_points[1]->
edge_circle = cell_edge_circle;
946 }
else if (two_intersect_possible && (num_edge_intersections == 1)) {
952 (start_is_inside == end_is_inside) ||
953 ((start_is_inside == 2) || (end_is_inside == 2)),
954 "ERROR: unhandled intersection case")
956 switch (
MAX(start_is_inside, end_is_inside)) {
966 cell_edge_start->
next = intersect_point;
967 intersect_point->
next = cell_edge_end;
969 intersect_point->
vec_coords[0] = intersection[0][0];
970 intersect_point->
vec_coords[1] = intersection[0][1];
971 intersect_point->
vec_coords[2] = intersection[0][2];
987 cell_edge_start->
next = intersect_point;
988 intersect_point->
next = cell_edge_end;
990 intersect_point->
vec_coords[0] = intersection[0][0];
991 intersect_point->
vec_coords[1] = intersection[0][1];
992 intersect_point->
vec_coords[2] = intersection[0][2];
995 if (start_is_inside == 2) {
997 if (end_is_inside == 0) {
1007 if (start_is_inside == 0) {
1019 cell_edge_start = cell_edge_end;
1020 cell_edge_end = cell_edge_end->
next;
1021 start_is_inside = end_is_inside;
1186 struct yac_grid_cell * cell,
double z_upper_bound,
double z_lower_bound,
1192 int upper_idx[2], lower_idx[2];
1194 if (cell_upper_bound < cell_lower_bound) {
1195 double temp = cell_upper_bound;
1196 cell_upper_bound = cell_lower_bound;
1197 cell_lower_bound = temp;
1225 if ((z_upper_bound == z_lower_bound) ||
1226 (cell_upper_bound <= z_lower_bound) ||
1227 (cell_lower_bound >= z_upper_bound)) {
1249 if (fabs(cell_lower_bound) < fabs(cell_upper_bound)) {
1266 if ((z_upper_bound < cell_upper_bound) &&
1267 (z_upper_bound > cell_lower_bound)) {
1269 double scale = sqrt((1.0 - z_upper_bound * z_upper_bound) / tmp_scale);
1280 if ((z_lower_bound < cell_upper_bound) &&
1281 (z_lower_bound > cell_lower_bound)) {
1283 double scale = sqrt((1.0 - z_lower_bound * z_lower_bound) / tmp_scale);
1317 double lat_bounds[2],
1320 double z_bounds[2] = {sin(lat_bounds[0]), sin(lat_bounds[1])};
1321 int upper_bound_idx = lat_bounds[0] < lat_bounds[1];
1322 int lower_bound_idx = upper_bound_idx ^ 1;
1323 int is_pole[2] = {fabs(fabs(lat_bounds[0]) - M_PI_2) <
yac_angle_tol,
1325 int upper_is_north_pole =
1326 is_pole[upper_bound_idx] && (lat_bounds[upper_bound_idx] > 0.0);
1327 int lower_is_south_pole =
1328 is_pole[lower_bound_idx] && (lat_bounds[lower_bound_idx] < 0.0);
1333 if ((fabs(lat_bounds[0] - lat_bounds[1]) <
yac_angle_tol) ||
1334 (is_pole[upper_bound_idx] ^ upper_is_north_pole) ||
1335 (is_pole[lower_bound_idx] ^ lower_is_south_pole)) {
1337 for (
size_t n = 0; n < N; ++n)
1338 overlap_buffer[n].num_corners = 0;
1344 {&(lat_circle_buffer[0]), &(lat_circle_buffer[1])};
1345 size_t num_lat_circles = 0;
1346 if (!lower_is_south_pole)
1347 lat_circle_buffer[num_lat_circles++] =
1349 if (!upper_is_north_pole)
1350 lat_circle_buffer[num_lat_circles++] =
1353 size_t max_num_cell_corners = 0;
1354 for (
size_t n = 0; n < N; ++n)
1355 if (cells[n].num_corners > max_num_cell_corners)
1356 max_num_cell_corners = cells[n].num_corners;
1358 xmalloc(max_num_cell_corners *
sizeof(*circle_buffer));
1364 for (
size_t n = 0; n < N; n++) {
1366 if (cells[n].num_corners < 2)
continue;
1374 "invalid source cell type (cell contains edges consisting "
1375 "of great circles and circles of latitude)\n")
1380 cells + n, z_bounds[upper_bound_idx], z_bounds[lower_bound_idx],
1381 overlap_buffer + n);
1388 size_t num_corners =
1390 &cell_list, cells[n], cell_ordering, circle_buffer);
1395 (
double[3]){0.0, 0.0, pole}, cells[n])) {
1402 double z_bound = z_bounds[upper_bound_idx ^ upper_is_north_pole];
1404 for (
size_t i = 0; i < num_corners; ++i) {
1405 flag |= (z_bound < cells[n].coordinates_xyz[i][2]);
1409 double z_bound = z_bounds[lower_bound_idx ^ lower_is_south_pole];
1411 for (
size_t i = 0; i < num_corners; ++i) {
1412 flag |= (z_bound > cells[n].coordinates_xyz[i][2]);
1418 "ERROR(yac_cell_lat_clipping): Latitude bounds are within a cell "
1419 "covering a pole, this is not supported. Increased grid resolution "
1420 "or widen lat bounds may help.")
1423 circle_clipping(&cell_list, num_corners, lat_circles, num_lat_circles);
1429 free(circle_buffer);