star-geometry-2d

Cleaning and decorating 2D geometries
git clone git://git.meso-star.fr/star-geometry-2d.git
Log | Files | Refs | README | LICENSE

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__ */