int lwcompound_contains_point(const LWCOMPOUND *comp, const POINT2D *pt) { int i; LWLINE *lwline; LWCIRCSTRING *lwcirc; int wn = 0; int winding_number = 0; int result; for ( i = 0; i < comp->ngeoms; i++ ) { LWGEOM *lwgeom = comp->geoms[i]; if ( lwgeom->type == LINETYPE ) { lwline = lwgeom_as_lwline(lwgeom); if ( comp->ngeoms == 1 ) { return ptarray_contains_point(lwline->points, pt); } else { /* Don't check closure while doing p-i-p test */ result = ptarray_contains_point_partial(lwline->points, pt, LW_FALSE, &winding_number); } } else { lwcirc = lwgeom_as_lwcircstring(lwgeom); if ( ! lwcirc ) { lwerror("Unexpected component of type %s in compound curve", lwtype_name(lwgeom->type)); return 0; } if ( comp->ngeoms == 1 ) { return ptarrayarc_contains_point(lwcirc->points, pt); } else { /* Don't check closure while doing p-i-p test */ result = ptarrayarc_contains_point_partial(lwcirc->points, pt, LW_FALSE, &winding_number); } } /* Propogate boundary condition */ if ( result == LW_BOUNDARY ) return LW_BOUNDARY; wn += winding_number; } /* Outside */ if (wn == 0) return LW_OUTSIDE; /* Inside */ return LW_INSIDE; }
int lwgeom_contains_point(const LWGEOM *geom, const POINT2D *pt) { switch( geom->type ) { case LINETYPE: return ptarray_contains_point(((LWLINE*)geom)->points, pt); case CIRCSTRINGTYPE: return ptarrayarc_contains_point(((LWCIRCSTRING*)geom)->points, pt); case COMPOUNDTYPE: return lwcompound_contains_point((LWCOMPOUND*)geom, pt); } lwerror("lwgeom_contains_point failed"); return LW_FAILURE; }
static void test_ptarrayarc_contains_point() { /* int ptarrayarc_contains_point(const POINTARRAY *pa, const POINT2D *pt) */ LWLINE *lwline; 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; /* Point in middle of square */ pt.x = 0; pt.y = 0; rv = ptarrayarc_contains_point(pa, &pt); CU_ASSERT_EQUAL(rv, LW_INSIDE); /* Point in left lobe */ pt.x = -1.1; pt.y = 0.1; rv = ptarrayarc_contains_point(pa, &pt); CU_ASSERT_EQUAL(rv, LW_INSIDE); /* Point on boundary of left lobe */ pt.x = -1; pt.y = 0; rv = ptarrayarc_contains_point(pa, &pt); CU_ASSERT_EQUAL(rv, LW_INSIDE); /* Point on boundary vertex */ pt.x = -1; pt.y = 1; rv = ptarrayarc_contains_point(pa, &pt); CU_ASSERT_EQUAL(rv, LW_BOUNDARY); /* Point outside */ pt.x = -1.5; pt.y = 1.5; rv = ptarrayarc_contains_point(pa, &pt); CU_ASSERT_EQUAL(rv, LW_OUTSIDE); /*** Two-edge ring made up of semi-circles (really, a circle) ***/ lwline_free(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 = ptarrayarc_contains_point(pa, &pt); CU_ASSERT_EQUAL(rv, LW_OUTSIDE); /* Point more outside */ pt.x = 2.5; pt.y = 1.5; rv = ptarrayarc_contains_point(pa, &pt); CU_ASSERT_EQUAL(rv, LW_OUTSIDE); /* Point more outside */ pt.x = 2.5; pt.y = 2.5; rv = ptarrayarc_contains_point(pa, &pt); CU_ASSERT_EQUAL(rv, LW_OUTSIDE); /* Point inside at middle */ pt.x = 0; pt.y = 0; rv = ptarrayarc_contains_point(pa, &pt); CU_ASSERT_EQUAL(rv, LW_INSIDE); /* Point inside offset from middle */ pt.x = 0.01; pt.y = 0.01; rv = ptarrayarc_contains_point(pa, &pt); CU_ASSERT_EQUAL(rv, LW_INSIDE); /* Point on edge vertex */ pt.x = 0; pt.y = 1; rv = ptarrayarc_contains_point(pa, &pt); CU_ASSERT_EQUAL(rv, LW_BOUNDARY); /*** Two-edge ring, closed ***/ lwline_free(lwline); lwline = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(1 6, 6 1, 9 7, 6 10, 1 6)")); pa = lwline->points; /* Point to left of ring */ pt.x = 20; pt.y = 4; rv = ptarrayarc_contains_point(pa, &pt); CU_ASSERT_EQUAL(rv, LW_OUTSIDE); /*** One-edge ring, closed circle ***/ lwline_free(lwline); lwline = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-1 0, 1 0, -1 0)")); pa = lwline->points; /* Point inside */ pt.x = 0; pt.y = 0; rv = ptarrayarc_contains_point(pa, &pt); CU_ASSERT_EQUAL(rv, LW_INSIDE); /* Point outside */ pt.x = 0; pt.y = 2; rv = ptarrayarc_contains_point(pa, &pt); CU_ASSERT_EQUAL(rv, LW_OUTSIDE); /* Point on boundary */ pt.x = 0; pt.y = 1; rv = ptarrayarc_contains_point(pa, &pt); CU_ASSERT_EQUAL(rv, LW_BOUNDARY); /*** Overshort ring ***/ lwline_free(lwline); lwline = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-1 0, 1 0)")); pa = lwline->points; cu_error_msg_reset(); rv = ptarrayarc_contains_point(pa, &pt); //printf("%s\n", cu_error_msg); CU_ASSERT_STRING_EQUAL("ptarrayarc_contains_point called with even number of points", cu_error_msg); /*** Unclosed ring ***/ lwline_free(lwline); lwline = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-1 0, 1 0, 2 0)")); pa = lwline->points; cu_error_msg_reset(); rv = ptarrayarc_contains_point(pa, &pt); CU_ASSERT_STRING_EQUAL("ptarrayarc_contains_point called on unclosed ring", cu_error_msg); lwline_free(lwline); }