PostGIS  3.2.2dev-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 3091 of file lwgeom_topo.c.

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

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: