project_to_line.cpp 5.4 KB

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