star-uniq

Filter out repeated triangles
git clone git://git.meso-star.fr/star-uniq.git
Log | Files | Refs | README | LICENSE

test_suniq.c (10436B)


      1 /* Copyright (C) 2025 |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 Lesser General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU Lesser General Public License
     14  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     15 
     16 #include "suniq.h"
     17 
     18 #include <rsys/double3.h>
     19 #include <rsys/mem_allocator.h>
     20 
     21 /* Box lower limits in X, Y and Z */
     22 #define LX 0.0
     23 #define LY 1.0
     24 #define LZ 2.0
     25 
     26 /* Box upper limits in X, Y and Z */
     27 #define UX 1.0
     28 #define UY 5.1
     29 #define UZ 10.314
     30 
     31 /* List of box triangles */
     32 static const struct suniq_triangle box[] = {
     33   {{{UX, UY, LZ}, {UX, LY, LZ}, {LX, LY, LZ}}},
     34   {{{UX, UY, LZ}, {LX, LY, LZ}, {LX, UY, LZ}}},
     35   {{{LX, UY, LZ}, {LX, LY, LZ}, {LX, LY, UZ}}},
     36   {{{LX, UY, LZ}, {LX, LY, UZ}, {LX, UY, UZ}}},
     37   {{{LX, UY, UZ}, {LX, LY, UZ}, {UX, UY, UZ}}},
     38   {{{UX, UY, UZ}, {LX, LY, UZ}, {UX, LY, UZ}}},
     39   {{{UX, LY, UZ}, {UX, LY, LZ}, {UX, UY, LZ}}},
     40   {{{UX, LY, UZ}, {UX, UY, LZ}, {UX, UY, UZ}}},
     41   {{{UX, UY, UZ}, {LX, UY, LZ}, {LX, UY, UZ}}},
     42   {{{UX, UY, UZ}, {UX, UY, LZ}, {LX, UY, LZ}}},
     43   {{{UX, LY, UZ}, {LX, LY, LZ}, {UX, LY, LZ}}},
     44   {{{UX, LY, UZ}, {LX, LY, UZ}, {LX, LY, LZ}}}
     45 };
     46 static const size_t box_ntris = sizeof(box)/sizeof(struct suniq_triangle);
     47 
     48 /*******************************************************************************
     49  * Helper functions
     50  ******************************************************************************/
     51 static void
     52 check_creation(void)
     53 {
     54   struct mem_allocator allocator;
     55   struct suniq* suniq = NULL;
     56 
     57   /* Check creation API */
     58   CHK(suniq_create(NULL, NULL) == RES_BAD_ARG);
     59   CHK(suniq_create(&allocator, NULL) == RES_BAD_ARG);
     60   CHK(suniq_create(NULL/*optional*/, &suniq) == RES_OK);
     61 
     62   /* Check ref count API */
     63   CHK(suniq_ref_get(NULL) == RES_BAD_ARG);
     64   CHK(suniq_ref_get(suniq) == RES_OK);
     65   CHK(suniq_ref_put(NULL) == RES_BAD_ARG);
     66   CHK(suniq_ref_put(suniq) == RES_OK);
     67   CHK(suniq_ref_put(suniq) == RES_OK);
     68 
     69   CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK);
     70 
     71   /* Check the use of a user-defined allocator */
     72   CHK(MEM_ALLOCATED_SIZE(&allocator) == 0);
     73   CHK(suniq_create(&allocator, &suniq) == RES_OK);
     74   CHK(MEM_ALLOCATED_SIZE(&allocator) > 0);
     75   CHK(suniq_ref_put(suniq) == RES_OK);
     76   CHK(MEM_ALLOCATED_SIZE(&allocator) == 0);
     77 
     78   mem_shutdown_proxy_allocator(&allocator);
     79 }
     80 
     81 static void
     82 check_registration_1_triangle(void)
     83 {
     84   struct suniq_triangle tri = SUNIQ_TRIANGLE_NULL;
     85   struct suniq* suniq = NULL;
     86   size_t id = 0;
     87 
     88   CHK(suniq_create(NULL, &suniq) == RES_OK);
     89 
     90   /* Check triangle registration API */
     91   CHK(suniq_register_triangle(NULL, &box[0], &id) == RES_BAD_ARG);
     92   CHK(suniq_register_triangle(suniq, NULL, &id) == RES_BAD_ARG);
     93   CHK(suniq_register_triangle(suniq, &box[0], NULL/*optional*/) == RES_OK);
     94 
     95   /* Register the same triangle again */
     96   CHK(suniq_register_triangle(suniq, &box[0], &id) == RES_OK);
     97   CHK(id == 0);
     98 
     99   /* Turn over the 1st triangle in the box and check that it is still registered
    100    * as the 1st triangle */
    101   d3_set(tri.vertices[0], box[0].vertices[1]);
    102   d3_set(tri.vertices[1], box[0].vertices[0]);
    103   d3_set(tri.vertices[2], box[0].vertices[2]);
    104   CHK(suniq_register_triangle(suniq, &tri, &id) == RES_OK);
    105   CHK(id == 0);
    106 
    107   /* Check triangle accessor API */
    108   CHK(suniq_get_triangle(NULL, id, &tri) == RES_BAD_ARG);
    109   CHK(suniq_get_triangle(suniq, 1, &tri) == RES_BAD_ARG);
    110   CHK(suniq_get_triangle(suniq, id, NULL) == RES_BAD_ARG);
    111   CHK(suniq_get_triangle(suniq, id, &tri) == RES_OK);
    112 
    113   /* Check that the 1st tri is saved as it was committed for the 1st time */
    114   CHK(d3_eq(tri.vertices[0], box[0].vertices[0]));
    115   CHK(d3_eq(tri.vertices[1], box[0].vertices[1]));
    116   CHK(d3_eq(tri.vertices[2], box[0].vertices[2]));
    117 
    118   /* Check the clear API */
    119   CHK(suniq_clear(NULL) == RES_BAD_ARG);
    120   CHK(suniq_clear(suniq) == RES_OK);
    121   CHK(suniq_get_triangle(suniq, 0, &tri) == RES_BAD_ARG); /* No more triangle */
    122 
    123   /* Turn over the 1st triangle in the box and register it */
    124   d3_set(tri.vertices[0], box[0].vertices[1]);
    125   d3_set(tri.vertices[1], box[0].vertices[0]);
    126   d3_set(tri.vertices[2], box[0].vertices[2]);
    127   CHK(suniq_register_triangle(suniq, &box[0], &id) == RES_OK);
    128   CHK(id == 0);
    129 
    130   CHK(suniq_ref_put(suniq) == RES_OK);
    131 }
    132 
    133 static void
    134 check_registration_box(void)
    135 {
    136   struct suniq_triangle tri = SUNIQ_TRIANGLE_NULL;
    137   struct suniq* suniq = NULL;
    138   size_t id = 0;
    139   size_t i = 0;
    140 
    141   CHK(suniq_create(NULL, &suniq) == RES_OK);
    142 
    143   /* Check the registration of the triangles in the box, where every 4th
    144    * triangle is inverted */
    145   FOR_EACH(i, 0, box_ntris) {
    146 
    147     if(i%4 != 0) {
    148       CHK(suniq_register_triangle(suniq, &box[i], &id) == RES_OK);
    149     } else {
    150       d3_set(tri.vertices[0], box[i].vertices[2]);
    151       d3_set(tri.vertices[1], box[i].vertices[1]);
    152       d3_set(tri.vertices[2], box[i].vertices[0]);
    153       CHK(suniq_register_triangle(suniq, &tri, &id) == RES_OK);
    154     }
    155 
    156     CHK(id == i);
    157   }
    158 
    159   /* Try to register all triangles again */
    160   FOR_EACH(i, 0, box_ntris) {
    161     CHK(suniq_register_triangle(suniq, &box[i], &id) == RES_OK);
    162   }
    163 
    164   /* Check that triangles are saved as they were first registered */
    165   FOR_EACH(i, 0, box_ntris) {
    166     CHK(suniq_get_triangle(suniq, i, &tri) == RES_OK);
    167 
    168     if(i%4 != 0) {
    169       CHK(d3_eq(tri.vertices[0], box[i].vertices[0]));
    170       CHK(d3_eq(tri.vertices[1], box[i].vertices[1]));
    171       CHK(d3_eq(tri.vertices[2], box[i].vertices[2]));
    172     } else {
    173       /* Every 4th triangle is inverted */
    174       CHK(d3_eq(tri.vertices[0], box[i].vertices[2]));
    175       CHK(d3_eq(tri.vertices[1], box[i].vertices[1]));
    176       CHK(d3_eq(tri.vertices[2], box[i].vertices[0]));
    177     }
    178   }
    179 
    180   CHK(suniq_clear(suniq) == RES_OK);
    181 
    182   /* Check that once cleared, everything is reset. So this time, all registered
    183    * triangles are returned, except all 4 triangles. This is exactly the
    184    * opposite of the previous situation */
    185   FOR_EACH(i, 0, box_ntris) {
    186     if(i%4 == 0) {
    187       CHK(suniq_register_triangle(suniq, &box[i], &id) == RES_OK);
    188 
    189       CHK(suniq_get_triangle(suniq, i, &tri) == RES_OK);
    190       CHK(d3_eq(tri.vertices[0], box[i].vertices[0]));
    191       CHK(d3_eq(tri.vertices[1], box[i].vertices[1]));
    192       CHK(d3_eq(tri.vertices[2], box[i].vertices[2]));
    193 
    194     } else {
    195       d3_set(tri.vertices[0], box[i].vertices[2]);
    196       d3_set(tri.vertices[1], box[i].vertices[1]);
    197       d3_set(tri.vertices[2], box[i].vertices[0]);
    198       CHK(suniq_register_triangle(suniq, &tri, &id) == RES_OK);
    199 
    200       CHK(suniq_get_triangle(suniq, i, &tri) == RES_OK);
    201       CHK(d3_eq(tri.vertices[0], box[i].vertices[2]));
    202       CHK(d3_eq(tri.vertices[1], box[i].vertices[1]));
    203       CHK(d3_eq(tri.vertices[2], box[i].vertices[0]));
    204     }
    205   }
    206 
    207   CHK(suniq_ref_put(suniq) == RES_OK);
    208 }
    209 
    210 static void
    211 check_descriptor(void)
    212 {
    213   struct suniq_desc desc = SUNIQ_DESC_NULL;
    214   struct suniq* suniq = NULL;
    215   size_t idx[3] = {0,0,0};
    216   double vtx[3] = {0,0,0};
    217   size_t i = 0;
    218 
    219   CHK(suniq_create(NULL, &suniq) == RES_OK);
    220 
    221   FOR_EACH(i, 0, box_ntris) {
    222     CHK(suniq_register_triangle(suniq, &box[i], NULL) == RES_OK);
    223   }
    224 
    225   /* Check descriptor API */
    226   CHK(suniq_get_desc(NULL, &desc) == RES_BAD_ARG);
    227   CHK(suniq_get_desc(suniq, NULL) == RES_BAD_ARG);
    228   CHK(suniq_get_desc(suniq, &desc) == RES_OK);
    229 
    230   /* Check the number of triangles and vertices indicated by the descriptor.
    231    * Note that the number of vertices cannot be known. It depends on how the
    232    * indexed mesh is constructed by the library. In any case, it cannot be less
    233    * than the number of vertices in the cube */
    234   CHK(desc.ntriangles == box_ntris);
    235   CHK(desc.nvertices >= 8);
    236 
    237   /* Check vertex API */
    238   CHK(suniq_desc_get_vertex(NULL, 0, vtx) == RES_BAD_ARG);
    239   CHK(suniq_desc_get_vertex(&desc, desc.nvertices, vtx) == RES_BAD_ARG);
    240   CHK(suniq_desc_get_vertex(&desc, 0, NULL) == RES_BAD_ARG);
    241   CHK(suniq_desc_get_vertex(&desc, 0, vtx) == RES_OK);
    242 
    243   /* Check triange indices API */
    244   CHK(suniq_desc_get_triangle_indices(NULL, 0, idx) == RES_BAD_ARG);
    245   CHK(suniq_desc_get_triangle_indices(&desc, desc.ntriangles, idx) == RES_BAD_ARG);
    246   CHK(suniq_desc_get_triangle_indices(&desc, 0, NULL) == RES_BAD_ARG);
    247   CHK(suniq_desc_get_triangle_indices(&desc, 0, idx) == RES_OK);
    248 
    249   /* Check descriptor data */
    250   FOR_EACH(i, 0, desc.ntriangles) {
    251     const size_t* indices;
    252     const double *vertex0, *vertex1, *vertex2;
    253 
    254     indices = desc.indices + i*3/*#indices per triangle */;
    255     vertex0 = desc.positions + indices[0] * 3/*#coords per vertex*/;
    256     vertex1 = desc.positions + indices[1] * 3/*#coords per vertex*/;
    257     vertex2 = desc.positions + indices[2] * 3/*#coords per vertex*/;
    258 
    259     CHK(d3_eq(vertex0, box[i].vertices[0]));
    260     CHK(d3_eq(vertex1, box[i].vertices[1]));
    261     CHK(d3_eq(vertex2, box[i].vertices[2]));
    262 
    263     CHK(suniq_desc_get_triangle_indices(&desc, i, idx) == RES_OK);
    264     CHK(idx[0] == indices[0]);
    265     CHK(idx[1] == indices[1]);
    266     CHK(idx[2] == indices[2]);
    267 
    268     CHK(suniq_desc_get_vertex(&desc, idx[0], vtx) == RES_OK);
    269     CHK(d3_eq(vtx, box[i].vertices[0]));
    270     CHK(suniq_desc_get_vertex(&desc, idx[1], vtx) == RES_OK);
    271     CHK(d3_eq(vtx, box[i].vertices[1]));
    272     CHK(suniq_desc_get_vertex(&desc, idx[2], vtx) == RES_OK);
    273     CHK(d3_eq(vtx, box[i].vertices[2]));
    274   }
    275 
    276   CHK(suniq_clear(suniq) == RES_OK);
    277 
    278   /* Check the descriptor once the registering is empty */
    279   CHK(suniq_get_desc(suniq, &desc) == RES_OK);
    280   CHK(desc.nvertices == 0);
    281   CHK(desc.ntriangles == 0);
    282 
    283   /* Check that no more triangles/vertexes can be recovered */
    284   CHK(suniq_desc_get_triangle_indices(&desc, 0, idx) == RES_BAD_ARG);
    285   CHK(suniq_desc_get_vertex(&desc, 0, vtx) == RES_BAD_ARG);
    286 
    287   CHK(suniq_ref_put(suniq) == RES_OK);
    288 }
    289 
    290 /*******************************************************************************
    291  * The test
    292  ******************************************************************************/
    293 int
    294 main(void)
    295 {
    296   check_creation();
    297   check_registration_1_triangle();
    298   check_registration_box();
    299   check_descriptor();
    300 
    301   CHK(mem_allocated_size() == 0);
    302   return 0;
    303 }