]> granicus.if.org Git - postgis/commitdiff
Add in arc ptarray vs ptarray and arc ptarray vs arc ptarray distance functions....
authorPaul Ramsey <pramsey@cleverelephant.ca>
Wed, 10 Oct 2012 00:00:54 +0000 (00:00 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Wed, 10 Oct 2012 00:00:54 +0000 (00:00 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@10390 b70326c6-7e19-0410-871a-916f4a2858ee

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

index e9ae11911688a2ed40042dfe77d94ad35bace4a8..b8bdf6e18c0b8e7e3d2803b562dab87595c32c02 100644 (file)
@@ -666,6 +666,51 @@ test_lw_dist2d_pt_ptarrayarc(void)
        lwline_free(lwline);
 }
 
+static void
+test_lw_dist2d_ptarray_ptarrayarc(void)
+{
+       /* int lw_dist2d_ptarray_ptarrayarc(const POINTARRAY *pa, const POINTARRAY *pb, DISTPTS *dl) */
+       DISTPTS dl;
+       int rv;
+       LWLINE *lwline1;
+       LWLINE *lwline2;
+
+       /* Unit semi-circle above X axis */
+       lwline1 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-1 0, 0 1, 1 0)"));
+       
+       /* Line above top of semi-circle */
+       lwline2 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-2 2, -1 2, 1 2, 2 2)"));
+       lw_dist2d_distpts_init(&dl, DIST_MIN);
+       rv = lw_dist2d_ptarray_ptarrayarc(lwline2->points, lwline1->points, &dl);
+       CU_ASSERT_DOUBLE_EQUAL(dl.distance, 1, 0.000001);
+
+       /* Reversed arguments, should fail */
+       lw_dist2d_distpts_init(&dl, DIST_MIN);
+       cu_error_msg_reset();
+       rv = lw_dist2d_ptarray_ptarrayarc(lwline1->points, lwline2->points, &dl);
+       //printf("%s\n", cu_error_msg);
+       CU_ASSERT_STRING_EQUAL("lw_dist2d_ptarray_ptarrayarc called with non-arc input", cu_error_msg);
+
+       lwline_free(lwline2);
+       
+       /* Line along side of semi-circle */
+       lwline2 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-2 -3, -2 -2, -2 2, -2 3)"));
+       lw_dist2d_distpts_init(&dl, DIST_MIN);
+       rv = lw_dist2d_ptarray_ptarrayarc(lwline2->points, lwline1->points, &dl);
+       CU_ASSERT_DOUBLE_EQUAL(dl.distance, 1, 0.000001);
+
+       /* Four unit semi-circles surrounding the 2x2 box around origin */
+       lwline_free(lwline1);
+       lwline_free(lwline2);
+       lwline1 = 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)"));
+       lwline2 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-2.5 -3, -2.5 -2, -2.5 2, -2.5 3)"));
+       rv = lw_dist2d_ptarray_ptarrayarc(lwline2->points, lwline1->points, &dl);
+       CU_ASSERT_DOUBLE_EQUAL(dl.distance, 0.5, 0.000001);
+
+       lwline_free(lwline2);
+       lwline_free(lwline1);
+}
+
 /*
 ** Used by test harness to register the tests in this file.
 */
@@ -681,6 +726,7 @@ CU_TestInfo measures_tests[] =
        PG_TEST(test_lw_dist2d_arc_arc),
        PG_TEST(test_lw_arc_length),
        PG_TEST(test_lw_dist2d_pt_ptarrayarc),
+       PG_TEST(test_lw_dist2d_ptarray_ptarrayarc),
        CU_TEST_INFO_NULL
 };
 CU_SuiteInfo measures_suite = {"PostGIS Measures Suite",  NULL,  NULL, measures_tests};
index 0cf28544571b16b759033b7b369d84cc3e27a489..47aa5eb47f9e2c48306b3efd44663423f6bd9573 100644 (file)
@@ -709,6 +709,18 @@ lw_dist2d_pt_ptarrayarc(const POINT2D *p, const POINTARRAY *pa, DISTPTS *dl)
 
        LWDEBUG(2, "lw_dist2d_pt_ptarrayarc is called");
 
+       if ( pa->npoints % 2 == 0 || pa->npoints < 3 )
+       {
+               lwerror("lw_dist2d_pt_ptarrayarc called with non-arc input");
+               return LW_FALSE;
+       }
+
+       if (dl->mode == DIST_MAX)
+       {
+               lwerror("lw_dist2d_pt_ptarrayarc does not currently support DIST_MAX mode");
+               return LW_FALSE;
+       }
+
        A1 = getPoint2d_cp(pa, 0);
 
        if ( ! lw_dist2d_pt_pt(p, A1, dl) ) 
@@ -811,8 +823,7 @@ lw_dist2d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly, DISTPTS *dl)
 
 
 /**
-
-test each segment of l1 against each segment of l2.
+* test each segment of l1 against each segment of l2.
 */
 int
 lw_dist2d_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2,DISTPTS *dl)
