project_to_line.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  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. int dim = P.cols();
  19. assert(dim == S.size());
  20. assert(dim == D.size());
  21. // number of points
  22. int np = P.rows();
  23. // vector from source to destination
  24. MatL DmS = D-S;
  25. double v_sqrlen = (double)(DmS.array().pow(2).sum());
  26. assert(v_sqrlen != 0);
  27. // resize output
  28. t.resize(np,1);
  29. sqrD.resize(np,1);
  30. // loop over points
  31. for(int i = 0;i<np;i++)
  32. {
  33. MatL Pi = P.row(i);
  34. // vector from point i to source
  35. MatL SmPi = S-Pi;
  36. t(i) = -(DmS.array()*SmPi.array()).sum() / v_sqrlen;
  37. // P projected onto line
  38. MatL projP = (1-t(i))*S + t(i)*D;
  39. sqrD(i) = (Pi-projP).array().pow(2).sum();
  40. }
  41. }
  42. template <typename Scalar>
  43. IGL_INLINE void igl::project_to_line(
  44. const Scalar px,
  45. const Scalar py,
  46. const Scalar pz,
  47. const Scalar sx,
  48. const Scalar sy,
  49. const Scalar sz,
  50. const Scalar dx,
  51. const Scalar dy,
  52. const Scalar dz,
  53. Scalar & t,
  54. Scalar & sqrd)
  55. {
  56. // vector from source to destination
  57. Scalar dms[3];
  58. dms[0] = dx-sx;
  59. dms[1] = dy-sy;
  60. dms[2] = dz-sz;
  61. Scalar v_sqrlen = dms[0]*dms[0] + dms[1]*dms[1] + dms[2]*dms[2];
  62. // line should have some length
  63. assert(v_sqrlen != 0);
  64. // vector from point to source
  65. Scalar smp[3];
  66. smp[0] = sx-px;
  67. smp[1] = sy-py;
  68. smp[2] = sz-pz;
  69. t = -(dms[0]*smp[0]+dms[1]*smp[1]+dms[2]*smp[2])/v_sqrlen;
  70. // P projectred onto line
  71. Scalar projp[3];
  72. projp[0] = (1.0-t)*sx + t*dx;
  73. projp[1] = (1.0-t)*sy + t*dy;
  74. projp[2] = (1.0-t)*sz + t*dz;
  75. // vector from projected point to p
  76. Scalar pmprojp[3];
  77. pmprojp[0] = px-projp[0];
  78. pmprojp[1] = py-projp[1];
  79. pmprojp[2] = pz-projp[2];
  80. sqrd = pmprojp[0]*pmprojp[0] + pmprojp[1]*pmprojp[1] + pmprojp[2]*pmprojp[2];
  81. }
  82. #ifndef IGL_HEADER_ONLY
  83. // Explicit template specialization
  84. 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>&);
  85. template void igl::project_to_line<double>(double, double, double, double, double, double, double, double, double, double&, double&);
  86. #endif