PostGIS  2.5.0dev-r@@SVN_REVISION@@

◆ lwt_GetFaceByPoint()

LWT_ELEMID lwt_GetFaceByPoint ( LWT_TOPOLOGY topo,
LWPOINT pt,
double  tol 
)

Find the face-id of a face containing a given point.

Parameters
topothe topology to operate on
pointthe point to use for query
tolmax distance around the given point to look for a containing face
Returns
a face identifier if one is found (0 if universe), -1 on error (multiple faces within distance or point on node or edge). The liblwgeom error handler will be invoked in case of error.

Definition at line 4924 of file lwgeom_topo.c.

References _lwt_release_edges(), LWT_TOPOLOGY_T::be_iface, LWT_ISO_EDGE::edge_id, LWT_ISO_EDGE::face_left, LWT_ISO_EDGE::face_right, LWT_ISO_EDGE::geom, LWDEBUG, LWDEBUGF, lwerror(), lwgeom_mindistance2d_tolerance(), lwline_as_lwgeom(), lwnotice(), lwpoint_as_lwgeom(), lwt_be_getEdgeWithinDistance2D(), lwt_be_getFaceContainingPoint(), lwt_be_lastErrorMessage(), LWT_COL_EDGE_EDGE_ID, LWT_COL_EDGE_FACE_LEFT, LWT_COL_EDGE_FACE_RIGHT, LWT_COL_EDGE_GEOM, and LWTFMT_ELEMID.

4925 {
4926  LWT_ELEMID id = 0;
4927  LWT_ISO_EDGE *elem;
4928  int num, i;
4929  int flds = LWT_COL_EDGE_EDGE_ID |
4933  LWGEOM *qp = lwpoint_as_lwgeom(pt);
4934 
4935  id = lwt_be_getFaceContainingPoint(topo, pt);
4936  if ( id == -2 ) {
4937  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4938  return -1;
4939  }
4940 
4941  if ( id > 0 )
4942  {
4943  return id;
4944  }
4945  id = 0; /* or it'll be -1 for not found */
4946 
4947  LWDEBUG(1, "No face properly contains query point,"
4948  " looking for edges");
4949 
4950  /* Not in a face, may be in universe or on edge, let's check
4951  * for distance */
4952  /* NOTE: we never pass a tolerance of 0 to avoid ever using
4953  * ST_Within, which doesn't include endpoints matches */
4954  elem = lwt_be_getEdgeWithinDistance2D(topo, pt, tol?tol:1e-5, &num, flds, 0);
4955  if ( num == -1 )
4956  {
4957  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4958  return -1;
4959  }
4960  for (i=0; i<num; ++i)
4961  {
4962  LWT_ISO_EDGE *e = &(elem[i]);
4963  LWT_ELEMID eface = 0;
4964  LWGEOM* geom;
4965  double dist;
4966 
4967  if ( ! e->geom )
4968  {
4969  _lwt_release_edges(elem, num);
4970  lwnotice("Corrupted topology: edge %" LWTFMT_ELEMID
4971  " has null geometry", e->edge_id);
4972  continue;
4973  }
4974 
4975  /* don't consider dangling edges */
4976  if ( e->face_left == e->face_right )
4977  {
4978  LWDEBUGF(1, "Edge %" LWTFMT_ELEMID
4979  " is dangling, won't consider it", e->edge_id);
4980  continue;
4981  }
4982 
4983  geom = lwline_as_lwgeom(e->geom);
4984  dist = lwgeom_mindistance2d_tolerance(geom, qp, tol);
4985 
4986  LWDEBUGF(1, "Distance from edge %" LWTFMT_ELEMID
4987  " is %g (tol=%g)", e->edge_id, dist, tol);
4988 
4989  /* we won't consider edges too far */
4990  if ( dist > tol ) continue;
4991  if ( e->face_left == 0 ) {
4992  eface = e->face_right;
4993  }
4994  else if ( e->face_right == 0 ) {
4995  eface = e->face_left;
4996  }
4997  else {
4998  _lwt_release_edges(elem, num);
4999  lwerror("Two or more faces found");
5000  return -1;
5001  }
5002 
5003  if ( id && id != eface )
5004  {
5005  _lwt_release_edges(elem, num);
5006  lwerror("Two or more faces found"
5007 #if 0 /* debugging */
5008  " (%" LWTFMT_ELEMID
5009  " and %" LWTFMT_ELEMID ")", id, eface
5010 #endif
5011  );
5012  return -1;
5013  }
5014  else id = eface;
5015  }
5016  if ( num ) _lwt_release_edges(elem, num);
5017 
5018  return id;
5019 }
LWT_ELEMID face_left
#define LWT_COL_EDGE_FACE_LEFT
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:177
double lwgeom_mindistance2d_tolerance(const LWGEOM *lw1, const LWGEOM *lw2, double tolerance)
Function handling min distance calculations and dwithin calculations.
Definition: measures.c:213
#define LWT_COL_EDGE_FACE_RIGHT
LWLINE * geom
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:330
const LWT_BE_IFACE * be_iface
LWT_ELEMID face_right
LWT_ELEMID edge_id
#define LWT_COL_EDGE_EDGE_ID
Edge fields.
static void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
Definition: lwgeom_topo.c:457
LWT_ISO_EDGE * lwt_be_getEdgeWithinDistance2D(LWT_TOPOLOGY *topo, LWPOINT *pt, double dist, int *numelems, int fields, int limit)
Definition: lwgeom_topo.c:260
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:335
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWT_COL_EDGE_GEOM
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
LWT_ELEMID lwt_be_getFaceContainingPoint(LWT_TOPOLOGY *topo, LWPOINT *pt)
Definition: lwgeom_topo.c:330
uint32_t e
Definition: geobuf.h:57
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
Here is the call graph for this function: