star-2d

Contour structuring for efficient 2D geometric queries
git clone git://git.meso-star.fr/star-2d.git
Log | Files | Refs | README | LICENSE

s2d_shape.c (6319B)


      1 /* Copyright (C) 2016-2021, 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 #include "s2d.h"
     17 #include "s2d_c.h"
     18 #include "s2d_device_c.h"
     19 #include "s2d_line_segments.h"
     20 #include "s2d_shape_c.h"
     21 
     22 #include <rsys/mem_allocator.h>
     23 
     24 /*******************************************************************************
     25  * Helper functions
     26  ******************************************************************************/
     27 static void
     28 shape_release(ref_T* ref)
     29 {
     30   struct s2d_shape* shape;
     31   struct s2d_device* dev;
     32   ASSERT(ref);
     33   shape = CONTAINER_OF(ref, struct s2d_shape, ref);
     34   dev = shape->dev;
     35 
     36   /* The shape should not be attached */
     37   ASSERT(is_list_empty(&shape->scene_attachment));
     38   line_segments_ref_put(shape->lines);
     39   flist_name_del(&dev->names, shape->id);
     40   MEM_RM(dev->allocator, shape);
     41   S2D(device_ref_put(dev));
     42 }
     43 
     44 /*******************************************************************************
     45  * Exported s2d_shape functions
     46  ******************************************************************************/
     47 res_T
     48 s2d_shape_create_line_segments
     49   (struct s2d_device* dev, struct s2d_shape** out_shape)
     50 {
     51   struct s2d_shape* shape = NULL;
     52   res_T res = RES_OK;
     53   if(!dev || !out_shape) {
     54     res = RES_BAD_ARG;
     55     goto error;
     56   }
     57 
     58   shape = (struct s2d_shape*)
     59     MEM_CALLOC(dev->allocator, 1, sizeof(struct s2d_shape));
     60   if(!shape) {
     61     res = RES_MEM_ERR;
     62     goto error;
     63   }
     64   list_init(&shape->scene_attachment);
     65   S2D(device_ref_get(dev));
     66   shape->dev = dev;
     67   ref_init(&shape->ref);
     68   shape->id = flist_name_add(&dev->names);
     69   shape->is_enabled = 1;
     70   shape->flip_contour = 0;
     71 
     72   res = line_segments_create(dev, &shape->lines);
     73   if(res != RES_OK) goto error;
     74 
     75 exit:
     76   if(out_shape) *out_shape = shape;
     77   return res;
     78 error:
     79   if(shape) {
     80     S2D(shape_ref_put(shape));
     81     shape = NULL;
     82   }
     83   goto exit;
     84 }
     85 
     86 res_T
     87 s2d_shape_ref_get(struct s2d_shape* shape)
     88 {
     89   if(!shape) return RES_BAD_ARG;
     90   ref_get(&shape->ref);
     91   return RES_OK;
     92 }
     93 
     94 res_T
     95 s2d_shape_ref_put(struct s2d_shape* shape)
     96 {
     97   if(!shape) return RES_BAD_ARG;
     98   ref_put(&shape->ref, shape_release);
     99   return RES_OK;
    100 }
    101 
    102 res_T
    103 s2d_shape_get_id(const struct s2d_shape* shape, unsigned* id)
    104 {
    105   if(!shape || !id) return RES_BAD_ARG;
    106   *id = shape->id.index;
    107   return RES_OK;
    108 }
    109 
    110 res_T
    111 s2d_shape_enable(struct s2d_shape* shape, const char enable)
    112 {
    113   if(!shape) return RES_BAD_ARG;
    114   shape->is_enabled = enable;
    115   return RES_OK;
    116 }
    117 
    118 res_T
    119 s2d_shape_is_enabled(const struct s2d_shape* shape, char* is_enabled)
    120 {
    121   if(!shape || !is_enabled) return RES_BAD_ARG;
    122   *is_enabled = shape->is_enabled;
    123   return RES_OK;
    124 }
    125 
    126 res_T
    127 s2d_shape_is_attached(const struct s2d_shape* shape, char* is_attached)
    128 {
    129   if(!shape || !is_attached) return RES_BAD_ARG;
    130   *is_attached = !is_list_empty(&shape->scene_attachment);
    131   return RES_OK;
    132 }
    133 
    134 res_T
    135 s2d_shape_flip_contour(struct s2d_shape* shape)
    136 {
    137   if(!shape) return RES_BAD_ARG;
    138   shape->flip_contour ^= 1;
    139   return RES_OK;
    140 }
    141 
    142 res_T
    143 s2d_line_segments_setup_indexed_vertices
    144   (struct s2d_shape* shape,
    145    const unsigned nsegments,
    146    void (*get_indices)
    147     (const unsigned isegment, unsigned ids[2], void* ctx),
    148    const unsigned nverts,
    149    struct s2d_vertex_data attribs[],
    150    const unsigned nattribs,
    151    void* data)
    152 {
    153   if(!shape) return RES_BAD_ARG;
    154   return line_segments_setup_indexed_vertices
    155     (shape->lines, nsegments, get_indices, nverts, attribs, nattribs, data);
    156 }
    157 
    158 res_T
    159 s2d_line_segments_copy(const struct s2d_shape* src, struct s2d_shape* dst)
    160 {
    161   if(!src || !dst) return RES_BAD_ARG;
    162   if(src == dst) return RES_OK;
    163   dst->flip_contour = src->flip_contour;
    164   dst->is_enabled = src->is_enabled;
    165   line_segments_copy_indexed_vertices(src->lines, dst->lines);
    166   return RES_OK;
    167 }
    168 
    169 res_T
    170 s2d_line_segments_get_vertices_count
    171   (const struct s2d_shape* shape, unsigned* nverts)
    172 {
    173   if(!shape || !nverts) return RES_BAD_ARG;
    174   *nverts = (unsigned)line_segments_get_nverts(shape->lines);
    175   return RES_OK;
    176 }
    177 
    178 res_T
    179 s2d_line_segments_get_vertex_attrib
    180   (const struct s2d_shape* shape,
    181    const unsigned ivert,
    182    const enum s2d_attrib_usage usage,
    183    struct s2d_attrib* attrib)
    184 {
    185   const float* data;
    186   unsigned i, dim;
    187 
    188   if(!shape
    189   || (unsigned)usage >= S2D_ATTRIBS_COUNT__
    190   || !shape->lines->attribs[usage]
    191   || !attrib
    192   || ivert >= (unsigned)line_segments_get_nverts(shape->lines))
    193     return RES_BAD_ARG;
    194 
    195   attrib->usage = usage;
    196   attrib->type = shape->lines->attribs_type[usage];
    197 
    198   dim = s2d_type_get_dimension(attrib->type);
    199   data = line_segments_get_attr(shape->lines, usage) + ivert * dim;
    200   FOR_EACH(i, 0, dim) attrib->value[i] = data[i];
    201   return RES_OK;
    202 }
    203 
    204 res_T
    205 s2d_line_segments_get_segments_count
    206   (const struct s2d_shape* shape, unsigned* nsegments)
    207 {
    208   if(!shape || !nsegments) return RES_BAD_ARG;
    209   *nsegments = (unsigned)line_segments_get_nsegments(shape->lines);
    210   return RES_OK;
    211 }
    212 
    213 res_T
    214 s2d_line_segments_get_segment_indices
    215   (const struct s2d_shape* shape,
    216    const unsigned isegment,
    217    unsigned ids[2])
    218 {
    219   const unsigned* data;
    220   if(!shape
    221   || !ids
    222   || isegment >= (unsigned)line_segments_get_nsegments(shape->lines))
    223     return RES_BAD_ARG;
    224 
    225   data = line_segments_get_ids(shape->lines) + isegment * 2/*#ids per segment*/;
    226   ids[0] = data[0];
    227   ids[1] = data[1];
    228   return RES_OK;
    229 }
    230 
    231 res_T
    232 s2d_line_segments_set_hit_filter_function
    233   (struct s2d_shape* shape,
    234    s2d_hit_filter_function_T func,
    235    void* data)
    236 {
    237   if(!shape) return RES_BAD_ARG;
    238   shape->lines->filter.func = func;
    239   shape->lines->filter.data = data;
    240   return RES_OK;
    241 }
    242 
    243 res_T
    244 s2d_line_segments_get_hit_filter_data(struct s2d_shape* shape, void** data)
    245 {
    246   if(!shape || !data) return RES_BAD_ARG;
    247   *data = shape->lines->filter.data;
    248   return RES_OK;
    249 }
    250