test_senc2d_utils.h (8353B)
1 /* Copyright (C) 2018-2021, 2023, 2024 |Méso|Star> (contact@meso-star.com) 2 * 3 * This program is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation, either version 3 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 16 #ifndef TEST_SENC2_UTILS_H 17 #define TEST_SENC2_UTILS_H 18 19 #include <rsys/rsys.h> 20 #include <rsys/mem_allocator.h> 21 #include <rsys/stretchy_array.h> 22 #include <rsys/double2.h> 23 24 #include <stdio.h> 25 26 #define OK(Expr) CHK((Expr) == RES_OK) 27 #define BA(Expr) CHK((Expr) == RES_BAD_ARG) 28 #define BO(Expr) CHK((Expr) == RES_BAD_OP) 29 30 /****************************************************************************** 31 * Geometry 32 *****************************************************************************/ 33 /* Distorded square */ 34 static const double 35 box_vertices[4/*#vertices*/ * 2/*#coords per vertex*/] = { 36 0.1, 0.0, 37 1.0, 0.0, 38 0.0, 1.1, 39 1.0, 1.0 40 }; 41 /* Need a true square for some tests */ 42 static const double 43 square_vertices[4/*#vertices*/ * 2/*#coords per vertex*/] = { 44 0.0, 0.0, 45 1.0, 0.0, 46 0.0, 1.0, 47 1.0, 1.0 48 }; 49 static const unsigned 50 nvertices = sizeof(box_vertices) / (2 * sizeof(*box_vertices)); 51 STATIC_ASSERT(sizeof(box_vertices) == sizeof(square_vertices), 52 The_2_geometries_must_have_the_same_number_of_vertices); 53 54 /* The following array lists the indices toward the 2D vertices of each 55 * segment. 56 * Y 57 * 2----3 | 58 * | | 0----X 59 * | | 60 * 0----1 61 */ 62 static const unsigned 63 box_indices[4/*#segments*/ * 2/*#indices per segment*/] = { 64 0, 2, 65 2, 3, 66 3, 1, 67 1, 0 68 }; 69 static const unsigned 70 nsegments = sizeof(box_indices) / (2 * sizeof(*box_indices)); 71 72 struct context { 73 const double* positions; 74 const unsigned* indices; 75 const unsigned* front_media; 76 const unsigned* back_media; 77 const unsigned* properties; 78 void* custom; 79 double offset[2]; 80 double scale; 81 char reverse_vrtx, reverse_med; 82 }; 83 #define CONTEXT_NULL__ {\ 84 NULL, NULL, NULL, NULL, NULL, NULL, {0,0}, 1, 0, 0\ 85 } 86 87 static const unsigned medium0[4] = { 0, 0, 0, 0 }; 88 static const unsigned medium1[4] = { 1, 1, 1, 1 }; 89 static const unsigned medium2[4] = { 2, 2, 2, 2 }; 90 static const unsigned medium1_3[4] = { 1, 1, 3, 1 }; 91 static const unsigned medium1_back0[4] = { 1, 1, 1, 0 }; 92 static const unsigned medium1_front0[4] = { 1, 0, 1, 1 }; 93 94 static INLINE void 95 get_indices(const unsigned iseg, unsigned ids[2], void* context) 96 { 97 const struct context* ctx = context; 98 ASSERT(ids && ctx); 99 ids[ctx->reverse_vrtx ? 1 : 0] = ctx->indices[iseg * 2 + 0]; 100 ids[ctx->reverse_vrtx ? 0 : 1] = ctx->indices[iseg * 2 + 1]; 101 } 102 103 static INLINE void 104 get_position(const unsigned ivert, double pos[2], void* context) 105 { 106 const struct context* ctx = context; 107 ASSERT(pos && ctx); 108 pos[0] = ctx->positions[ivert * 2 + 0] * ctx->scale + ctx->offset[0]; 109 pos[1] = ctx->positions[ivert * 2 + 1] * ctx->scale + ctx->offset[1]; 110 } 111 112 static INLINE void 113 get_media(const unsigned iseg, unsigned medium[2], void* context) 114 { 115 const struct context* ctx = context; 116 ASSERT(medium && ctx); 117 medium[ctx->reverse_med ? 1 : 0] = ctx->front_media[iseg]; 118 medium[ctx->reverse_med ? 0 : 1] = ctx->back_media[iseg]; 119 } 120 121 static INLINE void 122 get_media_from_properties(const unsigned iseg, unsigned medium[2], void* context) 123 { 124 const struct context* ctx = context; 125 ASSERT(medium && ctx); 126 medium[ctx->reverse_med ? 1 : 0] = ctx->properties[3 * iseg + 0]; 127 medium[ctx->reverse_med ? 0 : 1] = ctx->properties[3 * iseg + 1]; 128 } 129 130 /****************************************************************************** 131 * Miscellaneous 132 *****************************************************************************/ 133 static INLINE void 134 dump_global 135 (struct senc2d_scene* scn, 136 const char* name) 137 { 138 FILE* stream; 139 unsigned segments_count, vertices_count, i; 140 141 ASSERT(scn && name); 142 143 OK(senc2d_scene_get_vertices_count(scn, &vertices_count)); 144 OK(senc2d_scene_get_segments_count(scn, &segments_count)); 145 146 stream = fopen(name, "w"); 147 CHK(stream); 148 FOR_EACH(i, 0, vertices_count) { 149 double tmp[2]; 150 OK(senc2d_scene_get_vertex(scn, i, tmp)); 151 fprintf(stream, "v %g %g\n", SPLIT2(tmp)); 152 } 153 FOR_EACH(i, 0, segments_count) { 154 unsigned indices[2]; 155 OK(senc2d_scene_get_segment(scn, i, indices)); 156 fprintf(stream, "l %u %u\n", 1 + indices[0], 1 + indices[1]); 157 } 158 fclose(stream); 159 } 160 161 static INLINE void 162 dump_enclosure 163 (struct senc2d_scene* scn, 164 const unsigned enc, 165 const char* name) 166 { 167 struct senc2d_enclosure* enclosure; 168 struct senc2d_enclosure_header header; 169 FILE* stream; 170 unsigned count, i; 171 172 ASSERT(scn && name); 173 174 SENC2D(scene_get_enclosure_count(scn, &count)); 175 ASSERT(enc < count); 176 OK(senc2d_scene_get_enclosure(scn, enc, &enclosure)); 177 OK(senc2d_enclosure_get_header(enclosure, &header)); 178 179 stream = fopen(name, "w"); 180 CHK(stream); 181 FOR_EACH(i, 0, header.vertices_count) { 182 double tmp[2]; 183 OK(senc2d_enclosure_get_vertex(enclosure, i, tmp)); 184 fprintf(stream, "v %g %g\n", SPLIT2(tmp)); 185 } 186 FOR_EACH(i, 0, header.primitives_count) { 187 unsigned indices[2]; 188 OK(senc2d_enclosure_get_segment(enclosure, i, indices)); 189 fprintf(stream, "l %u %u\n", 1+indices[0], 1+indices[1]); 190 } 191 OK(senc2d_enclosure_ref_put(enclosure)); 192 fclose(stream); 193 } 194 195 static INLINE void 196 check_memory_allocator(struct mem_allocator* allocator) 197 { 198 if(MEM_ALLOCATED_SIZE(allocator)) { 199 char dump[1024]; 200 MEM_DUMP(allocator, dump, sizeof(dump)); 201 fprintf(stderr, "%s\n", dump); 202 FATAL("Memory leaks.\n"); 203 } 204 } 205 206 /****************************************************************************** 207 * Circle functions 208 *****************************************************************************/ 209 static INLINE void 210 create_circle 211 (const double radius, 212 const unsigned nslices, 213 struct context* ctx) 214 { 215 double step_theta; 216 unsigned itheta; 217 unsigned islice; 218 double* d = NULL; 219 unsigned* u = NULL; 220 ASSERT(radius > 0 && nslices >= 3 && ctx); 221 222 step_theta = 2 * PI / (double)nslices; 223 FOR_EACH(itheta, 0, nslices) { 224 const double theta = (double)itheta * step_theta; 225 const double x = cos(theta); 226 const double y = sin(theta); 227 sa_push(d, x * radius); 228 sa_push(d, y * radius); 229 } 230 ctx->positions = d; 231 232 FOR_EACH(islice, 0, nslices) { 233 const unsigned v0 = islice; 234 const unsigned v1 = ((islice + 1) % nslices); 235 sa_push(u, v0); 236 sa_push(u, v1); 237 } 238 ctx->indices = u; 239 } 240 241 static INLINE void 242 circle_release(struct context* ctx) 243 { 244 ASSERT(ctx); 245 sa_release(ctx->positions); 246 sa_release(ctx->indices); 247 ctx->positions = NULL; 248 ctx->indices = NULL; 249 } 250 251 /****************************************************************************** 252 * Check functions 253 *****************************************************************************/ 254 /* Compare the iseg-th segment of enclosure with a segment described by seg2 & vertices2 */ 255 static INLINE void 256 cmp_seg 257 (const unsigned iseg, 258 const struct senc2d_enclosure* enclosure, 259 const unsigned seg2[2], 260 const double* vertices2, 261 int* seg_eq, 262 int* seg_reversed) 263 { 264 unsigned seg1[2]; 265 double s1[2][2]; 266 double s2[2][2]; 267 unsigned seg1_eq[2] = { 2, 2 }; 268 unsigned i, j; 269 270 ASSERT(enclosure && seg2 && vertices2 && seg_eq && seg_reversed); 271 272 OK(senc2d_enclosure_get_segment(enclosure, iseg, seg1)); 273 FOR_EACH(i, 0, 2) { 274 OK(senc2d_enclosure_get_vertex(enclosure, seg1[i], s1[i])); 275 d2_set(s2[i], vertices2 + (2 * seg2[i])); 276 } 277 FOR_EACH(i, 0, 2) { 278 FOR_EACH(j, 0, 2) { 279 if(d2_eq(s1[i], s2[j])) { 280 seg1_eq[i] = j; 281 break; 282 } 283 } 284 } 285 FOR_EACH(i, 0, 2) { 286 if(seg1_eq[i] == 2) { 287 *seg_eq = 0; 288 return; 289 } 290 if(seg1_eq[i] == seg1_eq[(i + 1) % 2]) { 291 *seg_eq = 0; 292 return; 293 } 294 } 295 /* Same 2 vertices */ 296 *seg_eq = 1; 297 298 *seg_reversed = (0 != seg1_eq[0]); 299 ASSERT(*seg_reversed == (1 != seg1_eq[1])); 300 } 301 302 #endif /* TEST_SENC2_UTILS_H */