PostGIS  2.5.0beta2dev-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 3007 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.

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