PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ itree_point_in_ring_recursive()

static IntervalTreeResult itree_point_in_ring_recursive ( const IntervalTreeNode node,
const POINTARRAY pa,
const POINT2D pt,
int *  winding_number 
)
static

Definition at line 365 of file intervaltree.c.

370{
371 if (!node) return ITREE_OUTSIDE;
372 /*
373 * If Y value is not within range of node, we can
374 * learn nothing from this node or its children, so
375 * we exit early.
376 */
377 uint8_t node_contains_value = FP_CONTAINS_INCL(node->min, pt->y, node->max) ? 1 : 0;
378 if (!node_contains_value)
379 return ITREE_OK;
380
381 /* This is a leaf node, so evaluate winding number */
382 if (node->numChildren == 0)
383 {
384 const POINT2D *seg1 = getPoint2d_cp(pa, node->edgeIndex);
385 const POINT2D *seg2 = getPoint2d_cp(pa, node->edgeIndex + 1);
386 double side = itree_segment_side(seg1, seg2, pt);
387
388 /* Zero length segments are ignored. */
389 // xxxx need a unit test, what about really really short segments?
390 // if (distance2d_sqr_pt_pt(seg1, seg2) < FP_EPS*FP_EPS)
391 // return ITREE_OK;
392
393 /* A point on the boundary of a ring is not contained. */
394 /* WAS: if (fabs(side) < 1e-12), see ticket #852 */
395 if (side == 0.0 && itree_point_on_segment(seg1, seg2, pt) == 1)
396 return ITREE_BOUNDARY;
397
398 /*
399 * If the point is to the left of the line, and it's rising,
400 * then the line is to the right of the point and
401 * circling counter-clockwise, so increment.
402 */
403 if ((seg1->y <= pt->y) && (pt->y < seg2->y) && (side > 0))
404 {
405 *winding_number = *winding_number + 1;
406 }
407
408 /*
409 * If the point is to the right of the line, and it's falling,
410 * then the line is to the right of the point and circling
411 * clockwise, so decrement.
412 */
413 else if ((seg2->y <= pt->y) && (pt->y < seg1->y) && (side < 0))
414 {
415 *winding_number = *winding_number - 1;
416 }
417
418 return ITREE_OK;
419 }
420 /* This is an interior node, so recurse downwards */
421 else
422 {
423 for (uint32_t i = 0; i < node->numChildren; i++)
424 {
425 IntervalTreeResult rslt = itree_point_in_ring_recursive(node->children[i], pa, pt, winding_number);
426 /* Short circuit and send back boundary result */
427 if (rslt == ITREE_BOUNDARY)
428 return rslt;
429 }
430 }
431 return ITREE_OK;
432}
static int itree_point_on_segment(const POINT2D *seg1, const POINT2D *seg2, const POINT2D *point)
static IntervalTreeResult itree_point_in_ring_recursive(const IntervalTreeNode *node, const POINTARRAY *pa, const POINT2D *pt, int *winding_number)
static double itree_segment_side(const POINT2D *seg1, const POINT2D *seg2, const POINT2D *point)
IntervalTreeResult
@ ITREE_BOUNDARY
@ ITREE_OK
@ ITREE_OUTSIDE
#define FP_CONTAINS_INCL(A, X, B)
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
Definition lwinline.h:97
struct IntervalTreeNode * children[ITREE_MAX_NODES]
uint32_t numChildren
double y
Definition liblwgeom.h:390

References IntervalTreeNode::children, IntervalTreeNode::edgeIndex, FP_CONTAINS_INCL, getPoint2d_cp(), ITREE_BOUNDARY, ITREE_OK, ITREE_OUTSIDE, itree_point_in_ring_recursive(), itree_point_on_segment(), itree_segment_side(), IntervalTreeNode::max, IntervalTreeNode::min, IntervalTreeNode::numChildren, and POINT2D::y.

Referenced by itree_point_in_ring(), and itree_point_in_ring_recursive().

Here is the call graph for this function:
Here is the caller graph for this function: