PostGIS  2.2.8dev-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 3049 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(), 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.

3050 {
3051  LWGEOM *face;
3052  LWPOLY *facepoly;
3053  LWT_ISO_EDGE *edges;
3054  int numfaceedges;
3055  int fields, i;
3056  int nseid = 0; /* number of signed edge ids */
3057  int prevseid;
3058  LWT_ELEMID *seid; /* signed edge ids */
3059 
3060  /* Get list of face edges */
3061  numfaceedges = 1;
3062  fields = LWT_COL_EDGE_EDGE_ID |
3066  ;
3067  edges = lwt_be_getEdgeByFace( topo, &face_id, &numfaceedges, fields, NULL );
3068  if ( numfaceedges == -1 ) {
3069  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
3070  return -1;
3071  }
3072  if ( ! numfaceedges ) return 0; /* no edges in output */
3073 
3074  /* order edges by occurrence in face */
3075 
3076  face = _lwt_FaceByEdges(topo, edges, numfaceedges);
3077  if ( ! face )
3078  {
3079  /* _lwt_FaceByEdges should have already invoked lwerror in this case */
3080  _lwt_release_edges(edges, numfaceedges);
3081  return -1;
3082  }
3083 
3084  if ( lwgeom_is_empty(face) )
3085  {
3086  /* no edges in output */
3087  _lwt_release_edges(edges, numfaceedges);
3088  lwgeom_free(face);
3089  return 0;
3090  }
3091 
3092  /* force_lhr, if the face is not the universe */
3093  /* _lwt_FaceByEdges seems to guaranteed RHR */
3094  /* lwgeom_force_clockwise(face); */
3095  if ( face_id ) lwgeom_reverse(face);
3096 
3097 #if 0
3098  {
3099  size_t sz;
3100  char *wkt = lwgeom_to_wkt(face, WKT_EXTENDED, 6, &sz);
3101  LWDEBUGF(1, "Geometry of face %" LWTFMT_ELEMID " is: %s",
3102  face_id, wkt);
3103  lwfree(wkt);
3104  }
3105 #endif
3106 
3107  facepoly = lwgeom_as_lwpoly(face);
3108  if ( ! facepoly )
3109  {
3110  _lwt_release_edges(edges, numfaceedges);
3111  lwgeom_free(face);
3112  lwerror("Geometry of face %" LWTFMT_ELEMID " is not a polygon", face_id);
3113  return -1;
3114  }
3115 
3116  nseid = prevseid = 0;
3117  seid = lwalloc( sizeof(LWT_ELEMID) * numfaceedges );
3118 
3119  /* for each ring of the face polygon... */
3120  for ( i=0; i<facepoly->nrings; ++i )
3121  {
3122  const POINTARRAY *ring = facepoly->rings[i];
3123  int j = 0;
3124  LWT_ISO_EDGE *nextedge;
3125  LWLINE *nextline;
3126 
3127  LWDEBUGF(1, "Ring %d has %d points", i, ring->npoints);
3128 
3129  while ( j < ring->npoints-1 )
3130  {
3131  LWDEBUGF(1, "Looking for edge covering ring %d from vertex %d",
3132  i, j);
3133 
3134  int edgeno = _lwt_FindNextRingEdge(ring, j, edges, numfaceedges);
3135  if ( edgeno == -1 )
3136  {
3137  /* should never happen */
3138  _lwt_release_edges(edges, numfaceedges);
3139  lwgeom_free(face);
3140  lwfree(seid);
3141  lwerror("No edge (among %d) found to be defining geometry of face %"
3142  LWTFMT_ELEMID, numfaceedges, face_id);
3143  return -1;
3144  }
3145 
3146  nextedge = &(edges[edgeno]);
3147  nextline = nextedge->geom;
3148 
3149  LWDEBUGF(1, "Edge %" LWTFMT_ELEMID
3150  " covers ring %d from vertex %d to %d",
3151  nextedge->edge_id, i, j, j + nextline->points->npoints - 1);
3152 
3153 #if 0
3154  {
3155  size_t sz;
3156  char *wkt = lwgeom_to_wkt(lwline_as_lwgeom(nextline), WKT_EXTENDED, 6, &sz);
3157  LWDEBUGF(1, "Edge %" LWTFMT_ELEMID " is %s",
3158  nextedge->edge_id, wkt);
3159  lwfree(wkt);
3160  }
3161 #endif
3162 
3163  j += nextline->points->npoints - 1;
3164 
3165  /* Add next edge to the output array */
3166  seid[nseid++] = nextedge->face_left == face_id ?
3167  nextedge->edge_id :
3168  -nextedge->edge_id;
3169 
3170  /* avoid checking again on next time turn */
3171  nextedge->face_left = nextedge->face_right = -1;
3172  }
3173 
3174  /* now "scroll" the list of edges so that the one
3175  * with smaller absolute edge_id is first */
3176  /* Range is: [prevseid, nseid) -- [inclusive, exclusive) */
3177  if ( (nseid - prevseid) > 1 )
3178  {{
3179  LWT_ELEMID minid = 0;
3180  int minidx = 0;
3181  LWDEBUGF(1, "Looking for smallest id among the %d edges "
3182  "composing ring %d", (nseid-prevseid), i);
3183  for ( j=prevseid; j<nseid; ++j )
3184  {
3185  LWT_ELEMID id = llabs(seid[j]);
3186  LWDEBUGF(1, "Abs id of edge in pos %d is %" LWTFMT_ELEMID, j, id);
3187  if ( ! minid || id < minid )
3188  {
3189  minid = id;
3190  minidx = j;
3191  }
3192  }
3193  LWDEBUGF(1, "Smallest id is %" LWTFMT_ELEMID
3194  " at position %d", minid, minidx);
3195  if ( minidx != prevseid )
3196  {
3197  _lwt_RotateElemidArray(seid, prevseid, nseid, minidx);
3198  }
3199  }}
3200 
3201  prevseid = nseid;
3202  }
3203 
3204  lwgeom_free(face);
3205  _lwt_release_edges(edges, numfaceedges);
3206 
3207  *out = seid;
3208  return nseid;
3209 }
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:655
void lwfree(void *mem)
Definition: lwutil.c:214
int npoints
Definition: liblwgeom.h:355
#define LWT_COL_EDGE_FACE_RIGHT
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1050
LWLINE * geom
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:125
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:250
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:249
static LWGEOM * _lwt_FaceByEdges(LWT_TOPOLOGY *topo, LWT_ISO_EDGE *edges, int numfaceedges)
Definition: lwgeom_topo.c:2781
const LWT_BE_IFACE * be_iface
POINTARRAY ** rings
Definition: liblwgeom.h:441
LWT_ELEMID face_right
int nrings
Definition: liblwgeom.h:439
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:3040
#define WKT_EXTENDED
Definition: liblwgeom.h:1941
void lwgeom_reverse(LWGEOM *lwgeom)
Reverse vertex order of LWGEOM.
Definition: lwgeom.c:51
static void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
Definition: lwgeom_topo.c:471
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWT_COL_EDGE_GEOM
void * lwalloc(size_t size)
Definition: lwutil.c:199
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:1297
static int _lwt_FindNextRingEdge(const POINTARRAY *ring, int from, const LWT_ISO_EDGE *edges, int numedges)
Definition: lwgeom_topo.c:2901
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:55
const char * lwt_be_lastErrorMessage(const LWT_BE_IFACE *be)
Definition: lwgeom_topo.c:124
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:74
#define LWTFMT_ELEMID
Definition: lwgeom_topo.c:36
POINTARRAY * points
Definition: liblwgeom.h:406
Here is the call graph for this function: