Find the face-id of the face properly containing a given point.
7192 uint64_t numedges, i;
7194 const POINT2D *closestPointOnEdge = NULL;
7195 uint32_t closestSegmentIndex;
7196 int closestSegmentSide;
7197 uint32_t closestPointVertex;
7198 const POINT2D *closestSegmentP0, *closestSegmentP1;
7201 int containingFace = -1;
7211 if (numedges == UINT64_MAX)
7257 closestSegmentP0->
x,
7258 closestSegmentP0->
y,
7259 closestSegmentP1->
x,
7277 const POINT2D *p = queryPoint;
7278 const POINT2D *A = closestSegmentP0;
7279 const POINT2D *B = closestSegmentP1;
7280 double r = ( (p->
x-A->
x) * (B->
x-A->
x) + (p->
y-A->
y) * (B->
y-A->
y) )/( (B->
x-A->
x)*(B->
x-A->
x) +(B->
y-A->
y)*(B->
y-A->
y) );
7283 closestPointOnEdge = A;
7284 closestPointVertex = closestSegmentIndex;
7285 if ( closestSegmentIndex == 0 )
7292 closestPointOnEdge = B;
7293 closestPointVertex = closestSegmentIndex + 1;
7296 closestNode = closestEdge->
end_node;
7304 if ( closestNode != 0 )
7306 LWDEBUGF(1,
"Closest point is node %d", closestNode);
7309 LWDEBUGF(1,
"Query point is node %d", closestNode);
7320 lwerror(
"Two or more faces found");
7323 containingFace = closestEdge->
face_left;
7328 if (numedges == UINT64_MAX)
7335 for (i=0; i<numedges; ++i)
7337 if ( edges[i].face_left != containingFace ||
7338 edges[i].face_right != containingFace )
7342 lwerror(
"Two or more faces found");
7348 lwerror(
"Unexpected backend return: getEdgeByNode(%d) returns no edges when we previously found edge %d ending on that node",
7349 closestNode, closestEdge->
edge_id);
7354 LWDEBUGF(1,
"lwt_be_getEdgeByNode returned %d edges", numedges);
7357 return containingFace;
7365 lwerror(
"error computing azimuth of query point [%.15g %.15g,%.15g %.15g]",
7366 closestPointOnEdge->
x, closestPointOnEdge->
y,
7367 queryPoint->
x, queryPoint->
y);
7376 lwerror(
"Unexpected backend return: _lwt_FindAdjacentEdges(%d) found no edges when we previously found edge %d ending on that node",
7377 closestNode, closestEdge->
edge_id);
7387 LWDEBUG(1,
"Closest point is NOT a node");
7393 containingFace = closestEdge->
face_left;
7395 return containingFace;
7402 lwerror(
"Two or more faces found");
7410 LWDEBUGF(1,
"Closest point is vertex %d of closest segment", closestPointVertex);
7421 uint32_t prevVertexIndex = closestPointVertex > 0 ?
7422 closestPointVertex - 1u :
7430 LWDEBUGF(1,
"Previous vertex %u is POINT(%.15g %.15g)",
7436 uint32_t nextVertexIndex = closestPointVertex == closestEdge->
geom->
points->
npoints - 1u ?
7438 closestPointVertex + 1u;
7445 LWDEBUGF(1,
"Next vertex %u is POINT(%.15g %.15g)",
7456 if ( !
azimuth_pt_pt(closestPointOnEdge, prevVertex, &azS0)) {
7457 lwerror(
"error computing azimuth of segment to closest point [%.15g %.15g,%.15g %.15g]",
7458 closestPointOnEdge->
x, closestPointOnEdge->
y,
7459 prevVertex->
x, prevVertex->
y);
7463 if ( !
azimuth_pt_pt(closestPointOnEdge, nextVertex, &azS1)) {
7464 lwerror(
"error computing azimuth of segment from closest point [%.15g %.15g,%.15g %.15g]",
7465 closestPointOnEdge->
x, closestPointOnEdge->
y,
7466 nextVertex->
x, nextVertex->
y);
7470 if ( !
azimuth_pt_pt(closestPointOnEdge, queryPoint, &azSL) ) {
7471 lwerror(
"error computing azimuth of queryPoint [%.15g %.15g,%.15g %.15g]",
7472 closestPointOnEdge->
x, closestPointOnEdge->
y,
7473 queryPoint->
x, queryPoint->
y);
7478 double angle_S0_S1 = azS1 - azS0;
7479 if ( angle_S0_S1 < 0 ) angle_S0_S1 += 2 * M_PI;
7481 double angle_S0_SL = azSL - azS0;
7482 if ( angle_S0_SL < 0 ) angle_S0_SL += 2 * M_PI;
7484 LWDEBUGF(1,
"Azimuths from closest (vertex) point: P:%g, N:%g (+%g), Q:%g (+%g)",
7489 if ( angle_S0_SL < angle_S0_S1 )
7492 containingFace = closestEdge->
face_left;
7505 LWDEBUGF(1,
"Closest point is internal to closest segment, calling lw_segment_side((%g,%g),(%g,%g),(%g,%g)",
7506 closestSegmentP0->
x,
7507 closestSegmentP0->
y,
7508 closestSegmentP1->
x,
7509 closestSegmentP1->
y,
7514 closestSegmentSide =
lw_segment_side(closestSegmentP0, closestSegmentP1, queryPoint);
7515 LWDEBUGF(1,
"Side of closest segment query point falls on: %d", closestSegmentSide);
7517 if ( closestSegmentSide == -1 )
7519 containingFace = closestEdge->
face_left;
7521 else if ( closestSegmentSide == 1 )
7527 lwerror(
"Unexpected collinearity reported from lw_segment_side");
7535 return containingFace;
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
int ptarray_closest_segment_2d(const POINTARRAY *pa, const POINT2D *qp, double *dist)
int azimuth_pt_pt(const POINT2D *p1, const POINT2D *p2, double *ret)
Compute the azimuth of segment AB in radians.
int lw_segment_side(const POINT2D *p1, const POINT2D *p2, const POINT2D *q)
lw_segment_side()
#define LWT_COL_EDGE_FACE_RIGHT
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWT_COL_EDGE_START_NODE
#define LWT_COL_EDGE_FACE_LEFT
#define LWT_COL_EDGE_EDGE_ID
Edge fields.
#define LWT_COL_EDGE_END_NODE
#define LWT_COL_EDGE_GEOM
#define LWDEBUG(level, msg)
#define LWDEBUGF(level, msg,...)
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
#define LWDEBUGGF(level, geom, fmt,...)
const char * lwt_be_lastErrorMessage(const LWT_BE_IFACE *be)
static LWT_ISO_EDGE * lwt_be_getEdgeByNode(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, uint64_t *numelems, int fields)
static LWT_ISO_EDGE * lwt_be_getClosestEdge(const LWT_TOPOLOGY *topo, const LWPOINT *pt, uint64_t *numelems, int fields)
static int _lwt_FindAdjacentEdges(LWT_TOPOLOGY *topo, LWT_ELEMID node, edgeend *data, edgeend *other, int myedge_id)
static void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
const LWT_BE_IFACE * be_iface