project_to_line.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "project_to_line.h"
  9. #include <cassert>
  10. #include <Eigen/Core>
  11. template <
  12. typename DerivedP,
  13. typename DerivedS,
  14. typename DerivedD,
  15. typename Derivedt,
  16. typename DerivedsqrD>
  17. IGL_INLINE void igl::project_to_line(
  18. const Eigen::MatrixBase<DerivedP> & P,
  19. const Eigen::MatrixBase<DerivedS> & S,
  20. const Eigen::MatrixBase<DerivedD> & D,
  21. Eigen::PlainObjectBase<Derivedt> & t,
  22. Eigen::PlainObjectBase<DerivedsqrD> & sqrD)
  23. {
  24. // http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
  25. // number of dimensions
  26. #ifndef NDEBUG
  27. int dim = P.cols();
  28. assert(dim == S.size());
  29. assert(dim == D.size());
  30. #endif
  31. // number of points
  32. int np = P.rows();
  33. // vector from source to destination
  34. DerivedD DmS = D-S;
  35. double v_sqrlen = (double)(DmS.squaredNorm());
  36. assert(v_sqrlen != 0);
  37. // resize output
  38. t.resize(np,1);
  39. sqrD.resize(np,1);
  40. // loop over points
  41. #pragma omp parallel for if (np>10000)
  42. for(int i = 0;i<np;i++)
  43. {
  44. const typename DerivedP::ConstRowXpr Pi = P.row(i);
  45. // vector from point i to source
  46. const DerivedD SmPi = S-Pi;
  47. t(i) = -(DmS.array()*SmPi.array()).sum() / v_sqrlen;
  48. // P projected onto line
  49. const DerivedD projP = (1-t(i))*S + t(i)*D;
  50. sqrD(i) = (Pi-projP).squaredNorm();
  51. }
  52. }
  53. template <typename Scalar>
  54. IGL_INLINE void igl::project_to_line(
  55. const Scalar px,
  56. const Scalar py,
  57. const Scalar pz,
  58. const Scalar sx,
  59. const Scalar sy,
  60. const Scalar sz,
  61. const Scalar dx,
  62. const Scalar dy,
  63. const Scalar dz,
  64. Scalar & projpx,
  65. Scalar & projpy,
  66. Scalar & projpz,
  67. Scalar & t,
  68. Scalar & sqrd)
  69. {
  70. // vector from source to destination
  71. Scalar dms[3];
  72. dms[0] = dx-sx;
  73. dms[1] = dy-sy;
  74. dms[2] = dz-sz;
  75. Scalar v_sqrlen = dms[0]*dms[0] + dms[1]*dms[1] + dms[2]*dms[2];
  76. // line should have some length
  77. assert(v_sqrlen != 0);
  78. // vector from point to source
  79. Scalar smp[3];
  80. smp[0] = sx-px;
  81. smp[1] = sy-py;
  82. smp[2] = sz-pz;
  83. t = -(dms[0]*smp[0]+dms[1]*smp[1]+dms[2]*smp[2])/v_sqrlen;
  84. // P projectred onto line
  85. projpx = (1.0-t)*sx + t*dx;
  86. projpy = (1.0-t)*sy + t*dy;
  87. projpz = (1.0-t)*sz + t*dz;
  88. // vector from projected point to p
  89. Scalar pmprojp[3];
  90. pmprojp[0] = px-projpx;
  91. pmprojp[1] = py-projpy;
  92. pmprojp[2] = pz-projpz;
  93. sqrd = pmprojp[0]*pmprojp[0] + pmprojp[1]*pmprojp[1] + pmprojp[2]*pmprojp[2];
  94. }
  95. template <typename Scalar>
  96. IGL_INLINE void igl::project_to_line(
  97. const Scalar px,
  98. const Scalar py,
  99. const Scalar pz,
  100. const Scalar sx,
  101. const Scalar sy,
  102. const Scalar sz,
  103. const Scalar dx,
  104. const Scalar dy,
  105. const Scalar dz,
  106. Scalar & t,
  107. Scalar & sqrd)
  108. {
  109. Scalar projpx;
  110. Scalar projpy;
  111. Scalar projpz;
  112. return igl::project_to_line(
  113. px, py, pz, sx, sy, sz, dx, dy, dz,
  114. projpx, projpy, projpz, t, sqrd);
  115. }
  116. #ifdef IGL_STATIC_LIBRARY
  117. // Explicit template specialization
  118. // generated by autoexplicit.sh
  119. template void igl::project_to_line<Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, 1, 1, 0, 1, 1>, Eigen::Matrix<double, 1, 1, 0, 1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&);
  120. template void igl::project_to_line<double>(double, double, double, double, double, double, double, double, double, double&, double&);
  121. template void igl::project_to_line<double>(double, double, double, double, double, double, double, double, double, double&, double&,double&,double&, double&);
  122. template void igl::project_to_line<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 1, 0, 1, 1>, Eigen::Matrix<double, 1, 1, 0, 1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&);
  123. 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> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
  124. #endif