PostGIS  3.1.6dev-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 3074 of file lwgeom_topo.c.

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