line_dist.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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)) /
  71. (dx * dx + dy * dy + dz * dz);
  72. if (t <= 0.0) { /* go to x1,y1,z1 */
  73. if (t < 0.0) {
  74. st = -1;
  75. }
  76. tpx = x1;
  77. tpy = y1;
  78. tpz = z1;
  79. }
  80. else if (t >= 1.0) { /* go to x2,y2,z2 */
  81. if (t > 1.0) {
  82. st = 1;
  83. }
  84. tpx = x2;
  85. tpy = y2;
  86. tpz = z2;
  87. }
  88. else {
  89. /* go t from x1,y1,z1 towards x2,y2,z2 */
  90. tpx = dx * t + x1;
  91. tpy = dy * t + y1;
  92. tpz = dz * t + z1;
  93. }
  94. dx = tpx - x;
  95. dy = tpy - y;
  96. dz = tpz - z;
  97. }
  98. if (px)
  99. *px = tpx;
  100. if (py)
  101. *py = tpy;
  102. if (pz)
  103. *pz = tpz;
  104. if (status)
  105. *status = st;
  106. if (pdist) {
  107. dpx = tpx - x1;
  108. dpy = tpy - y1;
  109. dpz = tpz - z1;
  110. *pdist = sqrt(dpx * dpx + dpy * dpy + dpz * dpz);
  111. }
  112. return (dx * dx + dy * dy + dz * dz);
  113. }