POINTARRAY *pa;
POINT2D pt;
int rv;
-
+
/* Collection of semi-circles surrounding unit square */
lwline = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-1 -1, -2 0, -1 1, 0 2, 1 1, 2 0, 1 -1, 0 -2, -1 -1)"));
pa = lwline->points;
/* Two-edge ring made up of semi-circles (really, a circle) */
lwfree(lwline);
+
lwline = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-1 0, 0 1, 1 0, 0 -1, -1 0)"));
pa = lwline->points;
-
+
/* Point outside */
pt.x = -1.5;
pt.y = 1.5;
rv = ptarray_contains_point_arc(pa, &pt);
CU_ASSERT_EQUAL(rv, -1);
- /* Point inside */
- pt.x = -0.2;
- pt.y = 0.2;
+ /* Point inside at middle */
+ pt.x = 0;
+ pt.y = 0;
+ rv = ptarray_contains_point_arc(pa, &pt);
+ CU_ASSERT_EQUAL(rv, 1);
+
+ /* Point inside offset from middle */
+ pt.x = 0.01;
+ pt.y = 0.01;
rv = ptarray_contains_point_arc(pa, &pt);
CU_ASSERT_EQUAL(rv, 1);
pa = lwline->points;
cu_error_msg_reset();
rv = ptarray_contains_point_arc(pa, &pt);
- CU_ASSERT_STRING_EQUAL("ptarray_contains_point_arc called on unclosed ring", cu_error_msg);
+ //printf("%s\n", cu_error_msg);
+ CU_ASSERT_STRING_EQUAL("ptarray_contains_point_arc called with even number of points", cu_error_msg);
/* Unclosed ring */
lwfree(lwline);
lwline_free(lwline);
}
+
/*
** Used by the test harness to register the tests in this file.
*/
* Returns -1 for left and 1 for right and 0 for co-linearity
*/
int lw_segment_side(const POINT2D *p1, const POINT2D *p2, const POINT2D *q);
+int lw_arc_side(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3, const POINT2D *Q);
int lw_arc_calculate_gbox_cartesian_2d(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3, GBOX *gbox);
double lw_arc_center(const POINT2D *p1, const POINT2D *p2, const POINT2D *p3, POINT2D *result);
int lw_pt_in_seg(const POINT2D *P, const POINT2D *A1, const POINT2D *A2);
int lw_arc_is_pt(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3);
double lw_seg_length(const POINT2D *A1, const POINT2D *A2);
double lw_arc_length(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3);
-double lw_arc_side(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3, const POINT2D *Q);
int pt_in_ring_2d(const POINT2D *p, const POINTARRAY *ring);
int ptarray_contains_point(const POINTARRAY *pa, const POINT2D *pt);
int ptarray_contains_point_arc(const POINTARRAY *pa, const POINT2D *pt);
return circumference_A * (angle / (2*M_PI));
}
-double lw_arc_side(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3, const POINT2D *Q)
+int lw_arc_side(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3, const POINT2D *Q)
{
POINT2D C;
double radius_A;
return 0;
}
+ /* Q on A1-A3 line, so its on opposite side to A2 */
+ if ( side_Q == 0 )
+ {
+ return -1 * side_A2;
+ }
+
/*
* Q is inside the arc boundary, so it's not on the side we
* might think from examining only the end points
}
/**
-
* search all the segments of pointarray to see which one is closest to p1
* Returns minimum distance between point and pointarray
*/
return LW_TRUE;
}
+/**
+ * search all the segments of pointarray to see which one is closest to p1
+ * Returns minimum distance between point and pointarray
+ */
+#if 0
+int
+lw_dist2d_pt_ptarrayarc(const POINT2D *p, const POINTARRAY *pa, DISTPTS *dl)
+{
+ int t;
+ const POINT2D *A1;
+ const POINT2D *A2;
+ const POINT2D *A3;
+ int twist = dl->twisted;
+
+ LWDEBUG(2, "lw_dist2d_pt_ptarrayarc is called");
+
+ A1 = getPoint2d_cp(pa, 0);
+ A2 = getPoint2d_cp(pa, 1);
+
+ if ( !lw_dist2d_pt_pt(p, A1, dl) )
+ return LW_FALSE;
+
+ for ( t=2; t<pa->npoints; t++ )
+ {
+ dl->twisted=twist;
+ A3 = getPoint2d_cp(pa, t);
+
+ if ( lw_dist2d_pt_arc(p, A1, A2, A3, dl) == LW_FALSE )
+ return LW_FALSE;
+
+ if ( dl->distance<=dl->tolerance && dl->mode == DIST_MIN )
+ return LW_TRUE; /*just a check if the answer is already given*/
+
+ A1 = A2;
+ A2 = A3;
+ }
+
+ return LW_TRUE;
+}
+#endif
+
/**
* Brute force.
* Test line-ring distance against each ring.
/* Check for not an arc ring (always have odd # of points) */
if ( (pa->npoints % 2) == 0 )
+ {
lwerror("ptarray_contains_point_arc called with even number of points");
+ return -1;
+ }
/* Check for not an arc ring (always have >= 3 points) */
if ( pa->npoints < 3 )
+ {
lwerror("ptarray_contains_point_arc called too-short pointarray");
+ return -1;
+ }
/* Check for unclosed case */
seg1 = getPoint2d_cp(pa, 0);
if ( ! p2d_same(seg1, seg3) )
{
lwerror("ptarray_contains_point_arc called on unclosed ring");
+ return -1;
}
/* OK, it's closed. Is it just one circle? */
else if ( pa->npoints == 3 )
}
/* Start on the ring */
- seg2 = getPoint2d_cp(pa, 1);
- for ( i=2; i < pa->npoints; i++ )
+ seg1 = getPoint2d_cp(pa, 0);
+ for ( i=1; i < pa->npoints; i += 2 )
{
- seg3 = getPoint2d_cp(pa, i);
+ seg2 = getPoint2d_cp(pa, i);
+ seg3 = getPoint2d_cp(pa, i+1);
/* Catch an easy boundary case */
if( p2d_same(seg3, pt) )
/* Skip arcs that have no size */
if ( lw_arc_is_pt(seg1, seg2, seg3) )
{
- seg1 = seg2;
- seg2 = seg3;
+ seg1 = seg3;
continue;
}
-
/* Only test segments in our vertical range */
lw_arc_calculate_gbox_cartesian_2d(seg1, seg2, seg3, &gbox);
if ( pt->y > gbox.ymax || pt->y < gbox.ymin )
{
- seg1 = seg2;
- seg2 = seg3;
+ seg1 = seg3;
continue;
}
wn--;
}
- seg1 = seg2;
- seg2 = seg3;
+ /* Inside the arc! */
+ if ( pt->x <= gbox.xmax && pt->x >= gbox.xmin )
+ {
+ POINT2D C;
+ double radius = lw_arc_center(seg1, seg2, seg3, &C);
+ double d = distance2d_pt_pt(pt, &C);
+
+ /* On the boundary! */
+ if ( d == radius )
+ return 0;
+
+ /* Within the arc! */
+ if ( d < radius )
+ {
+ /* Left side, increment winding number */
+ if ( side < 0 )
+ wn++;
+ /* Right side, decrement winding number */
+ if ( side > 0 )
+ wn--;
+ }
+ }
+
+ seg1 = seg3;
}
/* Outside */