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)
110static inline double get_angle (
double a_lon,
double b_lon) {
111 double diff = a_lon - b_lon;
113 return diff - lround(diff / (2.0 * M_PI)) * (2.0 * M_PI);
115 return diff - round(diff / (2.0 * M_PI)) * (2.0 * M_PI);
110static inline double get_angle (
double a_lon,
double b_lon) {
…}
127 double diff = a_lon - b_lon;
129 return diff - lround(diff / 360.0) * (360.0);
131 return diff - round(diff / 360.0) * (360.0);
158 enum yac_edge_type edge_type_a,
double const a[3],
double const b[3],
159 enum yac_edge_type edge_type_b,
double const c[3],
double const d[3],
160 double p[3],
double q[3]);
181 double ab[3] = {a[0]-b[0], a[1]-b[1], a[2]-b[2]};
182 return ab[0] * ab[0] + ab[1] * ab[1] + ab[2] * ab[2];
187 double temp = 1.0 - angle.
cos;
188 return temp * temp + angle.
sin * angle.
sin;
200 if (bnd_circle->
sq_crd == DBL_MAX)
209 return val > -1.0 ? (val < 1.0 ? val : 1.0) : -1.0;
221 double angle,
double * sin_value,
double * cos_value) {
223 double abs_angle = fabs(angle);
231 *sin_value = copysign(1.0, angle);
249static inline void LLtoXYZ(
double lon,
double lat,
double p_out[]) {
251 while (lon < -M_PI) lon += 2.0 * M_PI;
252 while (lon >= M_PI) lon -= 2.0 * M_PI;
254 double sin_lon, cos_lon, sin_lat, cos_lat;
258 p_out[0] = cos_lat * cos_lon;
259 p_out[1] = cos_lat * sin_lon;
249static inline void LLtoXYZ(
double lon,
double lat,
double p_out[]) {
…}
269static inline void LLtoXYZ_deg(
double lon,
double lat,
double p_out[]) {
269static inline void LLtoXYZ_deg(
double lon,
double lat,
double p_out[]) {
…}
283static inline void XYZtoLL (
double const p_in[],
double * lon,
double * lat) {
285 *lon = atan2(p_in[1] , p_in[0]);
286 *lat = M_PI_2 - acos(p_in[2]);
283static inline void XYZtoLL (
double const p_in[],
double * lon,
double * lat) {
…}
290static inline double det2_kahan(
double a,
double b,
double c,
double d) {
292 double e_bc = fma(b,c,-bc);
293 double det = fma(a,d,-bc);
290static inline double det2_kahan(
double a,
double b,
double c,
double d) {
…}
298 double const a[],
double const b[],
double cross[]) {
302 cross[0] =
det2_kahan(a[1], a[2], b[1], b[2]);
303 cross[1] =
det2_kahan(a[2], a[0], b[2], b[0]);
304 cross[2] =
det2_kahan(a[0], a[1], b[0], b[1]);
313 const double a[],
const double b[],
double cross[]) {
317 cross[0] = a[1] * b[2] - a[2] * b[1];
318 cross[1] = a[2] * b[0] - a[0] * b[2];
319 cross[2] = a[0] * b[1] - a[1] * b[0];
331 double dot_product = a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
334 if (fabs(dot_product) > M_SQRT1_2) {
340 double asin_tmp = asin(sqrt(cross_ab[0]*cross_ab[0]+
341 cross_ab[1]*cross_ab[1]+
342 cross_ab[2]*cross_ab[2]));
344 if (dot_product > 0.0)
345 return MAX(asin_tmp,0.0);
347 return MIN(M_PI - asin_tmp, M_PI);
351 return acos(dot_product);
377 double const a[3], double const b[3]) {
383 cross_ab[1]*cross_ab[1] +
384 cross_ab[2]*cross_ab[2]),
385 a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
398 int t_a = fabs(a.
cos) <= M_SQRT1_2;
399 int t_b = fabs(b.
cos) <= M_SQRT1_2;
400 int a_section = t_a | ((((a.
sin < 0.0) & t_a) |
401 ((a.
cos < 0.0) & (fabs(a.
sin) < M_SQRT1_2))) << 1);
402 int b_section = t_b | ((((b.
sin < 0.0) & t_b) |
403 ((b.
cos < 0.0) & (fabs(b.
sin) < M_SQRT1_2))) << 1);
405 if (!a_section) a_section = (a.
sin < 0.0) << 2;
406 if (!b_section) b_section = (b.
sin < 0.0) << 2;
408 if (a_section != b_section)
409 return (a_section > b_section) - (a_section < b_section);
423 if (a.
sin >= 0.0)
return ret;
433 if (a.
cos >= 0.0)
return ret;
443 if (a.
sin >= 0.0)
return ret;
453 if (a.
cos <= 0.0)
return ret;
468 int t = fabs(angle.
cos) <= M_SQRT1_2;
469 int section = t | ((((angle.
sin < 0.0) & t) |
470 ((angle.
cos < 0.0) & (fabs(angle.
sin) < M_SQRT1_2))) << 1);
471 if (!section) section = (angle.
sin < 0.0) << 2;
475 case(0):
return 0.0 * M_SQRT1_2 + angle.
sin;
476 case(1):
return 2.0 * M_SQRT1_2 - angle.
cos;
477 case(2):
return 4.0 * M_SQRT1_2 - angle.
sin;
478 case(3):
return 6.0 * M_SQRT1_2 + angle.
cos;
479 case(4):
return 8.0 * M_SQRT1_2 + angle.
sin;
489 a.cos * b.cos - a.sin * b.sin);
513 a.cos * b.cos + a.sin * b.sin);
529 return compare_result < 0;
536 if (angle.
cos > M_SQRT1_2) {
538 double angle_ = asin(angle.
sin);
540 if (angle_ < 0.0) angle_ += 2.0 * M_PI;
543 }
else if (angle.
cos > - M_SQRT1_2) {
545 double angle_ = acos(angle.
cos);
547 if (angle.
sin > 0.0)
return angle_;
548 else return 2.0 * M_PI - angle_;
551 return M_PI - asin(angle.
sin);
563 double x = (1.0 + fabs(angle.cos));
565 double scale = 1.0 / sqrt(x * x + angle.sin * angle.sin);
568 if (angle.cos >= 0) {
569 scale = copysign(scale, angle.sin);
580 double tan = fabs(angle.sin / (1.0 + fabs(angle.cos)));
581 double one_plus_sq_tan = 1.0 + tan * tan;
582 double sqrt_one_plus_sq_tan = sqrt(one_plus_sq_tan);
588 if (angle.cos < 0.0) {
593 double scale = M_SQRT1_2 / sqrt(one_plus_sq_tan + a * sqrt_one_plus_sq_tan);
594 double x = b * scale;
595 double y = (a + sqrt_one_plus_sq_tan) * scale;
625 double dot_product = a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
629 if (dot_product > 0.9999) {
638 if (sqrt(cross_ab[0]*cross_ab[0] +
639 cross_ab[1]*cross_ab[1] +
644 if ((ret = (a[0] > b[0]) - (a[0] < b[0])))
return ret;
645 if ((ret = (a[1] > b[1]) - (a[1] < b[1])))
return ret;
646 return (a[2] > b[2]) - (a[2] < b[2]);
652 double norm = 1.0 / sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
666 double axis[],
struct sin_cos_angle angle,
double v_in[],
double v_out[]) {
673 double cross_axis_v_in[3];
676 double dot_axis_v_in = axis[0]*v_in[0] + axis[1]*v_in[1] + axis[2]*v_in[2];
677 double temp = dot_axis_v_in * (1.0 - angle.
cos);
680 v_in[0] * angle.
cos + cross_axis_v_in[0] * angle.
sin + axis[0] * temp;
682 v_in[1] * angle.
cos + cross_axis_v_in[1] * angle.
sin + axis[1] * temp;
684 v_in[2] * angle.
cos + cross_axis_v_in[2] * angle.
sin + axis[2] * temp;
694 double axis[],
double angle,
double v_in[],
double v_out[]) {
696 double sin_angle = sin(angle);
697 double cos_angle = cos(angle);
731 size_t const * corner_indices,
size_t num_corners,
size_t start_corner,
732 size_t (*triangle_indices)[3]);
745 double * vertices,
size_t num_vertices,
double triangle[][3],
752 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 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
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)
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 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 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 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::@9::@12 p
enum yac_circle_type type
struct yac_circle::@9::@10 gc
struct yac_circle::@9::@11 lat
union yac_circle::@9 data
struct yac_circle::@9::@10 lon
double(* p)(double lon, double lat)