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);
156 (overlap_barycenters[i][0] != 0.0) ||
157 (overlap_barycenters[i][1] != 0.0) ||
158 (overlap_barycenters[i][2] != 0.0),
159 "ERROR(yac_compute_overlap_info): "
160 "overlap was computed, still barycenter is sphere origin");
162 if (overlap_areas[i] < 0.0) {
163 overlap_areas[i] = -overlap_areas[i];
164 overlap_barycenters[i][0] = -overlap_barycenters[i][0];
165 overlap_barycenters[i][1] = -overlap_barycenters[i][1];
166 overlap_barycenters[i][2] = -overlap_barycenters[i][2];
170 overlap_areas[i] = 0.0;
182 "ERROR(yac_compute_overlap_info): invalid target cell type")
198 for (
size_t n = 0; n < N; n++) overlap_areas[n] = 0.0;
204 for (
size_t corner_idx = 1;
205 corner_idx < target_cell.
num_corners - 1; ++corner_idx ) {
227 for (
size_t n = 0; n < N; n++) {
231 if (overlap_barycenters == NULL)
241 for (
size_t n = 0; n < N; n++) {
243 if (overlap_areas[n] < 0.0) {
245 overlap_areas[n] = -overlap_areas[n];
247 if (overlap_barycenters != NULL) {
248 overlap_barycenters[n][0] = -overlap_barycenters[n][0];
249 overlap_barycenters[n][1] = -overlap_barycenters[n][1];
250 overlap_barycenters[n][2] = -overlap_barycenters[n][2];
255 if (overlap_barycenters != NULL)
256 for (
size_t n = 0; n < N; n++)
257 if ((overlap_areas[n] > 0.0) &&
258 ((overlap_barycenters[n][0] != 0.0) ||
259 (overlap_barycenters[n][1] != 0.0) ||
260 (overlap_barycenters[n][2] != 0.0)))
263#ifdef YAC_VERBOSE_CLIPPING
264 for (
size_t n = 0; n < N; n++)
265 printf(
"overlap area %zu: %lf \n", n, overlap_areas[n]);
587 struct point_list * cell,
size_t num_cell_edges,
588 struct yac_circle ** clipping_circles,
size_t num_clipping_circles) {
592 qsort(clipping_circles, num_clipping_circles,
sizeof(*clipping_circles),
596 for (
size_t i = 0; (i < num_clipping_circles) && (num_cell_edges > 1); ++i) {
601 struct yac_circle * clipping_circle = clipping_circles[i];
603 int start_is_inside, first_start_is_inside;
607 cell_edge_start->
vec_coords, clipping_circle);
608 first_start_is_inside = start_is_inside;
611 for (
size_t cell_edge_idx = 0; cell_edge_idx < num_cell_edges;
615 (cell_edge_idx != num_cell_edges - 1)?
617 cell_edge_end->
vec_coords, clipping_circle)):first_start_is_inside;
619 double * cell_edge_coords[2] =
623 double intersection[2][3];
624 int num_edge_intersections = -1;
634 int one_intersect_expected = (end_is_inside + start_is_inside == 1);
635 int two_intersect_possible =
638 (end_is_inside + start_is_inside != 1) &&
639 (end_is_inside + start_is_inside != 4);
642 if (one_intersect_expected || two_intersect_possible) {
646 int num_circle_intersections =
648 *clipping_circle, *cell_edge_circle,
649 intersection[0], intersection[1]);
652 (num_circle_intersections >= -1) && (num_circle_intersections <= 2),
653 "ERROR(circle_clipping): invalid number of intersections")
657 switch (num_circle_intersections) {
667 num_edge_intersections = 0;
669 one_intersect_expected = 0;
672 if (cell_edge_idx == 0) first_start_is_inside = 2;
680 num_edge_intersections = 0;
693 int is_on_edge[2] = {
695 intersection[0], cell_edge_coords[0], cell_edge_coords[1],
696 cell_edge_circle->
type),
697 (num_circle_intersections == 2)?
699 intersection[1], cell_edge_coords[0], cell_edge_coords[1],
700 cell_edge_circle->
type):0};
703 if (is_on_edge[0] && is_on_edge[1]) {
707 !one_intersect_expected,
708 "ERROR: two intersections found, even "
709 "though no circle of latitude involed and "
710 "both edge vertices on different sides of "
711 "the cutting plane.\n"
712 "cell edge (%lf %lf %lf) (%lf %lf %lf) (edge type %d)\n"
713 "circle (gc: norm_vec %lf %lf %lf\n"
714 " lon: norm_vec %lf %lf %lf\n"
715 " lat: z %lf north_is_out %d\n"
716 " point: vec %lf %lf %lf) (circle type %d)\n"
717 "intersections points (%lf %lf %lf) (%lf %lf %lf)\n",
718 cell_edge_coords[0][0],
719 cell_edge_coords[0][1],
720 cell_edge_coords[0][2],
721 cell_edge_coords[1][0],
722 cell_edge_coords[1][1],
723 cell_edge_coords[1][2], (
int)cell_edge_circle->
type,
734 clipping_circle->
data.
p.
vec[2], (
int)(clipping_circle->
type),
735 intersection[0][0], intersection[0][1], intersection[0][2],
736 intersection[1][0], intersection[1][1], intersection[1][2])
740 if (end_is_inside == start_is_inside) {
745 num_edge_intersections = 1;
755 double temp_intersection[3];
756 temp_intersection[0] = intersection[1][0];
757 temp_intersection[1] = intersection[1][1];
758 temp_intersection[2] = intersection[1][2];
759 intersection[1][0] = intersection[0][0];
760 intersection[1][1] = intersection[0][1];
761 intersection[1][2] = intersection[0][2];
762 intersection[0][0] = temp_intersection[0];
763 intersection[0][1] = temp_intersection[1];
764 intersection[0][2] = temp_intersection[2];
767 num_edge_intersections = 2;
775 double * cell_edge_coord = cell_edge_coords[end_is_inside == 2];
776 double distances[2] = {
785 num_edge_intersections = 0;
789 num_edge_intersections = 1;
792 if (distances[0] < distances[1]) {
793 intersection[0][0] = intersection[1][0];
794 intersection[0][1] = intersection[1][1];
795 intersection[0][2] = intersection[1][2];
800 }
else if (is_on_edge[0] || is_on_edge[1]) {
803 if ((end_is_inside == 2) || (start_is_inside == 2)) {
808 num_edge_intersections = 0;
814 intersection[0][0] = intersection[1][0];
815 intersection[0][1] = intersection[1][1];
816 intersection[0][2] = intersection[1][2];
819 num_edge_intersections = 1;
824 num_edge_intersections = 0;
833 if ((one_intersect_expected) && (num_edge_intersections == 0)) {
836 cell_edge_coords[0], cell_edge_coords[1],
837 clipping_circle) <= 0)
842 one_intersect_expected = 0;
845 if (cell_edge_idx == 0) first_start_is_inside = start_is_inside;
849 num_edge_intersections = 0;
853 num_edge_intersections != -1,
854 "ERROR(circle_clipping): internal error");
865 if (one_intersect_expected) {
871 cell_edge_start->
next = intersect_point;
872 intersect_point->
next = cell_edge_end;
874 intersect_point->
vec_coords[0] = intersection[0][0];
875 intersect_point->
vec_coords[1] = intersection[0][1];
876 intersect_point->
vec_coords[2] = intersection[0][2];
879 (start_is_inside)?clipping_circle:cell_edge_circle;
882 }
else if ((start_is_inside == 2) && (end_is_inside == 2)) {
890 int clipping_circle_contains_north =
892 int same_inside_direction =
893 clipping_circle_contains_north ==
895 int cell_edge_is_on_south_hemisphere =
903 if (same_inside_direction &&
904 (cell_edge_is_on_south_hemisphere ^
905 clipping_circle_contains_north ^
906 clipping_circle_is_lat))
913 }
else if ((num_edge_intersections == 0) && (start_is_inside == 2)) {
916 if (end_is_inside == 0)
921 }
else if (num_edge_intersections == 2) {
928 cell_edge_start->
next = intersect_points[0];
929 intersect_points[0]->
next = intersect_points[1];
930 intersect_points[1]->
next = cell_edge_end;
932 intersect_points[0]->
vec_coords[0] = intersection[0][0];
933 intersect_points[0]->
vec_coords[1] = intersection[0][1];
934 intersect_points[0]->
vec_coords[2] = intersection[0][2];
935 intersect_points[1]->
vec_coords[0] = intersection[1][0];
936 intersect_points[1]->
vec_coords[1] = intersection[1][1];
937 intersect_points[1]->
vec_coords[2] = intersection[1][2];
940 ((start_is_inside == 0) && (end_is_inside == 0)) ||
941 ((start_is_inside == 1) && (end_is_inside == 1)),
942 "ERROR: one cell edge vertex is on the clipping edge, therefore we "
943 "should not have two intersections.")
946 if ((start_is_inside == 0) && (end_is_inside == 0)) {
947 intersect_points[0]->
edge_circle = cell_edge_circle;
948 intersect_points[1]->
edge_circle = clipping_circle;
952 intersect_points[0]->
edge_circle = clipping_circle;
953 intersect_points[1]->
edge_circle = cell_edge_circle;
958 }
else if (two_intersect_possible && (num_edge_intersections == 1)) {
964 (start_is_inside == end_is_inside) ||
965 ((start_is_inside == 2) || (end_is_inside == 2)),
966 "ERROR: unhandled intersection case")
968 switch (
MAX(start_is_inside, end_is_inside)) {
978 cell_edge_start->
next = intersect_point;
979 intersect_point->
next = cell_edge_end;
981 intersect_point->
vec_coords[0] = intersection[0][0];
982 intersect_point->
vec_coords[1] = intersection[0][1];
983 intersect_point->
vec_coords[2] = intersection[0][2];
999 cell_edge_start->
next = intersect_point;
1000 intersect_point->
next = cell_edge_end;
1002 intersect_point->
vec_coords[0] = intersection[0][0];
1003 intersect_point->
vec_coords[1] = intersection[0][1];
1004 intersect_point->
vec_coords[2] = intersection[0][2];
1007 if (start_is_inside == 2) {
1009 if (end_is_inside == 0) {
1019 if (start_is_inside == 0) {
1031 cell_edge_start = cell_edge_end;
1032 cell_edge_end = cell_edge_end->
next;
1033 start_is_inside = end_is_inside;
1198 struct yac_grid_cell * cell,
double z_upper_bound,
double z_lower_bound,
1204 int upper_idx[2], lower_idx[2];
1206 if (cell_upper_bound < cell_lower_bound) {
1207 double temp = cell_upper_bound;
1208 cell_upper_bound = cell_lower_bound;
1209 cell_lower_bound = temp;
1237 if ((z_upper_bound == z_lower_bound) ||
1238 (cell_upper_bound <= z_lower_bound) ||
1239 (cell_lower_bound >= z_upper_bound)) {
1261 if (fabs(cell_lower_bound) < fabs(cell_upper_bound)) {
1278 if ((z_upper_bound < cell_upper_bound) &&
1279 (z_upper_bound > cell_lower_bound)) {
1281 double scale = sqrt((1.0 - z_upper_bound * z_upper_bound) / tmp_scale);
1292 if ((z_lower_bound < cell_upper_bound) &&
1293 (z_lower_bound > cell_lower_bound)) {
1295 double scale = sqrt((1.0 - z_lower_bound * z_lower_bound) / tmp_scale);
1329 double lat_bounds[2],
1332 double z_bounds[2] = {sin(lat_bounds[0]), sin(lat_bounds[1])};
1333 int upper_bound_idx = lat_bounds[0] < lat_bounds[1];
1334 int lower_bound_idx = upper_bound_idx ^ 1;
1335 int is_pole[2] = {fabs(fabs(lat_bounds[0]) - M_PI_2) <
yac_angle_tol,
1337 int upper_is_north_pole =
1338 is_pole[upper_bound_idx] && (lat_bounds[upper_bound_idx] > 0.0);
1339 int lower_is_south_pole =
1340 is_pole[lower_bound_idx] && (lat_bounds[lower_bound_idx] < 0.0);
1345 if ((fabs(lat_bounds[0] - lat_bounds[1]) <
yac_angle_tol) ||
1346 (is_pole[upper_bound_idx] ^ upper_is_north_pole) ||
1347 (is_pole[lower_bound_idx] ^ lower_is_south_pole)) {
1349 for (
size_t n = 0; n < N; ++n)
1350 overlap_buffer[n].num_corners = 0;
1356 {&(lat_circle_buffer[0]), &(lat_circle_buffer[1])};
1357 size_t num_lat_circles = 0;
1358 if (!lower_is_south_pole)
1359 lat_circle_buffer[num_lat_circles++] =
1361 if (!upper_is_north_pole)
1362 lat_circle_buffer[num_lat_circles++] =
1365 size_t max_num_cell_corners = 0;
1366 for (
size_t n = 0; n < N; ++n)
1367 if (cells[n].num_corners > max_num_cell_corners)
1368 max_num_cell_corners = cells[n].num_corners;
1370 xmalloc(max_num_cell_corners *
sizeof(*circle_buffer));
1376 for (
size_t n = 0; n < N; n++) {
1378 if (cells[n].num_corners < 2)
continue;
1386 "invalid source cell type (cell contains edges consisting "
1387 "of great circles and circles of latitude)\n")
1392 cells + n, z_bounds[upper_bound_idx], z_bounds[lower_bound_idx],
1393 overlap_buffer + n);
1400 size_t num_corners =
1402 &cell_list, cells[n], cell_ordering, circle_buffer);
1407 (
double[3]){0.0, 0.0, pole}, cells[n])) {
1414 double z_bound = z_bounds[upper_bound_idx ^ upper_is_north_pole];
1416 for (
size_t i = 0; i < num_corners; ++i) {
1417 flag |= (z_bound < cells[n].coordinates_xyz[i][2]);
1421 double z_bound = z_bounds[lower_bound_idx ^ lower_is_south_pole];
1423 for (
size_t i = 0; i < num_corners; ++i) {
1424 flag |= (z_bound > cells[n].coordinates_xyz[i][2]);
1430 "ERROR(yac_cell_lat_clipping): Latitude bounds are within a cell "
1431 "covering a pole, this is not supported. Increased grid resolution "
1432 "or widen lat bounds may help.")
1435 circle_clipping(&cell_list, num_corners, lat_circles, num_lat_circles);
1441 free(circle_buffer);