PostGIS  3.0.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 3022 of file lwgeom_topo.c.

3023 {
3024  LWGEOM *face;
3025  LWPOLY *facepoly;
3026  LWT_ISO_EDGE *edges;
3027  uint64_t numfaceedges;
3028  int fields;
3029  uint32_t i;
3030  int nseid = 0; /* number of signed edge ids */
3031  int prevseid;
3032  LWT_ELEMID *seid; /* signed edge ids */
3033 
3034  /* Get list of face edges */
3035  numfaceedges = 1;
3036  fields = LWT_COL_EDGE_EDGE_ID |
3040  ;
3041  edges = lwt_be_getEdgeByFace( topo, &face_id, &numfaceedges, fields, NULL );
3042  if (numfaceedges == UINT64_MAX)
3043  {
3044  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
3045  return -1;
3046  }
3047  if ( ! numfaceedges ) return 0; /* no edges in output */
3048 
3049  /* order edges by occurrence in face */
3050 
3051  face = _lwt_FaceByEdges(topo, edges, numfaceedges);
3052  if ( ! face )
3053  {
3054  /* _lwt_FaceByEdges should have already invoked lwerror in this case */
3055  _lwt_release_edges(edges, numfaceedges);
3056  lwerror("Corrupted topology: unable to build geometry of face %"
3057  LWTFMT_ELEMID " from its %"PRIu64" edges", face_id, numfaceedges);
3058  return -1;
3059  }
3060 
3061  if ( lwgeom_is_empty(face) )
3062  {
3063  /* no edges in output */
3064  _lwt_release_edges(edges, numfaceedges);
3065  lwgeom_free(face);
3066  return 0;
3067  }
3068 
3069  /* force_lhr, if the face is not the universe */
3070  /* _lwt_FaceByEdges seems to guaranteed RHR */
3071  /* lwgeom_force_clockwise(face); */
3072  if ( face_id ) lwgeom_reverse_in_place(face);
3073 
3074 #if 0
3075  {
3076  size_t sz;
3077  char *wkt = lwgeom_to_wkt(face, WKT_EXTENDED, 6, &sz);
3078  LWDEBUGF(1, "Geometry of face %" LWTFMT_ELEMID " is: %s",
3079  face_id, wkt);
3080  lwfree(wkt);
3081  }
3082 #endif
3083 
3084  facepoly = lwgeom_as_lwpoly(face);
3085  if ( ! facepoly )
3086  {
3087  _lwt_release_edges(edges, numfaceedges);
3088  lwgeom_free(face);
3089  lwerror("Geometry of face %" LWTFMT_ELEMID " is not a polygon", face_id);
3090  return -1;
3091  }
3092 
3093  nseid = prevseid = 0;
3094  seid = lwalloc( sizeof(LWT_ELEMID) * numfaceedges );
3095 
3096  /* for each ring of the face polygon... */
3097  for ( i=0; i<facepoly->nrings; ++i )
3098  {
3099  const POINTARRAY *ring = facepoly->rings[i];
3100  int32_t j = 0;
3101  LWT_ISO_EDGE *nextedge;
3102  LWLINE *nextline;
3103 
3104  LWDEBUGF(1, "Ring %d has %d points", i, ring->npoints);
3105 
3106  while ( j < (int32_t) ring->npoints-1 )
3107  {
3108  LWDEBUGF(1, "Looking for edge covering ring %d from vertex %d",
3109  i, j);
3110 
3111  int edgeno = _lwt_FindNextRingEdge(ring, j, edges, numfaceedges);
3112  if ( edgeno == -1 )
3113  {
3114  /* should never happen */
3115  _lwt_release_edges(edges, numfaceedges);
3116  lwgeom_free(face);
3117  lwfree(seid);
3118  lwerror("No edge (among %d) found to be defining geometry of face %"
3119  LWTFMT_ELEMID, numfaceedges, face_id);
3120  return -1;
3121  }
3122 
3123  nextedge = &(edges[edgeno]);
3124  nextline = nextedge->geom;
3125 
3126  LWDEBUGF(1, "Edge %" LWTFMT_ELEMID
3127  " covers ring %d from vertex %d to %d",
3128  nextedge->edge_id, i, j, j + nextline->points->npoints - 1);
3129 
3130 #if 0
3131  {
3132  size_t sz;
3133  char *wkt = lwgeom_to_wkt(lwline_as_lwgeom(nextline), WKT_EXTENDED, 6, &sz);
3134  LWDEBUGF(1, "Edge %" LWTFMT_ELEMID " is %s",
3135  nextedge->edge_id, wkt);
3136  lwfree(wkt);
3137  }
3138 #endif
3139 
3140  j += nextline->points->npoints - 1;
3141 
3142  /* Add next edge to the output array */
3143  seid[nseid++] = nextedge->face_left == face_id ?
3144  nextedge->edge_id :
3145  -nextedge->edge_id;
3146 
3147  /* avoid checking again on next time turn */
3148  nextedge->face_left = nextedge->face_right = -1;
3149  }
3150 
3151  /* now "scroll" the list of edges so that the one
3152  * with smaller absolute edge_id is first */
3153  /* Range is: [prevseid, nseid) -- [inclusive, exclusive) */
3154  if ( (nseid - prevseid) > 1 )
3155  {{
3156  LWT_ELEMID minid = 0;
3157  int minidx = 0;
3158  LWDEBUGF(1, "Looking for smallest id among the %d edges "
3159  "composing ring %d", (nseid-prevseid), i);
3160  for ( j=prevseid; j<nseid; ++j )
3161  {
3162  LWT_ELEMID id = llabs(seid[j]);
3163  LWDEBUGF(1, "Abs id of edge in pos %d is %" LWTFMT_ELEMID, j, id);
3164  if ( ! minid || id < minid )
3165  {
3166  minid = id;
3167  minidx = j;
3168  }
3169  }
3170  LWDEBUGF(1, "Smallest id is %" LWTFMT_ELEMID
3171  " at position %d", minid, minidx);
3172  if ( minidx != prevseid )
3173  {
3174  _lwt_RotateElemidArray(seid, prevseid, nseid, minidx);
3175  }
3176  }}
3177 
3178  prevseid = nseid;
3179  }
3180 
3181  lwgeom_free(face);
3182  _lwt_release_edges(edges, numfaceedges);
3183 
3184  *out = seid;
3185  return nseid;
3186 }
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:321
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1138
#define WKT_EXTENDED
Definition: liblwgeom.h:2132
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:676
void * lwalloc(size_t size)
Definition: lwutil.c:227
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:197
void lwgeom_reverse_in_place(LWGEOM *lwgeom)
Reverse vertex order of LWGEOM.
Definition: lwgeom.c:102
#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:2866
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:3013
static LWGEOM * _lwt_FaceByEdges(LWT_TOPOLOGY *topo, LWT_ISO_EDGE *edges, int numfaceedges)
Definition: lwgeom_topo.c:2744
#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:193
POINTARRAY * points
Definition: liblwgeom.h:469
POINTARRAY ** rings
Definition: liblwgeom.h:505
uint32_t nrings
Definition: liblwgeom.h:510
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:413

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: