line_dist.c

Go to the documentation of this file.
00001 /*
00002 * $Id: line_dist.c,v 1.8 2003/09/11 16:12:48 markus Exp $
00003 *
00004 ****************************************************************************
00005 *
00006 * MODULE:       Vector library 
00007 *               
00008 * AUTHOR(S):    Original author CERL, probably Dave Gerdes.
00009 *               Update to GRASS 5.7 Radim Blazek.
00010 *
00011 * PURPOSE:      Lower level functions for reading/writing/manipulating vectors.
00012 *
00013 * COPYRIGHT:    (C) 2001 by the GRASS Development Team
00014 *
00015 *               This program is free software under the GNU General Public
00016 *               License (>=v2). Read the file COPYING that comes with GRASS
00017 *               for details.
00018 *
00019 *****************************************************************************/
00020 #include    <math.h>
00021 
00022 #define ZERO(x) ((x) < tolerance && (x) > -tolerance)
00023 #define TOLERANCE 1.0e-10
00024 static double tolerance = TOLERANCE;
00025 
00026 int 
00027 dig_set_distance_to_line_tolerance (double t)
00028 {
00029   if (t <= 0.0)
00030     t = TOLERANCE;
00031   tolerance = t;
00032 
00033   return 0;
00034 }
00035 
00036 /*
00037 *   dig_distance2_point_to_line ()
00038 *   compute square of distance of point (x,y) to line segment (x1,y1 - x2,y2)
00039 *   ( works correctly for  x1==x2 && y1==y2 )
00040 *
00041 *   returns: square distance
00042 *   sets (if not NULL): *px, *py - nearest point on segment
00043 *                       *pdist - distance of px,py from segment start
00044 *                       *status = 0 if ok, -1 if t < 0  and 1 if t > 1
00045 *                                 (tells if point is w/in segment space, or past ends)
00046 */
00047 
00048 double 
00049 dig_distance2_point_to_line ( 
00050         double x, double y, double z,       /* point */
00051         double x1, double y1, double z1,    /* line segment */
00052         double x2, double y2, double z2,        
00053         int with_z, /* use z coordinate, (3D calculation) */ 
00054         double *px, double *py, double *pz, /* point on segment */
00055         double *pdist, /* distance of point on segment from the first point of segment */
00056         int *status)
00057 {
00058     register double dx, dy, dz;
00059     register double dpx, dpy, dpz;
00060     register double tpx, tpy, tpz;
00061     double t;
00062     int    st;
00063 
00064     st = 0;
00065 
00066     if ( !with_z ) {
00067        z = 0;
00068        z1 = 0;
00069        z2 = 0;
00070     }       
00071     
00072     dx = x2 - x1;
00073     dy = y2 - y1;
00074     dz = z2 - z1;
00075 
00076     if (ZERO (dx) && ZERO (dy) && ZERO (dz) )   { /* line is degenerate */
00077       dx = x1 - x;
00078       dy = y1 - y;
00079       dz = z1 - z;
00080       tpx = x1;
00081       tpy = y1;
00082       tpz = z1;
00083     } else {
00084         t = (dx * (x - x1) + dy * (y - y1) + dz * (z - z1)) / (dx * dx + dy * dy + dz * dz);
00085 
00086         if (t < 0.0) {                  /* go to x1,y1,z1 */
00087             t = 0.0;
00088             st = -1;
00089         } else if (t > 1.0) {           /* go to x2,y2,z2 */
00090             t = 1.0;
00091             st = 1;
00092         }
00093     
00094         /* go t from x1,y1,z1 towards x2,y2,z2 */
00095         tpx = dx * t + x1;
00096         tpy = dy * t + y1;
00097         tpz = dz * t + z1;
00098         dx = tpx - x;
00099         dy = tpy - y;
00100         dz = tpz - z;
00101     }
00102 
00103     if ( px ) *px = tpx;
00104     if ( py ) *py = tpy;
00105     if ( pz ) *pz = tpz;
00106     if ( status ) *status = st;
00107 
00108     if ( pdist ) {
00109         dpx = tpx - x1;
00110         dpy = tpy - y1;
00111         dpz = tpz - z1;
00112         *pdist = sqrt ( dpx * dpx + dpy * dpy + dpz * dpz ); 
00113     }
00114    
00115     return (dx * dx + dy * dy + dz * dz);
00116 }
00117 

Generated on Sun Apr 6 17:32:44 2008 for GRASS by  doxygen 1.5.5