PostGIS  2.1.10dev-r@@SVN_REVISION@@
int ptarray_contains_point_partial ( const POINTARRAY pa,
const POINT2D pt,
int  check_closed,
int *  winding_number 
)

Definition at line 703 of file ptarray.c.

References FP_MAX, FP_MIN, getPoint2d_cp(), LW_BOUNDARY, LW_INSIDE, LW_OUTSIDE, lw_pt_in_seg(), lw_segment_side(), lwerror(), POINTARRAY::npoints, p2d_same(), POINT2D::x, and POINT2D::y.

Referenced by lwcompound_contains_point(), and ptarray_contains_point().

704 {
705  int wn = 0;
706  int i;
707  double side;
708  const POINT2D *seg1;
709  const POINT2D *seg2;
710  double ymin, ymax;
711 
712  seg1 = getPoint2d_cp(pa, 0);
713  seg2 = getPoint2d_cp(pa, pa->npoints-1);
714  if ( check_closed && ! p2d_same(seg1, seg2) )
715  lwerror("ptarray_contains_point called on unclosed ring");
716 
717  for ( i=1; i < pa->npoints; i++ )
718  {
719  seg2 = getPoint2d_cp(pa, i);
720 
721  /* Zero length segments are ignored. */
722  if ( seg1->x == seg2->x && seg1->y == seg2->y )
723  {
724  seg1 = seg2;
725  continue;
726  }
727 
728  ymin = FP_MIN(seg1->y, seg2->y);
729  ymax = FP_MAX(seg1->y, seg2->y);
730 
731  /* Only test segments in our vertical range */
732  if ( pt->y > ymax || pt->y < ymin )
733  {
734  seg1 = seg2;
735  continue;
736  }
737 
738  side = lw_segment_side(seg1, seg2, pt);
739 
740  /*
741  * A point on the boundary of a ring is not contained.
742  * WAS: if (fabs(side) < 1e-12), see #852
743  */
744  if ( (side == 0) && lw_pt_in_seg(pt, seg1, seg2) )
745  {
746  return LW_BOUNDARY;
747  }
748 
749  /*
750  * If the point is to the left of the line, and it's rising,
751  * then the line is to the right of the point and
752  * circling counter-clockwise, so incremement.
753  */
754  if ( (side < 0) && (seg1->y <= pt->y) && (pt->y < seg2->y) )
755  {
756  wn++;
757  }
758 
759  /*
760  * If the point is to the right of the line, and it's falling,
761  * then the line is to the right of the point and circling
762  * clockwise, so decrement.
763  */
764  else if ( (side > 0) && (seg2->y <= pt->y) && (pt->y < seg1->y) )
765  {
766  wn--;
767  }
768 
769  seg1 = seg2;
770  }
771 
772  /* Sent out the winding number for calls that are building on this as a primitive */
773  if ( winding_number )
774  *winding_number = wn;
775 
776  /* Outside */
777  if (wn == 0)
778  {
779  return LW_OUTSIDE;
780  }
781 
782  /* Inside */
783  return LW_INSIDE;
784 }
int npoints
Definition: liblwgeom.h:327
#define FP_MIN(A, B)
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:67
double x
Definition: liblwgeom.h:284
int p2d_same(const POINT2D *p1, const POINT2D *p2)
Definition: lwalgorithm.c:47
const POINT2D * getPoint2d_cp(const POINTARRAY *pa, int n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from...
Definition: lwgeom_api.c:458
#define LW_INSIDE
Constants for point-in-polygon return values.
double y
Definition: liblwgeom.h:284
#define LW_BOUNDARY
int lw_pt_in_seg(const POINT2D *P, const POINT2D *A1, const POINT2D *A2)
Returns true if P is between A1/A2.
Definition: lwalgorithm.c:96
#define LW_OUTSIDE
int lw_segment_side(const POINT2D *p1, const POINT2D *p2, const POINT2D *q)
lw_segment_side()
Definition: lwalgorithm.c:62
#define FP_MAX(A, B)

Here is the call graph for this function:

Here is the caller graph for this function: