PostGIS 3.6.2dev-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 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 {
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}
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1218
#define WKT_EXTENDED
Definition liblwgeom.h:2218
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 lwfree(void *mem)
Definition lwutil.c:248
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:339
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)
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: