PostGIS  3.2.2dev-r@@SVN_REVISION@@

◆ ptarrayarc_raycast_intersections()

int ptarrayarc_raycast_intersections ( const POINTARRAY pa,
const POINT2D p,
int *  on_boundary 
)

Definition at line 935 of file ptarray.c.

936 {
937  int intersections = 0;
938  double px = p->x;
939  double py = p->y;
940 
941  assert(on_boundary);
942 
943  // A valid circular arc must have at least 3 vertices (circle).
944  if (pa->npoints < 3)
945  lwerror("%s called on invalid circularstring", __func__);
946 
947  if (pa->npoints % 2 == 0)
948  lwerror("%s called with even number of points", __func__);
949 
950  // Iterate through each arc of the circularstring
951  for (uint32_t i = 1; i < pa->npoints-1; i +=2)
952  {
953  const POINT2D* p0 = getPoint2d_cp(pa, i-1);
954  const POINT2D* p1 = getPoint2d_cp(pa, i);
955  const POINT2D* p2 = getPoint2d_cp(pa, i+1);
956  POINT2D center = {0,0};
957  double radius, d;
958  GBOX gbox;
959 
960  // Skip zero-length arc
961  if (lw_arc_is_pt(p0, p1, p2))
962  continue;
963 
964  // --- Step 1: Check if the point is ON the boundary edge ---
965  if (p2d_same(p0, p) || p2d_same(p1, p) || p2d_same(p2, p))
966  {
967  *on_boundary = LW_TRUE;
968  return 0;
969  }
970 
971  // Calculate some important pieces
972  radius = lw_arc_center(p0, p1, p2, &center);
973 
974  d = distance2d_pt_pt(p, &center);
975  if (FP_EQUALS(d, radius) && lw_pt_in_arc(p, p0, p1, p2))
976  {
977  *on_boundary = LW_TRUE;
978  return 0;
979  }
980 
981  // --- Step 2: Perform the Ray Casting intersection test ---
982 
983  // Only process arcs that our ray crosses
984  lw_arc_calculate_gbox_cartesian_2d(p0, p1, p2, &gbox);
985  if ((gbox.ymin <= py) && (py < gbox.ymax))
986  {
987  // Point of intersection on the circle that defines the arc
988  POINT2D i0, i1;
989 
990  // How many points of intersection are there
991  int iCount = circle_raycast_intersections(&center, radius, py, &i0, &i1);
992 
993  // Nothing to see here
994  if (iCount == 0)
995  continue;
996 
997  // Cannot think of a case where a grazing is not a
998  // no-op
999  if (iCount == 1)
1000  continue;
1001 
1002  // So we must have 2 intersections
1003  // Only increment the counter for intersections to the right
1004  // of the test point
1005  if (i0.x > px && lw_pt_in_arc(&i0, p0, p1, p2))
1006  intersections++;
1007 
1008  if (i1.x > px && lw_pt_in_arc(&i1, p0, p1, p2))
1009  intersections++;
1010  }
1011  }
1012 
1013  return intersections;
1014 }
int lw_arc_calculate_gbox_cartesian_2d(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3, GBOX *gbox)
Definition: gbox.c:453
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
Definition: measures.c:2306
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:107
double lw_arc_center(const POINT2D *p1, const POINT2D *p2, const POINT2D *p3, POINT2D *result)
Determines the center of the circle defined by the three given points.
Definition: lwalgorithm.c:237
#define FP_EQUALS(A, B)
int lw_arc_is_pt(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3)
Returns true if arc A is actually a point (all vertices are the same) .
Definition: lwalgorithm.c:114
int lw_pt_in_arc(const POINT2D *P, const POINT2D *A1, const POINT2D *A2, const POINT2D *A3)
Returns true if P is on the same side of the plane partition defined by A1/A3 as A2 is.
Definition: lwalgorithm.c:84
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
static int circle_raycast_intersections(const POINT2D *center, double radius, double ray, POINT2D *i0, POINT2D *i1)
Calculates the intersection points of a circle and a horizontal line.
Definition: ptarray.c:894
double ymax
Definition: liblwgeom.h:371
double ymin
Definition: liblwgeom.h:370
double y
Definition: liblwgeom.h:404
double x
Definition: liblwgeom.h:404
uint32_t npoints
Definition: liblwgeom.h:441

References circle_raycast_intersections(), distance2d_pt_pt(), FP_EQUALS, getPoint2d_cp(), lw_arc_calculate_gbox_cartesian_2d(), lw_arc_center(), lw_arc_is_pt(), lw_pt_in_arc(), LW_TRUE, lwerror(), POINTARRAY::npoints, p2d_same(), POINT2D::x, POINT2D::y, GBOX::ymax, and GBOX::ymin.

Referenced by lwcompound_contains_point(), and ptarrayarc_contains_point().

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