project_to_line.cpp 2.6 KB

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