/* **************************************************************************** * * MODULE: Vector library * * AUTHOR(S): Original author CERL, probably Dave Gerdes. * Update to GRASS 5.7 Radim Blazek. * * PURPOSE: Lower level functions for reading/writing/manipulating vectors. * * COPYRIGHT: (C) 2001 by the GRASS Development Team * * This program is free software under the GNU General Public * License (>=v2). Read the file COPYING that comes with GRASS * for details. * *****************************************************************************/ #include #define ZERO(x) ((x) < tolerance && (x) > -tolerance) #define TOLERANCE 1.0e-10 static double tolerance = TOLERANCE; int dig_set_distance_to_line_tolerance(double t) { if (t <= 0.0) t = TOLERANCE; tolerance = t; return 0; } /* * dig_distance2_point_to_line () * compute square of distance of point (x,y) to line segment (x1,y1 - x2,y2) * ( works correctly for x1==x2 && y1==y2 ) * * returns: square distance * sets (if not NULL): *px, *py - nearest point on segment * *pdist - distance of px,py from segment start * *status = 0 if ok, -1 if t < 0 and 1 if t > 1 * (tells if point is w/in segment space, or past ends) */ double dig_distance2_point_to_line(double x, double y, double z, /* point */ double x1, double y1, double z1, /* line segment */ double x2, double y2, double z2, int with_z, /* use z coordinate, (3D calculation) */ double *px, double *py, double *pz, /* point on segment */ double *pdist, /* distance of point on segment from the first point of segment */ int *status) { register double dx, dy, dz; register double dpx, dpy, dpz; register double tpx, tpy, tpz; double t; int st; st = 0; if (!with_z) { z = 0; z1 = 0; z2 = 0; } dx = x2 - x1; dy = y2 - y1; dz = z2 - z1; if (ZERO(dx) && ZERO(dy) && ZERO(dz)) { /* line is degenerate */ dx = x1 - x; dy = y1 - y; dz = z1 - z; tpx = x1; tpy = y1; tpz = z1; } else { t = (dx * (x - x1) + dy * (y - y1) + dz * (z - z1)) / (dx * dx + dy * dy + dz * dz); if (t <= 0.0) { /* go to x1,y1,z1 */ if (t < 0.0) { st = -1; } tpx = x1; tpy = y1; tpz = z1; } else if (t >= 1.0) { /* go to x2,y2,z2 */ if (t > 1.0) { st = 1; } tpx = x2; tpy = y2; tpz = z2; } else { /* go t from x1,y1,z1 towards x2,y2,z2 */ tpx = dx * t + x1; tpy = dy * t + y1; tpz = dz * t + z1; } dx = tpx - x; dy = tpy - y; dz = tpz - z; } if (px) *px = tpx; if (py) *py = tpy; if (pz) *pz = tpz; if (status) *status = st; if (pdist) { dpx = tpx - x1; dpy = tpy - y1; dpz = tpz - z1; *pdist = sqrt(dpx * dpx + dpy * dpy + dpz * dpz); } return (dx * dx + dy * dy + dz * dz); }