PostGIS  3.3.9dev-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 3098 of file lwgeom_topo.c.

3099 {
3100  LWGEOM *face;
3101  LWPOLY *facepoly;
3102  LWT_ISO_EDGE *edges;
3103  uint64_t numfaceedges;
3104  int fields;
3105  uint32_t i;
3106  int nseid = 0; /* number of signed edge ids */
3107  int prevseid;
3108  LWT_ELEMID *seid; /* signed edge ids */
3109 
3110  /* Get list of face edges */
3111  numfaceedges = 1;
3112  fields = LWT_COL_EDGE_EDGE_ID |
3116  ;
3117  edges = lwt_be_getEdgeByFace( topo, &face_id, &numfaceedges, fields, NULL );
3118  if (numfaceedges == UINT64_MAX)
3119  {
3120  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
3121  return -1;
3122  }
3123  if ( ! numfaceedges ) return 0; /* no edges in output */
3124  LWDEBUGF(1, "lwt_GetFaceEdges: lwt_be_getEdgeByFace returned %d edges", numfaceedges);
3125 
3126  /* order edges by occurrence in face */
3127 
3128  face = _lwt_FaceByEdges(topo, edges, numfaceedges);
3129  if ( ! face )
3130  {
3131  /* _lwt_FaceByEdges should have already invoked lwerror in this case */
3132  _lwt_release_edges(edges, numfaceedges);
3133  lwerror("Corrupted topology: unable to build geometry of face %"
3134  LWTFMT_ELEMID " from its %"PRIu64" edges", face_id, numfaceedges);
3135  return -1;
3136  }
3137 
3138  if ( lwgeom_is_empty(face) )
3139  {
3140  /* no edges in output */
3141  _lwt_release_edges(edges, numfaceedges);
3142  lwgeom_free(face);
3143  return 0;
3144  }
3145 
3146  /* force_lhr, if the face is not the universe */
3147  /* _lwt_FaceByEdges seems to guaranteed RHR */
3148  /* lwgeom_force_clockwise(face); */
3149  if ( face_id ) lwgeom_reverse_in_place(face);
3150 
3151 #if 0
3152  {
3153  size_t sz;
3154  char *wkt = lwgeom_to_wkt(face, WKT_EXTENDED, 6, &sz);
3155  LWDEBUGF(1, "Geometry of face %" LWTFMT_ELEMID " is: %s",
3156  face_id, wkt);
3157  lwfree(wkt);
3158  }
3159 #endif
3160 
3161  facepoly = lwgeom_as_lwpoly(face);
3162  if ( ! facepoly )
3163  {
3164  _lwt_release_edges(edges, numfaceedges);
3165  lwgeom_free(face);
3166  lwerror("Geometry of face %" LWTFMT_ELEMID " is not a polygon", face_id);
3167  return -1;
3168  }
3169 
3170  nseid = prevseid = 0;
3171  seid = lwalloc( sizeof(LWT_ELEMID) * numfaceedges );
3172 
3173  /* for each ring of the face polygon... */
3174  for ( i=0; i<facepoly->nrings; ++i )
3175  {
3176  const POINTARRAY *ring = facepoly->rings[i];
3177  int32_t j = 0;
3178  LWT_ISO_EDGE *nextedge;
3179  LWLINE *nextline;
3180 
3181  LWDEBUGF(1, "Ring %d has %d points", i, ring->npoints);
3182 
3183  while ( j < (int32_t) ring->npoints-1 )
3184  {
3185  LWDEBUGF(1, "Looking for edge covering ring %d from vertex %d",
3186  i, j);
3187 
3188  int edgeno = _lwt_FindNextRingEdge(ring, j, edges, numfaceedges);
3189  if ( edgeno == -1 )
3190  {
3191  /* should never happen */
3192  _lwt_release_edges(edges, numfaceedges);
3193  lwgeom_free(face);
3194  lwfree(seid);
3195  lwerror("No edge (among %d) found to be defining geometry of face %"
3196  LWTFMT_ELEMID, numfaceedges, face_id);
3197  return -1;
3198  }
3199 
3200  nextedge = &(edges[edgeno]);
3201  nextline = nextedge->geom;
3202 
3203  LWDEBUGF(1, "Edge %" LWTFMT_ELEMID
3204  " covers ring %d from vertex %d to %d",
3205  nextedge->edge_id, i, j, j + nextline->points->npoints - 1);
3206 
3207 #if 0
3208  {
3209  size_t sz;
3210  char *wkt = lwgeom_to_wkt(lwline_as_lwgeom(nextline), WKT_EXTENDED, 6, &sz);
3211  LWDEBUGF(1, "Edge %" LWTFMT_ELEMID " is %s",
3212  nextedge->edge_id, wkt);
3213  lwfree(wkt);
3214  }
3215 #endif
3216 
3217  j += nextline->points->npoints - 1;
3218 
3219  /* Add next edge to the output array */
3220  seid[nseid++] = nextedge->face_left == face_id ?
3221  nextedge->edge_id :
3222  -nextedge->edge_id;
3223 
3224  /* avoid checking again on next time turn */
3225  nextedge->face_left = nextedge->face_right = -1;
3226  }
3227 
3228  /* now "scroll" the list of edges so that the one
3229  * with smaller absolute edge_id is first */
3230  /* Range is: [prevseid, nseid) -- [inclusive, exclusive) */
3231  if ( (nseid - prevseid) > 1 )
3232  {{
3233  LWT_ELEMID minid = 0;
3234  int minidx = 0;
3235  LWDEBUGF(1, "Looking for smallest id among the %d edges "
3236  "composing ring %d", (nseid-prevseid), i);
3237  for ( j=prevseid; j<nseid; ++j )
3238  {
3239  LWT_ELEMID id = llabs(seid[j]);
3240  LWDEBUGF(1, "Abs id of edge in pos %d is %" LWTFMT_ELEMID, j, id);
3241  if ( ! minid || id < minid )
3242  {
3243  minid = id;
3244  minidx = j;
3245  }
3246  }
3247  LWDEBUGF(1, "Smallest id is %" LWTFMT_ELEMID
3248  " at position %d", minid, minidx);
3249  if ( minidx != prevseid )
3250  {
3251  _lwt_RotateElemidArray(seid, prevseid, nseid, minidx);
3252  }
3253  }}
3254 
3255  prevseid = nseid;
3256  }
3257 
3258  lwgeom_free(face);
3259  _lwt_release_edges(edges, numfaceedges);
3260 
3261  *out = seid;
3262  return nseid;
3263 }
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:339
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1155
#define WKT_EXTENDED
Definition: liblwgeom.h:2168
void lwfree(void *mem)
Definition: lwutil.c:242
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 LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
const char * lwt_be_lastErrorMessage(const LWT_BE_IFACE *be)
Definition: lwgeom_topo.c:119
static int _lwt_FindNextRingEdge(const POINTARRAY *ring, int from, const LWT_ISO_EDGE *edges, int numedges)
Definition: lwgeom_topo.c:2942
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:238
static void _lwt_RotateElemidArray(LWT_ELEMID *ary, int from, int to, int rotidx)
Definition: lwgeom_topo.c:3089
static LWGEOM * _lwt_FaceByEdges(LWT_TOPOLOGY *topo, LWT_ISO_EDGE *edges, int numfaceedges)
Definition: lwgeom_topo.c:2800
#define LWTFMT_ELEMID
Definition: lwgeom_topo.c:43
static void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
Definition: lwgeom_topo.c:465
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:203
POINTARRAY * points
Definition: liblwgeom.h:498
POINTARRAY ** rings
Definition: liblwgeom.h:534
uint32_t nrings
Definition: liblwgeom.h:539
LWT_ELEMID face_right
LWT_ELEMID face_left
LWLINE * geom
LWT_ELEMID edge_id
const LWT_BE_IFACE * be_iface
uint32_t npoints
Definition: liblwgeom.h:442

References _lwt_FaceByEdges(), _lwt_FindNextRingEdge(), _lwt_release_edges(), _lwt_RotateElemidArray(), LWT_TOPOLOGY_T::be_iface, 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_be_lastErrorMessage(), 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, LWLINE::points, LWPOLY::rings, and WKT_EXTENDED.

Here is the call graph for this function: