PostGIS  2.5.0dev-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 3111 of file lwgeom_topo.c.

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.

3112 {
3113  LWGEOM *face;
3114  LWPOLY *facepoly;
3115  LWT_ISO_EDGE *edges;
3116  int numfaceedges;
3117  int fields;
3118  uint32_t i;
3119  int nseid = 0; /* number of signed edge ids */
3120  int prevseid;
3121  LWT_ELEMID *seid; /* signed edge ids */
3122 
3123  /* Get list of face edges */
3124  numfaceedges = 1;
3125  fields = LWT_COL_EDGE_EDGE_ID |
3129  ;
3130  edges = lwt_be_getEdgeByFace( topo, &face_id, &numfaceedges, fields, NULL );
3131  if ( numfaceedges == -1 ) {
3132  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
3133  return -1;
3134  }
3135  if ( ! numfaceedges ) return 0; /* no edges in output */
3136 
3137  /* order edges by occurrence in face */
3138 
3139  face = _lwt_FaceByEdges(topo, edges, numfaceedges);
3140  if ( ! face )
3141  {
3142  /* _lwt_FaceByEdges should have already invoked lwerror in this case */
3143  _lwt_release_edges(edges, numfaceedges);
3144  return -1;
3145  }
3146 
3147  if ( lwgeom_is_empty(face) )
3148  {
3149  /* no edges in output */
3150  _lwt_release_edges(edges, numfaceedges);
3151  lwgeom_free(face);
3152  return 0;
3153  }
3154 
3155  /* force_lhr, if the face is not the universe */
3156  /* _lwt_FaceByEdges seems to guaranteed RHR */
3157  /* lwgeom_force_clockwise(face); */
3158  if ( face_id ) lwgeom_reverse_in_place(face);
3159 
3160 #if 0
3161  {
3162  size_t sz;
3163  char *wkt = lwgeom_to_wkt(face, WKT_EXTENDED, 6, &sz);
3164  LWDEBUGF(1, "Geometry of face %" LWTFMT_ELEMID " is: %s",
3165  face_id, wkt);
3166  lwfree(wkt);
3167  }
3168 #endif
3169 
3170  facepoly = lwgeom_as_lwpoly(face);
3171  if ( ! facepoly )
3172  {
3173  _lwt_release_edges(edges, numfaceedges);
3174  lwgeom_free(face);
3175  lwerror("Geometry of face %" LWTFMT_ELEMID " is not a polygon", face_id);
3176  return -1;
3177  }
3178 
3179  nseid = prevseid = 0;
3180  seid = lwalloc( sizeof(LWT_ELEMID) * numfaceedges );
3181 
3182  /* for each ring of the face polygon... */
3183  for ( i=0; i<facepoly->nrings; ++i )
3184  {
3185  const POINTARRAY *ring = facepoly->rings[i];
3186  int32_t j = 0;
3187  LWT_ISO_EDGE *nextedge;
3188  LWLINE *nextline;
3189 
3190  LWDEBUGF(1, "Ring %d has %d points", i, ring->npoints);
3191 
3192  while ( j < (int32_t) ring->npoints-1 )
3193  {
3194  LWDEBUGF(1, "Looking for edge covering ring %d from vertex %d",
3195  i, j);
3196 
3197  int edgeno = _lwt_FindNextRingEdge(ring, j, edges, numfaceedges);
3198  if ( edgeno == -1 )
3199  {
3200  /* should never happen */
3201  _lwt_release_edges(edges, numfaceedges);
3202  lwgeom_free(face);
3203  lwfree(seid);
3204  lwerror("No edge (among %d) found to be defining geometry of face %"
3205  LWTFMT_ELEMID, numfaceedges, face_id);
3206  return -1;
3207  }
3208 
3209  nextedge = &(edges[edgeno]);
3210  nextline = nextedge->geom;
3211 
3212  LWDEBUGF(1, "Edge %" LWTFMT_ELEMID
3213  " covers ring %d from vertex %d to %d",
3214  nextedge->edge_id, i, j, j + nextline->points->npoints - 1);
3215 
3216 #if 0
3217  {
3218  size_t sz;
3219  char *wkt = lwgeom_to_wkt(lwline_as_lwgeom(nextline), WKT_EXTENDED, 6, &sz);
3220  LWDEBUGF(1, "Edge %" LWTFMT_ELEMID " is %s",
3221  nextedge->edge_id, wkt);
3222  lwfree(wkt);
3223  }
3224 #endif
3225 
3226  j += nextline->points->npoints - 1;
3227 
3228  /* Add next edge to the output array */
3229  seid[nseid++] = nextedge->face_left == face_id ?
3230  nextedge->edge_id :
3231  -nextedge->edge_id;
3232 
3233  /* avoid checking again on next time turn */
3234  nextedge->face_left = nextedge->face_right = -1;
3235  }
3236 
3237  /* now "scroll" the list of edges so that the one
3238  * with smaller absolute edge_id is first */
3239  /* Range is: [prevseid, nseid) -- [inclusive, exclusive) */
3240  if ( (nseid - prevseid) > 1 )
3241  {{
3242  LWT_ELEMID minid = 0;
3243  int minidx = 0;
3244  LWDEBUGF(1, "Looking for smallest id among the %d edges "
3245  "composing ring %d", (nseid-prevseid), i);
3246  for ( j=prevseid; j<nseid; ++j )
3247  {
3248  LWT_ELEMID id = llabs(seid[j]);
3249  LWDEBUGF(1, "Abs id of edge in pos %d is %" LWTFMT_ELEMID, j, id);
3250  if ( ! minid || id < minid )
3251  {
3252  minid = id;
3253  minidx = j;
3254  }
3255  }
3256  LWDEBUGF(1, "Smallest id is %" LWTFMT_ELEMID
3257  " at position %d", minid, minidx);
3258  if ( minidx != prevseid )
3259  {
3260  _lwt_RotateElemidArray(seid, prevseid, nseid, minidx);
3261  }
3262  }}
3263 
3264  prevseid = nseid;
3265  }
3266 
3267  lwgeom_free(face);
3268  _lwt_release_edges(edges, numfaceedges);
3269 
3270  *out = seid;
3271  return nseid;
3272 }
LWT_ELEMID face_left
#define LWT_COL_EDGE_FACE_LEFT
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
Definition: lwout_wkt.c:675
void lwfree(void *mem)
Definition: lwutil.c:244
void lwgeom_reverse_in_place(LWGEOM *lwgeom)
Reverse vertex order of LWGEOM.
Definition: lwgeom.c:102
#define LWT_COL_EDGE_FACE_RIGHT
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1144
LWLINE * geom
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:206
uint32_t nrings
Definition: liblwgeom.h:457
unsigned int uint32_t
Definition: uthash.h:78
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
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:330
static LWGEOM * _lwt_FaceByEdges(LWT_TOPOLOGY *topo, LWT_ISO_EDGE *edges, int numfaceedges)
Definition: lwgeom_topo.c:2835
const LWT_BE_IFACE * be_iface
POINTARRAY ** rings
Definition: liblwgeom.h:459
LWT_ELEMID face_right
LWT_ELEMID edge_id
#define LWT_COL_EDGE_EDGE_ID
Edge fields.
static void _lwt_RotateElemidArray(LWT_ELEMID *ary, int from, int to, int rotidx)
Definition: lwgeom_topo.c:3102
#define WKT_EXTENDED
Definition: liblwgeom.h:2076
static void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
Definition: lwgeom_topo.c:457
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWT_COL_EDGE_GEOM
void * lwalloc(size_t size)
Definition: lwutil.c:229
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
static int _lwt_FindNextRingEdge(const POINTARRAY *ring, int from, const LWT_ISO_EDGE *edges, int numedges)
Definition: lwgeom_topo.c:2955
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
const char * lwt_be_lastErrorMessage(const LWT_BE_IFACE *be)
Definition: lwgeom_topo.c:120
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
#define LWTFMT_ELEMID
Definition: lwgeom_topo.c:44
POINTARRAY * points
Definition: liblwgeom.h:424
uint32_t npoints
Definition: liblwgeom.h:373
Here is the call graph for this function: