line_dist.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /*
  2. ****************************************************************************
  3. *
  4. * MODULE: Vector library
  5. *
  6. * AUTHOR(S): Original author CERL, probably Dave Gerdes.
  7. * Update to GRASS 5.7 Radim Blazek.
  8. *
  9. * PURPOSE: Lower level functions for reading/writing/manipulating vectors.
  10. *
  11. * COPYRIGHT: (C) 2001 by the GRASS Development Team
  12. *
  13. * This program is free software under the GNU General Public
  14. * License (>=v2). Read the file COPYING that comes with GRASS
  15. * for details.
  16. *
  17. *****************************************************************************/
  18. #include <math.h>
  19. #define ZERO(x) ((x) < tolerance && (x) > -tolerance)
  20. #define TOLERANCE 1.0e-10
  21. static double tolerance = TOLERANCE;
  22. int dig_set_distance_to_line_tolerance(double t)
  23. {
  24. if (t <= 0.0)
  25. t = TOLERANCE;
  26. tolerance = t;
  27. return 0;
  28. }
  29. /*
  30. * dig_distance2_point_to_line ()
  31. * compute square of distance of point (x,y) to line segment (x1,y1 - x2,y2)
  32. * ( works correctly for x1==x2 && y1==y2 )
  33. *
  34. * returns: square distance
  35. * sets (if not NULL): *px, *py - nearest point on segment
  36. * *pdist - distance of px,py from segment start
  37. * *status = 0 if ok, -1 if t < 0 and 1 if t > 1
  38. * (tells if point is w/in segment space, or past ends)
  39. */
  40. double dig_distance2_point_to_line(double x, double y, double z, /* point */
  41. double x1, double y1, double z1, /* line segment */
  42. double x2, double y2, double z2, int with_z, /* use z coordinate, (3D calculation) */
  43. double *px, double *py, double *pz, /* point on segment */
  44. double *pdist, /* distance of point on segment from the first point of segment */
  45. int *status)
  46. {
  47. register double dx, dy, dz;
  48. register double dpx, dpy, dpz;
  49. register double tpx, tpy, tpz;
  50. double t;
  51. int st;
  52. st = 0;
  53. if (!with_z) {
  54. z = 0;
  55. z1 = 0;
  56. z2 = 0;
  57. }
  58. dx = x2 - x1;
  59. dy = y2 - y1;
  60. dz = z2 - z1;
  61. if (ZERO(dx) && ZERO(dy) && ZERO(dz)) { /* line is degenerate */
  62. dx = x1 - x;
  63. dy = y1 - y;
  64. dz = z1 - z;
  65. tpx = x1;
  66. tpy = y1;
  67. tpz = z1;
  68. }
  69. else {
  70. t = (dx * (x - x1) + dy * (y - y1) + dz * (z - z1)) / (dx * dx +
  71. dy * dy +
  72. dz * dz);
  73. if (t < 0.0) { /* go to x1,y1,z1 */
  74. t = 0.0;
  75. st = -1;
  76. }
  77. else if (t > 1.0) { /* go to x2,y2,z2 */
  78. t = 1.0;
  79. st = 1;
  80. }
  81. /* go t from x1,y1,z1 towards x2,y2,z2 */
  82. tpx = dx * t + x1;
  83. tpy = dy * t + y1;
  84. tpz = dz * t + z1;
  85. dx = tpx - x;
  86. dy = tpy - y;
  87. dz = tpz - z;
  88. }
  89. if (px)
  90. *px = tpx;
  91. if (py)
  92. *py = tpy;
  93. if (pz)
  94. *pz = tpz;
  95. if (status)
  96. *status = st;
  97. if (pdist) {
  98. dpx = tpx - x1;
  99. dpy = tpy - y1;
  100. dpz = tpz - z1;
  101. *pdist = sqrt(dpx * dpx + dpy * dpy + dpz * dpz);
  102. }
  103. return (dx * dx + dy * dy + dz * dz);
  104. }