19#define YAC_EARTH_RADIUS (6371.2290)
21static int utest_compare_area(
double a,
double b);
22static void utest_area(
struct yac_grid_cell cell,
double ref_area,
36 puts (
"----- calculating area -----\n");
54 utest_generate_cell_deg((
double[4]){0.5, 0.0, -0.5, 0.0},
55 (
double[4]){0.0, 0.5, 0.0, -0.5},
gc_edges, 4);
58 printf (
"grid cell area of quad over Equator is %f sqr km\n",
67 utest_generate_cell_deg((
double[3]){0.5, 0.0, -0.5},
68 (
double[3]){0.0, 0.5, 0.0},
gc_edges, 3);
71 printf (
"grid cell area of triangle over Equator is %f sqr km\n",
92 utest_generate_cell_deg((
double[4]){-0.5, 0.5, 0.5, -0.5},
93 (
double[4]){-0.5, -0.5, 0.5, 0.5},
gc_edges, 4);
96 printf (
"grid cell area of quad over Equator is %f sqr km\n",
105 utest_generate_cell_deg((
double[3]){-0.5, 0.5, 0.5},
106 (
double[3]){-0.5, -0.5, 0.5},
gc_edges, 3);
109 printf (
"grid cell area of triangle over Equator is %f sqr km\n",
118 utest_generate_cell_deg((
double[3]){150.0, 180.0, 180.0},
119 (
double[3]){-60.0, -60.0, -90.0},
gc_edges, 3);
122 printf (
"grid cell area of triangle over South Pole is %f sqr km\n",
144 utest_generate_cell_deg((
double[4]){0.0, 90.0, -180.0, -90.0},
145 (
double[4]){89.5, 89.5, 89.5, 89.5},
gc_edges, 4);
148 printf (
"grid cell area of quad over North Pole is %f sqr km\n",
156 utest_generate_cell_deg((
double[4]){-180.0, -150.0, -150.0, -180.0},
157 (
double[4]){60.0, 60.0, 90.0, 90.0},
gc_edges, 4);
160 printf (
"grid cell area of quad near North Pole is %f sqr km\n",
168 utest_generate_cell_deg((
double[4]){-180.0, -150.0, -150.0, -180.0},
169 (
double[4]){-90.0, -90.0, -60.0, -60.0},
gc_edges, 4);
172 printf (
"grid cell area of quad near South Pole is %f sqr km \n",
180 utest_generate_cell_deg((
double[5]){-180.0, -150.0, 0.0, -150.0, -180.0},
181 (
double[5]){60.0, 60.0, 90.0, 90.0, 90.0},
gc_edges, 5);
184 printf (
"grid cell area of quin near North Pole is %f sqr km\n",
194 utest_generate_cell_deg((
double[3]){-0.5, 0.5, -0.5},
195 (
double[3]){-0.5, -0.5, -0.5},
gc_edges, 3);
198 printf (
"grid cell area of triangle over Equator is %f sqr km\n",
201 if ((area < 0.0) || (area > 1e-9))
202 PUT_ERR(
"ERROR in yac_grid_cell_area for zero size triangle");
209 utest_generate_cell_deg((
double[4]){0, 1, 1, 0},
210 (
double[4]){0, 0, 1, 1},
gc_edges, 4);
212 utest_generate_cell_deg((
double[3]){1, 1, 1},
222 double dx[] = {1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1,
223 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9};
225 for (
size_t i = 0;
i <
sizeof(dx) /
sizeof(dx[0]); ++
i) {
229 utest_generate_cell_deg((
double[4]){0, 1.0-dx[
i], 1, 0},
230 (
double[4]){0, 0, 1, 1},
gc_edges, 4);
232 utest_generate_cell_deg((
double[3]){1.0-dx[
i], 1, 1},
241 if (utest_compare_area(base_area, partial_area))
242 PUT_ERR(
"yac_grid_cell_area computed wrong area\n");
244 printf (
"accuracy check for (base_area - partial_area) %8.1e sqr km for dx %.1e\n",
245 base_area - partial_area, dx[i]);
251 utest_generate_cell_deg(
259 PUT_ERR(
"grid cell computed wrong area\n");
261 printf (
"grid cell accuracy check of very small area %.2e sqr km\n",
269 for (
int y = -90;
y <= 90;
y += 5) {
272 utest_generate_cell_deg((
double[2]){0.0, 20.0},
273 (
double[2]){(double)y, (
double)
y},
284 if ((y == -90) || (
y == 90) || (y == 0)) {
321 { 0.0, 0.5, 0.5, 0.0}};
323 { 0.0, 0.0, 0.5, 0.5}};
325 for (
int x = 0;
x < 2; ++
x) {
326 for (
int y = 0;
y < 2; ++
y) {
343 utest_generate_cell_deg((
double[4]){-0.5, 0.5, 0.5, -0.5},
344 (
double[4]){-0.5, -0.5, 0.5, 0.5}, lat_edges, 4);
352 double ref_area = sin(1.0 *
YAC_RAD);
353 ref_area -= sin(0.5 *
YAC_RAD);
357 for (
int i = 0;
i < 2; ++
i) {
361 {-0.5,-0.5,-1.0, -1.0}};
376 double intersections[2][3];
387 double intersections_lon[2], intersections_lat[2];
388 XYZtoLL(intersections[0], &(intersections_lon[0]), &(intersections_lat[0]));
389 XYZtoLL(intersections[1], &(intersections_lon[1]), &(intersections_lat[1]));
393 utest_generate_cell_deg(
394 (
double[]){20.0, intersections_lon[0]/
YAC_RAD,
396 (
double[]){59.0, 60.0, 60.0},
401 double ref_area = 2.0 * partial_area;
404 {utest_generate_cell_deg(
409 -intersections_lon[0]/
YAC_RAD, -20.0},
410 (
double[]){59.0, 60.0, 60.0, 60.0, 60.0, 59.0},
414 utest_generate_cell_deg(
421 (
double[]){59.0, 60.0, 60.0, 59.0, 60.0, 60.0},
426 for (
int i = 0;
i < 2; ++
i) {
437 utest_generate_cell_deg((
double[]){-151.1489316535362661,
438 -151.7087167856307133,
439 -150.6174180645230933},
440 (
double[]){ 10.6333746562670566,
443 utest_generate_cell_deg((
double[]){-152.8132296086113513,
444 -153.8786613849353557,
445 -151.6929566531634066},
446 (
double[]){ 13.4512385235805798,
449 utest_generate_cell_deg((
double[]){-152.8132296086113513,
450 -151.6929566531634066,
451 -150.6265735326831532},
452 (
double[]){ 13.4512385235805798,
455 utest_generate_cell_deg((
double[]){-153.8786613849353557,
456 -151.6929566531634066,
457 -152.7627337461449031},
458 (
double[]){ 11.4650630285209161,
461 utest_generate_cell_deg((
double[]){-151.6929566531634066,
462 -152.7627337461449031,
463 -150.5840076321059371},
464 (
double[]){ 11.5568484830228009,
467 utest_generate_cell_deg((
double[]){-151.6929566531634066,
468 -150.6265735326831532,
469 -149.5139953075027108},
470 (
double[]){ 11.5568484830228009,
473 utest_generate_cell_deg((
double[]){-151.6929566531634066,
474 -149.5139953075027108,
475 -150.5840076321059371},
476 (
double[]){ 11.5568484830228009,
479 size_t num_cells =
sizeof(cells) /
sizeof(cells[0]);
481 struct yac_grid_cell overlap_cells[sizeof(cells) / sizeof(cells[0]) - 1];
488 double area_tol = tgt_area * 1e-8;
489 double diff_area = tgt_area;
494 if (fabs(diff_area) > area_tol)
495 PUT_ERR(
"yac_grid_cell_area is too inaccurate");
504 double ref_area = 0.0;
505 double ref_barycenter[3] = {0.0, 0.0, 0.0};
509 utest_generate_cell_deg(
510 (
double[]){0.0,1.0,1.0, 0.0},
511 (
double[]){0.0,0.0,1.0, 1.0},
gc_edges, 4);
517 enum {NUM_CORNERS = 6};
518 double coordinates_x[NUM_CORNERS] = {0.0, 1.0, 1.0, 0.0, 1.0, 0.0};
519 double coordinates_y[NUM_CORNERS] = {0.0, 0.0, 1.0, 0.0, 1.0, 1.0};
521 for (
size_t i = 0;
i < NUM_CORNERS; ++
i) {
523 double temp_coordinates_x[NUM_CORNERS];
524 double temp_coordinates_y[NUM_CORNERS];
526 for (
size_t j = 0; j < NUM_CORNERS; ++j) {
530 double area = 0.0, barycenter[3] = {0.0, 0.0, 0.0};
532 utest_generate_cell_deg(
533 temp_coordinates_x, temp_coordinates_y,
gc_edges, NUM_CORNERS);
539 PUT_ERR(
"ERROR in yac_grid_cell_area_info (area)");
542 PUT_ERR(
"ERROR in yac_grid_cell_area_info (barycenter)");
545 if ((barycenter[0] != barycenter[0]) ||
546 (barycenter[1] != barycenter[1]) ||
547 (barycenter[2] != barycenter[2]))
548 PUT_ERR(
"ERROR in yac_grid_cell_area_info (barycenter NAN)");
555 for (
int pole = -1; pole <= 1; pole += 2) {
556 for (
int cell_order_a = 0; cell_order_a < 2; ++cell_order_a) {
557 for (
int cell_order_b = 0; cell_order_b < 2; ++cell_order_b) {
561 double lon[2][3] = {{0.0,0.0,20.0}, {20.0, 20.0, 0.0}};
563 utest_generate_cell_deg(
565 (
double[]){copysign(88.0,(
double)pole),
566 copysign(90.0,(
double)pole),
567 copysign(88.0,(
double)pole)},
gc_edges, 3);
569 utest_generate_cell_deg(
571 (
double[]){copysign(88.0,(
double)pole),
572 copysign(90.0,(
double)pole),
573 copysign(88.0,(
double)pole)}, ll_edges, 3);
575 double gc_barycenter[3] = {0.0, 0.0, 0.0};
578 double ll_barycenter[3] = {0.0, 0.0, 0.0};
584 gc_barycenter[0] = -gc_barycenter[0];
585 gc_barycenter[1] = -gc_barycenter[1];
586 gc_barycenter[2] = -gc_barycenter[2];
592 ll_barycenter[0] = -ll_barycenter[0];
593 ll_barycenter[1] = -ll_barycenter[1];
594 ll_barycenter[2] = -ll_barycenter[2];
600 PUT_ERR(
"ERROR in yac_grid_cell_area_info (area)");
604 if (((gc_barycenter[2] - ll_barycenter[2]) * (
double)pole) < 1e-9)
605 PUT_ERR(
"ERROR in yac_grid_cell_area_info (barycenter)");
614static void utest_area(
struct yac_grid_cell cell,
double ref_area,
617 double mem_dummy_[128][3];
620 .edge_type = edge_dummy,
623 for (
int order = -1; order <= 1; order += 2) {
624 for (
int start = 0; start < (int)(cell.
num_corners); ++start) {
635 double area = area_func(test_cell);
637 if (utest_compare_area(area, ref_area))
PUT_ERR(
"ERROR: wrong area\n");
642static int utest_compare_area(
double a,
double b) {
644 double diff = fabs(a - b);
647 if (diff <
tol)
return 0;
648 else return (a > b) - (a < b);
double yac_grid_cell_area(struct yac_grid_cell cell)
Area calculation of a spherical cell.
double yac_grid_cell_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
static void normalise_vector(double v[])
static double get_vector_angle(double const a[3], double const b[3])
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 enum yac_edge_type gc_edges[]
static void XYZtoLL(double const p_in[], double *lon, double *lat)