PostGIS  2.5.7dev-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 3015 of file lwgeom_topo.c.

3016 {
3017  LWGEOM *face;
3018  LWPOLY *facepoly;
3019  LWT_ISO_EDGE *edges;
3020  int numfaceedges;
3021  int fields;
3022  uint32_t i;
3023  int nseid = 0; /* number of signed edge ids */
3024  int prevseid;
3025  LWT_ELEMID *seid; /* signed edge ids */
3026 
3027  /* Get list of face edges */
3028  numfaceedges = 1;
3029  fields = LWT_COL_EDGE_EDGE_ID |
3033  ;
3034  edges = lwt_be_getEdgeByFace( topo, &face_id, &numfaceedges, fields, NULL );
3035  if ( numfaceedges == -1 ) {
3036  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
3037  return -1;
3038  }
3039  if ( ! numfaceedges ) return 0; /* no edges in output */
3040 
3041  /* order edges by occurrence in face */
3042 
3043  face = _lwt_FaceByEdges(topo, edges, numfaceedges);
3044  if ( ! face )
3045  {
3046  /* _lwt_FaceByEdges should have already invoked lwerror in this case */
3047  _lwt_release_edges(edges, numfaceedges);
3048  return -1;
3049  }
3050 
3051  if ( lwgeom_is_empty(face) )
3052  {
3053  /* no edges in output */
3054  _lwt_release_edges(edges, numfaceedges);
3055  lwgeom_free(face);
3056  return 0;
3057  }
3058 
3059  /* force_lhr, if the face is not the universe */
3060  /* _lwt_FaceByEdges seems to guaranteed RHR */
3061  /* lwgeom_force_clockwise(face); */
3062  if ( face_id ) lwgeom_reverse_in_place(face);
3063 
3064 #if 0
3065  {
3066  size_t sz;
3067  char *wkt = lwgeom_to_wkt(face, WKT_EXTENDED, 6, &sz);
3068  LWDEBUGF(1, "Geometry of face %" LWTFMT_ELEMID " is: %s",
3069  face_id, wkt);
3070  lwfree(wkt);
3071  }
3072 #endif
3073 
3074  facepoly = lwgeom_as_lwpoly(face);
3075  if ( ! facepoly )
3076  {
3077  _lwt_release_edges(edges, numfaceedges);
3078  lwgeom_free(face);
3079  lwerror("Geometry of face %" LWTFMT_ELEMID " is not a polygon", face_id);
3080  return -1;
3081  }
3082 
3083  nseid = prevseid = 0;
3084  seid = lwalloc( sizeof(LWT_ELEMID) * numfaceedges );
3085 
3086  /* for each ring of the face polygon... */
3087  for ( i=0; i<facepoly->nrings; ++i )
3088  {
3089  const POINTARRAY *ring = facepoly->rings[i];
3090  int32_t j = 0;
3091  LWT_ISO_EDGE *nextedge;
3092  LWLINE *nextline;
3093 
3094  LWDEBUGF(1, "Ring %d has %d points", i, ring->npoints);
3095 
3096  while ( j < (int32_t) ring->npoints-1 )
3097  {
3098  LWDEBUGF(1, "Looking for edge covering ring %d from vertex %d",
3099  i, j);
3100 
3101  int edgeno = _lwt_FindNextRingEdge(ring, j, edges, numfaceedges);
3102  if ( edgeno == -1 )
3103  {
3104  /* should never happen */
3105  _lwt_release_edges(edges, numfaceedges);
3106  lwgeom_free(face);
3107  lwfree(seid);
3108  lwerror("No edge (among %d) found to be defining geometry of face %"
3109  LWTFMT_ELEMID, numfaceedges, face_id);
3110  return -1;
3111  }
3112 
3113  nextedge = &(edges[edgeno]);
3114  nextline = nextedge->geom;
3115 
3116  LWDEBUGF(1, "Edge %" LWTFMT_ELEMID
3117  " covers ring %d from vertex %d to %d",
3118  nextedge->edge_id, i, j, j + nextline->points->npoints - 1);
3119 
3120 #if 0
3121  {
3122  size_t sz;
3123  char *wkt = lwgeom_to_wkt(lwline_as_lwgeom(nextline), WKT_EXTENDED, 6, &sz);
3124  LWDEBUGF(1, "Edge %" LWTFMT_ELEMID " is %s",
3125  nextedge->edge_id, wkt);
3126  lwfree(wkt);
3127  }
3128 #endif
3129 
3130  j += nextline->points->npoints - 1;
3131 
3132  /* Add next edge to the output array */
3133  seid[nseid++] = nextedge->face_left == face_id ?
3134  nextedge->edge_id :
3135  -nextedge->edge_id;
3136 
3137  /* avoid checking again on next time turn */
3138  nextedge->face_left = nextedge->face_right = -1;
3139  }
3140 
3141  /* now "scroll" the list of edges so that the one
3142  * with smaller absolute edge_id is first */
3143  /* Range is: [prevseid, nseid) -- [inclusive, exclusive) */
3144  if ( (nseid - prevseid) > 1 )
3145  {{
3146  LWT_ELEMID minid = 0;
3147  int minidx = 0;
3148  LWDEBUGF(1, "Looking for smallest id among the %d edges "
3149  "composing ring %d", (nseid-prevseid), i);
3150  for ( j=prevseid; j<nseid; ++j )
3151  {
3152  LWT_ELEMID id = llabs(seid[j]);
3153  LWDEBUGF(1, "Abs id of edge in pos %d is %" LWTFMT_ELEMID, j, id);
3154  if ( ! minid || id < minid )
3155  {
3156  minid = id;
3157  minidx = j;
3158  }
3159  }
3160  LWDEBUGF(1, "Smallest id is %" LWTFMT_ELEMID
3161  " at position %d", minid, minidx);
3162  if ( minidx != prevseid )
3163  {
3164  _lwt_RotateElemidArray(seid, prevseid, nseid, minidx);
3165  }
3166  }}
3167 
3168  prevseid = nseid;
3169  }
3170 
3171  lwgeom_free(face);
3172  _lwt_release_edges(edges, numfaceedges);
3173 
3174  *out = seid;
3175  return nseid;
3176 }
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:330
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1144
#define WKT_EXTENDED
Definition: liblwgeom.h:2077
void lwfree(void *mem)
Definition: lwutil.c:244
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition: lwgeom.c:1393
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:229
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:206
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:120
static int _lwt_FindNextRingEdge(const POINTARRAY *ring, int from, const LWT_ISO_EDGE *edges, int numedges)
Definition: lwgeom_topo.c:2859
static LWT_ISO_EDGE * lwt_be_getEdgeByFace(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, int *numelems, int fields, const GBOX *box)
Definition: lwgeom_topo.c:246
static void _lwt_RotateElemidArray(LWT_ELEMID *ary, int from, int to, int rotidx)
Definition: lwgeom_topo.c:3006
static LWGEOM * _lwt_FaceByEdges(LWT_TOPOLOGY *topo, LWT_ISO_EDGE *edges, int numfaceedges)
Definition: lwgeom_topo.c:2739
#define LWTFMT_ELEMID
Definition: lwgeom_topo.c:44
static void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
Definition: lwgeom_topo.c:457
POINTARRAY * points
Definition: liblwgeom.h:425
POINTARRAY ** rings
Definition: liblwgeom.h:460
uint32_t nrings
Definition: liblwgeom.h:458
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:374
unsigned int uint32_t
Definition: uthash.h:78

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: