]> granicus.if.org Git - postgis/commitdiff
Add in arc ptarray vs point distance function (#2018)
authorPaul Ramsey <pramsey@cleverelephant.ca>
Tue, 9 Oct 2012 22:48:39 +0000 (22:48 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Tue, 9 Oct 2012 22:48:39 +0000 (22:48 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@10387 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/cunit/cu_measures.c
liblwgeom/cunit/cu_ptarray.c
liblwgeom/measures.c
liblwgeom/measures.h

index fee2bdf43239e3db13882322fd2236ddc9aa714f..e9ae11911688a2ed40042dfe77d94ad35bace4a8 100644 (file)
 #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};
index 3e562a02fddb0ccd2e5484daaa18e7dde884ecd0..4ad95f6227d657a0a4a8aab0541cf8e1dbe72f11 100644 (file)
@@ -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;
index 382d6863a1382b93966a152a997a7c31089e3e70..0cf28544571b16b759033b7b369d84cc3e27a489 100644 (file)
@@ -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; t<pa->npoints; t++ )
+       for ( t=1; t<pa->npoints; 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.
index 8cd3d9bd71ed5541d444317e06e06388e7db8d7c..37777413156fa226a1461271cf243c92ebf25fc8 100644 (file)
@@ -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);