star-enclosures-2d

Extract enclosures from 2D geometry
git clone git://git.meso-star.fr/star-enclosures-2d.git
Log | Files | Refs | README | LICENSE

senc2d.h (14055B)


      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 SENC2D_H
     17 #define SENC2D_H
     18 
     19 #include <rsys/rsys.h>
     20 
     21 #include <limits.h>
     22 
     23 /* Library symbol management */
     24 #if defined(SENC2D_SHARED_BUILD)
     25   #define SENC2D_API extern EXPORT_SYM
     26 #elif defined(SENC2D_STATIC_BUILD)
     27   #define SENC2D_API extern LOCAL_SYM
     28 #else /* Use shared library */
     29   #define SENC2D_API extern IMPORT_SYM
     30 #endif
     31 
     32 /* Helper macro that asserts if the invocation of the StarEnc function `Func'
     33  * returns an error. One should use this macro on StarEnc function calls for
     34  * which no explicit error checking is performed. */
     35 #ifndef NDEBUG
     36   #define SENC2D(Func) ASSERT(senc2d_ ## Func == RES_OK)
     37 #else
     38   #define SENC2D(Func) senc2d_ ## Func
     39 #endif
     40 
     41 /* Syntactic sugar used to inform the library that it can use as many threads
     42  * as CPU cores */
     43 #define SENC2D_NTHREADS_DEFAULT (~0u)
     44 
     45 /* A constant to denote an unspecified medium */
     46 #define SENC2D_UNSPECIFIED_MEDIUM UINT_MAX
     47 
     48 /* Forward declaration of external opaque data types */
     49 struct logger;
     50 struct mem_allocator;
     51 
     52 /* Forward declaration of star-enclosures-2d opaque data types. These data
     53  * types are ref counted. Once created with the appropriated
     54  * `senc2d_<TYPE>_create' function, the caller implicitly owns the created
     55  * data, i.e. its reference counter is set to 1.
     56  * The senc2d_<TYPE>_ref_<get|put> functions get or release a reference on the
     57  * data, i.e. they increment or decrement the reference counter, respectively.
     58  * When this counter reaches 0, the object is silently destroyed and cannot be
     59  * used anymore. */
     60 struct senc2d_device;
     61 struct senc2d_scene;
     62 struct senc2d_enclosure;
     63 
     64 /******************************************************************************
     65  * The dimension of the geometry used in the library.
     66  *****************************************************************************/
     67 #define SENC2D_GEOMETRY_DIMENSION 2
     68 
     69 /* A type to discriminate segment sides */
     70 enum senc2d_side {
     71   SENC2D_FRONT,
     72   SENC2D_BACK
     73 };
     74 
     75 /* Enclosure header type */
     76 struct senc2d_enclosure_header {
     77   /* The ID of the enclosure; 0, 1, ... */
     78   unsigned enclosure_id;
     79   /* Number of segments; a segment can be counted twice, once by side */
     80   unsigned primitives_count;
     81   /* Number of segments; a segment cannot be counted twice */
     82   unsigned unique_primitives_count;
     83   /* Number of vertices */
     84   unsigned vertices_count;
     85   /* The number of media inside the enclosure,
     86    * SENC2D_UNSPECIFIED_MEDIUM included */
     87   unsigned enclosed_media_count;
     88   /* Is the enclosure open/infinite?
     89    * Only the outermost enclosure is infinite. */
     90   int is_infinite;
     91   /* The volume of the enclosure, in m^2 (2D volume is in m^2!).
     92    * For the outermost enclosure, that goes to infinity, the volume is negative
     93    * and is the volume substracted from an hypothetical surrounding object.
     94    * If the two sides of a segment are part of the enclosure, the segment is
     95    * counted as 0. */
     96   double volume;
     97   /* The area of the enclosure, in m (2D area is in m!).
     98    * If the two sides of a segment are part of the enclosure, the segment is
     99    * counted twice. */
    100   double area;
    101 };
    102 
    103 /* We consider the geometrical normal Ng to a segment V0 V1 that verifies
    104  * "(V0, V0V1, Ng) is a direct system" (right-handed system).
    105  *
    106  * The user can set the convention used to determine which side of
    107  * a segment is to be considered front/back by using the flags :
    108  * SENC2D_CONVENTION_NORMAL_FRONT => Ng points toward the front side,
    109  * SENC2D_CONVENTION_NORMAL_BACK => Ng points toward the back side.
    110  *
    111  * Additionally the user can set the convention used to output enclosures
    112  * so that Ng points toward the enclosure or on the opposite direction
    113  * (for a closed enclosure Ng points toward the inside or toward the outside)
    114  * by using the flags :
    115  * SENC2D_CONVENTION_NORMAL_INSIDE => Ng points toward the enclosure,
    116  * SENC2D_CONVENTION_NORMAL_OUTSIDE => Ng points toward the opposite of the
    117  * enclosure.
    118  *
    119  * Note that normals in output data can be opposite to normals in input data
    120  * (vertices are then given in reverse order).
    121  *
    122  * Also note that both sides of a segment can be part of the same enclosure;
    123  * in this case the 2 sides will be given with opposite Ng (meaning they
    124  * will be given with opposite vertices order).
    125  */
    126 enum senc2d_convention {
    127   /*
    128    * Convention regarding FRONT/BACK sides in input data
    129    */
    130 
    131   /* Geometrical normals point toward the front side */
    132   SENC2D_CONVENTION_NORMAL_FRONT = BIT(0),
    133   /* Geometrical normals point toward the back side */
    134   SENC2D_CONVENTION_NORMAL_BACK = BIT(1),
    135 
    136   /*
    137    * Convention regarding geometrical normals in output data
    138    */
    139 
    140   /* Geometrical normals point toward the enclosure */
    141   SENC2D_CONVENTION_NORMAL_INSIDE = BIT(2),
    142   /* Geometrical normals point to the opposite of the enclosure */
    143   SENC2D_CONVENTION_NORMAL_OUTSIDE = BIT(3)
    144 };
    145 
    146 BEGIN_DECLS
    147 
    148 /******************************************************************************
    149  * star-enclosures-2d device. It is an handle toward the StarEnc library.
    150  * It manages the lib resources.
    151  * If provided, the allocator has to be suitable for parallel high frequency
    152  * allocations. As a consequence, a rsys proxy allocator should be avoided.
    153  *****************************************************************************/
    154 SENC2D_API res_T
    155 senc2d_device_create
    156   (struct logger* logger, /* May be NULL <=> use default logger */
    157    struct mem_allocator* allocator, /* May be NULL <=> use default allocator */
    158    const unsigned nthreads_hint,
    159    const int verbose,
    160    struct senc2d_device** device);
    161 
    162 SENC2D_API res_T
    163 senc2d_device_ref_get
    164   (struct senc2d_device* device);
    165 
    166 SENC2D_API res_T
    167 senc2d_device_ref_put
    168   (struct senc2d_device* device);
    169 
    170 /******************************************************************************
    171  * star-enclosures-2d scene. A scene is a collection of segments. Each segment
    172  * is defined with a medium on each side.
    173  * Scenes with overlapping segments are considered ill-formed and any
    174  * enclosure-related API call on such a scene will return RES_BAD_OP.
    175  *****************************************************************************/
    176 /* Creates a scene from some vertices and segments.
    177  * Neither vertices nor segments can include duplicates.
    178  * Segments cannot be degenerated. */
    179 SENC2D_API res_T
    180 senc2d_scene_create
    181   (struct senc2d_device* device,
    182    const int convention,
    183    /* Number of segments */
    184    const unsigned segments_count,
    185    /* User function that provides vertices ids for segments */
    186    void(*get_indices)(
    187      const unsigned iseg,
    188      unsigned ids[SENC2D_GEOMETRY_DIMENSION],
    189      void* context),
    190    /* User function that provides media ids for segments */
    191    void(*get_media) /* Can be NULL <=> SENC2D_UNSPECIFIED_MEDIUM medium used */
    192      (const unsigned iseg, unsigned med[2], void* context),
    193    /* Number of vertices */
    194    const unsigned vertices_count,
    195    /* User function that provides coordinates for vertices */
    196    void(*get_position)(
    197      const unsigned ivert,
    198      double pos[SENC2D_GEOMETRY_DIMENSION],
    199      void* context),
    200    /* Context provided to user callbacks; can be NULL */
    201    void* context,
    202     /* The created scene */
    203    struct senc2d_scene** scene);
    204 
    205 /* Returns the convention flags in use with the scene. */
    206 SENC2D_API res_T
    207 senc2d_scene_get_convention
    208   (const struct senc2d_scene* scene,
    209    int* convention);
    210 
    211 /* Returns the number of segments in the scene. */
    212 SENC2D_API res_T
    213 senc2d_scene_get_segments_count
    214   (const struct senc2d_scene* scene,
    215    unsigned* count);
    216 
    217 /* Returns the iseg_th segment vertices' indices. */
    218 SENC2D_API res_T
    219 senc2d_scene_get_segment
    220   (const struct senc2d_scene* scene,
    221    const unsigned iseg,
    222    unsigned indices[SENC2D_GEOMETRY_DIMENSION]);
    223 
    224 /* Returns the media for the iseg_th segment. */
    225 SENC2D_API res_T
    226 senc2d_scene_get_segment_media
    227   (const struct senc2d_scene* scene,
    228    const unsigned iseg,
    229    unsigned media[2]);
    230 
    231 /* Returns the number of vertices in the scene. */
    232 SENC2D_API res_T
    233 senc2d_scene_get_vertices_count
    234   (const struct senc2d_scene* scene,
    235    unsigned* count);
    236 
    237 /* Returns the coordinates of the ivert_th vertex. */
    238 SENC2D_API res_T
    239 senc2d_scene_get_vertex
    240   (const struct senc2d_scene* scene,
    241    const unsigned ivert,
    242    double coord[SENC2D_GEOMETRY_DIMENSION]);
    243 
    244 /* Returns the greater medium id found in added geometry. In API calls using a
    245  * medium, any value in the [0 max_medium_id[ range is valid. However there can
    246  * be unused ids (no geometry refered to this medium id).  */
    247 SENC2D_API res_T
    248 senc2d_scene_get_max_medium
    249   (const struct senc2d_scene* scene,
    250    unsigned* max_medium_id);
    251 
    252 /* Returns the number of enclosures. */
    253 SENC2D_API res_T
    254 senc2d_scene_get_enclosure_count
    255   (const struct senc2d_scene* scene,
    256    unsigned* count);
    257 
    258 /* Returns the number of enclosures that have some geometry refering to the
    259  * imed_th medium or SENC2D_UNSPECIFIED_MEDIUM. */
    260 SENC2D_API res_T
    261 senc2d_scene_get_enclosure_count_by_medium
    262   (const struct senc2d_scene* scene,
    263    const unsigned imed,
    264    unsigned* count);
    265 
    266 /* Returns the idx_th enclosure. */
    267 SENC2D_API res_T
    268 senc2d_scene_get_enclosure
    269   (struct senc2d_scene* scene,
    270    const unsigned idx,
    271    struct senc2d_enclosure** enclosure);
    272 
    273 /* Returns the idx_th enclosure using the imed_th medium or
    274  * SENC2D_UNSPECIFIED_MEDIUM. */
    275 SENC2D_API res_T
    276 senc2d_scene_get_enclosure_by_medium
    277   (struct senc2d_scene* scene,
    278    const unsigned imed,
    279    const unsigned idx,
    280    struct senc2d_enclosure** enclosure);
    281 
    282 /* Returns the enclosures the iseg_th segment front and back sides are member
    283  * of. */
    284 SENC2D_API res_T
    285 senc2d_scene_get_segment_enclosures
    286   (const struct senc2d_scene* scene,
    287    const unsigned iseg,
    288    unsigned enclosures[2]);
    289 
    290 /* Returns the number of vertices that are frontier vertices:
    291  * - that have arity 1 (single segment using the vertex)
    292  * - that connect 2 different media */
    293 SENC2D_API res_T
    294 senc2d_scene_get_frontier_vertice_count
    295   (const struct senc2d_scene* scene,
    296    unsigned* count);
    297 
    298 /* Returns the iver_th frontier vertex (segment and vertex global IDs). */
    299 SENC2D_API res_T
    300 senc2d_scene_get_frontier_vertex
    301   (const struct senc2d_scene* scene,
    302    const unsigned iver,
    303    unsigned vrtx_id[SENC2D_GEOMETRY_DIMENSION-1],
    304    unsigned* seg_id);
    305 
    306 /* Returns the number of overlapping segments.
    307  * A model including overlapping segments cannot be split into enclosures
    308  * unequivocally and will probably be ruled invalid by most softwares.
    309  * As a consequence, one cannot query enclosure-related information on a model
    310  * with overlapping segments.
    311  * The library currently only detects overlapping segments that share a
    312  * vertex. */
    313 SENC2D_API res_T
    314 senc2d_scene_get_overlapping_segments_count
    315   (const struct senc2d_scene* scene,
    316    unsigned* count);
    317 
    318 /* Returns the idx_th overlapping triangle id. */
    319 SENC2D_API res_T
    320 senc2d_scene_get_overlapping_segment
    321   (const struct senc2d_scene* scene,
    322    const unsigned idx,
    323    unsigned* id);
    324 
    325 SENC2D_API res_T
    326 senc2d_scene_ref_get
    327   (struct senc2d_scene* scene);
    328 
    329 SENC2D_API res_T
    330 senc2d_scene_ref_put
    331   (struct senc2d_scene* scene);
    332 
    333 /******************************************************************************
    334  * star-enclosures-2d enclosure. It is an handle toward an enclosure.
    335  * Counts and other information on enclosures are not individually accessible,
    336  * but as a whole through header access.
    337  * An enclosure can list the "same" segment twice if both sides are in. In this
    338  * case the 2 occurences of the segment have reversed vertices order and
    339  * unique_primitives_count and primitives_count differ.
    340  * Vertices and segments numbering schemes are specific to each enclosure:
    341  * the "same" item appearing in 2 different enclosures has no reason to get the
    342  * same index twice or to have the same index in the global numbering scheme.
    343  * By-index API accesses of segments (or properties) visit unique segments
    344  * for indices in the [0 unique_primitives_count[ range and back-faces of the
    345  * doubly-included segments in the [unique_primitives_count primitives_count[
    346  * range.
    347  *****************************************************************************/
    348 /* Returns the header of an enclosure. */
    349 SENC2D_API res_T
    350 senc2d_enclosure_get_header
    351   (const struct senc2d_enclosure* enclosure,
    352    struct senc2d_enclosure_header* header);
    353 
    354 /* Returns the iseg_th segment of an enclosure.
    355  * Indices are local to the enclosure. */
    356 SENC2D_API res_T
    357 senc2d_enclosure_get_segment
    358   (const struct senc2d_enclosure* enclosure,
    359    const unsigned iseg,
    360    unsigned indices[SENC2D_GEOMETRY_DIMENSION]);
    361 
    362 /* Returns the coordinates of the ivert_th vertex of an enclosure. */
    363 SENC2D_API res_T
    364 senc2d_enclosure_get_vertex
    365   (const struct senc2d_enclosure* enclosure,
    366    const unsigned ivert,
    367    double coord[SENC2D_GEOMETRY_DIMENSION]);
    368 
    369 /* Returns the global id of the iseg_th segment of an enclosure
    370  * and the involved side. */
    371 SENC2D_API res_T
    372 senc2d_enclosure_get_segment_id
    373   (const struct senc2d_enclosure* enclosure,
    374    const unsigned iseg,
    375    unsigned* gid,
    376    enum senc2d_side* side);
    377 
    378 /* Returns the id of the imed_th medium of an enclosure. */
    379 SENC2D_API res_T
    380 senc2d_enclosure_get_medium
    381   (const struct senc2d_enclosure* enclosure,
    382    const unsigned imed,
    383    unsigned* medium);
    384 
    385 SENC2D_API res_T
    386 senc2d_enclosure_ref_get
    387   (struct senc2d_enclosure* enclosure);
    388 
    389 SENC2D_API res_T
    390 senc2d_enclosure_ref_put
    391   (struct senc2d_enclosure* enclosure);
    392 
    393 END_DECLS
    394 
    395 #endif /* SENC2D_H */