YetAnotherCoupler 3.1.1
Loading...
Searching...
No Matches
grid_cell.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 <string.h>
7#include <stdio.h>
8
9#include "grid_cell.h"
10#include "utils_core.h"
11#include "ensure_array_size.h"
12#include "geometry.h"
13
14void yac_init_grid_cell(struct grid_cell * cell) {
15
16 cell->coordinates_xyz = NULL;
17 cell->edge_type = NULL;
18 cell->num_corners = 0;
19 cell->array_size = 0;
20}
21
23 struct grid_cell * cell, size_t num_corners) {
24
25 if (num_corners > cell->array_size) {
26 cell->coordinates_xyz = xrealloc(cell->coordinates_xyz, num_corners *
27 sizeof(*(cell->coordinates_xyz)));
28 cell->edge_type = xrealloc(cell->edge_type, num_corners *
29 sizeof(*(cell->edge_type)));
30 cell->array_size = num_corners;
31 }
32}
33
34void yac_copy_grid_cell(struct grid_cell in_cell, struct grid_cell * out_cell) {
35
36 ensure_grid_cell_size(out_cell, in_cell.num_corners);
37 memcpy(out_cell->coordinates_xyz, in_cell.coordinates_xyz,
38 in_cell.num_corners * sizeof(*(out_cell->coordinates_xyz)));
39 memcpy(out_cell->edge_type, in_cell.edge_type,
40 in_cell.num_corners * sizeof(*(out_cell->edge_type)));
41 out_cell->num_corners = in_cell.num_corners;
42}
43
44void yac_free_grid_cell(struct grid_cell * cell) {
45
46 if (cell->coordinates_xyz != NULL) free(cell->coordinates_xyz);
47 if (cell->edge_type != NULL) free(cell->edge_type);
48
50}
51
52static void set_triangle(
53 struct grid_cell cell, struct grid_cell * triangle, size_t idx[3]) {
54
55 ensure_grid_cell_size(triangle, 3);
56 for (size_t i = 0; i < 3; ++i) {
57 size_t curr_idx = idx[i];
58 triangle->coordinates_xyz[i][0] = cell.coordinates_xyz[curr_idx][0];
59 triangle->coordinates_xyz[i][1] = cell.coordinates_xyz[curr_idx][1];
60 triangle->coordinates_xyz[i][2] = cell.coordinates_xyz[curr_idx][2];
61 triangle->edge_type[i] = GREAT_CIRCLE_EDGE;
62 }
63 triangle->num_corners = 3;
64}
65
67 struct grid_cell cell, size_t start_corner, struct grid_cell * triangles) {
68
69 size_t num_corners = cell.num_corners;
70
71 YAC_ASSERT(num_corners >= 3, "ERROR(yac_triangulate_cell): number < 3")
72
73 switch (num_corners) {
74 case(3):
75 if (start_corner == 0) {
76 yac_copy_grid_cell(cell, triangles);
77 return;
78 }
79
81 cell, triangles,
82 (size_t [3]){(size_t)((start_corner + 0)%3),
83 (size_t)((start_corner + 1)%3),
84 (size_t)((start_corner + 2)%3)});
85 return;
86 case(4): {
87 size_t idx[5] = {(size_t)((start_corner + 0)%num_corners),
88 (size_t)((start_corner + 1)%num_corners),
89 (size_t)((start_corner + 2)%num_corners),
90 (size_t)((start_corner + 3)%num_corners),
91 (size_t)((start_corner + 0)%num_corners)};
92 set_triangle(cell, triangles + 0, &(idx[0]));
93 set_triangle(cell, triangles + 1, &(idx[2]));
94 return;
95 }
96 case(5): {
97 size_t idx[7] = {(size_t)((start_corner + 0)%num_corners),
98 (size_t)((start_corner + 1)%num_corners),
99 (size_t)((start_corner + 2)%num_corners),
100 (size_t)((start_corner + 3)%num_corners),
101 (size_t)((start_corner + 4)%num_corners),
102 (size_t)((start_corner + 0)%num_corners),
103 (size_t)((start_corner + 2)%num_corners)};
104 set_triangle(cell, triangles + 0, &(idx[0]));
105 set_triangle(cell, triangles + 1, &(idx[2]));
106 set_triangle(cell, triangles + 2, &(idx[4]));
107 return;
108 }
109 case(6): {
110 size_t idx[9] = {(size_t)((start_corner + 0)%num_corners),
111 (size_t)((start_corner + 1)%num_corners),
112 (size_t)((start_corner + 2)%num_corners),
113 (size_t)((start_corner + 3)%num_corners),
114 (size_t)((start_corner + 4)%num_corners),
115 (size_t)((start_corner + 5)%num_corners),
116 (size_t)((start_corner + 0)%num_corners),
117 (size_t)((start_corner + 2)%num_corners),
118 (size_t)((start_corner + 4)%num_corners)};
119 set_triangle(cell, triangles + 0, &(idx[0]));
120 set_triangle(cell, triangles + 1, &(idx[2]));
121 set_triangle(cell, triangles + 2, &(idx[4]));
122 set_triangle(cell, triangles + 3, &(idx[6]));
123 return;
124 }
125 default: {
126
127 size_t temp_corner_indices[2*num_corners];
128 size_t j = 0;
129 for (size_t i = start_corner; i < num_corners; ++i, ++j)
130 temp_corner_indices[j] = i;
131 for (size_t i = 0; i < start_corner; ++i, ++j)
132 temp_corner_indices[j] = i;
133
134 for (size_t i = 0; i < num_corners - 2; ++i, ++j) {
136 cell, triangles + i, &(temp_corner_indices[2 * i]));
137 temp_corner_indices[j] = temp_corner_indices[2 * i];
138 }
139 return;
140 }
141 }
142}
143
145 size_t const * corner_indices, size_t num_corners, size_t start_corner,
146 size_t (*triangle_indices)[3]) {
147
149 num_corners >= 3, "ERROR(yac_triangulate_corner_indices): number < 3")
150
151 switch (num_corners) {
152 case(3):
153 triangle_indices[0][0] = corner_indices[(start_corner + 0)%3];
154 triangle_indices[0][1] = corner_indices[(start_corner + 1)%3];
155 triangle_indices[0][2] = corner_indices[(start_corner + 2)%3];
156 return;
157 case(4):
158 triangle_indices[0][0] = corner_indices[start_corner];
159 triangle_indices[0][1] = corner_indices[(start_corner + 1)%4];
160 triangle_indices[0][2] = corner_indices[(start_corner + 2)%4];
161 triangle_indices[1][0] = corner_indices[(start_corner + 2)%4];
162 triangle_indices[1][1] = corner_indices[(start_corner + 3)%4];
163 triangle_indices[1][2] = corner_indices[start_corner];
164 return;
165 case(6):
166 triangle_indices[0][0] = corner_indices[start_corner];
167 triangle_indices[0][1] = corner_indices[(start_corner + 1)%6];
168 triangle_indices[0][2] = corner_indices[(start_corner + 2)%6];
169 triangle_indices[1][0] = corner_indices[(start_corner + 2)%6];
170 triangle_indices[1][1] = corner_indices[(start_corner + 3)%6];
171 triangle_indices[1][2] = corner_indices[(start_corner + 4)%6];
172 triangle_indices[2][0] = corner_indices[(start_corner + 4)%6];
173 triangle_indices[2][1] = corner_indices[(start_corner + 5)%6];
174 triangle_indices[2][2] = corner_indices[start_corner];
175 triangle_indices[3][0] = corner_indices[start_corner];
176 triangle_indices[3][1] = corner_indices[(start_corner + 2)%6];
177 triangle_indices[3][2] = corner_indices[(start_corner + 4)%6];
178 return;
179 default: {
180 size_t temp_corner_indices[2*num_corners];
181 size_t j = 0;
182 for (size_t i = start_corner; i < num_corners; ++i, ++j)
183 temp_corner_indices[j] = corner_indices[i];
184 for (size_t i = 0; i < start_corner; ++i, ++j)
185 temp_corner_indices[j] = corner_indices[i];
186
187 for (size_t i = 0; i < num_corners - 2; ++i, ++j) {
188 memcpy(triangle_indices[i], temp_corner_indices + 2 * i,
189 3 * sizeof(*temp_corner_indices));
190 temp_corner_indices[j] = temp_corner_indices[2 * i];
191 }
192 return;
193 }
194 }
195}
196
197#ifdef YAC_DEBUG_GRID_CELL
198void print_grid_cell(FILE * stream, struct grid_cell cell, char * name) {
199
200 char * out = NULL;
201 size_t out_array_size = 0;
202 size_t out_size = 0;
203
204 if (name != NULL) {
205
206 out_size = strlen(name) + 1 + 1 + 1;
207 ENSURE_ARRAY_SIZE(out, out_array_size, out_size);
208
209 strcpy(out, name);
210 strcat(out, ":\n");
211 }
212
213 for (size_t i = 0; i < cell.num_corners; ++i) {
214
215 char buffer[1024];
216
217 double coordinates_x, coordinates_y;
218 XYZtoLL(cell.coordinates_xyz[i], &coordinates_x, &coordinates_y);
219 sprintf(buffer, "%d x %.16f y %.16f %s\n", i,
220 coordinates_x, coordinates_y,
221 (cell.edge_type[i] == LAT_CIRCLE_EDGE)?("LAT_CIRCLE_EDGE"):
222 ((cell.edge_type[i] == LON_CIRCLE_EDGE)?("LON_CIRCLE_EDGE"):
223 ("GREAT_CIRCLE_EDGE")));
224
225 out_size += strlen(buffer);
226
227 ENSURE_ARRAY_SIZE(out, out_array_size, out_size);
228
229 strcat(out, buffer);
230 }
231
232 if (out != NULL)
233 fputs(out, stream);
234
235 free(out);
236}
237#endif
238
#define ENSURE_ARRAY_SIZE(arrayp, curr_array_size, req_size)
static void XYZtoLL(double const p_in[], double *lon, double *lat)
Definition geometry.h:318
static void ensure_grid_cell_size(struct grid_cell *cell, size_t num_corners)
Definition grid_cell.c:22
void yac_copy_grid_cell(struct grid_cell in_cell, struct grid_cell *out_cell)
Definition grid_cell.c:34
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 void set_triangle(struct grid_cell cell, struct grid_cell *triangle, size_t idx[3])
Definition grid_cell.c:52
void yac_init_grid_cell(struct grid_cell *cell)
Definition grid_cell.c:14
void yac_triangulate_cell(struct grid_cell cell, size_t start_corner, struct grid_cell *triangles)
Definition grid_cell.c:66
void yac_free_grid_cell(struct grid_cell *cell)
Definition grid_cell.c:44
@ LAT_CIRCLE_EDGE
latitude circle
Definition grid_cell.h:12
@ GREAT_CIRCLE_EDGE
great circle
Definition grid_cell.h:11
@ LON_CIRCLE_EDGE
longitude circle
Definition grid_cell.h:13
#define xrealloc(ptr, size)
Definition ppm_xfuncs.h:67
double(* coordinates_xyz)[3]
Definition grid_cell.h:17
enum yac_edge_type * edge_type
Definition grid_cell.h:18
size_t array_size
Definition grid_cell.h:20
size_t num_corners
Definition grid_cell.h:19
#define YAC_ASSERT(exp, msg)