sgX2.h (18481B)
1 /* Copyright (C) 2019, 2020, 2023 |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 STAR_GEOMETRY_X_2D_H__ 17 #define STAR_GEOMETRY_X_2D_H__ 18 19 #include <star/sg2.h> 20 #include <star/sg2d_senc2d_helper.h> 21 #include <star/sg2d_s2d_helper.h> 22 #include <rsys/rsys.h> 23 24 #include <stdio.h> 25 26 /* This file can be used in conjunction with sgX3.h from the the star-geometry 27 * library to write code for both 2D and 3D geometries using the following 28 * pattern: 29 * 30 * #if (DIM==2) 31 * #include <star/sgX2d.h> 32 * #elif (DIM==3) 33 * #include <star/sgX3.h> 34 * #else 35 * #error DIM should be defined; possible values are 2 and 3 36 * #endif 37 * 38 * Then use the sgX_... types and functions in your code. 39 * 40 * Definitions from sgX2d.h and sgX3.h cannot be visible at the same time 41 * as some of them conflict. 42 */ 43 44 /* Helper macro that asserts if the invocation of the StarGeometry2D function 45 * `Func' returns an error. One should use this macro on StarEnc function calls 46 * for which no explicit error checking is performed. */ 47 #ifndef NDEBUG 48 #define SGX(Func) ASSERT(sgX_ ## Func == RES_OK) 49 #else 50 #define SGX(Func) sgX_ ## Func 51 #endif 52 53 /* Forward declaration of external opaque data types */ 54 struct logger; 55 struct mem_allocator; 56 57 /* Forward declaration of the star-geometry-2D opaque data types. These data 58 * types are ref counted. Once created the caller implicitly owns the created 59 * data, i.e. its reference counter is set to 1. The sdis_<TYPE>_ref_<get|put> 60 * functions get or release a reference on the data, i.e. they increment or 61 * decrement the reference counter, respectively. When this counter reaches 0, 62 * the object is silently destroyed and cannot be used anymore. */ 63 typedef struct sg2d_device sgX_device; 64 typedef struct sg2d_geometry sgX_geometry; 65 66 /****************************************************************************** 67 * The dimension of the geometry used in the library. 68 *****************************************************************************/ 69 #define SGX_GEOMETRY_DIMENSION SG2D_GEOMETRY_DIMENSION 70 71 /****************************************************************************** 72 * A type to list the different user properties attached to segments. 73 *****************************************************************************/ 74 enum sgX_property_type { 75 SGX_FRONT = SG2D_FRONT, 76 SGX_BACK = SG2D_BACK, 77 SGX_INTFACE = SG2D_INTFACE, 78 SGX_PROP_TYPES_COUNT__ = SG2D_PROP_TYPES_COUNT__ 79 }; 80 81 /****************************************************************************** 82 * A type to list the different possible partitions of segments. 83 *****************************************************************************/ 84 enum sgX_obj_dump_content { 85 SGX_OBJ_DUMP_MERGE_CONFLICTS = SG2D_OBJ_DUMP_MERGE_CONFLICTS, 86 SGX_OBJ_DUMP_PROPERTY_CONFLICTS = SG2D_OBJ_DUMP_PROPERTY_CONFLICTS, 87 SGX_OBJ_DUMP_VALID_PRIMITIVE = SG2D_OBJ_DUMP_VALID_PRIMITIVE, 88 SGX_OBJ_DUMP_ALL = SG2D_OBJ_DUMP_ALL 89 }; 90 91 /****************************************************************************** 92 * A type to list the different qualifiers of C code variable output. 93 *****************************************************************************/ 94 enum sgX_c_dump_qualifiers { 95 SGX_C_DUMP_CONST = SG2D_C_DUMP_CONST, 96 SGX_C_DUMP_STATIC = SG2D_C_DUMP_STATIC 97 }; 98 99 /****************************************************************************** 100 * The value that should be used for properties attached to segments (i.e. 101 * media or interface) when let unspecified. 102 * SG2D_UNSPECIFIED_PROPERTY can be used for a property that has already been 103 * defined; in this case the previous value will remain. 104 *****************************************************************************/ 105 #define SGX_UNSPECIFIED_PROPERTY SG2D_UNSPECIFIED_PROPERTY 106 107 /***************************************************************************** 108 * A type to hold callbacks for sg2d_geometry_add. 109 ****************************************************************************/ 110 typedef struct sg2d_geometry_add_callbacks sgX_geometry_add_callbacks; 111 #define SGX_ADD_CALLBACKS_NULL__ SG2D_ADD_CALLBACKS_NULL__ 112 113 BEGIN_DECLS 114 115 /****************************************************************************** 116 * A helper function on properties compatibility. 117 *****************************************************************************/ 118 static FINLINE int 119 sgX_compatible_property 120 (const unsigned p1, 121 const unsigned p2) 122 { 123 return sg2d_compatible_property(p1, p2); 124 } 125 126 /****************************************************************************** 127 * star-geometry device. It is an handle toward the star-geometry library. 128 * It manages the star-geometry resources. 129 *****************************************************************************/ 130 static FINLINE res_T 131 sgX_device_create 132 (struct logger* logger, /* Can be NULL <=> use default logger */ 133 struct mem_allocator* allocator, /* Can be NULL <=> use default allocator */ 134 const int verbose, /* Verbosity level */ 135 sgX_device** dev) 136 { 137 return sg2d_device_create(logger, allocator, verbose, dev); 138 } 139 140 static FINLINE res_T 141 sgX_device_ref_get 142 (sgX_device* dev) 143 { 144 return sg2d_device_ref_get(dev); 145 } 146 147 static FINLINE res_T 148 sgX_device_ref_put 149 (sgX_device* dev) 150 { 151 return sg2d_device_ref_put(dev); 152 } 153 154 /****************************************************************************** 155 * star-geometry geometry. 156 * It stores decorated geometry accumulated through calls to sg2d_geometry_add, 157 * information related to this geometry and its creation process, including 158 * merge conflicts. 159 *****************************************************************************/ 160 /* Create a geometry that can be used to accumulate vertices and segments 161 * decorated with properties. */ 162 static FINLINE res_T 163 sgX_geometry_create 164 (sgX_device* dev, 165 sgX_geometry** geometry) 166 { 167 return sg2d_geometry_create(dev, geometry); 168 } 169 170 /* Reserve memory according to anticipated geometry size. */ 171 static FINLINE res_T 172 sgX_geometry_reserve 173 (sgX_geometry* geometry, 174 const unsigned vertices_count, 175 const unsigned segments_count, 176 const unsigned properties_count) 177 { 178 return sg2d_geometry_reserve( 179 geometry, vertices_count, segments_count, properties_count); 180 } 181 182 /* Add a new set of 2D vertices and segments to the geometry; segments can 183 * be decorated with 3 properties (front and back media and interface) that can 184 * be let unspecified using the SG2D_UNSPECIFIED_PROPERTY special value. 185 * Vertices can be duplicates and are silently deduplicated, always valid. 186 * Segments can be duplicates, but this can be ruled invalid due to property 187 * inconsistency. Segment duplicates are silently deduplicated, even if 188 * invalid. Consistency is to be understood as the consistency of the 189 * successive values for the same property across calls of sg2d_geometry_add, 190 * not as the consistency of the values of the 3 properties of a segment at 191 * some given time (this question has its own callback (validate) in the 192 * sg2d_geometry_validate_properties API call). 193 * Duplicate segments validity is either ruled by the user-provided 194 * merge_segment callback, or is just a matter of properties consistency if no 195 * callback is provided. In either case, sg2d_geometry_add never stops 196 * prematurely nor returns an error code due to a merge conflict. 197 * - if provided, the callback must return the consistency status using the 198 * merge_conflict_status int* paramater (0 for consistent; any other value 199 * for inconsistent, this value being recorded); regardless of 200 * merge_conflict_status, the callback can change the properties of the 201 * segment before the SG2D_UNSPECIFIED_PROPERTY overwriting step; 202 * - if not, a non-SG2D_UNSPECIFIED_PROPERTY is only consistent with itself and 203 * with SG2D_UNSPECIFIED_PROPERTY (if inconsistent, merge_conflict_status is 204 * set to 1 and recorded) ; regardless of merge_conflict_status, a 205 * non-SG2D_UNSPECIFIED_PROPERTY property is never overridden. 206 * When deduplicating segments, the first occurence remains (with its 207 * original index in user world). After consistency being computed, a final 208 * step consists in rewriting SG2D_UNSPECIFIED_PROPERTY properties if the merged 209 * property is defined. */ 210 static FINLINE res_T 211 sgX_geometry_add 212 (sgX_geometry* geometry, 213 const unsigned vertices_count, 214 const unsigned segments_count, 215 const sgX_geometry_add_callbacks* callbacks, 216 void* context) /* Can be NULL */ 217 { 218 return sg2d_geometry_add( 219 geometry, vertices_count, segments_count, callbacks, context); 220 } 221 222 /* Apply a validation callback on each segment included in this geometry that 223 * is not already flagged with a merge error. If validate returns a non-RES_OK 224 * value, the validation stops and returns the same error value; on the other 225 * hand, validation goes to the end regardless of properties conflicts. 226 * The properties_conflict_status argument can be set to any value. Any non-0 227 * value is accounted for a conflict and is kept as-is in dumps, allowing 228 * different shades of conflict. 229 * If validation is processed again, the properties conflict count is reset, 230 * as well as the properties_conflict_status status of the segments. */ 231 static FINLINE res_T 232 sgX_geometry_validate_properties 233 (sgX_geometry* geometry, 234 res_T(*validate) 235 (const unsigned iseg, 236 const unsigned properties[SGX_PROP_TYPES_COUNT__], 237 void* context, 238 int* properties_conflict_status), 239 void* context) /* Can be NULL */ 240 { 241 return sg2d_geometry_validate_properties(geometry, validate, context); 242 } 243 244 /* Get the number of unique vertices. */ 245 static FINLINE res_T 246 sgX_geometry_get_unique_vertices_count 247 (const sgX_geometry* geometry, 248 unsigned* count) 249 { 250 return sg2d_geometry_get_unique_vertices_count(geometry, count); 251 } 252 253 /* Get the ivtx_th vertex. */ 254 static FINLINE res_T 255 sgX_geometry_get_unique_vertex 256 (const sgX_geometry* geometry, 257 const unsigned ivtx, 258 double coord[SGX_GEOMETRY_DIMENSION]) 259 { 260 return sg2d_geometry_get_unique_vertex(geometry, ivtx, coord); 261 } 262 263 /* Get the number of segments added to the geometry, regardless of unicity. */ 264 static FINLINE res_T 265 sgX_geometry_get_added_primitives_count 266 (const sgX_geometry* geometry, 267 unsigned* count) 268 { 269 return sg2d_geometry_get_added_segments_count(geometry, count); 270 } 271 272 /* Get the number of unique segments. */ 273 static FINLINE res_T 274 sgX_geometry_get_unique_primitives_count 275 (const sgX_geometry* geometry, 276 unsigned* count) 277 { 278 return sg2d_geometry_get_unique_segments_count(geometry, count); 279 } 280 281 /* Get the vertex indices of the iseg_th unique segment. */ 282 static FINLINE res_T 283 sgX_geometry_get_unique_primitive_vertices 284 (const sgX_geometry* geometry, 285 const unsigned iseg, 286 unsigned indices[SGX_GEOMETRY_DIMENSION]) 287 { 288 return sg2d_geometry_get_unique_segment_vertices(geometry, iseg, indices); 289 } 290 291 /* Get the properties of the iseg_th unique segment. */ 292 static FINLINE res_T 293 sgX_geometry_get_unique_primitive_properties 294 (const sgX_geometry* geometry, 295 const unsigned iseg, 296 unsigned properties[SG2D_PROP_TYPES_COUNT__]) 297 { 298 return sg2d_geometry_get_unique_segment_properties( 299 geometry, iseg, properties); 300 } 301 302 /* Get the user ID of the iseg_th unique segment, that is the user world's 303 * index of the segment that first created this unique segment. 304 * User world index starts at 0 and increases for every segment that is 305 * submitted to sg2d_geometry_add calls, regardless of duplication or 306 * sg2d_geometry_add failures (non-RES_OK return value). */ 307 static FINLINE res_T 308 sgX_geometry_get_unique_primitive_user_id 309 (const sgX_geometry* geometry, 310 const unsigned iseg, 311 unsigned* user_id) 312 { 313 return sg2d_geometry_get_unique_segment_user_id(geometry, iseg, user_id); 314 } 315 316 /* Get the number of segments with (at least) one unspecified side. */ 317 static FINLINE res_T 318 sgX_geometry_get_unique_primitives_with_unspecified_side_count 319 (const sgX_geometry* geometry, 320 unsigned* count) 321 { 322 return sg2d_geometry_get_unique_segments_with_unspecified_side_count( 323 geometry, count); 324 } 325 326 /* Get the number of segments with unspecified interface. */ 327 static FINLINE res_T 328 sgX_geometry_get_unique_primitives_with_unspecified_interface_count 329 (const sgX_geometry* geometry, 330 unsigned* count) 331 { 332 return sg2d_geometry_get_unique_segments_with_unspecified_interface_count( 333 geometry, count); 334 } 335 336 /* Get the number of segments flagged with a merge conflict. */ 337 static FINLINE res_T 338 sgX_geometry_get_unique_primitives_with_merge_conflict_count 339 (const sgX_geometry* geometry, 340 unsigned* count) 341 { 342 return sg2d_geometry_get_unique_segments_with_merge_conflict_count( 343 geometry, count); 344 } 345 346 /* Get the number of segments flagged with a property conflict. Only meaningful 347 * after sg2d_geometry_validate_properties has been called. */ 348 static FINLINE res_T 349 sgX_geometry_get_unique_primitives_with_properties_conflict_count 350 (const sgX_geometry* geometry, 351 unsigned* count) 352 { 353 return sg2d_geometry_get_unique_segments_with_properties_conflict_count( 354 geometry, count); 355 } 356 357 /* Dump a geometry in the provided stream in the OBJ format. 358 * The geometry can include conflicts, but cannot be empty. Note that vertices 359 * in this output are 3D with Z==0, as OBJ files cannot define 2D vertices. 360 * The dump is made of the vertices and some segments, without their 361 * properties. The dumped segments are defined by the flags argument, that 362 * must be ORed enum sg2d_obj_dump_content values. 363 * The dumped segments are partitioned in the following groups: 364 * - Valid_segments 365 * - Merge_conflicts 366 * - Property_conflict */ 367 static FINLINE res_T 368 sgX_geometry_dump_as_obj 369 (const sgX_geometry* geometry, 370 FILE* stream, 371 const int flags) 372 { 373 return sg2d_geometry_dump_as_obj(geometry, stream, flags); 374 } 375 376 /* Dump a geometry in the provided stream in the VTK ascii format. 377 * The geometry can include conflicts, but cannot be empty. Note that POINTS 378 * in this output are 3D with Z==0, as VTK text files cannot define 2D POINTS. 379 * The dump is made of the vertices and segments, with most of their 380 * properties: 381 * - Front_medium (medium ID of the front side, INT_MAX for both unspecified 382 * and conflicted) 383 * - Back_medium (medium ID of the back side, INT_MAX for both unspecified and 384 * conflicted) 385 * - Interface (interface ID, INT_MAX for both unspecified and conflicted) 386 * - Merge_conflict (merge conflict status) 387 * - Property_conflict (property conflict status) 388 * - Created_at_sg2d_geometry_add (rank of the sg2d_geometry_add that created the 389 * segment) */ 390 static FINLINE res_T 391 sgX_geometry_dump_as_vtk 392 (const sgX_geometry* geometry, 393 FILE* stream) 394 { 395 return sg2d_geometry_dump_as_vtk(geometry, stream); 396 } 397 398 /* Dump the geometry as C code. 399 * The geometry cannot be empty and must be conflict-free. 400 * The C code defines the 5 variables: 401 * - [static] [const] unsigned <name_prefix>_vertices_count = N1; 402 * - [static] [const] double <name_prefix>_vertices[<N1>] = { .... }; 403 * - [static] [const] unsigned <name_prefix>_segments_count = N2; 404 * - [static] [const] unsigned <name_prefix>_segments[<N2>] = { .... }; 405 * - [static] [const] unsigned <name_prefix>_properties[<N3>] = { .... }; 406 * Where <N1> is 2 * vertices_count, <N2> is 2 * segments_count and <N3> is 407 * 3 * segments_count. 408 * The two qualifiers static and const are output or not according to flags; 409 * flags must be ORed enum sg2d_c_dump_qualifiers values. */ 410 static FINLINE res_T 411 sgX_geometry_dump_as_c_code 412 (const sgX_geometry* geometry, 413 FILE* stream, 414 const char* name_prefix, /* Can be NULL or "" */ 415 const int flags) 416 { 417 return sg2d_geometry_dump_as_c_code(geometry, stream, name_prefix, flags); 418 } 419 420 static FINLINE res_T 421 sgX_geometry_ref_get 422 (sgX_geometry* geometry) 423 { 424 return sg2d_geometry_ref_get(geometry); 425 } 426 427 static FINLINE res_T 428 sgX_geometry_ref_put 429 (sgX_geometry* geometry) 430 { 431 return sg2d_geometry_ref_put(geometry); 432 } 433 434 /****************************************************************************** 435 * StarGeometryXD to StarEnclosuresXD helper. 436 *****************************************************************************/ 437 438 /* Get vertex indices for the itri_th triangle. 439 * Suitable for use as get_indices callback in senc2d_scene_create calls. */ 440 static FINLINE void 441 sgX_sencX_geometry_get_indices 442 (const unsigned itri, 443 unsigned indices[SGX_GEOMETRY_DIMENSION], 444 void* ctx) 445 { 446 sg2d_senc_geometry_get_indices(itri, indices, ctx); 447 } 448 449 /* Get vertex indices for the itri_th triangle. 450 * Suitable for use as get_media callback in senc2d_scene_create calls. */ 451 static FINLINE void 452 sgX_sencX_geometry_get_media 453 (const unsigned itri, 454 unsigned media[2], 455 void* ctx) 456 { 457 sg2d_senc_geometry_get_media(itri, media, ctx); 458 } 459 460 /* Get vertex indices for the itri_th triangle. 461 * Suitable for use as get_position callback in senc2d_scene_create calls. */ 462 static FINLINE void 463 sgX_sencX_geometry_get_position 464 (const unsigned ivert, 465 double coord[SGX_GEOMETRY_DIMENSION], 466 void* ctx) 467 { 468 sg2d_senc_geometry_get_position(ivert, coord, ctx); 469 } 470 471 /****************************************************************************** 472 * StarGeometryXD to StarXD helper. 473 *****************************************************************************/ 474 475 /* Get vertex indices for the itri_th triangle. 476 * Suitable for use as get_indice callback in s2d_mesh_setup_indexed_vertices 477 * calls. */ 478 static FINLINE void 479 sgX_sXd_geometry_get_indices 480 (const unsigned itri, 481 unsigned indices[SGX_GEOMETRY_DIMENSION], 482 void* ctx) 483 { 484 sg2d_s2d_geometry_get_indices(itri, indices, ctx); 485 } 486 487 /* Get coordinates for the ivert_th vertex. 488 * Suitable for use as s2d_vertex_data getter for S2D_POSITION s2d_attrib_usage 489 * in s2d_mesh_setup_indexed_vertices calls. */ 490 static FINLINE void 491 sgX_sXd_geometry_get_position 492 (const unsigned ivert, 493 float coord[SGX_GEOMETRY_DIMENSION], 494 void* ctx) 495 { 496 sg2d_s2d_geometry_get_position(ivert, coord, ctx); 497 } 498 499 END_DECLS 500 501 #endif /* STAR_GEOMETRY_X_2D_H__ */