]> granicus.if.org Git - postgis/commitdiff
Increase robustness in distance-calculations when point is on segment.
authorNicklas Avén <nicklas.aven@jordogskog.no>
Sun, 29 Jan 2012 23:30:18 +0000 (23:30 +0000)
committerNicklas Avén <nicklas.aven@jordogskog.no>
Sun, 29 Jan 2012 23:30:18 +0000 (23:30 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@8965 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/measures.c
regress/measures.sql
regress/measures_expected

index 2ba714c02808f07192b3242c52300edef6262cac..b601006fa562f69d192ad5634eb14b66b997d0f6 100644 (file)
@@ -1312,17 +1312,25 @@ lw_dist2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B, DISTPTS *dl)
                }
        }
 
-       if (r<0)        /*If the first vertex A is closest to the point p*/
+       if (r<0)        /*If p projected on the line is outside point A*/
        {
                return lw_dist2d_pt_pt(p,A,dl);
        }
-       if (r>=1)       /*If the second vertex B is closest or equal to the point p*/
+       if (r>=1)       /*If p projected on the line is outside point B or on point B*/
        {
                return lw_dist2d_pt_pt(p,B,dl);
        }
-
-       /*else if the point p is closer to some point between a and b
-       then we find that point and send it to lw_dist2d_pt_pt*/
+       
+       /*If the point p is on the segment this is a more robust way to find out that*/
+       if (( ((A->y-p->y)*(B->x-A->x)==(A->x-p->x)*(B->y-A->y) ) ) && (dl->mode ==  DIST_MIN))
+       {
+               dl->distance = 0.0;
+               dl->p1 = *p;
+               dl->p2 = *p;
+       }
+       
+       /*If the projection of point p on the segment is between A and B
+       then we find that "point on segment" and send it to lw_dist2d_pt_pt*/
        c.x=A->x + r * (B->x-A->x);
        c.y=A->y + r * (B->y-A->y);
 
index fab2a54d4f82ea1356681532fa67e1d58cc4da8b..22136bab06b5ad9e8396d27eb7089f24a2eb4d54 100644 (file)
@@ -1,27 +1,4 @@
-select '113', ST_Area2d('MULTIPOLYGON( ((0 0, 10 0, 10 10, 0 10, 0 0)),( (0 0, 10 0, 10 10, 0 10, 0 0),(5 5, 7 5, 7 7 , 5 7, 5 5) ) ,( (0 0, 10 0, 10 10, 0 10, 0 0),(5 5, 7 5, 7 7, 5 7, 5 5),(1 1,2 1, 2 2, 1 2, 1 1) ) )'::GEOMETRY) as value;
 
-select '114', ST_Perimeter2d('MULTIPOLYGON( ((0 0, 10 0, 10 10, 0 10, 0 0)),( (0 0, 10 0, 10 10, 0 10, 0 0),(5 5, 7 5, 7 7 , 5 7, 5 5) ) ,( (0 0, 10 0, 10 10, 0 10, 0 0),(5 5, 7 5, 7 7, 5 7, 5 5),(1 1,2 1, 2 2, 1 2, 1 1) ) )'::GEOMETRY) as value;
-
-select '115', ST_3DPerimeter('MULTIPOLYGON( ((0 0 0, 10 0 0, 10 10 0, 0 10 0, 0 0 0)),( (0 0 0, 10 0 0, 10 10 0, 0 10 0, 0 0 0),(5 5 0, 7 5 0, 7 7  0, 5 7 0, 5 5 0) ) ,( (0 0 1, 10 0 1, 10 10 1, 0 10 1, 0 0 1),(5 5 1, 7 5 1, 7 7 1, 5 7 1, 5 5 1),(1 1 1,2 1 1, 2 2 1, 1 2 1, 1 1 1) ) )'::GEOMETRY) as value;
-
-
-select '116', ST_Length2d('MULTILINESTRING((0 0, 1 1),(0 0, 1 1, 2 2) )'::GEOMETRY) as value;
-select '117', ST_3DLength('MULTILINESTRING((0 0, 1 1),(0 0, 1 1, 2 2) )'::GEOMETRY) as value;
-select '118', ST_3DLength('MULTILINESTRING((0 0 0, 1 1 1),(0 0 0, 1 1 1, 2 2 2) )'::GEOMETRY) as value;
-
-select '134', ST_Distance('POINT(1 2)', 'POINT(1 2)');
-select '135', ST_Distance('POINT(5 0)', 'POINT(10 12)');
-
-select '136', ST_Distance('POINT(0 0)', ST_Translate('POINT(0 0)', 5, 12, 0));
-
--- postgis-users/2006-May/012174.html
-select 'dist', ST_Distance(a,b), ST_Distance(b,a) from (
-       select 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry as a,
-               'POLYGON((11 0, 11 10, 20 10, 20 0, 11 0),
-                       (15 5, 15 8, 17 8, 17 5, 15 5))'::geometry as b
-       ) as foo;
-
--- Apply the same tests using the new function names.
 select '113', ST_area2d('MULTIPOLYGON( ((0 0, 10 0, 10 10, 0 10, 0 0)),( (0 0, 10 0, 10 10, 0 10, 0 0),(5 5, 7 5, 7 7 , 5 7, 5 5) ) ,( (0 0, 10 0, 10 10, 0 10, 0 0),(5 5, 7 5, 7 7, 5 7, 5 5),(1 1,2 1, 2 2, 1 2, 1 1) ) )'::GEOMETRY) as value;
 
 select '114', ST_perimeter2d('MULTIPOLYGON( ((0 0, 10 0, 10 10, 0 10, 0 0)),( (0 0, 10 0, 10 10, 0 10, 0 0),(5 5, 7 5, 7 7 , 5 7, 5 5) ) ,( (0 0, 10 0, 10 10, 0 10, 0 0),(5 5, 7 5, 7 7, 5 7, 5 5),(1 1,2 1, 2 2, 1 2, 1 1) ) )'::GEOMETRY) as value;
@@ -46,6 +23,9 @@ select 'dist', ST_Distance(a,b), ST_Distance(b,a) from (
                        (15 5, 15 8, 17 8, 17 5, 15 5))'::geometry as b
        ) as foo;
 
+--#1502
+SELECT '#1502', ST_Dwithin(a,b,0.0)  from 
+(SELECT 'LINESTRING(-97364 -97364, 9736.4 9736.4)'::geometry a, 'POINT(0 0)'::geometry b ) foo;
 
 --st_shortestline
 
index 3b0a35905cf74c2b59652a61a64682e9e3a1a164..f945b15023454c82b63611d9613611efb6310d66 100644 (file)
@@ -8,16 +8,7 @@
 135|13
 136|13
 dist|1|1
-113|291
-114|140
-115|140
-116|4.24264068711929
-117|4.24264068711929
-118|5.19615242270663
-134|0
-135|13
-136|13
-dist|1|1
+#1502|t
 st_shortestline_134|LINESTRING(1 2,1 2)
 st_shortestline_135|LINESTRING(5 0,10 12)
 st_shortestline_136|LINESTRING(0 0,5 12)