YAC 3.7.0
Yet Another Coupler
Loading...
Searching...
No Matches
geometry.h
Go to the documentation of this file.
1// Copyright (c) 2024 The YAC Authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
13#ifndef GEOMETRY_H
14#define GEOMETRY_H
15
16#ifdef HAVE_CONFIG_H
17// We include 'config.h' in this header file (which is a bad practice)
18// because we need the definition of the 'restrict' keyword for the
19// inlined functions.
20#include "config.h"
21#endif
22
23#include <math.h>
24#include <float.h>
25
26#include "basic_grid.h"
27#include "grid_cell.h"
28#include "utils_core.h"
29
30#define YAC_RAD (0.01745329251994329576923690768489) // M_PI / 180
31
32// angle tolerance
33
34#define yac_angle_tol (1e-9)
35#define yac_sq_angle_tol (1e-9 * 1e-9)
36#define yac_cos_angle_tol (0.9999999999999999995)
37#define yac_angle_low_tol (1e-11)
38#define yac_cos_angle_low_tol (1.0)
39
41 double sin, cos;
42};
43
44static const struct sin_cos_angle SIN_COS_ZERO = {0.0, 1.0};
47
48static const struct sin_cos_angle SIN_COS_M_PI_2 = {1.0, 0.0}; /* PI/2 */
49static const struct sin_cos_angle SIN_COS_M_PI = {0.0, -1.0}; /* PI */
50static const struct sin_cos_angle SIN_COS_7_M_PI_4 = {-0.707106781186547524401, +0.707106781186547524401}; /* (7 * PI)/4 */
51
56
59 double base_vector[3];
64 double sq_crd; // sq_crd = (chord)^2
65};
66
78
79// each circle partitions the sphere into an inside and an outside part
80// (the point is the exception; everything except the point is outside)
81struct yac_circle {
83 union {
84 struct {
85 // the norm vector points into the inside direction
86 double norm_vector[3];
87 } gc, lon;
88 struct {
90 double z;
91 } lat;
92 struct {
93 double vec[3];
94 } p;
96};
97
108int yac_point_in_cell (double point_coords[3], struct yac_grid_cell cell);
109
117int yac_point_in_cell2 (double point_coords[3], struct yac_grid_cell cell,
118 struct bounding_circle bnd_circle);
119
127static inline double get_angle (double a_lon, double b_lon) {
128 double diff = a_lon - b_lon;
129#if defined(CDO)
130 return diff - lround(diff / (2.0 * M_PI)) * (2.0 * M_PI);
131#else
132 return diff - round(diff / (2.0 * M_PI)) * (2.0 * M_PI);
133#endif
134}
135
143static inline double get_angle_deg (double a_lon, double b_lon) {
144 double diff = a_lon - b_lon;
145#if defined(CDO)
146 return diff - lround(diff / 360.0) * (360.0);
147#else
148 return diff - round(diff / 360.0) * (360.0);
149#endif
150}
151
175 enum yac_edge_type edge_type_a, double const a[3], double const b[3],
176 enum yac_edge_type edge_type_b, double const c[3], double const d[3],
177 double p[3], double q[3]);
178
189 struct bounding_circle * bnd_circle);
190
197int yac_extents_overlap(struct bounding_circle * extent_a,
198 struct bounding_circle * extent_b);
199
201static inline double sq_len_diff_vec(double const a[3], double const b[3]) {
202 double ab[3] = {a[0]-b[0], a[1]-b[1], a[2]-b[2]};
203 return ab[0] * ab[0] + ab[1] * ab[1] + ab[2] * ab[2];
204}
205
206static inline double compute_sq_crd(struct sin_cos_angle angle) {
207
208 double temp = 1.0 - angle.cos;
209 return temp * temp + angle.sin * angle.sin;
210}
211
219 double point_vector[3], struct bounding_circle * bnd_circle) {
220
221 if (bnd_circle->sq_crd == DBL_MAX)
222 bnd_circle->sq_crd = compute_sq_crd(bnd_circle->inc_angle);
223
224 return
225 bnd_circle->sq_crd >=
226 sq_len_diff_vec(bnd_circle->base_vector, point_vector);
227}
228
229static inline double clamp_abs_one(double val) {
230 return val > -1.0 ? (val < 1.0 ? val : 1.0) : -1.0;
231}
232
241static inline void compute_sin_cos(
242 double angle, double * sin_value, double * cos_value) {
243
244 double abs_angle = fabs(angle);
245 if (abs_angle < yac_angle_low_tol) {
246 *sin_value = 0.0;
247 *cos_value = 1.0;
248 } else if (fabs(abs_angle - M_PI) < yac_angle_low_tol) {
249 *sin_value = 0.0;
250 *cos_value = -1.0;
251 } else if (fabs(abs_angle - M_PI_2) < yac_angle_low_tol) {
252 *sin_value = copysign(1.0, angle);
253 *cos_value = 0.0;
254 } else {
255 *sin_value = clamp_abs_one(sin(angle));
256 *cos_value = clamp_abs_one(cos(angle));
257 }
258}
259
270static inline void LLtoXYZ(double lon, double lat, double p_out[]) {
271
272 while (lon < -M_PI) lon += 2.0 * M_PI;
273 while (lon >= M_PI) lon -= 2.0 * M_PI;
274
275 double sin_lon, cos_lon, sin_lat, cos_lat;
276 compute_sin_cos(lon, &sin_lon, &cos_lon);
277 compute_sin_cos(lat, &sin_lat, &cos_lat);
278
279 p_out[0] = cos_lat * cos_lon;
280 p_out[1] = cos_lat * sin_lon;
281 p_out[2] = sin_lat;
282}
283
290static inline void LLtoXYZ_deg(double lon, double lat, double p_out[]) {
291 LLtoXYZ(lon*YAC_RAD, lat*YAC_RAD, p_out);
292}
293
304static inline void XYZtoLL (double const p_in[], double * lon, double * lat) {
305
306 *lon = atan2(p_in[1] , p_in[0]);
307 *lat = M_PI_2 - acos(p_in[2]);
308}
309
310// computation of the determinant of a 2x2 matrix using Kahan summation
311static inline double det2_kahan(double a, double b, double c, double d) {
312 double bc = b*c;
313 double e_bc = fma(b,c,-bc); // the rounding error of the multiplication
314 double det = fma(a,d,-bc);
315 return det + e_bc;
316}
317
318static inline void crossproduct_kahan (
319 double const a[], double const b[], double cross[]) {
320
321 /* crossproduct in Cartesian coordinates */
322
323 cross[0] = det2_kahan(a[1], a[2], b[1], b[2]);
324 cross[1] = det2_kahan(a[2], a[0], b[2], b[0]);
325 cross[2] = det2_kahan(a[0], a[1], b[0], b[1]);
326
327}
328
333static inline void crossproduct_d (
334 const double a[], const double b[], double cross[]) {
335
336/* crossproduct in Cartesian coordinates */
337
338 cross[0] = a[1] * b[2] - a[2] * b[1];
339 cross[1] = a[2] * b[0] - a[0] * b[2];
340 cross[2] = a[0] * b[1] - a[1] * b[0];
341}
342
350static inline double get_vector_angle(double const a[3], double const b[3]) {
351
352 double dot_product = a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
353
354 // the acos most accurate in the range [-M_SQRT1_2;M_SQRT1_2]
355 if (fabs(dot_product) > M_SQRT1_2) {
356
357 double cross_ab[3];
358
359 crossproduct_kahan(a, b, cross_ab);
360
361 double asin_tmp = asin(sqrt(cross_ab[0]*cross_ab[0]+
362 cross_ab[1]*cross_ab[1]+
363 cross_ab[2]*cross_ab[2]));
364
365 if (dot_product > 0.0) // if the angle is smaller than (PI / 2)
366 return MAX(asin_tmp,0.0);
367 else
368 return MIN(M_PI - asin_tmp, M_PI);
369
370 } else {
371
372 return acos(dot_product);
373 }
374
375 /*
376 // this solution is simpler, but has a much worse performance
377 double cross[3], dot, cross_abs;
378
379 crossproduct_kahan(a, b, cross);
380 dot = a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
381 cross_abs = sqrt(cross[0]*cross[0] + cross[1]*cross[1] + cross[2]*cross[2]);
382
383 return fabs(atan2(cross_abs, dot));
384 */
385}
386
387static inline struct sin_cos_angle sin_cos_angle_new(double sin, double cos) {
388
389 struct sin_cos_angle angle;
390
391 angle.sin = clamp_abs_one(sin);
392 angle.cos = clamp_abs_one(cos);
393
394 return angle;
395}
396
398 double const a[3], double const b[3]) {
399
400 double cross_ab[3];
401 crossproduct_kahan(a, b, cross_ab);
402
403 return sin_cos_angle_new(sqrt(cross_ab[0]*cross_ab[0] +
404 cross_ab[1]*cross_ab[1] +
405 cross_ab[2]*cross_ab[2]),
406 a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
407}
408
409// works for angles in the range [0;2*PI[
410static inline int compare_angles(
411 struct sin_cos_angle a, struct sin_cos_angle b) {
412
413 // there are 5 sections:
414 // 0: 0 <= angle < PI/4
415 // 1: PI/4 <= angle < 3*PI/4
416 // 2: 3*PI/4 <= angle < 5*PI/4
417 // 3: 5*PI/4 <= angle < 7*PI/4
418 // 4: 7*PI/4 <= angle < 2*PI
419 int t_a = fabs(a.cos) <= M_SQRT1_2;
420 int t_b = fabs(b.cos) <= M_SQRT1_2;
421 int a_section = t_a | ((((a.sin < 0.0) & t_a) |
422 ((a.cos < 0.0) & (fabs(a.sin) < M_SQRT1_2))) << 1);
423 int b_section = t_b | ((((b.sin < 0.0) & t_b) |
424 ((b.cos < 0.0) & (fabs(b.sin) < M_SQRT1_2))) << 1);
425 // if current section is 0, then it could be actually section 4
426 if (!a_section) a_section = (a.sin < 0.0) << 2;
427 if (!b_section) b_section = (b.sin < 0.0) << 2;
428
429 if (a_section != b_section)
430 return (a_section > b_section) - (a_section < b_section);
431
432 int ret;
433
434 switch (a_section) {
435 case(0):
436 case(4):
437 default:
438 ret = (b.sin < a.sin + yac_angle_low_tol) -
439 (a.sin < b.sin + yac_angle_low_tol);
440 if (ret) return ret;
441 else {
442 ret = (a.cos < b.cos + yac_angle_low_tol) -
443 (b.cos < a.cos + yac_angle_low_tol);
444 if (a.sin >= 0.0) return ret;
445 else return -ret;
446 }
447 case(1):
448 ret = (a.cos < b.cos + yac_angle_low_tol) -
449 (b.cos < a.cos + yac_angle_low_tol);
450 if (ret) return ret;
451 else {
452 ret = (b.sin < a.sin + yac_angle_low_tol) -
453 (a.sin < b.sin + yac_angle_low_tol);
454 if (a.cos >= 0.0) return ret;
455 else return -ret;
456 }
457 case(2):
458 ret = (a.sin < b.sin + yac_angle_low_tol) -
459 (b.sin < a.sin + yac_angle_low_tol);
460 if (ret) return ret;
461 else {
462 ret = (a.cos < b.cos + yac_angle_low_tol) -
463 (b.cos < a.cos + yac_angle_low_tol);
464 if (a.sin >= 0.0) return ret;
465 else return -ret;
466 }
467 case(3):
468 ret = (b.cos < a.cos + yac_angle_low_tol) -
469 (a.cos < b.cos + yac_angle_low_tol);
470 if (ret) return ret;
471 else {
472 ret = (a.sin < b.sin + yac_angle_low_tol) -
473 (b.sin < a.sin + yac_angle_low_tol);
474 if (a.cos <= 0.0) return ret;
475 else return -ret;
476 }
477 }
478}
479
487static inline double sin_cos_angle_to_dble(struct sin_cos_angle angle) {
488
489 int t = fabs(angle.cos) <= M_SQRT1_2;
490 int section = t | ((((angle.sin < 0.0) & t) |
491 ((angle.cos < 0.0) & (fabs(angle.sin) < M_SQRT1_2))) << 1);
492 if (!section) section = (angle.sin < 0.0) << 2;
493
494 switch (section) {
495 default:
496 case(0): return 0.0 * M_SQRT1_2 + angle.sin;
497 case(1): return 2.0 * M_SQRT1_2 - angle.cos;
498 case(2): return 4.0 * M_SQRT1_2 - angle.sin;
499 case(3): return 6.0 * M_SQRT1_2 + angle.cos;
500 case(4): return 8.0 * M_SQRT1_2 + angle.sin;
501 }
502}
503
507 struct sin_cos_angle a, struct sin_cos_angle b) {
508
509 return sin_cos_angle_new(a.sin * b.cos + a.cos * b.sin,
510 a.cos * b.cos - a.sin * b.sin);
511}
512
516static inline int sum_angles(
517 struct sin_cos_angle a, struct sin_cos_angle b,
518 struct sin_cos_angle * restrict sum) {
519
520 struct sin_cos_angle sum_ = sum_angles_no_check(a, b);
521
522 *sum = sum_;
523
524 // if a or b is smaller than the result
525 return (compare_angles(sum_, a) < 0) || (compare_angles(sum_, b) < 0);
526}
527
531 struct sin_cos_angle a, struct sin_cos_angle b) {
532
533 return sin_cos_angle_new(a.sin * b.cos - a.cos * b.sin,
534 a.cos * b.cos + a.sin * b.sin);
535}
536
540static inline int sub_angles(
541 struct sin_cos_angle a, struct sin_cos_angle b,
542 struct sin_cos_angle * restrict sub) {
543
544 int compare_result = compare_angles(a, b);
545
546 // return sin=0.0 and cos=1.0 if the angles are equal to each other,
547 // i.e. compare_result == 0
548 *sub = compare_result ? sub_angles_no_check(a, b) : SIN_COS_ZERO;
549
550 return compare_result < 0;
551}
552
554static inline double compute_angle(struct sin_cos_angle angle) {
555
556 // the acos and asin are most accurate in the range [-M_SQRT1_2;M_SQRT1_2]
557 if (angle.cos > M_SQRT1_2) {
558
559 double angle_ = asin(angle.sin);
560
561 if (angle_ < 0.0) angle_ += 2.0 * M_PI;
562 return angle_;
563
564 } else if (angle.cos > - M_SQRT1_2) {
565
566 double angle_ = acos(angle.cos);
567
568 if (angle.sin > 0.0) return angle_;
569 else return 2.0 * M_PI - angle_;
570
571 } else {
572 return M_PI - asin(angle.sin);
573 }
574}
575
582static inline struct sin_cos_angle half_angle(struct sin_cos_angle angle) {
583
584 double x = (1.0 + fabs(angle.cos));
585
586 double scale = 1.0 / sqrt(x * x + angle.sin * angle.sin);
587
588 // first or fourth quadrant
589 if (angle.cos >= 0) {
590 scale = copysign(scale, angle.sin);
591 return sin_cos_angle_new(angle.sin * scale, x * scale);
592
593 // second and third quadrant
594 } else return sin_cos_angle_new(x * scale, angle.sin * scale);
595}
596
599static inline struct sin_cos_angle quarter_angle(struct sin_cos_angle angle) {
600
601 double tan = fabs(angle.sin / (1.0 + fabs(angle.cos)));
602 double one_plus_sq_tan = 1.0 + tan * tan;
603 double sqrt_one_plus_sq_tan = sqrt(one_plus_sq_tan);
604
605 double a = 1.0;
606 double b = tan;
607
608 // second and third quadrant
609 if (angle.cos < 0.0) {
610 a = tan;
611 b = 1.0;
612 }
613
614 double scale = M_SQRT1_2 / sqrt(one_plus_sq_tan + a * sqrt_one_plus_sq_tan);
615 double x = b * scale;
616 double y = (a + sqrt_one_plus_sq_tan) * scale;
617
618 // first and second quadrant
619 if (angle.sin >= 0.0) return sin_cos_angle_new(x, y);
620 // third and fourth quadrant
621 else return sin_cos_angle_new(y, x);
622}
623
630static inline int points_are_identically(double const * a, double const * b) {
631
632 // for small angles the Euclidean distance is nearly identical to
633 // great circle distance between vectors a and b
634 return sq_len_diff_vec(a, b) <= yac_sq_angle_tol;
635}
636
644static inline int compare_coords(double const * a, double const * b) {
645
646 double dot_product = a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
647
648 // if the angle is smaller than ~0.81 degree
649 // (in this range the acos is still rather accurate)
650 if (dot_product > 0.9999) { // (acos(0.9999) = ~0.81 degree)
651
652 // both points are close to each other -> use cross product for higher
653 // accuracy
654
655 double cross_ab[3];
656 crossproduct_kahan(a, b, cross_ab);
657
658 // for very small angles: asin(alpha) = ~alpha (alpha in rad)
659 if (sqrt(cross_ab[0]*cross_ab[0] +
660 cross_ab[1]*cross_ab[1] +
661 cross_ab[2]*cross_ab[2]) < yac_angle_tol) return 0;
662 }
663
664 int ret;
665 if ((ret = (a[0] > b[0]) - (a[0] < b[0]))) return ret;
666 if ((ret = (a[1] > b[1]) - (a[1] < b[1]))) return ret;
667 return (a[2] > b[2]) - (a[2] < b[2]);
668}
669
671static inline void normalise_vector(double v[]) {
672
673 double norm = 1.0 / sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
674
675 v[0] *= norm;
676 v[1] *= norm;
677 v[2] *= norm;
678}
679
686static inline void rotate_vector2(
687 double axis[], struct sin_cos_angle angle, double v_in[], double v_out[]) {
688
689 // using Rodrigues' rotation formula
690 // v_out = v_in * cos(angle) +
691 // (axis x v_in) * sin(angle) +
692 // axis * (axis * v_in) * (1 - cos(angle))
693
694 double cross_axis_v_in[3];
695 crossproduct_d(axis, v_in, cross_axis_v_in);
696
697 double dot_axis_v_in = axis[0]*v_in[0] + axis[1]*v_in[1] + axis[2]*v_in[2];
698 double temp = dot_axis_v_in * (1.0 - angle.cos);
699
700 v_out[0] =
701 v_in[0] * angle.cos + cross_axis_v_in[0] * angle.sin + axis[0] * temp;
702 v_out[1] =
703 v_in[1] * angle.cos + cross_axis_v_in[1] * angle.sin + axis[1] * temp;
704 v_out[2] =
705 v_in[2] * angle.cos + cross_axis_v_in[2] * angle.sin + axis[2] * temp;
706}
707
714static inline void rotate_vector(
715 double axis[], double angle, double v_in[], double v_out[]) {
716
717 double sin_angle = sin(angle);
718 double cos_angle = cos(angle);
720 axis, sin_cos_angle_new(sin_angle, cos_angle), v_in, v_out);
721}
722
737 struct yac_grid_cell cell, size_t start_corner, struct yac_grid_cell * triangles);
738
752 size_t const * corner_indices, size_t num_corners, size_t start_corner,
753 size_t (*triangle_indices)[3]);
754
766 double * vertices, size_t num_vertices, double triangle[][3],
767 size_t num_tests);
768
770 struct yac_circle a, struct yac_circle b, double p[3], double q[3]);
771
773 double p[3], double const a[3], double const b[3],
774 enum yac_circle_type circle_type);
775
776#endif // GEOMETRY_H
777
static struct sin_cos_angle get_vector_angle_2(double const a[3], double const b[3])
Definition geometry.h:397
static int compare_coords(double const *a, double const *b)
Definition geometry.h:644
static double compute_sq_crd(struct sin_cos_angle angle)
Definition geometry.h:206
static const struct sin_cos_angle SIN_COS_LOW_TOL
Definition geometry.h:46
static double clamp_abs_one(double val)
Definition geometry.h:229
static const struct sin_cos_angle SIN_COS_7_M_PI_4
Definition geometry.h:50
static const struct sin_cos_angle SIN_COS_ZERO
Definition geometry.h:44
int yac_circle_intersect(struct yac_circle a, struct yac_circle b, double p[3], double q[3])
static double det2_kahan(double a, double b, double c, double d)
Definition geometry.h:311
void yac_triangulate_cell_indices(size_t const *corner_indices, size_t num_corners, size_t start_corner, size_t(*triangle_indices)[3])
Definition grid_cell.c:144
static int points_are_identically(double const *a, double const *b)
Definition geometry.h:630
static const struct sin_cos_angle SIN_COS_M_PI
Definition geometry.h:49
static void compute_sin_cos(double angle, double *sin_value, double *cos_value)
Definition geometry.h:241
void yac_compute_bnd_triangle(double *vertices, size_t num_vertices, double triangle[][3], size_t num_tests)
static int yac_point_in_bounding_circle_vec(double point_vector[3], struct bounding_circle *bnd_circle)
Definition geometry.h:218
static double sq_len_diff_vec(double const a[3], double const b[3])
computes square of the lenght of the vector ab
Definition geometry.h:201
static void crossproduct_d(const double a[], const double b[], double cross[])
Definition geometry.h:333
static struct sin_cos_angle sum_angles_no_check(struct sin_cos_angle a, struct sin_cos_angle b)
Definition geometry.h:506
static double sin_cos_angle_to_dble(struct sin_cos_angle angle)
Definition geometry.h:487
static void crossproduct_kahan(double const a[], double const b[], double cross[])
Definition geometry.h:318
static void rotate_vector(double axis[], double angle, double v_in[], double v_out[])
Definition geometry.h:714
static struct sin_cos_angle quarter_angle(struct sin_cos_angle angle)
Definition geometry.h:599
static const struct sin_cos_angle SIN_COS_TOL
Definition geometry.h:45
static const struct sin_cos_angle SIN_COS_M_PI_2
Definition geometry.h:48
#define yac_sq_angle_tol
Definition geometry.h:35
#define yac_cos_angle_low_tol
Definition geometry.h:38
int yac_point_in_cell(double point_coords[3], struct yac_grid_cell cell)
static void rotate_vector2(double axis[], struct sin_cos_angle angle, double v_in[], double v_out[])
Definition geometry.h:686
#define yac_cos_angle_tol
Definition geometry.h:36
void yac_triangulate_cell(struct yac_grid_cell cell, size_t start_corner, struct yac_grid_cell *triangles)
Definition grid_cell.c:66
#define YAC_RAD
Definition geometry.h:30
static void LLtoXYZ_deg(double lon, double lat, double p_out[])
Definition geometry.h:290
int yac_point_in_cell2(double point_coords[3], struct yac_grid_cell cell, struct bounding_circle bnd_circle)
static int compare_angles(struct sin_cos_angle a, struct sin_cos_angle b)
Definition geometry.h:410
int yac_intersect_vec(enum yac_edge_type edge_type_a, double const a[3], double const b[3], enum yac_edge_type edge_type_b, double const c[3], double const d[3], double p[3], double q[3])
static int sub_angles(struct sin_cos_angle a, struct sin_cos_angle b, struct sin_cos_angle *restrict sub)
Definition geometry.h:540
int yac_point_on_edge(double p[3], double const a[3], double const b[3], enum yac_circle_type circle_type)
static struct sin_cos_angle sub_angles_no_check(struct sin_cos_angle a, struct sin_cos_angle b)
Definition geometry.h:530
void yac_get_cell_bounding_circle(struct yac_grid_cell cell, struct bounding_circle *bnd_circle)
Definition bnd_circle.c:422
int yac_extents_overlap(struct bounding_circle *extent_a, struct bounding_circle *extent_b)
Definition bnd_circle.c:533
static double compute_angle(struct sin_cos_angle angle)
return angles in the range of [0;2PI[
Definition geometry.h:554
#define yac_angle_low_tol
Definition geometry.h:37
#define yac_angle_tol
Definition geometry.h:34
static void normalise_vector(double v[])
Definition geometry.h:671
static double get_angle(double a_lon, double b_lon)
Definition geometry.h:127
static void LLtoXYZ(double lon, double lat, double p_out[])
Definition geometry.h:270
static double get_vector_angle(double const a[3], double const b[3])
Definition geometry.h:350
static int sum_angles(struct sin_cos_angle a, struct sin_cos_angle b, struct sin_cos_angle *restrict sum)
Definition geometry.h:516
static double get_angle_deg(double a_lon, double b_lon)
Definition geometry.h:143
yac_circle_type
Definition geometry.h:72
@ POINT
Definition geometry.h:76
@ LAT_CIRCLE
Definition geometry.h:74
@ GREAT_CIRCLE
Definition geometry.h:73
@ LON_CIRCLE
Definition geometry.h:75
static struct sin_cos_angle sin_cos_angle_new(double sin, double cos)
Definition geometry.h:387
static struct sin_cos_angle half_angle(struct sin_cos_angle angle)
Definition geometry.h:582
static void XYZtoLL(double const p_in[], double *lon, double *lat)
Definition geometry.h:304
yac_edge_type
Definition grid_cell.h:12
@ YAC_GREAT_CIRCLE_EDGE
great circle
Definition grid_cell.h:13
@ YAC_LAT_CIRCLE_EDGE
latitude circle
Definition grid_cell.h:14
@ YAC_LON_CIRCLE_EDGE
longitude circle
Definition grid_cell.h:15
struct sin_cos_angle inc_angle
angle between the middle point and the boundary of the spherical cap
Definition geometry.h:61
double base_vector[3]
Definition geometry.h:59
double sq_crd
Definition geometry.h:64
double sin
Definition geometry.h:41
double cos
Definition geometry.h:41
struct yac_circle::@2::@4 lat
struct yac_circle::@2::@3 lon
double z
Definition geometry.h:90
enum yac_circle_type type
Definition geometry.h:82
struct yac_circle::@2::@3 gc
struct yac_circle::@2::@5 p
int north_is_out
Definition geometry.h:89
double norm_vector[3]
Definition geometry.h:86
double vec[3]
Definition geometry.h:93
union yac_circle::@2 data
#define MIN(a, b)
#define MAX(a, b)