PostGIS  3.2.2dev-r@@SVN_REVISION@@

◆ ptarray_contains_point_partial()

int ptarray_contains_point_partial ( const POINTARRAY pa,
const POINT2D pt,
int  check_closed,
int *  winding_number 
)

Definition at line 1017 of file ptarray.c.

1018 {
1019  int wn = 0;
1020  uint32_t i;
1021  double side;
1022  const POINT2D *seg1;
1023  const POINT2D *seg2;
1024  double ymin, ymax;
1025 
1026  seg1 = getPoint2d_cp(pa, 0);
1027  seg2 = getPoint2d_cp(pa, pa->npoints-1);
1028  if ( check_closed && ! p2d_same(seg1, seg2) )
1029  lwerror("ptarray_contains_point called on unclosed ring");
1030 
1031  for ( i=1; i < pa->npoints; i++ )
1032  {
1033  seg2 = getPoint2d_cp(pa, i);
1034 
1035  /* Zero length segments are ignored. */
1036  if ( seg1->x == seg2->x && seg1->y == seg2->y )
1037  {
1038  seg1 = seg2;
1039  continue;
1040  }
1041 
1042  ymin = FP_MIN(seg1->y, seg2->y);
1043  ymax = FP_MAX(seg1->y, seg2->y);
1044 
1045  /* Only test segments in our vertical range */
1046  if ( pt->y > ymax || pt->y < ymin )
1047  {
1048  seg1 = seg2;
1049  continue;
1050  }
1051 
1052  side = lw_segment_side(seg1, seg2, pt);
1053 
1054  /*
1055  * A point on the boundary of a ring is not contained.
1056  * WAS: if (fabs(side) < 1e-12), see #852
1057  */
1058  if ( (side == 0) && lw_pt_in_seg(pt, seg1, seg2) )
1059  {
1060  return LW_BOUNDARY;
1061  }
1062 
1063  /*
1064  * If the point is to the left of the line, and it's rising,
1065  * then the line is to the right of the point and
1066  * circling counter-clockwise, so increment.
1067  */
1068  if ( (side < 0) && (seg1->y <= pt->y) && (pt->y < seg2->y) )
1069  {
1070  wn++;
1071  }
1072 
1073  /*
1074  * If the point is to the right of the line, and it's falling,
1075  * then the line is to the right of the point and circling
1076  * clockwise, so decrement.
1077  */
1078  else if ( (side > 0) && (seg2->y <= pt->y) && (pt->y < seg1->y) )
1079  {
1080  wn--;
1081  }
1082 
1083  seg1 = seg2;
1084  }
1085 
1086  /* Sent out the winding number for calls that are building on this as a primitive */
1087  if ( winding_number )
1088  *winding_number = wn;
1089 
1090  /* Outside */
1091  if (wn == 0)
1092  {
1093  return LW_OUTSIDE;
1094  }
1095 
1096  /* Inside */
1097  return LW_INSIDE;
1098 }
#define LW_INSIDE
Constants for point-in-polygon return values.
#define LW_BOUNDARY
#define FP_MAX(A, B)
#define FP_MIN(A, B)
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:63
int p2d_same(const POINT2D *p1, const POINT2D *p2)
Definition: lwalgorithm.c:50
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
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:101
double y
Definition: liblwgeom.h:404
double x
Definition: liblwgeom.h:404
uint32_t npoints
Definition: liblwgeom.h:441

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 _lwt_AddPoint(), _lwt_CheckEdgeCrossing(), and lwt_ChangeEdgeGeom().

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