star-cpr

Clip 2D meshes with 2D polygons
git clone git://git.meso-star.fr/star-cpr.git
Log | Files | Refs | README | LICENSE

test_scpr_offset.c (12351B)


      1 /* Copyright (C) 2016-2018, 2021-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 #define _POSIX_C_SOURCE 200112L
     17 
     18 #include "scpr.h"
     19 #include "test_scpr_utils.h"
     20 
     21 #include <memory.h>
     22 
     23 static void
     24 test_single(void)
     25 {
     26   const double coords0[] = {
     27     0.0, 0.0,
     28     0.0, 1.0,
     29     1.0, 1.0,
     30     1.0, 0.0
     31   };
     32   const double coords1[] = {
     33     -1.0, -1.0,
     34     -1.0, 2.0,
     35     2.0, 2.0,
     36     2.0, -1.0
     37   };
     38   double coords2[] = {
     39     0.12345678901234, 0.0,
     40     0.0, 1.0,
     41     1.0, 1000000000000, /* To be replaced */
     42     1.0, 0.0
     43   };
     44   double coords2_reverse[] = {
     45     0.12345678901234, 0.0,
     46     1.0, 0.0,
     47     1.0, 1000000000000, /* To be replaced */
     48     0.0, 1.0
     49   };
     50   double** coords;
     51   double range[2];
     52   size_t nverts[] = { 4 };
     53   size_t ncomps = 1;
     54   struct mem_allocator allocator;
     55   struct polygon_context ctx;
     56   struct scpr_polygon* polygon;
     57   struct scpr_polygon* expected;
     58   struct scpr_device_create_args args = SCPR_DEVICE_CREATE_ARGS_DEFAULT;
     59   struct scpr_device* dev;
     60   int eq;
     61 
     62   mem_init_proxy_allocator(&allocator, &mem_default_allocator);
     63   args.allocator = &allocator;
     64   OK(scpr_device_create(&args, &dev));
     65 
     66   /* Set barely in-range value in coords2 */
     67   SCPR(device_get_range(dev, range));
     68   coords2[5] = coords2_reverse[5] = range[1];
     69 
     70   coords = (double**)MEM_CALLOC(&allocator, ncomps, sizeof(*coords));
     71   *coords = (double*)MEM_CALLOC(&allocator, nverts[0], 2*sizeof(**coords));
     72   memcpy(*coords, coords0, 2*nverts[0]*sizeof(**coords));
     73 
     74   OK(scpr_polygon_create(dev, &polygon));
     75   OK(scpr_polygon_create(dev, &expected));
     76 
     77   ctx.coords = coords;
     78   ctx.nverts = nverts;
     79   ctx.ncomps = ncomps;
     80 
     81   OK(scpr_polygon_setup_indexed_vertices(polygon, ncomps, pget_nverts, pget_pos, &ctx));
     82   OK(scpr_polygon_setup_indexed_vertices(expected, ncomps, pget_nverts, pget_pos, &ctx));
     83 
     84   /* Offset 0 = unchanged */
     85   OK(scpr_offset_polygon(polygon, 0, SCPR_JOIN_MITER));
     86   OK(scpr_polygon_eq(polygon, expected, &eq));
     87   CHK(eq);
     88   CHK(check_stability(dev, polygon));
     89 
     90   /* Offset 1 */
     91   memcpy(*coords, coords1, 2*nverts[0]*sizeof(**coords));
     92   OK(scpr_polygon_setup_indexed_vertices(expected, ncomps, pget_nverts, pget_pos, &ctx));
     93 
     94   OK(scpr_offset_polygon(polygon, 1, SCPR_JOIN_MITER));
     95   OK(scpr_polygon_eq(polygon, expected, &eq));
     96   CHK(eq);
     97   CHK(check_stability(dev, polygon));
     98 
     99   /* Offset -1: back to original polygon */
    100   memcpy(*coords, coords0, 2*nverts[0]*sizeof(**coords));
    101   OK(scpr_polygon_setup_indexed_vertices(expected, ncomps, pget_nverts, pget_pos, &ctx));
    102 
    103   OK(scpr_offset_polygon(polygon, -1, SCPR_JOIN_MITER));
    104   OK(scpr_polygon_eq(polygon, expected, &eq));
    105   CHK(eq);
    106   CHK(check_stability(dev, polygon));
    107 
    108   /* Non representable offset: truncation will ensure stability */
    109   OK(scpr_offset_polygon(polygon, 0.123456789, SCPR_JOIN_MITER));
    110   OK(scpr_offset_polygon(expected, 0.123457, SCPR_JOIN_MITER));
    111   OK(scpr_polygon_eq(polygon, expected, &eq));
    112   CHK(eq);
    113   CHK(check_stability(dev, polygon));
    114 
    115   /* Offset -5: empty polygon */
    116   ncomps = 0;
    117   ctx.ncomps = ncomps;
    118   OK(scpr_polygon_setup_indexed_vertices(expected, ncomps, pget_nverts, pget_pos, &ctx));
    119 
    120   OK(scpr_offset_polygon(polygon, -5, SCPR_JOIN_MITER));
    121   OK(scpr_polygon_eq(polygon, expected, &eq));
    122   CHK(eq);
    123   CHK(check_stability(dev, polygon));
    124 
    125   /* Check coordinates barely in-range */
    126   memcpy(*coords, coords2, 2*nverts[0]*sizeof(**coords));
    127 
    128   ncomps = 1;
    129   ctx.ncomps = ncomps;
    130 
    131   OK(scpr_polygon_setup_indexed_vertices(polygon, ncomps, pget_nverts, pget_pos, &ctx));
    132   OK(scpr_polygon_setup_indexed_vertices(expected, ncomps, pget_nverts, pget_pos, &ctx));
    133 
    134   /* Offset 0 = unchanged */
    135   OK(scpr_offset_polygon(polygon, 0, SCPR_JOIN_MITER));
    136   OK(scpr_polygon_eq(polygon, expected, &eq));
    137   CHK(eq);
    138   CHK(check_stability(dev, polygon));
    139 
    140   /* Check non-effect of CW/CCW */
    141   memcpy(*coords, coords2_reverse, 2*nverts[0]*sizeof(**coords));
    142   OK(scpr_polygon_setup_indexed_vertices(polygon, ncomps, pget_nverts, pget_pos, &ctx));
    143   OK(scpr_offset_polygon(polygon, 0, SCPR_JOIN_MITER));
    144   OK(scpr_polygon_eq(polygon, expected, &eq));
    145   CHK(eq);
    146   CHK(check_stability(dev, polygon));
    147 
    148   /* Check out of range after offset being detected */
    149   BAD(scpr_offset_polygon(polygon, 1, SCPR_JOIN_MITER));
    150 
    151   /* Cleanup */
    152   OK(scpr_polygon_ref_put(polygon));
    153   OK(scpr_device_ref_put(dev));
    154   OK(scpr_polygon_ref_put(expected));
    155 
    156   MEM_RM(&allocator, *coords);
    157   MEM_RM(&allocator, coords);
    158 
    159   check_memory_allocator(&allocator);
    160   mem_shutdown_proxy_allocator(&allocator);
    161   CHK(mem_allocated_size() == 0);
    162 }
    163 
    164 static void
    165 test_double(void)
    166 {
    167   const double coords0[] = {
    168     0.0, 0.0,
    169     0.0, 1.0,
    170     1.0, 1.0,
    171     1.0, 0.0
    172   };
    173   const double coords1[] = {
    174     10.0, 0.0,
    175     10.0, 1.0,
    176     11.0, 1.0,
    177     11.0, 0.0
    178   };
    179   const double coords2[] = {
    180     -1.0, -1.0,
    181     -1.0, 2.0,
    182     2.0, 2.0,
    183     2.0, -1.0
    184   };
    185   const double coords3[] = {
    186     9.0, -1.0,
    187     9.0, 2.0,
    188     12.0, 2.0,
    189     12.0, -1.0
    190   };
    191   const double coords4[] = {
    192     -4.5, -4.5,
    193     -4.5, 5.5,
    194     15.5, 5.5,
    195     15.5, -4.5
    196   };
    197   double** coords;
    198   size_t nverts[] = { 4, 4 };
    199   size_t ncomps = 2;
    200   struct mem_allocator allocator;
    201   struct polygon_context ctx;
    202   struct scpr_polygon* polygon;
    203   struct scpr_polygon* expected;
    204   struct scpr_device_create_args args = SCPR_DEVICE_CREATE_ARGS_DEFAULT;
    205   struct scpr_device* dev;
    206   int eq;
    207 
    208   mem_init_proxy_allocator(&allocator, &mem_default_allocator);
    209   args.allocator = &allocator;
    210   OK(scpr_device_create(&args, &dev));
    211 
    212   coords = (double**)MEM_CALLOC(&allocator, ncomps, sizeof(*coords));
    213   *coords = (double*)MEM_CALLOC(&allocator, nverts[0], 2*sizeof(**coords));
    214   *(coords+1) = (double*)MEM_CALLOC(&allocator, nverts[1], 2*sizeof(**coords));
    215   memcpy(*coords, coords0, 2*nverts[0]*sizeof(**coords));
    216   memcpy(*(coords+1), coords1, 2*nverts[1]*sizeof(**coords));
    217 
    218   OK(scpr_polygon_create(dev, &polygon));
    219   OK(scpr_polygon_create(dev, &expected));
    220 
    221   ctx.coords = coords;
    222   ctx.nverts = nverts;
    223   ctx.ncomps = ncomps;
    224 
    225   OK(scpr_polygon_setup_indexed_vertices(polygon, ncomps, pget_nverts, pget_pos, &ctx));
    226   OK(scpr_polygon_setup_indexed_vertices(expected, ncomps, pget_nverts, pget_pos, &ctx));
    227 
    228   /* Offset 0 = unchanged */
    229   OK(scpr_offset_polygon(polygon, 0, SCPR_JOIN_MITER));
    230   OK(scpr_polygon_eq(polygon, expected, &eq));
    231   CHK(eq);
    232 
    233   /* Offset 1 */
    234   memcpy(*coords, coords2, 2*nverts[0]*sizeof(**coords));
    235   memcpy(*(coords+1), coords3, 2*nverts[1]*sizeof(**coords));
    236   OK(scpr_polygon_setup_indexed_vertices(expected, ncomps, pget_nverts, pget_pos, &ctx));
    237 
    238   OK(scpr_offset_polygon(polygon, 1, SCPR_JOIN_MITER));
    239   OK(scpr_polygon_eq(polygon, expected, &eq));
    240   CHK(eq);
    241 
    242   /* Offset -1: back to original polygon */
    243   memcpy(*coords, coords0, 2*nverts[0]*sizeof(**coords));
    244   memcpy(*(coords+1), coords1, 2*nverts[1]*sizeof(**coords));
    245   OK(scpr_polygon_setup_indexed_vertices(expected, ncomps, pget_nverts, pget_pos, &ctx));
    246 
    247   OK(scpr_offset_polygon(polygon, -1, SCPR_JOIN_MITER));
    248   OK(scpr_polygon_eq(polygon, expected, &eq));
    249   CHK(eq);
    250 
    251   /* Offset 4.5: the 2 squares merge */
    252   ncomps = 1;
    253   ctx.ncomps = ncomps;
    254   memcpy(*coords, coords4, 2*nverts[0]*sizeof(**coords));
    255   OK(scpr_polygon_setup_indexed_vertices(expected, ncomps, pget_nverts, pget_pos, &ctx));
    256 
    257   OK(scpr_offset_polygon(polygon, 4.5, SCPR_JOIN_MITER));
    258   OK(scpr_polygon_eq(polygon, expected, &eq));
    259   CHK(eq);
    260 
    261   /* Offset -5: empty polygon */
    262   ncomps = 0;
    263   ctx.ncomps = ncomps;
    264   OK(scpr_polygon_setup_indexed_vertices(expected, ncomps, pget_nverts, pget_pos, &ctx));
    265 
    266   OK(scpr_offset_polygon(polygon, -5, SCPR_JOIN_MITER));
    267   OK(scpr_polygon_eq(polygon, expected, &eq));
    268   CHK(eq);
    269 
    270   OK(scpr_polygon_ref_put(polygon));
    271   OK(scpr_device_ref_put(dev));
    272   OK(scpr_polygon_ref_put(expected));
    273 
    274   MEM_RM(&allocator, *coords);
    275   MEM_RM(&allocator, *(coords+1));
    276   MEM_RM(&allocator, coords);
    277 
    278   check_memory_allocator(&allocator);
    279   mem_shutdown_proxy_allocator(&allocator);
    280   CHK(mem_allocated_size() == 0);
    281 }
    282 
    283 static void
    284 test_internal(void)
    285 {
    286   const double coords0[] = {
    287     -10, -10,
    288     -10, 10,
    289     10, 10,
    290     10, -10
    291   };
    292   const double coords1[] = {
    293     -5, -5,
    294     5, -5,
    295     5, 5,
    296     -5, 5
    297   };
    298   const double coords2[] = {
    299     -9, -9,
    300     -9, 9,
    301     9, 9,
    302     9, -9
    303   };
    304   const double coords3[] = {
    305     -6, -6,
    306     6, -6,
    307     6, 6,
    308     -6, 6
    309   };
    310   const double coords4[] = {
    311     -15, -15,
    312     -15, 15,
    313     15, 15,
    314     15, -15
    315   };
    316   double** coords;
    317   size_t nverts[] = { 4, 4 };
    318   size_t ncomps = 2;
    319   struct mem_allocator allocator;
    320   struct polygon_context ctx;
    321   struct scpr_polygon* polygon;
    322   struct scpr_polygon* expected;
    323   struct scpr_device_create_args args = SCPR_DEVICE_CREATE_ARGS_DEFAULT;
    324   struct scpr_device* dev;
    325   int eq;
    326 
    327   mem_init_proxy_allocator(&allocator, &mem_default_allocator);
    328   args.allocator = &allocator;
    329   OK(scpr_device_create(&args, &dev));
    330 
    331   coords = (double**)MEM_CALLOC(&allocator, ncomps, sizeof(*coords));
    332   *coords = (double*)MEM_CALLOC(&allocator, nverts[0], 2*sizeof(**coords));
    333   *(coords+1) = (double*)MEM_CALLOC(&allocator, nverts[1], 2*sizeof(**coords));
    334   memcpy(*coords, coords0, 2*nverts[0]*sizeof(**coords));
    335   memcpy(*(coords+1), coords1, 2*nverts[1]*sizeof(**coords));
    336 
    337   OK(scpr_polygon_create(dev, &polygon));
    338   OK(scpr_polygon_create(dev, &expected));
    339 
    340   ctx.coords = coords;
    341   ctx.nverts = nverts;
    342   ctx.ncomps = ncomps;
    343 
    344   OK(scpr_polygon_setup_indexed_vertices(polygon, ncomps, pget_nverts, pget_pos, &ctx));
    345   OK(scpr_polygon_setup_indexed_vertices(expected, ncomps, pget_nverts, pget_pos, &ctx));
    346 
    347   /* Offset 0 = unchanged */
    348   OK(scpr_offset_polygon(polygon, 0, SCPR_JOIN_MITER));
    349   OK(scpr_polygon_eq(polygon, expected, &eq));
    350   CHK(eq);
    351 
    352   /* Offset -1 */
    353   memcpy(*coords, coords3, 2*nverts[0]*sizeof(**coords));
    354   memcpy(*(coords+1), coords2, 2*nverts[1]*sizeof(**coords));
    355   OK(scpr_polygon_setup_indexed_vertices(expected, ncomps, pget_nverts, pget_pos, &ctx));
    356 
    357   OK(scpr_offset_polygon(polygon, -1, SCPR_JOIN_MITER));
    358   OK(scpr_polygon_eq(polygon, expected, &eq));
    359   CHK(eq);
    360 
    361   /* Offset 1: back to original polygon */
    362   memcpy(*coords, coords0, 2*nverts[0]*sizeof(**coords));
    363   memcpy(*(coords+1), coords1, 2*nverts[1]*sizeof(**coords));
    364   OK(scpr_polygon_setup_indexed_vertices(expected, ncomps, pget_nverts, pget_pos, &ctx));
    365 
    366   OK(scpr_offset_polygon(polygon, 1, SCPR_JOIN_MITER));
    367   OK(scpr_polygon_eq(polygon, expected, &eq));
    368   CHK(eq);
    369 
    370   /* Offset 5: internal path disappears */
    371   ncomps = 1;
    372   ctx.ncomps = ncomps;
    373   memcpy(*coords, coords4, 2*nverts[0]*sizeof(**coords));
    374   OK(scpr_polygon_setup_indexed_vertices(expected, ncomps, pget_nverts, pget_pos, &ctx));
    375 
    376   OK(scpr_offset_polygon(polygon, 5, SCPR_JOIN_MITER));
    377   OK(scpr_polygon_eq(polygon, expected, &eq));
    378   CHK(eq);
    379 
    380   /* From the original polygon, offset -2.5: empty polygon */
    381   ncomps = 2;
    382   ctx.ncomps = ncomps;
    383   memcpy(*coords, coords0, 2*nverts[0]*sizeof(**coords));
    384   memcpy(*(coords+1), coords1, 2*nverts[1]*sizeof(**coords));
    385   OK(scpr_polygon_setup_indexed_vertices(polygon, ncomps, pget_nverts, pget_pos, &ctx));
    386 
    387   ncomps = 0;
    388   ctx.ncomps = ncomps;
    389   OK(scpr_polygon_setup_indexed_vertices(expected, ncomps, pget_nverts, pget_pos, &ctx));
    390 
    391   OK(scpr_offset_polygon(polygon, -2.5, SCPR_JOIN_MITER));
    392   OK(scpr_polygon_eq(polygon, expected, &eq));
    393   CHK(eq);
    394 
    395   OK(scpr_polygon_ref_put(polygon));
    396   OK(scpr_polygon_ref_put(expected));
    397   OK(scpr_device_ref_put(dev));
    398 
    399   MEM_RM(&allocator, *coords);
    400   MEM_RM(&allocator, *(coords+1));
    401   MEM_RM(&allocator, coords);
    402 
    403   check_memory_allocator(&allocator);
    404   mem_shutdown_proxy_allocator(&allocator);
    405   CHK(mem_allocated_size() == 0);
    406 }
    407 
    408 int
    409 main(int argc, char** argv)
    410 {
    411   (void)argc; (void)argv;
    412   test_single();
    413   test_double();
    414   test_internal();
    415   return 0;
    416 }