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_primitive.c (5636B)


      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_geometry.h"
     19 #include "s2d_line_segments.h"
     20 
     21 #include <rsys/float2.h>
     22 
     23 /*******************************************************************************
     24  * Helper functions
     25  ******************************************************************************/
     26 static int
     27 check_primitive(const struct s2d_primitive* prim)
     28 {
     29   return prim
     30       && prim->geom_id != S2D_INVALID_ID
     31       && prim->prim_id != S2D_INVALID_ID
     32       && prim->mesh__ != NULL;
     33 }
     34 
     35 /*******************************************************************************
     36  * Exported functions
     37  ******************************************************************************/
     38 res_T
     39 s2d_primitive_get_attrib
     40   (const struct s2d_primitive* prim,
     41    const enum s2d_attrib_usage usage,
     42    const float s,
     43    struct s2d_attrib* attrib)
     44 {
     45   const uint32_t* ids;
     46   struct geometry* geom = NULL;
     47   res_T res = RES_OK;
     48 
     49   if(!check_primitive(prim)
     50   || !attrib
     51   || (usage != S2D_GEOMETRY_NORMAL && (unsigned)usage >= S2D_ATTRIBS_COUNT__)) {
     52     res = RES_BAD_ARG;
     53     goto error;
     54   }
     55 
     56   /* Unnormalized barycentric coordinates */
     57   if(s < 0.f || s > 1.f) {
     58     res = RES_BAD_ARG;
     59     goto error;
     60   }
     61 
     62   geom = (struct geometry*)prim->mesh__;
     63 
     64   /* The line segments haven't tge required attrib */
     65   if(usage != S2D_GEOMETRY_NORMAL && !geom->lines->attribs[usage]) {
     66     res = RES_BAD_ARG;
     67     goto error;
     68   }
     69 
     70   /* Out of bound primitive index */
     71   if(prim->prim_id >= line_segments_get_nsegments(geom->lines)) {
     72     res = RES_BAD_ARG;
     73     goto error;
     74   }
     75 
     76   ids = line_segments_get_ids(geom->lines) + prim->prim_id * 2/*#segment ids*/;
     77   attrib->usage = usage;
     78 
     79   if(usage == S2D_POSITION || usage == S2D_GEOMETRY_NORMAL) {
     80     const float* v0;
     81     const float* v1;
     82     const float* pos;
     83 
     84     attrib->type = S2D_FLOAT2;
     85     pos = line_segments_get_pos(geom->lines);
     86     v0 = pos + ids[0] * 2;
     87     v1 = pos + ids[1] * 2;
     88 
     89     if(usage == S2D_POSITION) {
     90       float tmp[2];
     91       f2_mulf(attrib->value, v1, s);
     92       f2_add(attrib->value, attrib->value, f2_mulf(tmp, v0, 1.f-s));
     93     } else { ASSERT(usage == S2D_GEOMETRY_NORMAL);
     94       const float dx = v1[0] - v0[0];
     95       const float dy = v1[1] - v0[1];
     96       /* Build the segment normal with respect to edge orientation.
     97        * Default is clock wise */
     98       if(geom->flip_contour) {
     99         attrib->value[0] = -dy;
    100         attrib->value[1] = dx;
    101       } else {
    102         attrib->value[0] = dy;
    103         attrib->value[1] = -dx;
    104       }
    105     }
    106   } else {
    107     FATAL("Unimplemented attribute getter.\n");
    108   }
    109 
    110 exit:
    111   return res;
    112 error:
    113   goto exit;
    114 }
    115 
    116 res_T
    117 s2d_primitive_sample
    118   (const struct s2d_primitive* prim,
    119    const float u,
    120    float* s)
    121 {
    122   if(!check_primitive(prim) || !s)
    123     return RES_BAD_ARG;
    124 
    125   if(u < 0.f || u >= 1.f)
    126     return RES_BAD_ARG;
    127 
    128   /* Only line segments primitives are currently supported. So the "u"
    129    * canonical variable is directly the parametric coordinate of the sample
    130    * onto the segment */
    131   *s = u;
    132   return RES_OK;
    133 }
    134 
    135 res_T
    136 s2d_primitive_compute_length(const struct s2d_primitive* prim, float* length)
    137 {
    138   const uint32_t* ids;
    139   const float* pos;
    140   const float* v0, *v1;
    141   float tmp[2];
    142   struct geometry* geom;
    143 
    144   if(!check_primitive(prim) || !length)
    145     return RES_BAD_ARG;
    146 
    147   geom = (struct geometry*)prim->mesh__;
    148   pos = line_segments_get_pos(geom->lines);
    149   ids = line_segments_get_ids(geom->lines) + prim->prim_id * 2/*#segment ids*/;
    150   v0 = pos + ids[0] * 2/*#coords*/;
    151   v1 = pos + ids[1] * 2/*#coords*/;
    152   *length = f2_len(f2_sub(tmp, v1, v0));
    153   return RES_OK;
    154 }
    155 
    156 res_T
    157 s2d_segment_get_vertex_attrib
    158   (const struct s2d_primitive* prim,
    159    const size_t ivertex, /* in [0..2[ */
    160    const enum s2d_attrib_usage usage,
    161    struct s2d_attrib* attrib) /* Resulting attrib */
    162 {
    163   struct geometry* geom;
    164   const uint32_t* ids;
    165 
    166   if(!check_primitive(prim) || ivertex > 1
    167   || (unsigned)usage >= S2D_ATTRIBS_COUNT__ || !attrib) {
    168     return RES_BAD_ARG;
    169   }
    170 
    171   geom = (struct geometry*)prim->mesh__;
    172   ASSERT(prim->geom_id == geom->name);
    173 
    174   /* The segment have not the required attrib */
    175   if(!geom->lines->attribs[usage]) {
    176     return RES_BAD_ARG;
    177   }
    178 
    179   /* Out of bound primitive index */
    180   if(prim->prim_id >= line_segments_get_nsegments(geom->lines)) {
    181     return RES_BAD_ARG;
    182   }
    183 
    184   ids = line_segments_get_ids(geom->lines) + prim->prim_id*2/*#segment ids*/;
    185   attrib->usage = usage;
    186 
    187   if(usage != S2D_POSITION) {
    188     const float* attr;
    189     unsigned i, dim;
    190     attrib->type = geom->lines->attribs_type[usage];
    191     /* Fetch attrib data */
    192     dim = s2d_type_get_dimension(attrib->type);
    193     attr = line_segments_get_attr(geom->lines, usage) + ids[ivertex]*dim;
    194     FOR_EACH(i, 0, dim) attrib->value[i] = attr[i];
    195   } else {
    196     const float* pos;
    197     attrib->type = S2D_FLOAT2;
    198     /* Fetch data */
    199     pos = line_segments_get_pos(geom->lines) + ids[ivertex]*2;
    200     f2_set(attrib->value, pos);
    201   }
    202   return RES_OK;
    203 }
    204