PostGIS  3.6.1dev-r@@SVN_REVISION@@

◆ ptarrayarc_raycast_intersections()

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

Definition at line 944 of file ptarray.c.

945 {
946  int intersections = 0;
947  double px = p->x;
948  double py = p->y;
949 
950  assert(on_boundary);
951 
952  // A valid circular arc must have at least 3 vertices (circle).
953  if (pa->npoints < 3)
954  lwerror("%s called on invalid circularstring", __func__);
955 
956  if (pa->npoints % 2 == 0)
957  lwerror("%s called with even number of points", __func__);
958 
959  // Iterate through each arc of the circularstring
960  for (uint32_t i = 1; i < pa->npoints-1; i +=2)
961  {
962  const POINT2D* p0 = getPoint2d_cp(pa, i-1);
963  const POINT2D* p1 = getPoint2d_cp(pa, i);
964  const POINT2D* p2 = getPoint2d_cp(pa, i+1);
965  POINT2D center = {0,0};
966  double radius, d;
967  GBOX gbox;
968 
969  // Skip zero-length arc
970  if (lw_arc_is_pt(p0, p1, p2))
971  continue;
972 
973  // --- Step 1: Check if the point is ON the boundary edge ---
974  if (p2d_same(p0, p) || p2d_same(p1, p) || p2d_same(p2, p))
975  {
976  *on_boundary = LW_TRUE;
977  return 0;
978  }
979 
980  // Calculate some important pieces
981  radius = lw_arc_center(p0, p1, p2, &center);
982 
983  d = distance2d_pt_pt(p, &center);
984  if (FP_EQUALS(d, radius) && lw_pt_in_arc(p, p0, p1, p2))
985  {
986  *on_boundary = LW_TRUE;
987  return 0;
988  }
989 
990  // --- Step 2: Perform the Ray Casting intersection test ---
991 
992  // Only process arcs that our ray crosses
993  lw_arc_calculate_gbox_cartesian_2d(p0, p1, p2, &gbox);
994  if ((gbox.ymin <= py) && (py < gbox.ymax))
995  {
996  // Point of intersection on the circle that defines the arc
997  POINT2D i0, i1;
998 
999  // How many points of intersection are there
1000  int iCount = circle_raycast_intersections(&center, radius, py, &i0, &i1);
1001 
1002  // Nothing to see here
1003  if (iCount == 0)
1004  continue;
1005 
1006  // Cannot think of a case where a grazing is not a
1007  // no-op
1008  if (iCount == 1)
1009  continue;
1010 
1011  // So we must have 2 intersections
1012  // Only increment the counter for intersections to the right
1013  // of the test point
1014  if (i0.x > px && lw_pt_in_arc(&i0, p0, p1, p2))
1015  intersections++;
1016 
1017  if (i1.x > px && lw_pt_in_arc(&i1, p0, p1, p2))
1018  intersections++;
1019  }
1020  }
1021 
1022  return intersections;
1023 }
int lw_arc_calculate_gbox_cartesian_2d(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3, GBOX *gbox)
Definition: gbox.c:465
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
Definition: measures.c:2344
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:93
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:244
#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:121
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:91
int p2d_same(const POINT2D *p1, const POINT2D *p2)
Definition: lwalgorithm.c:57
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
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
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:903
double ymax
Definition: liblwgeom.h:357
double ymin
Definition: liblwgeom.h:356
double y
Definition: liblwgeom.h:390
double x
Definition: liblwgeom.h:390
uint32_t npoints
Definition: liblwgeom.h:427

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: