PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ lwt_GetFaceEdges()

int lwt_GetFaceEdges ( LWT_TOPOLOGY topo,
LWT_ELEMID  face,
LWT_ELEMID **  edges 
)

Return the list of directed edges bounding a face.

For ST_GetFaceEdges

Parameters
topothe topology to operate on
faceidentifier of the face
edgeswill be set to an array of signed edge identifiers, will need to be released with lwfree
Returns
the number of edges in the edges array, or -1 on error (liblwgeom error handler will be invoked with error message)

Definition at line 3092 of file lwgeom_topo.c.

3093 {
3094  LWGEOM *face;
3095  LWPOLY *facepoly;
3096  LWT_ISO_EDGE *edges;
3097  uint64_t numfaceedges;
3098  int fields;
3099  uint32_t i;
3100  int nseid = 0; /* number of signed edge ids */
3101  int prevseid;
3102  LWT_ELEMID *seid; /* signed edge ids */
3103 
3104  /* Get list of face edges */
3105  numfaceedges = 1;
3106  fields = LWT_COL_EDGE_EDGE_ID |
3110  ;
3111  edges = lwt_be_getEdgeByFace( topo, &face_id, &numfaceedges, fields, NULL );
3112  if (numfaceedges == UINT64_MAX)
3113  {
3114  PGTOPO_BE_ERROR();
3115  return -1;
3116  }
3117  if ( ! numfaceedges ) return 0; /* no edges in output */
3118  LWDEBUGF(1, "lwt_GetFaceEdges: lwt_be_getEdgeByFace returned %llu edges", numfaceedges);
3119 
3120  /* order edges by occurrence in face */
3121 
3122  face = _lwt_FaceByEdges(topo, edges, numfaceedges);
3123  if ( ! face )
3124  {
3125  /* _lwt_FaceByEdges should have already invoked lwerror in this case */
3126  _lwt_release_edges(edges, numfaceedges);
3127  lwerror("Corrupted topology: unable to build geometry of face %"
3128  LWTFMT_ELEMID " from its %"PRIu64" edges", face_id, numfaceedges);
3129  return -1;
3130  }
3131 
3132  if ( lwgeom_is_empty(face) )
3133  {
3134  /* no edges in output */
3135  _lwt_release_edges(edges, numfaceedges);
3136  lwgeom_free(face);
3137  return 0;
3138  }
3139 
3140  /* force_lhr, if the face is not the universe */
3141  /* _lwt_FaceByEdges seems to guaranteed RHR */
3142  /* lwgeom_force_clockwise(face); */
3143  if ( face_id ) lwgeom_reverse_in_place(face);
3144 
3145 #if 0
3146  {
3147  size_t sz;
3148  char *wkt = lwgeom_to_wkt(face, WKT_EXTENDED, 6, &sz);
3149  LWDEBUGF(1, "Geometry of face %" LWTFMT_ELEMID " is: %s",
3150  face_id, wkt);
3151  lwfree(wkt);
3152  }
3153 #endif
3154 
3155  facepoly = lwgeom_as_lwpoly(face);
3156  if ( ! facepoly )
3157  {
3158  _lwt_release_edges(edges, numfaceedges);
3159  lwgeom_free(face);
3160  lwerror("Geometry of face %" LWTFMT_ELEMID " is not a polygon", face_id);
3161  return -1;
3162  }
3163 
3164  nseid = prevseid = 0;
3165  seid = lwalloc( sizeof(LWT_ELEMID) * numfaceedges );
3166 
3167  /* for each ring of the face polygon... */
3168  for ( i=0; i<facepoly->nrings; ++i )
3169  {
3170  const POINTARRAY *ring = facepoly->rings[i];
3171  int32_t j = 0;
3172  LWT_ISO_EDGE *nextedge;
3173  LWLINE *nextline;
3174 
3175  LWDEBUGF(1, "Ring %d has %d points", i, ring->npoints);
3176 
3177  while ( j < (int32_t) ring->npoints-1 )
3178  {
3179  LWDEBUGF(1, "Looking for edge covering ring %d from vertex %d",
3180  i, j);
3181 
3182  int edgeno = _lwt_FindNextRingEdge(ring, j, edges, numfaceedges);
3183  if ( edgeno == -1 )
3184  {
3185  /* should never happen */
3186  _lwt_release_edges(edges, numfaceedges);
3187  lwgeom_free(face);
3188  lwfree(seid);
3189  lwerror("No edge (among %" PRIu64 ") found to be defining geometry of face %"
3190  LWTFMT_ELEMID, numfaceedges, face_id);
3191  return -1;
3192  }
3193 
3194  nextedge = &(edges[edgeno]);
3195  nextline = nextedge->geom;
3196 
3197  LWDEBUGF(1, "Edge %" LWTFMT_ELEMID
3198  " covers ring %d from vertex %d to %d",
3199  nextedge->edge_id, i, j, j + nextline->points->npoints - 1);
3200 
3201 #if 0
3202  {
3203  size_t sz;
3204  char *wkt = lwgeom_to_wkt(lwline_as_lwgeom(nextline), WKT_EXTENDED, 6, &sz);
3205  LWDEBUGF(1, "Edge %" LWTFMT_ELEMID " is %s",
3206  nextedge->edge_id, wkt);
3207  lwfree(wkt);
3208  }
3209 #endif
3210 
3211  j += nextline->points->npoints - 1;
3212 
3213  /* Add next edge to the output array */
3214  seid[nseid++] = nextedge->face_left == face_id ?
3215  nextedge->edge_id :
3216  -nextedge->edge_id;
3217 
3218  /* avoid checking again on next time turn */
3219  nextedge->face_left = nextedge->face_right = -1;
3220  }
3221 
3222  /* now "scroll" the list of edges so that the one
3223  * with smaller absolute edge_id is first */
3224  /* Range is: [prevseid, nseid) -- [inclusive, exclusive) */
3225  if ( (nseid - prevseid) > 1 )
3226  {{
3227  LWT_ELEMID minid = 0;
3228  int minidx = 0;
3229  LWDEBUGF(1, "Looking for smallest id among the %d edges "
3230  "composing ring %d", (nseid-prevseid), i);
3231  for ( j=prevseid; j<nseid; ++j )
3232  {
3233  LWT_ELEMID id = llabs(seid[j]);
3234  LWDEBUGF(1, "Abs id of edge in pos %d is %" LWTFMT_ELEMID, j, id);
3235  if ( ! minid || id < minid )
3236  {
3237  minid = id;
3238  minidx = j;
3239  }
3240  }
3241  LWDEBUGF(1, "Smallest id is %" LWTFMT_ELEMID
3242  " at position %d", minid, minidx);
3243  if ( minidx != prevseid )
3244  {
3245  _lwt_RotateElemidArray(seid, prevseid, nseid, minidx);
3246  }
3247  }}
3248 
3249  prevseid = nseid;
3250  }
3251 
3252  lwgeom_free(face);
3253  _lwt_release_edges(edges, numfaceedges);
3254 
3255  *out = seid;
3256  return nseid;
3257 }
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:339
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1218
#define WKT_EXTENDED
Definition: liblwgeom.h:2218
void lwfree(void *mem)
Definition: lwutil.c:248
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
Definition: lwout_wkt.c:708
void * lwalloc(size_t size)
Definition: lwutil.c:227
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:215
void lwgeom_reverse_in_place(LWGEOM *lwgeom)
Reverse vertex order of LWGEOM.
Definition: lwgeom.c:103
#define LWT_COL_EDGE_FACE_RIGHT
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWT_COL_EDGE_FACE_LEFT
#define LWT_COL_EDGE_EDGE_ID
Edge fields.
#define LWT_COL_EDGE_GEOM
#define PGTOPO_BE_ERROR()
#define LWTFMT_ELEMID
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:106
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
static int _lwt_FindNextRingEdge(const POINTARRAY *ring, int from, const LWT_ISO_EDGE *edges, int numedges)
Definition: lwgeom_topo.c:2936
static LWT_ISO_EDGE * lwt_be_getEdgeByFace(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, uint64_t *numelems, int fields, const GBOX *box)
Definition: lwgeom_topo.c:233
static void _lwt_RotateElemidArray(LWT_ELEMID *ary, int from, int to, int rotidx)
Definition: lwgeom_topo.c:3083
void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
Definition: lwgeom_topo.c:460
static LWGEOM * _lwt_FaceByEdges(LWT_TOPOLOGY *topo, LWT_ISO_EDGE *edges, int numfaceedges)
Definition: lwgeom_topo.c:2794
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition: lwinline.h:199
POINTARRAY * points
Definition: liblwgeom.h:483
POINTARRAY ** rings
Definition: liblwgeom.h:519
uint32_t nrings
Definition: liblwgeom.h:524
LWT_ELEMID face_right
LWT_ELEMID face_left
LWLINE * geom
LWT_ELEMID edge_id
uint32_t npoints
Definition: liblwgeom.h:427

References _lwt_FaceByEdges(), _lwt_FindNextRingEdge(), _lwt_release_edges(), _lwt_RotateElemidArray(), LWT_ISO_EDGE::edge_id, LWT_ISO_EDGE::face_left, LWT_ISO_EDGE::face_right, LWT_ISO_EDGE::geom, lwalloc(), LWDEBUGF, lwerror(), lwfree(), lwgeom_as_lwpoly(), lwgeom_free(), lwgeom_is_empty(), lwgeom_reverse_in_place(), lwgeom_to_wkt(), lwline_as_lwgeom(), lwt_be_getEdgeByFace(), LWT_COL_EDGE_EDGE_ID, LWT_COL_EDGE_FACE_LEFT, LWT_COL_EDGE_FACE_RIGHT, LWT_COL_EDGE_GEOM, LWTFMT_ELEMID, POINTARRAY::npoints, LWPOLY::nrings, PGTOPO_BE_ERROR, LWLINE::points, LWPOLY::rings, and WKT_EXTENDED.

Here is the call graph for this function: