star-enclosures-3d

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

test_senc3d_utils.h (8328B)


      1 /* Copyright (C) 2018-2020, 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_UTILS_H
     17 #define TEST_UTILS_H
     18 
     19 #include <rsys/rsys.h>
     20 #include <rsys/mem_allocator.h>
     21 #include <rsys/double3.h>
     22 
     23 #include <stdio.h>
     24 
     25 #include <star/senc3d.h>
     26 
     27 #define OK(Expr) CHK((Expr) == RES_OK)
     28 #define BA(Expr) CHK((Expr) == RES_BAD_ARG)
     29 #define BO(Expr) CHK((Expr) == RES_BAD_OP)
     30 
     31 /******************************************************************************
     32  * Geometry
     33  *****************************************************************************/
     34 /* Distorded cube */
     35 static const double box_vertices[8/*#vertices*/*3/*#coords per vertex*/] = {
     36   0.1, 0.0, 0.0,
     37   1.0, 0.0, 0.0,
     38   0.0, 1.0, 0.0,
     39   1.0, 1.0, 0.0,
     40   0.0, 0.0, 1.1,
     41   1.0, 0.0, 1.0,
     42   0.0, 1.0, 1.0,
     43   1.0, 1.1, 1.0
     44 };
     45 /* Need a true cube for some tests */
     46 static const double cube_vertices[8/*#vertices*/ * 3/*#coords per vertex*/] = {
     47   0.0, 0.0, 0.0,
     48   1.0, 0.0, 0.0,
     49   0.0, 1.0, 0.0,
     50   1.0, 1.0, 0.0,
     51   0.0, 0.0, 1.0,
     52   1.0, 0.0, 1.0,
     53   0.0, 1.0, 1.0,
     54   1.0, 1.0, 1.0
     55 };
     56 static const unsigned nvertices = sizeof(box_vertices) / (3*sizeof(double));
     57 STATIC_ASSERT(sizeof(box_vertices) == sizeof(cube_vertices),
     58   The_2_geometries_must_have_the_same_number_of_vertices);
     59 
     60 /* The following array lists the indices toward the 3D vertices of each
     61  * triangle.
     62  *        ,2---,3           ,2----3
     63  *      ,' | ,'/|         ,'/| \  |
     64  *    6----7' / |       6' / |  \ |        Y
     65  *    |',  | / ,1       | / ,0---,1        |
     66  *    |  ',|/,'         |/,' | ,'          o--X
     67  *    4----5'           4----5'           /
     68  *  Front, right      Back, left and     Z
     69  * and Top faces       bottom faces */
     70 static const unsigned
     71 box_indices[12/*#triangles*/*3/*#indices per triangle*/] = {
     72   0, 2, 1, 1, 2, 3, /* Front face */
     73   0, 4, 2, 2, 4, 6, /* Left face*/
     74   4, 5, 6, 6, 5, 7, /* Back face */
     75   3, 7, 1, 1, 7, 5, /* Right face */
     76   2, 6, 3, 3, 6, 7, /* Top face */
     77   0, 1, 4, 4, 1, 5  /* Bottom face */
     78 };
     79 static const unsigned
     80 ntriangles = sizeof(box_indices) / (3 * sizeof(*box_indices));
     81 
     82 struct context {
     83   const double* positions;
     84   const unsigned* indices;
     85   const unsigned* front_media;
     86   const unsigned* back_media;
     87   const unsigned* properties;
     88   void* custom;
     89   double offset[3];
     90   double scale;
     91   char reverse_vrtx, reverse_med;
     92 };
     93 #define CONTEXT_NULL__ {\
     94   NULL, NULL, NULL, NULL, NULL, NULL, {0,0,0}, 1, 0, 0\
     95 }
     96 
     97 static const unsigned medium0[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
     98 static const unsigned medium1[12] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
     99 static const unsigned medium2[12] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 };
    100 static const unsigned medium1_3[12] = { 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1 };
    101 static const unsigned medium1_back0[12] = { 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1 };
    102 static const unsigned medium1_front0[12] = { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
    103 
    104 static INLINE void
    105 get_indices(const unsigned itri, unsigned ids[3], void* context)
    106 {
    107   const struct context* ctx = context;
    108   ASSERT(ids && ctx);
    109   ids[0] = ctx->indices[itri * 3 + 0];
    110   ids[ctx->reverse_vrtx ? 2 : 1] = ctx->indices[itri * 3 + 1];
    111   ids[ctx->reverse_vrtx ? 1 : 2] = ctx->indices[itri * 3 + 2];
    112 }
    113 
    114 static INLINE void
    115 get_position(const unsigned ivert, double pos[3], void* context)
    116 {
    117   const struct context* ctx = context;
    118   ASSERT(pos && ctx && ctx->scale != 0);
    119   pos[0] = ctx->positions[ivert * 3 + 0] * ctx->scale + ctx->offset[0];
    120   pos[1] = ctx->positions[ivert * 3 + 1] * ctx->scale + ctx->offset[1];
    121   pos[2] = ctx->positions[ivert * 3 + 2] * ctx->scale + ctx->offset[2];
    122 }
    123 
    124 static INLINE void
    125 get_media(const unsigned itri, unsigned medium[2], void* context)
    126 {
    127   const struct context* ctx = context;
    128   ASSERT(medium && ctx);
    129   medium[ctx->reverse_med ? 1 : 0] = ctx->front_media[itri];
    130   medium[ctx->reverse_med ? 0 : 1] = ctx->back_media[itri];
    131 }
    132 
    133 static INLINE void
    134 get_media_from_properties(const unsigned itri, unsigned medium[2], void* context)
    135 {
    136   const struct context* ctx = context;
    137   ASSERT(medium && ctx);
    138   medium[ctx->reverse_med ? 1 : 0] = ctx->properties[3 * itri + 0];
    139   medium[ctx->reverse_med ? 0 : 1] = ctx->properties[3 * itri + 1];
    140 }
    141 
    142 /******************************************************************************
    143  * Miscellaneous
    144  *****************************************************************************/
    145 static INLINE void
    146 dump_global
    147   (struct senc3d_scene* scn,
    148    const char* name)
    149 {
    150   FILE* stream;
    151   unsigned triangles_count, vertices_count, i;
    152 
    153   ASSERT(scn && name);
    154 
    155   OK(senc3d_scene_get_vertices_count(scn, &vertices_count));
    156   OK(senc3d_scene_get_triangles_count(scn, &triangles_count));
    157 
    158   stream = fopen(name, "w");
    159   CHK(stream);
    160   FOR_EACH(i, 0, vertices_count) {
    161     double tmp[3];
    162     OK(senc3d_scene_get_vertex(scn, i, tmp));
    163     fprintf(stream, "v %g %g %g\n", SPLIT3(tmp));
    164   }
    165   FOR_EACH(i, 0, triangles_count) {
    166     unsigned indices[3];
    167     OK(senc3d_scene_get_triangle(scn, i, indices));
    168     fprintf(stream, "f %u %u %u\n",
    169       1 + indices[0], 1 + indices[1], 1 + indices[2]);
    170   }
    171   fclose(stream);
    172 }
    173 
    174 static INLINE void
    175 dump_enclosure
    176   (struct senc3d_scene* scn,
    177    const unsigned enc,
    178    const char* name)
    179 {
    180   struct senc3d_enclosure* enclosure;
    181   struct senc3d_enclosure_header header;
    182   FILE* stream;
    183   unsigned count, i;
    184 
    185   ASSERT(scn && name);
    186 
    187   SENC3D(scene_get_enclosure_count(scn, &count));
    188   ASSERT(enc < count);
    189   OK(senc3d_scene_get_enclosure(scn, enc, &enclosure));
    190   OK(senc3d_enclosure_get_header(enclosure, &header));
    191 
    192   stream = fopen(name, "w");
    193   CHK(stream);
    194   FOR_EACH(i, 0, header.vertices_count) {
    195     double tmp[3];
    196     OK(senc3d_enclosure_get_vertex(enclosure, i, tmp));
    197     fprintf(stream, "v %g %g %g\n", SPLIT3(tmp));
    198   }
    199   FOR_EACH(i, 0, header.primitives_count) {
    200     unsigned indices[3];
    201     OK(senc3d_enclosure_get_triangle(enclosure, i, indices));
    202     fprintf(stream, "f %u %u %u\n",
    203       1+indices[0], 1+indices[1], 1+indices[2]);
    204   }
    205   OK(senc3d_enclosure_ref_put(enclosure));
    206   fclose(stream);
    207 }
    208 
    209 static INLINE void
    210 check_memory_allocator(struct mem_allocator* allocator)
    211 {
    212   if(MEM_ALLOCATED_SIZE(allocator)) {
    213     char dump[1024];
    214     MEM_DUMP(allocator, dump, sizeof(dump));
    215     fprintf(stderr, "%s\n", dump);
    216     FATAL("Memory leaks.\n");
    217   }
    218 }
    219 
    220 /******************************************************************************
    221  * Check functions
    222  *****************************************************************************/
    223 /* Compare the itri-th triangle of enclosure with a triangle described by trg2 & vertices2 */
    224 static INLINE void
    225 cmp_trg
    226   (const unsigned itri,
    227    const struct senc3d_enclosure* enclosure,
    228    const unsigned trg2[3],
    229    const double* vertices2,
    230    int* trg_eq,
    231    int* trg_reversed)
    232 {
    233   unsigned trg1[3];
    234   double t1[3][3];
    235   double t2[3][3];
    236   unsigned trg1_eq[3] = { 3, 3, 3 };
    237   unsigned i, j, fst_vrtx = 3;
    238 
    239   ASSERT(enclosure && trg2 && vertices2 && trg_eq && trg_reversed);
    240 
    241   OK(senc3d_enclosure_get_triangle(enclosure, itri, trg1));
    242   FOR_EACH(i, 0, 3) {
    243     OK(senc3d_enclosure_get_vertex(enclosure, trg1[i], t1[i]));
    244     d3_set(t2[i], vertices2 + (3 * trg2[i]));
    245   }
    246   FOR_EACH(i, 0, 3) {
    247     FOR_EACH(j, 0, 3) {
    248       if(d3_eq(t1[i], t2[j])) {
    249         trg1_eq[i] = j;
    250         if(i == 0) fst_vrtx = j;
    251         break;
    252       }
    253     }
    254   }
    255   FOR_EACH(i, 0, 3) {
    256     if(trg1_eq[i] == 3) {
    257       *trg_eq = 0;
    258       return;
    259     }
    260     if(trg1_eq[i] == trg1_eq[(i + 1) % 3]
    261       || trg1_eq[i] == trg1_eq[(i + 2) % 3]) {
    262       *trg_eq = 0;
    263       return;
    264     }
    265   }
    266   /* Same 3 vertices */
    267   ASSERT(fst_vrtx != 3);
    268   *trg_eq = 1;
    269 
    270   *trg_reversed = (trg1_eq[1] != (fst_vrtx + 1) % 3);
    271   ASSERT(*trg_reversed != (trg1_eq[1] != (fst_vrtx + 2) % 3));
    272 }
    273 
    274 #endif /* TEST_UTILS_H */