48static double tri_area(
double const * restrict a,
49 double const * restrict b,
50 double const * restrict c) {
58 det2_error(b[1], b[2], c[1], c[2], &bc[0], &bc_e[0]);
59 det2_error(b[2], b[0], c[2], c[0], &bc[1], &bc_e[1]);
60 det2_error(b[0], b[1], c[0], c[1], &bc[2], &bc_e[2]);
68 {a[0]*bc[0], a[1]*bc[1], a[2]*bc[2]};
70 {fma(a[0], bc[0], -abc[0]) + a[0] * bc_e[0],
71 fma(a[1], bc[1], -abc[1]) + a[1] * bc_e[1],
72 fma(a[2], bc[2], -abc[2]) + a[2] * bc_e[2]};
74 double triple = 0.0, triple_e = 0.0;
76 accu_eft(abc_e[0], &triple, &triple_e);
77 accu_eft(abc_e[1], &triple, &triple_e);
78 accu_eft(abc_e[2], &triple, &triple_e);
79 accu_eft(abc[0], &triple, &triple_e);
80 accu_eft(abc[1], &triple, &triple_e);
81 accu_eft(abc[2], &triple, &triple_e);
107 return 2.0 * atan2(triple + triple_e, D + D_e);
116 double scale = sqrt(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]);
130 return atan2(a[1] , a[0]);
134 double base_vec[3],
double a[3],
double b[3],
double * middle_lat) {
141 double const tol = 1e-8;
144 fabs(a[2]-b[2]) <=
tol,
145 "ERROR(lat_edge_correction_): "
146 "latitude of both corners is not identical")
148 double h = fabs(a[2]);
151 if (h <
tol || fabs(1.0 - h) <
tol)
return 0.0;
164 double pole[3] = {0, 0, copysign(1.0, a[2])};
165 double gc_area = fabs(
tri_area(a, b, pole));
169 double correction =
MAX(lat_area - gc_area, 0.0);
177 middle_lat[0] = a[0]+b[0];
178 middle_lat[1] = a[1]+b[1];
179 middle_lat[2] = a[2];
180 double scale = sqrt(middle_lat[0]*middle_lat[0]+middle_lat[1]*middle_lat[1]);
183 middle_lat[0] *=
scale;
184 middle_lat[1] *=
scale;
190 int negative_correction_flag;
193 if (fabs(scalar_base) < 1e-11) {
199 double norm_middle[3];
203 negative_correction_flag = scalar_a <= 0;
210 negative_correction_flag = scalar_middle_lat >= 0;
213 return negative_correction_flag?-correction:correction;
217 double base_vec[3],
double a[3],
double b[3]) {
219 double middle_lat[3];
224 double base_vec[3],
double a[3],
double b[3],
225 double * barycenter,
double sign) {
227 double middle_lat[3];
230 if (correction == 0.0)
return 0.0;
232 double middle_gc[3] = {a[0] + b[0], a[1] + b[1], a[2] + b[2]};
235 double temp_barycenter[3] =
236 {middle_lat[0] + middle_gc[0],
237 middle_lat[1] + middle_gc[1],
238 middle_lat[2] + middle_gc[2]};
241 barycenter[0] += temp_barycenter[0] * correction * sign;
242 barycenter[1] += temp_barycenter[1] * correction * sign;
243 barycenter[2] += temp_barycenter[2] * correction * sign;
245 return correction * sign;
275 if (M < 2)
return 0.0;
279 for (
size_t i = 0; i < M; i++)
284 if (M == 3 && !lat_flag) {
298 for (
size_t i = 1; i < M - 1; ++i) {
311 for (
size_t i = 0, j = M - 1; i < M; j = i++) {
349 double ref[3],
double a[3],
double b[3],
350 double * barycenter,
double sign) {
356 double * corners[3] = {b, ref, a};
357 for (
int i = 0, j = 2; i < 3; j = i++) {
362 sqrt(cross[0]*cross[0] + cross[1]*cross[1] + cross[2]*cross[2]);
367 double angle = asin(sin_angle);
369 double scale = 0.5 * angle / sin_angle * sign;
370 for (
int k = 0; k < 3; ++k) barycenter[k] += cross[k] *
scale;
404 struct yac_grid_cell cell,
double * barycenter,
double sign) {
408 if (M < 2)
return 0.0;
412 for (
size_t i = 0; i < M; i++)
417 if (M == 3 && !lat_flag) {
431 for (
size_t i = 1; i < M - 1; ++i) {
447 for (
size_t i = 0, j = M - 1; i < M; j = i++) {
471 return (a[0] * b[0] + a[1] * b[1] + a[2] * b[2]);
#define YAC_ASSERT(exp, msg)
static int compute_norm_vector(double a[], double b[], double norm[])
double yac_grid_cell_area(struct yac_grid_cell cell)
Area calculation of a spherical cell.
static double scalar_product(double a[], double b[])
static double tri_area_info(double ref[3], double a[3], double b[3], double *barycenter, double sign)
static double lat_edge_correction_info(double base_vec[3], double a[3], double b[3], double *barycenter, double sign)
double yac_grid_cell_area_info(struct yac_grid_cell cell, double *barycenter, double sign)
static double XYZtoLon(double a[3])
static double lat_edge_correction_(double base_vec[3], double a[3], double b[3], double *middle_lat)
static double lat_edge_correction(double base_vec[3], double a[3], double b[3])
static double tri_area(double const *restrict a, double const *restrict b, double const *restrict c)
Structs and interfaces for area calculations.
static void det2_error(double a, double b, double c, double d, double *restrict det, double *restrict det_error)
static void crossproduct_kahan(double const a[], double const b[], double cross[])
static void accu_product_eft(double a, double b, double *restrict accu, double *restrict accu_error)
static void normalise_vector(double v[])
static double get_angle(double a_lon, double b_lon)
static void accu_eft(double a, double *restrict accu, double *restrict error)
@ YAC_LAT_CIRCLE_EDGE
latitude circle
enum yac_edge_type * edge_type
double(* coordinates_xyz)[3]