PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ 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)
Definition: intervaltree.c:352
static IntervalTreeResult itree_point_in_ring_recursive(const IntervalTreeNode *node, const POINTARRAY *pa, const POINT2D *pt, int *winding_number)
Definition: intervaltree.c:365
static double itree_segment_side(const POINT2D *seg1, const POINT2D *seg2, const POINT2D *point)
Definition: intervaltree.c:336
IntervalTreeResult
Definition: intervaltree.h:32
@ ITREE_BOUNDARY
Definition: intervaltree.h:34
@ ITREE_OK
Definition: intervaltree.h:36
@ ITREE_OUTSIDE
Definition: intervaltree.h:35
#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]
Definition: intervaltree.h:43
uint32_t edgeIndex
Definition: intervaltree.h:44
uint32_t numChildren
Definition: intervaltree.h:45
double y
Definition: liblwgeom.h:390

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

Referenced by itree_point_in_ring().

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