]> granicus.if.org Git - postgis/commitdiff
Fix ST_ClosestPointOfApproach assumption of lwgeom->bbox being exact
authorSandro Santilli <strk@keybit.net>
Wed, 27 May 2015 16:47:29 +0000 (16:47 +0000)
committerSandro Santilli <strk@keybit.net>
Wed, 27 May 2015 16:47:29 +0000 (16:47 +0000)
See #3136

git-svn-id: http://svn.osgeo.org/postgis/trunk@13569 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/cunit/cu_measures.c
liblwgeom/lwlinearreferencing.c
regress/regress_lrs.sql
regress/regress_lrs_expected

index 466732e0a67d43d3670322fa5e9e6b3003076638..8e8ce2e5d901c5496bfa08c6ee7565dd29b8c3ee 100644 (file)
@@ -1089,6 +1089,18 @@ test_lwgeom_tcpa(void)
        ASSERT_DOUBLE_EQUAL(m, 3.0);
        ASSERT_DOUBLE_EQUAL(dist, 1.0);
 
+
+  /* Test for https://trac.osgeo.org/postgis/ticket/3136 */
+
+       g1 = lwgeom_from_wkt("LINESTRING M (0 0 1432291464,2 0 1432291536) ", LW_PARSER_CHECK_NONE);
+       g2 = lwgeom_from_wkt("LINESTRING M (0 0 1432291464,1 0 1432291466.25,2 0 1432291500)", LW_PARSER_CHECK_NONE);
+       dist = -1;
+       m = lwgeom_tcpa(g1, g2, &dist);
+       lwgeom_free(g1);
+       lwgeom_free(g2);
+       ASSERT_DOUBLE_EQUAL(m, 1432291464.0);
+       ASSERT_DOUBLE_EQUAL(dist, 0.0);
+
 }
 
 /*
index b728580d35d9cad33e265adb603dbc3a283db4bc..1db0ff3c5dbd6272d662c6e28cefd79fb13e9a06 100644 (file)
@@ -1043,7 +1043,7 @@ lwgeom_tcpa(const LWGEOM *g1, const LWGEOM *g2, double *mindist)
   double *mvals;
   int nmvals = 0;
   double mintime;
-  double mindist2; /* minimum distance, squared */
+  double mindist2 = FLT_MAX; /* minimum distance, squared */
 
        if ( ! lwgeom_has_m(g1) || ! lwgeom_has_m(g2) ) {
                lwerror("Both input geometries must have a measure dimension");
@@ -1063,6 +1063,7 @@ lwgeom_tcpa(const LWGEOM *g1, const LWGEOM *g2, double *mindist)
     return -1;
   }
 
+  /* WARNING: these ranges may be wider than real ones */
   gbox1 = lwgeom_get_bbox(g1);
   gbox2 = lwgeom_get_bbox(g2);
 
@@ -1071,6 +1072,7 @@ lwgeom_tcpa(const LWGEOM *g1, const LWGEOM *g2, double *mindist)
 
   /*
    * Find overlapping M range
+   * WARNING: may be larger than the real one
    */
 
   tmin = FP_MAX(gbox1->mmin, gbox2->mmin);
@@ -1130,39 +1132,19 @@ lwgeom_tcpa(const LWGEOM *g1, const LWGEOM *g2, double *mindist)
     /*lwnotice("T %g-%g", t0, t1);*/
 
     seg = ptarray_locate_along_linear(l1->points, t0, &p0, 0);
-    if ( -1 == seg )
-    {
-      lwfree(mvals);
-      lwerror("Non-linear measures in first geometry");
-      return -1;
-    }
+    if ( -1 == seg ) continue; /* possible, if GBOX is approximated */
     /*lwnotice("Measure %g on segment %d of line 1: %g, %g, %g", t0, seg, p0.x, p0.y, p0.z);*/
 
     seg = ptarray_locate_along_linear(l1->points, t1, &p1, seg);
-    if ( -1 == seg )
-    {
-      lwfree(mvals);
-      lwerror("Non-linear measures in first geometry");
-      return -1;
-    }
+    if ( -1 == seg ) continue; /* possible, if GBOX is approximated */
     /*lwnotice("Measure %g on segment %d of line 1: %g, %g, %g", t1, seg, p1.x, p1.y, p1.z);*/
 
     seg = ptarray_locate_along_linear(l2->points, t0, &q0, 0);
-    if ( -1 == seg )
-    {
-      lwfree(mvals);
-      lwerror("Non-linear measures in second geometry");
-      return -1;
-    }
+    if ( -1 == seg ) continue; /* possible, if GBOX is approximated */
     /*lwnotice("Measure %g on segment %d of line 2: %g, %g, %g", t0, seg, q0.x, q0.y, q0.z);*/
 
     seg = ptarray_locate_along_linear(l2->points, t1, &q1, seg);
-    if ( -1 == seg )
-    {
-      lwfree(mvals);
-      lwerror("Non-linear measures in second geometry");
-      return -1;
-    }
+    if ( -1 == seg ) continue; /* possible, if GBOX is approximated */
     /*lwnotice("Measure %g on segment %d of line 2: %g, %g, %g", t1, seg, q1.x, q1.y, q1.z);*/
 
     t = segments_tcpa(&p0, &p1, &q0, &q1, t0, t1);
@@ -1176,7 +1158,7 @@ lwgeom_tcpa(const LWGEOM *g1, const LWGEOM *g2, double *mindist)
     dist2 = ( q0.x - p0.x ) * ( q0.x - p0.x ) +
            ( q0.y - p0.y ) * ( q0.y - p0.y ) +
            ( q0.z - p0.z ) * ( q0.z - p0.z );
-    if ( i == 1 || dist2 < mindist2 )
+    if ( dist2 < mindist2 )
     {
       mindist2 = dist2;
       mintime = t;
index 54678b0c502b67371c5a081038e54806dab04676..05c044d88ca2669190c51f8509a369f6c31a7812 100644 (file)
@@ -79,6 +79,13 @@ select 'pca2', ST_ClosestPointOfApproach(
 select 'pca3', ST_ClosestPointOfApproach(
   'LINESTRINGZM(0 0 0 0, 0 0 0 10)',
   'LINESTRINGZM(-30 0 5 4, 10 0 5 6)');
+-- Ticket #3136
+WITH inp as ( SELECT
+ 'LINESTRING M (0 0 80000002,1 0 80000003)'::geometry g1,
+ 'LINESTRING M (2 2 80000000,1 1 80000001,0 0 80000002)'::geometry g2 )
+SELECT 'pca#3136',
+ST_ClosestPointOfApproach(g2,g1), ST_ClosestPointOfApproach(g1,g2)
+FROM inp;
 
 --
 -- ST_AddMeasure
index f3c5696a5cb790728217d173f1e4d26176d2662a..59ebf4bdbfd5b17b854aaf7139e4a3802879b7df 100644 (file)
@@ -37,6 +37,7 @@ line_interpolate_point|POINT Z (0.5 0.5 7.5)
 pca1|10
 pca2|5
 pca3|5.5
+pca#3136|80000002|80000002
 addMeasure1|LINESTRING M (0 0 10,2 0 15,4 0 20)
 addMeasure2|LINESTRING M (0 0 10,9 0 19,10 0 20)
 interpolatePoint1|2