PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ 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 3209 of file lwgeom_topo.c.

3210{
3211 LWGEOM *face;
3212 LWPOLY *facepoly;
3213 LWT_ISO_EDGE *edges;
3214 uint64_t numfaceedges;
3215 int fields;
3216 uint32_t i;
3217 int nseid = 0; /* number of signed edge ids */
3218 int prevseid;
3219 LWT_ELEMID *seid; /* signed edge ids */
3220
3221 /* Get list of face edges */
3222 numfaceedges = 1;
3223 fields = LWT_COL_EDGE_EDGE_ID |
3227 ;
3228 edges = lwt_be_getEdgeByFace( topo, &face_id, &numfaceedges, fields, NULL );
3229 if (numfaceedges == UINT64_MAX)
3230 {
3232 return -1;
3233 }
3234 if ( ! numfaceedges ) return 0; /* no edges in output */
3235 LWDEBUGF(1, "lwt_GetFaceEdges: lwt_be_getEdgeByFace returned %llu edges", numfaceedges);
3236
3237 /* order edges by occurrence in face */
3238
3239 face = _lwt_FaceByEdges(topo, edges, numfaceedges);
3240 if ( ! face )
3241 {
3242 /* _lwt_FaceByEdges should have already invoked lwerror in this case */
3243 _lwt_release_edges(edges, numfaceedges);
3244 lwerror("Corrupted topology: unable to build geometry of face %"
3245 LWTFMT_ELEMID " from its %"PRIu64" edges", face_id, numfaceedges);
3246 return -1;
3247 }
3248
3249 if ( lwgeom_is_empty(face) )
3250 {
3251 /* no edges in output */
3252 _lwt_release_edges(edges, numfaceedges);
3253 lwgeom_free(face);
3254 return 0;
3255 }
3256
3257 /* force_lhr, if the face is not the universe */
3258 /* _lwt_FaceByEdges seems to guaranteed RHR */
3259 /* lwgeom_force_clockwise(face); */
3260 if ( face_id ) lwgeom_reverse_in_place(face);
3261
3262#if 0
3263 {
3264 size_t sz;
3265 char *wkt = lwgeom_to_wkt(face, WKT_EXTENDED, 6, &sz);
3266 LWDEBUGF(1, "Geometry of face %" LWTFMT_ELEMID " is: %s",
3267 face_id, wkt);
3268 lwfree(wkt);
3269 }
3270#endif
3271
3272 facepoly = lwgeom_as_lwpoly(face);
3273 if ( ! facepoly )
3274 {
3275 _lwt_release_edges(edges, numfaceedges);
3276 lwgeom_free(face);
3277 lwerror("Geometry of face %" LWTFMT_ELEMID " is not a polygon", face_id);
3278 return -1;
3279 }
3280
3281 nseid = prevseid = 0;
3282 seid = lwalloc( sizeof(LWT_ELEMID) * numfaceedges );
3283
3284 /* for each ring of the face polygon... */
3285 for ( i=0; i<facepoly->nrings; ++i )
3286 {
3287 const POINTARRAY *ring = facepoly->rings[i];
3288 int32_t j = 0;
3289 LWT_ISO_EDGE *nextedge;
3290 LWLINE *nextline;
3291
3292 LWDEBUGF(1, "Ring %d has %d points", i, ring->npoints);
3293
3294 while ( j < (int32_t) ring->npoints-1 )
3295 {
3296 LWDEBUGF(1, "Looking for edge covering ring %d from vertex %d",
3297 i, j);
3298
3299 int edgeno = _lwt_FindNextRingEdge(ring, j, edges, numfaceedges);
3300 if ( edgeno == -1 )
3301 {
3302 /* should never happen */
3303 _lwt_release_edges(edges, numfaceedges);
3304 lwgeom_free(face);
3305 lwfree(seid);
3306 lwerror("No edge (among %" PRIu64 ") found to be defining geometry of face %"
3307 LWTFMT_ELEMID, numfaceedges, face_id);
3308 return -1;
3309 }
3310
3311 nextedge = &(edges[edgeno]);
3312 nextline = nextedge->geom;
3313
3314 LWDEBUGF(1, "Edge %" LWTFMT_ELEMID
3315 " covers ring %d from vertex %d to %d",
3316 nextedge->edge_id, i, j, j + nextline->points->npoints - 1);
3317
3318#if 0
3319 {
3320 size_t sz;
3321 char *wkt = lwgeom_to_wkt(lwline_as_lwgeom(nextline), WKT_EXTENDED, 6, &sz);
3322 LWDEBUGF(1, "Edge %" LWTFMT_ELEMID " is %s",
3323 nextedge->edge_id, wkt);
3324 lwfree(wkt);
3325 }
3326#endif
3327
3328 j += nextline->points->npoints - 1;
3329
3330 /* Add next edge to the output array */
3331 seid[nseid++] = nextedge->face_left == face_id ?
3332 nextedge->edge_id :
3333 -nextedge->edge_id;
3334
3335 /* avoid checking again on next time turn */
3336 nextedge->face_left = nextedge->face_right = -1;
3337 }
3338
3339 /* now "scroll" the list of edges so that the one
3340 * with smaller absolute edge_id is first */
3341 /* Range is: [prevseid, nseid) -- [inclusive, exclusive) */
3342 if ( (nseid - prevseid) > 1 )
3343 {{
3344 LWT_ELEMID minid = 0;
3345 int minidx = 0;
3346 LWDEBUGF(1, "Looking for smallest id among the %d edges "
3347 "composing ring %d", (nseid-prevseid), i);
3348 for ( j=prevseid; j<nseid; ++j )
3349 {
3350 LWT_ELEMID id = llabs(seid[j]);
3351 LWDEBUGF(1, "Abs id of edge in pos %d is %" LWTFMT_ELEMID, j, id);
3352 if ( ! minid || id < minid )
3353 {
3354 minid = id;
3355 minidx = j;
3356 }
3357 }
3358 LWDEBUGF(1, "Smallest id is %" LWTFMT_ELEMID
3359 " at position %d", minid, minidx);
3360 if ( minidx != prevseid )
3361 {
3362 _lwt_RotateElemidArray(seid, prevseid, nseid, minidx);
3363 }
3364 }}
3365
3366 prevseid = nseid;
3367 }
3368
3369 lwgeom_free(face);
3370 _lwt_release_edges(edges, numfaceedges);
3371
3372 *out = seid;
3373 return nseid;
3374}
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1246
#define WKT_EXTENDED
Definition liblwgeom.h:2221
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:243
void lwfree(void *mem)
Definition lwutil.c:248
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:367
void lwgeom_reverse_in_place(LWGEOM *lwgeom)
Reverse vertex order of LWGEOM.
Definition lwgeom.c:131
#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)
static void _lwt_RotateElemidArray(LWT_ELEMID *ary, int from, int to, int rotidx)
static LWT_ISO_EDGE * lwt_be_getEdgeByFace(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, uint64_t *numelems, int fields, const GBOX *box)
void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
static LWGEOM * _lwt_FaceByEdges(LWT_TOPOLOGY *topo, LWT_ISO_EDGE *edges, int numfaceedges)
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
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: