project_to_line.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #include "project_to_line.h"
  2. #include <cassert>
  3. #include <Eigen/Core>
  4. template <
  5. typename MatP,
  6. typename MatL,
  7. typename Matt,
  8. typename MatsqrD>
  9. IGL_INLINE void igl::project_to_line(
  10. const MatP & P,
  11. const MatL & S,
  12. const MatL & D,
  13. Matt & t,
  14. MatsqrD & sqrD)
  15. {
  16. // http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
  17. // number of dimensions
  18. #ifndef NDEBUG
  19. int dim = P.cols();
  20. assert(dim == S.size());
  21. assert(dim == D.size());
  22. #endif
  23. // number of points
  24. int np = P.rows();
  25. // vector from source to destination
  26. MatL DmS = D-S;
  27. double v_sqrlen = (double)(DmS.array().pow(2).sum());
  28. assert(v_sqrlen != 0);
  29. // resize output
  30. t.resize(np,1);
  31. sqrD.resize(np,1);
  32. // loop over points
  33. #pragma omp parallel for
  34. for(int i = 0;i<np;i++)
  35. {
  36. MatL Pi = P.row(i);
  37. // vector from point i to source
  38. MatL SmPi = S-Pi;
  39. t(i) = -(DmS.array()*SmPi.array()).sum() / v_sqrlen;
  40. // P projected onto line
  41. MatL projP = (1-t(i))*S + t(i)*D;
  42. sqrD(i) = (Pi-projP).array().pow(2).sum();
  43. }
  44. }
  45. template <typename Scalar>
  46. IGL_INLINE void igl::project_to_line(
  47. const Scalar px,
  48. const Scalar py,
  49. const Scalar pz,
  50. const Scalar sx,
  51. const Scalar sy,
  52. const Scalar sz,
  53. const Scalar dx,
  54. const Scalar dy,
  55. const Scalar dz,
  56. Scalar & projpx,
  57. Scalar & projpy,
  58. Scalar & projpz,
  59. Scalar & t,
  60. Scalar & sqrd)
  61. {
  62. // vector from source to destination
  63. Scalar dms[3];
  64. dms[0] = dx-sx;
  65. dms[1] = dy-sy;
  66. dms[2] = dz-sz;
  67. Scalar v_sqrlen = dms[0]*dms[0] + dms[1]*dms[1] + dms[2]*dms[2];
  68. // line should have some length
  69. assert(v_sqrlen != 0);
  70. // vector from point to source
  71. Scalar smp[3];
  72. smp[0] = sx-px;
  73. smp[1] = sy-py;
  74. smp[2] = sz-pz;
  75. t = -(dms[0]*smp[0]+dms[1]*smp[1]+dms[2]*smp[2])/v_sqrlen;
  76. // P projectred onto line
  77. projpx = (1.0-t)*sx + t*dx;
  78. projpy = (1.0-t)*sy + t*dy;
  79. projpz = (1.0-t)*sz + t*dz;
  80. // vector from projected point to p
  81. Scalar pmprojp[3];
  82. pmprojp[0] = px-projpx;
  83. pmprojp[1] = py-projpy;
  84. pmprojp[2] = pz-projpz;
  85. sqrd = pmprojp[0]*pmprojp[0] + pmprojp[1]*pmprojp[1] + pmprojp[2]*pmprojp[2];
  86. }
  87. template <typename Scalar>
  88. IGL_INLINE void igl::project_to_line(
  89. const Scalar px,
  90. const Scalar py,
  91. const Scalar pz,
  92. const Scalar sx,
  93. const Scalar sy,
  94. const Scalar sz,
  95. const Scalar dx,
  96. const Scalar dy,
  97. const Scalar dz,
  98. Scalar & t,
  99. Scalar & sqrd)
  100. {
  101. Scalar projpx;
  102. Scalar projpy;
  103. Scalar projpz;
  104. return igl::project_to_line(
  105. px, py, pz, sx, sy, sz, dx, dy, dz,
  106. projpx, projpy, projpz, t, sqrd);
  107. }
  108. #ifndef IGL_HEADER_ONLY
  109. // Explicit template specialization
  110. template void igl::project_to_line<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1>&, Eigen::Matrix<double, -1, 1, 0, -1, 1>&);
  111. template void igl::project_to_line<double>(double, double, double, double, double, double, double, double, double, double&, double&);
  112. template void igl::project_to_line<double>(double, double, double, double, double, double, double, double, double, double&, double&,double&,double&, double&);
  113. #endif