This contains some examples on how to use the yac_cell_lat_clipping routine.
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "tests.h"
#include "test_common.h"
double deg_lat_bounds[2],
unsigned num_ref_cells);
static double get_intersection(
double intersection[3], intersection_lon, intersection_lat;
points[1][0], lat, intersection))
exit(EXIT_FAILURE);
XYZtoLL(intersection, &intersection_lon, &intersection_lat);
}
double temp_lon[16];
test_lat_clipping(
generate_cell_deg(
(double[4]){-5,5,5,-5},
(double[4]){-5,-5,5,5}, latlon_edges, 4),
(double[2]){10, 20}, NULL, 0);
test_lat_clipping(
generate_cell_deg(
(double[4]){-5,5,5,-5},
(double[4]){-5,-5,10,10}, latlon_edges, 4),
(double[2]){10, 20}, NULL, 0);
test_lat_clipping(
generate_cell_deg(
(double[4]){-5,5,5,-5},
(double[4]){20,20,30,30}, latlon_edges, 4),
(double[2]){10, 20}, NULL, 0);
test_lat_clipping(
generate_cell_deg(
(double[4]){-5,5,5,-5},
(double[4]){80,80,90,90}, latlon_edges, 4),
(double[2]){10, 20}, NULL, 0);
test_lat_clipping(
generate_cell_deg(
(double[4]){-5,5,5,-5},
(double[4]){-80,-80,-90,-90}, latlon_edges, 4),
(double[2]){10, 20}, NULL, 0);
test_lat_clipping(
generate_cell_deg(
(double[4]){-5,5,5,-5},
(double[4]){10,10,20,20}, latlon_edges, 4),
(double[2]){80, 90}, NULL, 0);
test_lat_clipping(
generate_cell_deg(
(double[4]){-5,5,5,-5},
(double[4]){10,10,20,20}, latlon_edges, 4),
(double[2]){0, 0}, NULL, 0);
test_lat_clipping(
generate_cell_deg(
(double[4]){-5,5,5,-5},
(double[4]){-10,-10,-20,-20}, latlon_edges, 4),
(double[2]){0, 0}, NULL, 0);
test_lat_clipping(
generate_cell_deg(
(double[4]){-5,5,5,-5},
(double[4]){-5,-5,5,5}, latlon_edges, 4),
(double[2]){0, 0}, NULL, 0);
test_lat_clipping(
generate_cell_deg(
(double[4]){-5,5,5,-5},
(double[4]){-10,-10,10,10}, latlon_edges, 4),
(double[2]){-5, 5},
generate_cell_deg(
(double[4]){-5,5,5,-5},
(double[4]){-5,-5,5,5}, latlon_edges, 4)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){10,10,20,20}, latlon_edges, 4),
(double[2]){12, 15},
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){12,12,15,15}, latlon_edges, 4)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){10,10,20,20}, latlon_edges, 4),
(double[2]){15, 25},
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){15,15,20,20}, latlon_edges, 4)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){10,10,20,20}, latlon_edges, 4),
(double[2]){15, 5},
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){15,15,10,10}, latlon_edges, 4)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){10,10,20,20}, latlon_edges, 4),
(double[2]){5, 25},
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){10,10,20,20}, latlon_edges, 4)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){10,10,20,20}, latlon_edges, 4),
(double[2]){90, 80}, NULL, 0);
test_lat_clipping(
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){90,90,70,70}, latlon_edges, 4),
(double[2]){90, 80},
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){90,90,80,80}, latlon_edges, 4)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){90,90,85,85}, latlon_edges, 4),
(double[2]){90, 80},
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){90,90,85,85}, latlon_edges, 4)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){88,88,83,83}, latlon_edges, 4),
(double[2]){90, 80},
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){88,88,83,83}, latlon_edges, 4)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){88,88,83,83}, latlon_edges, 4),
(double[2]){90, 80},
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){88,88,83,83}, latlon_edges, 4)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){88,88,70,70}, latlon_edges, 4),
(double[2]){90, 80},
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){88,88,80,80}, latlon_edges, 4)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){10,10,20,20}, latlon_edges, 4),
(double[2]){-90, -80}, NULL, 0);
test_lat_clipping(
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){-90,-90,-70,-70}, latlon_edges, 4),
(double[2]){-90, -80},
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){-90,-90,-80,-80}, latlon_edges, 4)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){-90,-90,-85,-85}, latlon_edges, 4),
(double[2]){-90, -80},
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){-90,-90,-85,-85}, latlon_edges, 4)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){-88,-88,-83,-83}, latlon_edges, 4),
(double[2]){-90, -80},
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){-88,-88,-83,-83}, latlon_edges, 4)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){-88,-88,-83,-83}, latlon_edges, 4),
(double[2]){-90, -80},
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){-88,-88,-83,-83}, latlon_edges, 4)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){-88,-88,-70,-70}, latlon_edges, 4),
(double[2]){-90, -80},
generate_cell_deg(
(double[4]){40,45,45,40},
(double[4]){-88,-88,-80,-80}, latlon_edges, 4)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[4]){0,5,5,0},
(double[4]){90,90,85,85}, latlon_edges, 4),
(double[2]){89.9, 80},
generate_cell_deg(
(double[4]){0,5,5,0},
(double[4]){89.9,89.9,85,85}, latlon_edges, 4)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[3]){10,20,15},
(double[3]){30,30,40}, gc_edges, 3),
(double[2]){35, 50},
generate_cell_deg(
(double[]){15,
get_intersection(
(double[2][2]){{15, 40}, {10, 30}}, 35),
get_intersection(
(double[2][2]){{15, 40}, {20, 30}}, 35)},
(double[]){40,35,35},
test_lat_clipping(
generate_cell_deg(
(double[3]){10,20,15},
(double[3]){30,30,40}, gc_edges, 3),
(double[2]){35, 25},
generate_cell_deg(
(double[]){20, 10,
get_intersection(
(double[2][2]){{15, 40}, {10, 30}}, 35),
get_intersection(
(double[2][2]){{15, 40}, {20, 30}}, 35)},
(double[]){30,30,35,35},
test_lat_clipping(
generate_cell_deg(
(double[]){10,20,15},
(double[]){30,30,40}, gc_edges, 3),
(double[2]){45, 25},
generate_cell_deg(
(double[]){10,20,15},
(double[]){30,30,40}, gc_edges, 3)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[3]){10,20,15},
(double[3]){30,30,40}, gc_edges, 3),
(double[2]){32, 38},
generate_cell_deg(
(double[]){get_intersection(
(double[2][2]){{15, 40}, {20, 30}}, 32),
get_intersection(
(double[2][2]){{15, 40}, {20, 30}}, 38),
get_intersection(
(double[2][2]){{15, 40}, {10, 30}}, 38),
get_intersection(
(double[2][2]){{15, 40}, {10, 30}}, 32)},
(double[]){32,38,38,32},
test_lat_clipping(
generate_cell_deg(
(double[3]){-20,20,0},
(double[3]){80,80,85}, gc_edges, 3),
(double[2]){80.001, 89},
generate_cell_deg(
(double[]){0,
get_intersection(
(double[2][2]){{0, 85}, {-20, 80}}, 80.001),
-fabs(get_intersection(
(double[2][2]){{-20, 80}, {20, 80}}, 80.001)),
fabs(get_intersection(
(double[2][2]){{-20, 80}, {20, 80}}, 80.001)),
get_intersection(
(double[2][2]){{0, 85}, {20, 80}}, 80.001),},
(double[]){85,80.001,80.001,80.001,80.001},
test_lat_clipping(
generate_cell_deg(
(double[]){10,20,15},
(double[]){82,82,88}, gc_edges, 3),
(double[2]){90, 80},
generate_cell_deg(
(double[]){10,20,15},
(double[]){82,82,88}, gc_edges, 3)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[]){10,20,15},
(double[]){-82,-82,-88}, gc_edges, 3),
(double[2]){90, 80}, NULL, 0);
test_lat_clipping(
generate_cell_deg(
(double[]){10,20,15},
(double[]){-82,-82,-88}, gc_edges, 3),
(double[2]){-90, -80},
generate_cell_deg(
(double[]){10,20,15},
(double[]){-82,-82,-88}, gc_edges, 3)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[]){10,20,15},
(double[]){82,82,88}, gc_edges, 3),
(double[2]){-90, -80}, NULL, 0);
test_lat_clipping(
generate_cell_deg(
(double[]){10,20,15},
(double[]){82,82,88}, gc_edges, 3),
(double[2]){90, 90}, NULL, 0);
test_lat_clipping(
generate_cell_deg(
(double[]){10,20,15},
(double[]){82,82,88}, gc_edges, 3),
(double[2]){-90, -90}, NULL, 0);
test_lat_clipping(
generate_cell_deg(
(double[]){0,120,240},
(double[]){80,80,80}, gc_edges, 3),
(double[2]){90, 70},
generate_cell_deg(
(double[]){0,120,240},
(double[]){80,80,80}, gc_edges, 3)}, 1);
test_lat_clipping(
generate_cell_deg(
(double[]){0,120,240},
(double[]){80,80,80}, gc_edges, 3),
(double[2]){60, 70}, NULL, 0);
temp_lon[0] =
temp_lon[1] =
test_lat_clipping(
generate_cell_deg(
(double[]){0,120,240},
(double[]){85,70,70}, gc_edges, 3),
(double[2]){90, 80},
generate_cell_deg(
(double[]){0,temp_lon[0],temp_lon[1]},
(double[]){85,80,80},
temp_lon[0] =
temp_lon[1] =
temp_lon[1] = (temp_lon[1] < 0)?(temp_lon[1] + 360):(temp_lon[1]);
temp_lon[1] = (temp_lon[1] < 180)?(temp_lon[1]):(360 - temp_lon[1]);
temp_lon[2] = 360 - temp_lon[1];
temp_lon[3] =
test_lat_clipping(
generate_cell_deg(
(double[]){0,120,240},
(double[]){85,70,70}, gc_edges, 3),
(double[2]){90, 72},
generate_cell_deg(
(double[]){0,temp_lon[0],temp_lon[1],temp_lon[2],temp_lon[3]},
(double[]){85,72,72,72,72},
temp_lon[0] =
temp_lon[1] =
test_lat_clipping(
generate_cell_deg(
(double[]){0,120,240},
(double[]){85,70,70}, gc_edges, 3),
(double[2]){80, 65},
generate_cell_deg(
(double[]){temp_lon[0],120,240,temp_lon[1]},
(double[]){80,70,70,80},
temp_lon[0] =
temp_lon[1] =
temp_lon[2] =
temp_lon[3] =
test_lat_clipping(
generate_cell_deg(
(double[]){0,120,240},
(double[]){85,70,70}, gc_edges, 3),
(double[2]){80, 84},
generate_cell_deg(
(double[]){temp_lon[0],temp_lon[1],temp_lon[2],temp_lon[3]},
(double[]){84,80,80,84},
temp_lon[0] =
temp_lon[1] =
temp_lon[2] =
temp_lon[2] = (temp_lon[2] < 0)?(temp_lon[2] + 360):(temp_lon[2]);
temp_lon[2] = (temp_lon[2] < 180)?(temp_lon[2]):(360 - temp_lon[2]);
temp_lon[3] = 360 - temp_lon[2];
temp_lon[4] =
temp_lon[5] =
test_lat_clipping(
generate_cell_deg(
(double[]){0,120,240},
(double[]){85,70,70}, gc_edges, 3),
(double[2]){80, 72},
generate_cell_deg(
(double[]){temp_lon[0],temp_lon[1],temp_lon[2],
temp_lon[3],temp_lon[4],temp_lon[5]},
(double[]){80,72,72,72,72,80},
temp_lon[0] =
temp_lon[1] =
test_lat_clipping(
generate_cell_deg(
(double[]){0,120,240},
(double[]){90,80,80}, gc_edges, 3),
(double[2]){90, 85},
generate_cell_deg(
(double[]){0,temp_lon[0],temp_lon[1]},
(double[]){90,85,85},
temp_lon[0] =
temp_lon[1] =
temp_lon[2] =
temp_lon[3] =
test_lat_clipping(
generate_cell_deg(
(double[]){0,10,10},
(double[]){0,5,-5}, gc_edges, 3),
(double[2]){2.5, -2.5},
generate_cell_deg(
(double[]){0,temp_lon[0],temp_lon[1],temp_lon[2],temp_lon[3]},
(double[]){0,2.5,2.5,-2.5,-2.5},
test_lat_clipping(
generate_cell_deg(
(double[]){0,0,0},
(double[]){-5,0,5}, gc_edges, 3),
(double[2]){2.5, -2.5}, NULL, 0);
return TEST_EXIT_CODE;
}
double const angle_tol = 1e-6;
for (int order = -1; order <= 1; order += 2) {
for (
int start = 0; start < (int)(a.
num_corners); ++start) {
int differences = 0;
int j =
++differences;
++differences;
}
if (!differences) return 0;
}
}
return 1;
}
double deg_lat_bounds[2],
unsigned num_ref_cells) {
double rad_lat_bounds[2] =
double mem_dummy_[128][3];
test_cell =
.edge_type = edge_dummy,
for (int pole = 0; pole < 2; ++pole) {
for (int order = -1; order <= 1; order += 2) {
for (
int start = 0; start < (int)(cell.
num_corners); ++start) {
}
for (int bound_tol_a = -1; bound_tol_a <= 1; ++bound_tol_a) {
for (int bound_tol_b = -1; bound_tol_b <= 1; ++bound_tol_b) {
for (int bound_order = 0; bound_order <= 1; ++bound_order) {
double test_rad_lat_bounds[2] = {
rad_lat_bounds[bound_order] +
rad_lat_bounds[bound_order^1] +
1, &test_cell,test_rad_lat_bounds, &overlap_cell);
if (num_ref_cells == 0) {
if ((overlap_cell.num_corners != 0) &&
PUT_ERR("ERROR: wrong clipping cell\n");
} else {
int match = 0;
for (int i = 0; i < (int)num_ref_cells; ++i)
match |= !compare_cells(overlap_cell, ref_cells[i]);
if (!match)
PUT_ERR("ERROR: wrong clipping cell\n");
}
}
}
}
}
}
rad_lat_bounds[0] *= -1.0, rad_lat_bounds[1] *= -1.0;
for (unsigned i = 0; i < num_ref_cells; ++i)
for (int j = 0; j < (int)(ref_cells[i].num_corners); ++j)
ref_cells[i].coordinates_xyz[j][2] *= -1.0;
}
for (unsigned i = 0; i < num_ref_cells; ++i)
}
double yac_huiliers_area(struct yac_grid_cell cell)
Area calculation on a unit sphere taken from ESMF based on L'Huilier's Theorem.
Structs and interfaces for area calculations.
void yac_cell_lat_clipping(size_t N, struct yac_grid_cell *cells, double lat_bounds[2], struct yac_grid_cell *overlap_buffer)
cell clipping to get the cells describing the intersections
int main(int argc, char **argv)
#define yac_angle_low_tol
static double get_vector_angle(double const a[3], double const b[3])
static void XYZtoLL(double const p_in[], double *lon, double *lat)
void yac_init_grid_cell(struct yac_grid_cell *cell)
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
enum yac_edge_type * edge_type
double(* coordinates_xyz)[3]
static struct user_input_data_points ** points