22#define YAC_RAD (0.01745329251994329576923690768489)
26#define yac_angle_tol (1e-9)
27#define yac_sq_angle_tol (1e-9 * 1e-9)
28#define yac_cos_angle_tol (0.9999999999999999995)
29#define yac_angle_low_tol (1e-11)
30#define yac_cos_angle_low_tol (1.0)
117static inline double get_angle (
double a_lon,
double b_lon) {
118 double diff = a_lon - b_lon;
120 return diff - lround(diff / (2.0 * M_PI)) * (2.0 * M_PI);
122 return diff - round(diff / (2.0 * M_PI)) * (2.0 * M_PI);
134 double diff = a_lon - b_lon;
136 return diff - lround(diff / 360.0) * (360.0);
138 return diff - round(diff / 360.0) * (360.0);
165 enum yac_edge_type edge_type_a,
double const a[3],
double const b[3],
166 enum yac_edge_type edge_type_b,
double const c[3],
double const d[3],
167 double p[3],
double q[3]);
189 double ab[3] = {a[0]-b[0], a[1]-b[1], a[2]-b[2]};
190 return ab[0] * ab[0] + ab[1] * ab[1] + ab[2] * ab[2];
195 double temp = 1.0 - angle.
cos;
196 return temp * temp + angle.
sin * angle.
sin;
209 if (bnd_circle->
sq_crd == DBL_MAX)
218 return val > -1.0 ? (val < 1.0 ? val : 1.0) : -1.0;
230 double angle,
double * sin_value,
double * cos_value) {
232 double abs_angle = fabs(angle);
240 *sin_value = copysign(1.0, angle);
258static inline void LLtoXYZ(
double lon,
double lat,
double p_out[]) {
260 while (lon < -M_PI) lon += 2.0 * M_PI;
261 while (lon >= M_PI) lon -= 2.0 * M_PI;
263 double sin_lon, cos_lon, sin_lat, cos_lat;
267 p_out[0] = cos_lat * cos_lon;
268 p_out[1] = cos_lat * sin_lon;
278static inline void LLtoXYZ_deg(
double lon,
double lat,
double p_out[]) {
292static inline void XYZtoLL (
double const p_in[],
double * lon,
double * lat) {
294 *lon = atan2(p_in[1] , p_in[0]);
295 *lat = M_PI_2 - acos(p_in[2]);
310 double a,
double b,
double * restrict product,
double * restrict
error) {
312 *
error = fma(a, b, -*product);
327 double a,
double b,
double * restrict sum,
double * restrict
error) {
329 double temp = *sum - a;
330 *
error = (a - (*sum - temp)) + (b - temp);
344 double a,
double * restrict accu,
double * restrict
error) {
345 double a_ = a - *
error;
346 double temp = *accu + a_;
347 *
error = (temp - *accu) - a_;
367 double a,
double b,
double * restrict accu,
double * restrict accu_error) {
370 double product, product_error;
374 accu_eft(product, accu, accu_error);
375 *accu_error += product_error;
392 double a,
double b,
double c,
double d,
393 double * restrict det,
double * restrict det_error) {
402 sum_eft(ad, bc, det, &temp_err);
403 *det_error = ad_err + (temp_err + bc_err);
407static inline double det2_kahan(
double a,
double b,
double c,
double d) {
409 double e_bc = fma(b,c,-bc);
410 double det = fma(a,d,-bc);
415 double const a[],
double const b[],
double cross[]) {
419 cross[0] =
det2_kahan(a[1], a[2], b[1], b[2]);
420 cross[1] =
det2_kahan(a[2], a[0], b[2], b[0]);
421 cross[2] =
det2_kahan(a[0], a[1], b[0], b[1]);
430 const double a[],
const double b[],
double cross[]) {
434 cross[0] = a[1] * b[2] - a[2] * b[1];
435 cross[1] = a[2] * b[0] - a[0] * b[2];
436 cross[2] = a[0] * b[1] - a[1] * b[0];
444 double accu = 0.0, err = 0.0;
449 double result, result_err;
450 sum_eft(accu, -err, &result, &result_err);
451 return result + result_err;
474 double sub[3] = {a[0] - b[0], a[1] - b[1], a[2] - b[2]};
475 double add[3] = {a[0] + b[0], a[1] + b[1], a[2] + b[2]};
476 double sq_sub = sub[0] * sub[0] + sub[1] * sub[1] + sub[2] * sub[2];
477 double sq_add = add[0] * add[0] + add[1] * add[1] + add[2] * add[2];
480 return (fabs(sq_add) > 1e-12)?(2.0 * atan(sqrt(sq_sub/sq_add))):M_PI;
494 double const a[3], double const b[3]) {
500 cross_ab[1]*cross_ab[1] +
501 cross_ab[2]*cross_ab[2]),
502 a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
515 int t_a = fabs(a.
cos) <= M_SQRT1_2;
516 int t_b = fabs(b.
cos) <= M_SQRT1_2;
517 int a_section = t_a | ((((a.
sin < 0.0) & t_a) |
518 ((a.
cos < 0.0) & (fabs(a.
sin) < M_SQRT1_2))) << 1);
519 int b_section = t_b | ((((b.
sin < 0.0) & t_b) |
520 ((b.
cos < 0.0) & (fabs(b.
sin) < M_SQRT1_2))) << 1);
522 if (!a_section) a_section = (a.
sin < 0.0) << 2;
523 if (!b_section) b_section = (b.
sin < 0.0) << 2;
525 if (a_section != b_section)
526 return (a_section > b_section) - (a_section < b_section);
540 if (a.
sin >= 0.0)
return ret;
550 if (a.
cos >= 0.0)
return ret;
560 if (a.
sin >= 0.0)
return ret;
570 if (a.
cos <= 0.0)
return ret;
585 int t = fabs(angle.
cos) <= M_SQRT1_2;
586 int section = t | ((((angle.
sin < 0.0) & t) |
587 ((angle.
cos < 0.0) & (fabs(angle.
sin) < M_SQRT1_2))) << 1);
588 if (!section) section = (angle.
sin < 0.0) << 2;
592 case(0):
return 0.0 * M_SQRT1_2 + angle.
sin;
593 case(1):
return 2.0 * M_SQRT1_2 - angle.
cos;
594 case(2):
return 4.0 * M_SQRT1_2 - angle.
sin;
595 case(3):
return 6.0 * M_SQRT1_2 + angle.
cos;
596 case(4):
return 8.0 * M_SQRT1_2 + angle.
sin;
606 a.cos * b.cos - a.sin * b.sin);
630 a.cos * b.cos + a.sin * b.sin);
646 return compare_result < 0;
653 if (angle.
cos > M_SQRT1_2) {
655 double angle_ = asin(angle.
sin);
657 if (angle_ < 0.0) angle_ += 2.0 * M_PI;
660 }
else if (angle.
cos > - M_SQRT1_2) {
662 double angle_ = acos(angle.
cos);
664 if (angle.
sin > 0.0)
return angle_;
665 else return 2.0 * M_PI - angle_;
668 return M_PI - asin(angle.
sin);
680 double x = (1.0 + fabs(angle.cos));
682 double scale = 1.0 / sqrt(x * x + angle.sin * angle.sin);
685 if (angle.cos >= 0) {
686 scale = copysign(scale, angle.sin);
697 double tan = fabs(angle.sin / (1.0 + fabs(angle.cos)));
698 double one_plus_sq_tan = 1.0 + tan * tan;
699 double sqrt_one_plus_sq_tan = sqrt(one_plus_sq_tan);
705 if (angle.cos < 0.0) {
710 double scale = M_SQRT1_2 / sqrt(one_plus_sq_tan + a * sqrt_one_plus_sq_tan);
711 double x = b * scale;
712 double y = (a + sqrt_one_plus_sq_tan) * scale;
748 if ((ret = (a[0] > b[0]) - (a[0] < b[0])))
return ret;
749 if ((ret = (a[1] > b[1]) - (a[1] < b[1])))
return ret;
750 return (a[2] > b[2]) - (a[2] < b[2]);
756 double norm = 1.0 / sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
770 double axis[],
struct sin_cos_angle angle,
double v_in[],
double v_out[]) {
777 double cross_axis_v_in[3];
780 double dot_axis_v_in = axis[0]*v_in[0] + axis[1]*v_in[1] + axis[2]*v_in[2];
781 double temp = dot_axis_v_in * (1.0 - angle.
cos);
784 v_in[0] * angle.
cos + cross_axis_v_in[0] * angle.
sin + axis[0] * temp;
786 v_in[1] * angle.
cos + cross_axis_v_in[1] * angle.
sin + axis[1] * temp;
788 v_in[2] * angle.
cos + cross_axis_v_in[2] * angle.
sin + axis[2] * temp;
798 double axis[],
double angle,
double v_in[],
double v_out[]) {
800 double sin_angle = sin(angle);
801 double cos_angle = cos(angle);
835 size_t const * corner_indices,
size_t num_corners,
size_t start_corner,
836 size_t (*triangle_indices)[3]);
849 double * vertices,
size_t num_vertices,
double triangle[][3],
856 double p[3],
double const a[3],
double const b[3],
static struct sin_cos_angle get_vector_angle_2(double const a[3], double const b[3])
static int compare_coords(double const *a, double const *b)
static double compute_sq_crd(struct sin_cos_angle angle)
static void product_eft(double a, double b, double *restrict product, double *restrict error)
static const struct sin_cos_angle SIN_COS_LOW_TOL
static double clamp_abs_one(double val)
static const struct sin_cos_angle SIN_COS_7_M_PI_4
static const struct sin_cos_angle SIN_COS_ZERO
static void det2_error(double a, double b, double c, double d, double *restrict det, double *restrict det_error)
int yac_circle_intersect(struct yac_circle a, struct yac_circle b, double p[3], double q[3])
static double dotproduct_eft(double const a[], double const b[])
static double det2_kahan(double a, double b, double c, double d)
void yac_triangulate_cell_indices(size_t const *corner_indices, size_t num_corners, size_t start_corner, size_t(*triangle_indices)[3])
static int points_are_identically(double const *a, double const *b)
static const struct sin_cos_angle SIN_COS_M_PI
static void compute_sin_cos(double angle, double *sin_value, double *cos_value)
void yac_compute_bnd_triangle(double *vertices, size_t num_vertices, double triangle[][3], size_t num_tests)
static void sum_eft(double a, double b, double *restrict sum, double *restrict error)
static int yac_point_in_bounding_circle_vec(double point_vector[3], struct bounding_circle *bnd_circle)
static double sq_len_diff_vec(double const a[3], double const b[3])
computes square of the lenght of the vector ab
static void crossproduct_d(const double a[], const double b[], double cross[])
static struct sin_cos_angle sum_angles_no_check(struct sin_cos_angle a, struct sin_cos_angle b)
static double sin_cos_angle_to_dble(struct sin_cos_angle angle)
static void crossproduct_kahan(double const a[], double const b[], double cross[])
static void rotate_vector(double axis[], double angle, double v_in[], double v_out[])
static struct sin_cos_angle quarter_angle(struct sin_cos_angle angle)
static const struct sin_cos_angle SIN_COS_TOL
static const struct sin_cos_angle SIN_COS_M_PI_2
#define yac_cos_angle_low_tol
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[])
#define yac_cos_angle_tol
void yac_triangulate_cell(struct yac_grid_cell cell, size_t start_corner, struct yac_grid_cell *triangles)
static void accu_product_eft(double a, double b, double *restrict accu, double *restrict accu_error)
static void LLtoXYZ_deg(double lon, double lat, double p_out[])
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)
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)
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)
void yac_get_cell_bounding_circle(struct yac_grid_cell cell, struct bounding_circle *bnd_circle)
int yac_extents_overlap(struct bounding_circle *extent_a, struct bounding_circle *extent_b)
static double compute_angle(struct sin_cos_angle angle)
return angles in the range of [0;2PI[
#define yac_angle_low_tol
static void normalise_vector(double v[])
static double get_angle(double a_lon, double b_lon)
static void LLtoXYZ(double lon, double lat, double p_out[])
static double get_vector_angle(double const a[3], double const b[3])
static int sum_angles(struct sin_cos_angle a, struct sin_cos_angle b, struct sin_cos_angle *restrict sum)
static double get_angle_deg(double a_lon, double b_lon)
static struct sin_cos_angle sin_cos_angle_new(double sin, double cos)
static void accu_eft(double a, double *restrict accu, double *restrict error)
static struct sin_cos_angle half_angle(struct sin_cos_angle angle)
static void XYZtoLL(double const p_in[], double *lon, double *lat)
@ YAC_GREAT_CIRCLE_EDGE
great circle
@ YAC_LAT_CIRCLE_EDGE
latitude circle
@ YAC_LON_CIRCLE_EDGE
longitude circle
struct sin_cos_angle inc_angle
angle between the middle point and the boundary of the spherical cap
struct yac_circle::@8::@10 lat
struct yac_circle::@8::@11 p
double z
z-coordinate of the latitude circle (sin(latitude))
enum yac_circle_type type
struct yac_circle::@8::@9 gc
union yac_circle::@8 data
struct yac_circle::@8::@9 lon
double(* p)(double lon, double lat)