From: Paul Ramsey Date: Tue, 9 Oct 2012 22:48:39 +0000 (+0000) Subject: Add in arc ptarray vs point distance function (#2018) X-Git-Tag: 2.1.0beta2~576 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dc469753b709a51946d3f79fb81855ac6725462e;p=postgis Add in arc ptarray vs point distance function (#2018) git-svn-id: http://svn.osgeo.org/postgis/trunk@10387 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/liblwgeom/cunit/cu_measures.c b/liblwgeom/cunit/cu_measures.c index fee2bdf43..e9ae11911 100644 --- a/liblwgeom/cunit/cu_measures.c +++ b/liblwgeom/cunit/cu_measures.c @@ -20,6 +20,14 @@ #include "measures.h" #include "lwtree.h" +static LWGEOM* lwgeom_from_text(const char *str) +{ + LWGEOM_PARSER_RESULT r; + if( LW_FAILURE == lwgeom_parse_wkt(&r, (char*)str, LW_PARSER_CHECK_NONE) ) + return NULL; + return r.geom; +} + static void do_test_mindistance2d_tolerance(char *in1, char *in2, double expected_res) { LWGEOM *lw1; @@ -584,6 +592,80 @@ test_lw_arc_length(void) CU_ASSERT_DOUBLE_EQUAL(d, 3*M_PI/2, 0.000001); } +static void +test_lw_dist2d_pt_ptarrayarc(void) +{ + /* lw_dist2d_pt_ptarrayarc(const POINT2D *p, const POINTARRAY *pa, DISTPTS *dl) */ + DISTPTS dl; + int rv; + LWLINE *lwline; + POINT2D P; + + /* Unit semi-circle above X axis */ + lwline = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-1 0, 0 1, 1 0)")); + + /* Point at origin */ + P.x = P.y = 0; + lw_dist2d_distpts_init(&dl, DIST_MIN); + rv = lw_dist2d_pt_ptarrayarc(&P, lwline->points, &dl); + CU_ASSERT_DOUBLE_EQUAL(dl.distance, 1, 0.000001); + + /* Point above arc on Y axis */ + P.y = 2; + lw_dist2d_distpts_init(&dl, DIST_MIN); + rv = lw_dist2d_pt_ptarrayarc(&P, lwline->points, &dl); + CU_ASSERT_DOUBLE_EQUAL(dl.distance, 1, 0.000001); + + /* Point 45 degrees off arc, 2 radii from center */ + P.y = P.x = 2 * cos(M_PI/4); + lw_dist2d_distpts_init(&dl, DIST_MIN); + rv = lw_dist2d_pt_ptarrayarc(&P, lwline->points, &dl); + CU_ASSERT_DOUBLE_EQUAL(dl.distance, 1, 0.000001); + + /* Four unit semi-circles surrounding the 2x2 box around origin */ + lwline_free(lwline); + 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)")); + + /* Point at origin */ + P.x = P.y = 0; + lw_dist2d_distpts_init(&dl, DIST_MIN); + rv = lw_dist2d_pt_ptarrayarc(&P, lwline->points, &dl); + CU_ASSERT_DOUBLE_EQUAL(dl.distance, sqrt(2.0), 0.000001); + + /* Point on box edge */ + P.x = -1; P.y = 0; + lw_dist2d_distpts_init(&dl, DIST_MIN); + rv = lw_dist2d_pt_ptarrayarc(&P, lwline->points, &dl); + CU_ASSERT_DOUBLE_EQUAL(dl.distance, 1, 0.000001); + + /* Point within a semicircle lobe */ + P.x = -1.5; P.y = 0; + lw_dist2d_distpts_init(&dl, DIST_MIN); + rv = lw_dist2d_pt_ptarrayarc(&P, lwline->points, &dl); + CU_ASSERT_DOUBLE_EQUAL(dl.distance, 0.5, 0.000001); + + /* Point outside a semicircle lobe */ + P.x = -2.5; P.y = 0; + lw_dist2d_distpts_init(&dl, DIST_MIN); + rv = lw_dist2d_pt_ptarrayarc(&P, lwline->points, &dl); + CU_ASSERT_DOUBLE_EQUAL(dl.distance, 0.5, 0.000001); + + /* Point outside a semicircle lobe */ + P.y = -2.5; P.x = 0; + lw_dist2d_distpts_init(&dl, DIST_MIN); + rv = lw_dist2d_pt_ptarrayarc(&P, lwline->points, &dl); + CU_ASSERT_DOUBLE_EQUAL(dl.distance, 0.5, 0.000001); + + /* Point outside a semicircle lobe */ + P.y = 2; P.x = 1; + lw_dist2d_distpts_init(&dl, DIST_MIN); + rv = lw_dist2d_pt_ptarrayarc(&P, lwline->points, &dl); + CU_ASSERT_DOUBLE_EQUAL(dl.distance, sqrt(2.0)-1.0, 0.000001); + + /* Clean up */ + lwline_free(lwline); +} + /* ** Used by test harness to register the tests in this file. */ @@ -598,6 +680,7 @@ CU_TestInfo measures_tests[] = PG_TEST(test_lw_dist2d_seg_arc), PG_TEST(test_lw_dist2d_arc_arc), PG_TEST(test_lw_arc_length), + PG_TEST(test_lw_dist2d_pt_ptarrayarc), CU_TEST_INFO_NULL }; CU_SuiteInfo measures_suite = {"PostGIS Measures Suite", NULL, NULL, measures_tests}; diff --git a/liblwgeom/cunit/cu_ptarray.c b/liblwgeom/cunit/cu_ptarray.c index 3e562a02f..4ad95f622 100644 --- a/liblwgeom/cunit/cu_ptarray.c +++ b/liblwgeom/cunit/cu_ptarray.c @@ -466,7 +466,7 @@ static void test_ptarray_contains_point() static void test_ptarray_contains_point_arc() { -/* int ptarray_contains_point_arc(const POINTARRAY *pa, const POINT2D *pt) */ + /* int ptarray_contains_point_arc(const POINTARRAY *pa, const POINT2D *pt) */ LWLINE *lwline; POINTARRAY *pa; diff --git a/liblwgeom/measures.c b/liblwgeom/measures.c index 382d6863a..0cf285445 100644 --- a/liblwgeom/measures.c +++ b/liblwgeom/measures.c @@ -695,10 +695,9 @@ lw_dist2d_pt_ptarray(POINT2D *p, POINTARRAY *pa,DISTPTS *dl) } /** - * search all the segments of pointarray to see which one is closest to p1 - * Returns minimum distance between point and pointarray - */ -#if 0 +* Search all the arcs of pointarray to see which one is closest to p1 +* Returns minimum distance between point and arc pointarray. +*/ int lw_dist2d_pt_ptarrayarc(const POINT2D *p, const POINTARRAY *pa, DISTPTS *dl) { @@ -711,29 +710,28 @@ lw_dist2d_pt_ptarrayarc(const POINT2D *p, const POINTARRAY *pa, DISTPTS *dl) 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) ) + if ( ! lw_dist2d_pt_pt(p, A1, dl) ) return LW_FALSE; - for ( t=2; tnpoints; t++ ) + for ( t=1; tnpoints; t += 2 ) { - dl->twisted=twist; - A3 = getPoint2d_cp(pa, t); + dl->twisted = twist; + A2 = getPoint2d_cp(pa, t); + A3 = getPoint2d_cp(pa, t+1); if ( lw_dist2d_pt_arc(p, A1, A2, A3, dl) == LW_FALSE ) return LW_FALSE; - if ( dl->distance<=dl->tolerance && dl->mode == DIST_MIN ) + 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; + A1 = A3; } return LW_TRUE; } -#endif + /** * Brute force. diff --git a/liblwgeom/measures.h b/liblwgeom/measures.h index 8cd3d9bd7..377774131 100644 --- a/liblwgeom/measures.h +++ b/liblwgeom/measures.h @@ -48,6 +48,7 @@ int lw_dist2d_distribute_fast(LWGEOM *lwg1, LWGEOM *lwg2, DISTPTS *dl); * Brute force functions */ int lw_dist2d_pt_ptarray(POINT2D *p, POINTARRAY *pa, DISTPTS *dl); +int lw_dist2d_pt_ptarrayarc(const POINT2D *p, const POINTARRAY *pa, DISTPTS *dl); int lw_dist2d_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2, DISTPTS *dl); int lw_dist2d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly, DISTPTS *dl); int lw_dist2d_point_point(LWPOINT *point1, LWPOINT *point2, DISTPTS *dl);