pgsql-4872

Version:

8.2.5

Bug Link:

http://postgresql.1045698.n5.nabble.com/BUG-4872-Geometric-function-problem-td2129688.html

Symptom:

Wrong result of geometric calculation for distance between point and lseg(represents line segment in the plane).

How it is diagnosed:

Reproduced!

How to reproduce:

postgres=# select point(0,0) <-> lseg(point(10,-100),point(10,450));

 ?column?

----------

       10  // this result is correct!

(1 row)

posgres=# select point(0,0) <-> lseg(point(10,-100),point(11,450));

     ?column?

------------------

 100.498756211209 // this is wrong, should be 10.1818013524084

(1 row)

Root Cause:

In function dist_ps(or rather dist_ps_internal), which is responsible for calculating distance from point to line segment, it miscalculated the

slope of the perpendicular (a line at right angles to a line or plane) to the given line segment anytime that slope was other than 0(like the first one, the lseg’s perpendicular slope is 0, so the result is correct), infinite, or +/-1.  In some cases the error would be masked because the true closest point on the line segment was one of its endpoints rather than the intersection point, but in other cases it could give an arbitrarily bad result.

static double

dist_ps_internal(Point *pt, LSEG *lseg)

{

        double                m;                                /* slope of perp. */

        LINE           *ln;

        double                result,tmpdist;

        Point           *ip;

/*

 * Construct a line perpendicular to the input segment

 * and through the input point

 */

        if (lseg->p[1].x == lseg->p[0].x)

                m = 0;

        else if (lseg->p[1].y == lseg->p[0].y)

        {                                                        /* slope is infinite */

                m = (double) DBL_MAX;

        }

        else

                //this slope is lseg’s, not perpendicular’s

-                m = ((lseg->p[0].y - lseg->p[1].y) / (lseg->p[1].x - lseg->p[0].x));

                //slope of perpendicular * slope of lseg = -1

+                m = (lseg->p[0].x - lseg->p[1].x) / (lseg->p[1].y - lseg->p[0].y);

        ln = line_construct_pm(pt, m);

#ifdef GEODEBUG

        printf("dist_ps- line is A=%g B=%g C=%g from (point) slope (%f,%f) %g\n",

                   ln->A, ln->B, ln->C, pt->x, pt->y, m);

#endif

….

}

Is there any log message?

No

Can ErrLog insert a log message?

Yes.Via the generic default-switch pattern:

if (XXX) …

else if (XXX) …

else {log}