PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ 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.
#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) .
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: