YAC 3.12.0
Yet Another Coupler
Loading...
Searching...
No Matches
test_cxc.c
Go to the documentation of this file.
1// Copyright (c) 2024 The YAC Authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#include <stdlib.h>
6#include <math.h>
7
8#include "geometry.h"
9#include "test_cxc.h"
10
16enum {
17 error = -1,
18 p_on_a = 1,
19 q_on_a = 2,
20 p_on_b = 4,
21 q_on_b = 8,
23};
24
25static void test_results_vec(double p[3], double q[3], int ret_val,
26 double ref_p[3], double ref_q[3],
27 int ref_ret_value) {
28
29 int const mask_p = p_on_a + p_on_b;
30 int const mask_q = q_on_a + q_on_b;
31
32 // if intersection could be computed or no intersection is possible
33 if (ref_ret_value == error) {
34
35 if (ret_val != error)
36 PUT_ERR("error in ret_val (no error indicated)\n")
37
38 } else {
39
40 if ((ret_val & circles_are_identical) ^
41 (ref_ret_value & circles_are_identical))
42 PUT_ERR("error in ret_val (identically circles)\n")
43
44 // if there is only one intersection point
45 if (points_are_identically(ref_q, ref_p)) {
46
47 if (ret_val != ref_ret_value)
48 PUT_ERR("error in ret_val (a)");
49
50 if (!points_are_identically(p, ref_p))
51 PUT_ERR("p does not match\n")
52
53 if (!points_are_identically(q, ref_p))
54 PUT_ERR("q does not match\n")
55
56 } else {
57
58 if (points_are_identically(p, ref_p)) {
59
60 if ((ret_val & mask_p) != (ref_ret_value & mask_p))
61 PUT_ERR("error in ret_val (b)\n")
62
63 if (!points_are_identically(q, ref_q))
64 PUT_ERR("q does not match\n")
65
66 if ((ret_val & mask_q) != (ref_ret_value & mask_q))
67 PUT_ERR("error in ret_val (c)\n")
68
69 } else {
70
71 if (!points_are_identically(p, ref_q))
72 PUT_ERR("p does not match\n")
73
74 if ((ret_val & mask_p) << 1 != (ref_ret_value & mask_q))
75 PUT_ERR("error in ret_val (d)\n")
76
77 if (!points_are_identically(q, ref_p))
78 PUT_ERR("q does not match\n")
79
80 if ((ret_val & mask_q) >> 1 != (ref_ret_value & mask_p))
81 PUT_ERR("error in ret_val (e)\n")
82 }
83
84 if (ref_ret_value == 0 && ret_val != 0)
85 PUT_ERR("error in return value (f)\n")
86 }
87 }
88}
89
90void test_cxc_rad(double lon_a, double lat_a, double lon_b, double lat_b,
91 double lon_c, double lat_c, double lon_d, double lat_d,
92 enum yac_edge_type edge_type_a, enum yac_edge_type edge_type_b,
93 double lon_ref_p, double lat_ref_p,
94 double lon_ref_q, double lat_ref_q, int ref_ret_val) {
95
96 double edges[2][2][3];
97 LLtoXYZ(lon_a, lat_a, edges[0][0]);
98 LLtoXYZ(lon_b, lat_b, edges[0][1]);
99 LLtoXYZ(lon_c, lat_c, edges[1][0]);
100 LLtoXYZ(lon_d, lat_d, edges[1][1]);
101
102 enum yac_edge_type edge_types[2] = {edge_type_a, edge_type_b};
103
104 double ref_pq[2][3];
105 LLtoXYZ(lon_ref_p, lat_ref_p, ref_pq[0]);
106 LLtoXYZ(lon_ref_q, lat_ref_q, ref_pq[1]);
107
108 int ref_ret_vals[2] =
109 {ref_ret_val,
110 // remove p/q bits
111 (ref_ret_val & (~(1+2+4+8))) |
112 // move p_on_a bit to q_on_b
113 ((ref_ret_val & p_on_a)?(q_on_b):(0)) |
114 // move q_on_a bit to p_on_b
115 ((ref_ret_val & q_on_a)?(p_on_b):(0)) |
116 // move p_on_b bit to q_on_a
117 ((ref_ret_val & p_on_b)?(q_on_a):(0)) |
118 // move q_on_b bit to p_on_a
119 ((ref_ret_val & q_on_b)?(p_on_a):(0))};
120
121 // edge order (results have to be independent of the order of both edge)
122 for (int i = 0; i < 2; ++i) {
123 // vertex order of first edge
124 for (int j = 0; j < 2; ++j) {
125 // vertex order of second edge
126 for (int k = 0; k < 2; ++k) {
127
128 double p[3], q[3];
129 int ret_val =
131 edge_types[i], edges[i][j], edges[i][j^1],
132 edge_types[i^1], edges[i^1][k], edges[i^1][k^1],
133 p, q);
135 p, q, ret_val, ref_pq[i], ref_pq[i^1], ref_ret_vals[i]);
136 }
137 }
138 }
139}
140
141void test_cxc(double lon_a, double lat_a, double lon_b, double lat_b,
142 double lon_c, double lat_c, double lon_d, double lat_d,
143 enum yac_edge_type edge_type_a, enum yac_edge_type edge_type_b,
144 double lon_ref_p, double lat_ref_p,
145 double lon_ref_q, double lat_ref_q, int ref_ret_val) {
146
147 test_cxc_rad(lon_a*YAC_RAD, lat_a*YAC_RAD, lon_b*YAC_RAD, lat_b*YAC_RAD,
148 lon_c*YAC_RAD, lat_c*YAC_RAD, lon_d*YAC_RAD, lat_d*YAC_RAD,
149 edge_type_a, edge_type_b, lon_ref_p*YAC_RAD, lat_ref_p*YAC_RAD,
150 lon_ref_q*YAC_RAD, lat_ref_q*YAC_RAD, ref_ret_val);
151}
152
153static double adjust_lon(double lon, double ref) {
154 while (lon < ref - 180) lon += 360;
155 while (lon > ref + 180) lon -= 360;
156 return lon;
157}
158
160 enum yac_edge_type edge_type,
161 double lon_a, double lat_a, double lon_b, double lat_b,
162 double * lon_middle, double * lat_middle) {
163
164 double a[3], b[3];
165 LLtoXYZ_deg(lon_a, lat_a, a);
166 LLtoXYZ_deg(lon_b, lat_b, b);
167
169 (edge_type == YAC_GREAT_CIRCLE_EDGE) ||
170 (edge_type == YAC_LON_CIRCLE_EDGE) ||
171 (edge_type == YAC_LAT_CIRCLE_EDGE),
172 "ERROR(get_edge_middle_point): invalid edge_type")
173
174 switch (edge_type) {
175 default:
176 case (YAC_LON_CIRCLE_EDGE):
177 case (YAC_GREAT_CIRCLE_EDGE): {
178 double middle[3];
179 middle[0] = a[0] + b[0];
180 middle[1] = a[1] + b[1];
181 middle[2] = a[2] + b[2];
182
183 normalise_vector(middle);
184
185 XYZtoLL(middle, lon_middle, lat_middle);
186 *lon_middle /= YAC_RAD;
187 *lat_middle /= YAC_RAD;
188 break;
189 }
190 case (YAC_LAT_CIRCLE_EDGE): {
191 *lon_middle = (lon_a + adjust_lon(lon_b, lon_a))*0.5;
192 *lat_middle = lat_a;
193 }
194 }
195}
#define YAC_ASSERT(exp, msg)
#define YAC_RAD
static int points_are_identically(double const *a, double const *b)
Definition geometry.h:594
static void LLtoXYZ_deg(double lon, double lat, double p_out[])
Definition geometry.h:269
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 void normalise_vector(double v[])
Definition geometry.h:635
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
static void XYZtoLL(double const p_in[], double *lon, double *lat)
static void test_results_vec(double p[3], double q[3], int ret_val, double ref_p[3], double ref_q[3], int ref_ret_value)
Definition test_cxc.c:25
void test_cxc(double lon_a, double lat_a, double lon_b, double lat_b, double lon_c, double lat_c, double lon_d, double lat_d, enum yac_edge_type edge_type_a, enum yac_edge_type edge_type_b, double lon_ref_p, double lat_ref_p, double lon_ref_q, double lat_ref_q, int ref_ret_val)
Definition test_cxc.c:141
static double adjust_lon(double lon, double ref)
Definition test_cxc.c:153
@ p_on_a
Definition test_cxc.c:18
@ q_on_b
Definition test_cxc.c:21
@ q_on_a
Definition test_cxc.c:19
@ circles_are_identical
Definition test_cxc.c:22
@ error
Definition test_cxc.c:17
@ p_on_b
Definition test_cxc.c:20
void test_cxc_rad(double lon_a, double lat_a, double lon_b, double lat_b, double lon_c, double lat_c, double lon_d, double lat_d, enum yac_edge_type edge_type_a, enum yac_edge_type edge_type_b, double lon_ref_p, double lat_ref_p, double lon_ref_q, double lat_ref_q, int ref_ret_val)
Definition test_cxc.c:90
void get_edge_middle_point(enum yac_edge_type edge_type, double lon_a, double lat_a, double lon_b, double lat_b, double *lon_middle, double *lat_middle)
Definition test_cxc.c:159
#define PUT_ERR(string)
Definition tests.h:10
double(* p)(double lon, double lat)
Definition toy_scrip.c:119
static void LLtoXYZ(double lon, double lat, double p_out[])
Definition toy_scrip.c:587