@@ -863,6 +874,109 @@ lw_dist2d_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2,DISTPTS *dl)
        return LW_TRUE;
 }
 
+/**
+* Test each segment of pa against each arc of pb for distance.
+*/
+int
+lw_dist2d_ptarray_ptarrayarc(const POINTARRAY *pa, const POINTARRAY *pb, DISTPTS *dl)
+{
+       int t, u;
+       const POINT2D *A1;
+       const POINT2D *A2;
+       const POINT2D *B1;
+       const POINT2D *B2;
+       const POINT2D *B3;
+       int twist = dl->twisted;
+
+       LWDEBUGF(2, "lw_dist2d_ptarray_ptarrayarc called (points: %d-%d)",pa->npoints, pb->npoints);
+
+       if ( pb->npoints % 2 == 0 || pb->npoints < 3 )
+       {
+               lwerror("lw_dist2d_ptarray_ptarrayarc called with non-arc input");
+               return LW_FALSE;
+       }
+
+       if ( dl->mode == DIST_MAX )
+       {
+               lwerror("lw_dist2d_ptarray_ptarrayarc does not currently support DIST_MAX mode");
+               return LW_FALSE;
+       }
+       else
+       {
+               A1 = getPoint2d_cp(pa, 0);
+               for ( t=1; t < pa->npoints; t++ ) /* For each segment in pa */
+               {
+                       A2 = getPoint2d_cp(pa, t);
+                       B1 = getPoint2d_cp(pb, 0);
+                       for ( u=1; u < pb->npoints; u += 2 ) /* For each arc in pb */
+                       {
+                               B2 = getPoint2d_cp(pb, u);
+                               B3 = getPoint2d_cp(pb, u+1);
+                               dl->twisted = twist;
+
+                               lw_dist2d_seg_arc(A1, A2, B1, B2, B3, dl);
+
+                               /* If we've found a distance within tolerance, we're done */
+                               if ( dl->distance <= dl->tolerance && dl->mode == DIST_MIN ) 
+                                       return LW_TRUE; 
+
+                               B1 = B3;
+                       }
+                       A1 = A2;
+               }
+       }
+       return LW_TRUE;
+}
+
+/**
+* Test each arc of pa against each arc of pb for distance.
+*/
+int
+lw_dist2d_ptarrayarc_ptarrayarc(const POINTARRAY *pa, const POINTARRAY *pb, DISTPTS *dl)
+{
+       int t, u;
+       const POINT2D *A1;
+       const POINT2D *A2;
+       const POINT2D *A3;
+       const POINT2D *B1;
+       const POINT2D *B2;
+       const POINT2D *B3;
+       int twist = dl->twisted;
+
+       LWDEBUGF(2, "lw_dist2d_ptarrayarc_ptarrayarc called (points: %d-%d)",pa->npoints, pb->npoints);
+
+       if (dl->mode == DIST_MAX)
+       {
+               lwerror("lw_dist2d_ptarrayarc_ptarrayarc does not currently support DIST_MAX mode");
+               return LW_FALSE;
+       }
+       else
+       {
+               A1 = getPoint2d_cp(pa, 0);
+               for ( t=1; t < pa->npoints; t++ ) /* For each segment in pa */
+               {
+                       A2 = getPoint2d_cp(pa, t);
+                       A3 = getPoint2d_cp(pa, t+1);
+                       B1 = getPoint2d_cp(pb, 0);
+                       for ( u=1; u < pb->npoints; u += 2 ) /* For each arc in pb */
+                       {
+                               B2 = getPoint2d_cp(pb, u);
+                               B3 = getPoint2d_cp(pb, u+1);
+                               dl->twisted = twist;
+
+                               lw_dist2d_arc_arc(A1, A2, A3, B1, B2, B3, dl);
+
+                               /* If we've found a distance within tolerance, we're done */
+                               if ( dl->distance <= dl->tolerance && dl->mode == DIST_MIN ) 
+                                       return LW_TRUE; 
+
+                               B1 = B3;
+                       }
+                       A1 = A3;
+               }
+       }
+       return LW_TRUE;
+}
 /**
 * Calculate the shortest distance between an arc and an edge.
 * Line/circle approach from http://stackoverflow.com/questions/1073336/circle-line-collision-detection 
index 37777413156fa226a1461271cf243c92ebf25fc8..0a3958dda0b813e0f470da391cb8054909bf1405 100644 (file)
@@ -50,6 +50,8 @@ int lw_dist2d_distribute_fast(LWGEOM *lwg1, LWGEOM *lwg2, DISTPTS *dl);
 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_ptarrayarc(const POINTARRAY *pa, const POINTARRAY *pb, DISTPTS *dl);
+int lw_dist2d_ptarrayarc_ptarrayarc(const POINTARRAY *pa, const POINTARRAY *pb, DISTPTS *dl);
 int lw_dist2d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly, DISTPTS *dl);
 int lw_dist2d_point_point(LWPOINT *point1, LWPOINT *point2, DISTPTS *dl);
 int lw_dist2d_point_line(LWPOINT *point, LWLINE *line, DISTPTS *dl);