Increase robustness in distance-calculations when point is on segment.

git-svn-id: http://svn.osgeo.org/postgis/trunk@8965 b70326c6-7e19-0410-871a-916f4a2858ee
This commit is contained in:
Nicklas Avén 2012-01-29 23:30:18 +00:00
parent ea2883e5ae
commit 75ce3f50f8
3 changed files with 17 additions and 38 deletions

View 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);

View 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

View 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)