diff --git a/liblwgeom/measures.c b/liblwgeom/measures.c index 2ba714c02..b601006fa 100644 --- a/liblwgeom/measures.c +++ b/liblwgeom/measures.c @@ -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); diff --git a/regress/measures.sql b/regress/measures.sql index fab2a54d4..22136bab0 100644 --- a/regress/measures.sql +++ b/regress/measures.sql @@ -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 diff --git a/regress/measures_expected b/regress/measures_expected index 3b0a35905..f945b1502 100644 --- a/regress/measures_expected +++ b/regress/measures_expected @@ -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)