point_simplex_squared_distance.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2016 Alec Jacobson <[email protected]>
  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 "point_simplex_squared_distance.h"
  9. #include "project_to_line_segment.h"
  10. #include "barycentric_coordinates.h"
  11. #include <Eigen/Geometry>
  12. #include <limits>
  13. #include <cassert>
  14. template <
  15. int DIM,
  16. typename Derivedp,
  17. typename DerivedV,
  18. typename DerivedEle,
  19. typename Derivedsqr_d,
  20. typename Derivedc,
  21. typename Derivedb>
  22. IGL_INLINE void igl::point_simplex_squared_distance(
  23. const Eigen::MatrixBase<Derivedp> & p,
  24. const Eigen::MatrixBase<DerivedV> & V,
  25. const Eigen::MatrixBase<DerivedEle> & Ele,
  26. const typename DerivedEle::Index primitive,
  27. Derivedsqr_d & sqr_d,
  28. Eigen::PlainObjectBase<Derivedc> & c,
  29. Eigen::PlainObjectBase<Derivedb> & bary)
  30. {
  31. static_assert(DerivedV::ColsAtCompileTime == DIM || DerivedV::ColsAtCompileTime == Eigen::Dynamic,"DerivedV::ColsAtCompileTime == DIM || DerivedV::ColsAtCompileTime == Eigen::Dynamic");
  32. typedef typename Derivedp::Scalar Scalar;
  33. typedef typename Eigen::Matrix<Scalar,1,DIM> Vector;
  34. typedef Vector Point;
  35. //typedef Derivedb BaryPoint;
  36. typedef Eigen::Matrix<typename Derivedb::Scalar,1,3> BaryPoint;
  37. const auto & Dot = [](const Point & a, const Point & b)->Scalar
  38. {
  39. return a.dot(b);
  40. };
  41. // Real-time collision detection, Ericson, Chapter 5
  42. const auto & ClosestBaryPtPointTriangle =
  43. [&Dot](Point p, Point a, Point b, Point c, BaryPoint& bary_out )->Point
  44. {
  45. // Check if P in vertex region outside A
  46. Vector ab = b - a;
  47. Vector ac = c - a;
  48. Vector ap = p - a;
  49. Scalar d1 = Dot(ab, ap);
  50. Scalar d2 = Dot(ac, ap);
  51. if (d1 <= 0.0 && d2 <= 0.0) {
  52. // barycentric coordinates (1,0,0)
  53. bary_out << 1, 0, 0;
  54. return a;
  55. }
  56. // Check if P in vertex region outside B
  57. Vector bp = p - b;
  58. Scalar d3 = Dot(ab, bp);
  59. Scalar d4 = Dot(ac, bp);
  60. if (d3 >= 0.0 && d4 <= d3) {
  61. // barycentric coordinates (0,1,0)
  62. bary_out << 0, 1, 0;
  63. return b;
  64. }
  65. // Check if P in edge region of AB, if so return projection of P onto AB
  66. Scalar vc = d1*d4 - d3*d2;
  67. if( a != b)
  68. {
  69. if (vc <= 0.0 && d1 >= 0.0 && d3 <= 0.0) {
  70. Scalar v = d1 / (d1 - d3);
  71. // barycentric coordinates (1-v,v,0)
  72. bary_out << 1-v, v, 0;
  73. return a + v * ab;
  74. }
  75. }
  76. // Check if P in vertex region outside C
  77. Vector cp = p - c;
  78. Scalar d5 = Dot(ab, cp);
  79. Scalar d6 = Dot(ac, cp);
  80. if (d6 >= 0.0 && d5 <= d6) {
  81. // barycentric coordinates (0,0,1)
  82. bary_out << 0, 0, 1;
  83. return c;
  84. }
  85. // Check if P in edge region of AC, if so return projection of P onto AC
  86. Scalar vb = d5*d2 - d1*d6;
  87. if (vb <= 0.0 && d2 >= 0.0 && d6 <= 0.0) {
  88. Scalar w = d2 / (d2 - d6);
  89. // barycentric coordinates (1-w,0,w)
  90. bary_out << 1-w, 0, w;
  91. return a + w * ac;
  92. }
  93. // Check if P in edge region of BC, if so return projection of P onto BC
  94. Scalar va = d3*d6 - d5*d4;
  95. if (va <= 0.0 && (d4 - d3) >= 0.0 && (d5 - d6) >= 0.0) {
  96. Scalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
  97. // barycentric coordinates (0,1-w,w)
  98. bary_out << 0, 1-w, w;
  99. return b + w * (c - b);
  100. }
  101. // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
  102. Scalar denom = 1.0 / (va + vb + vc);
  103. Scalar v = vb * denom;
  104. Scalar w = vc * denom;
  105. bary_out << 1.0-v-w, v, w;
  106. return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = 1.0-v-w
  107. };
  108. assert(p.size() == DIM);
  109. assert(V.cols() == DIM);
  110. assert(Ele.cols() <= DIM+1);
  111. assert(Ele.cols() <= 3 && "Only simplices up to triangles are considered");
  112. assert((Derivedb::RowsAtCompileTime == 1 || Derivedb::ColsAtCompileTime == 1) && "bary must be Eigen Vector or Eigen RowVector");
  113. assert(
  114. ((Derivedb::RowsAtCompileTime == -1 || Derivedb::ColsAtCompileTime == -1) ||
  115. (Derivedb::RowsAtCompileTime == Ele.cols() || Derivedb::ColsAtCompileTime == Ele.cols())
  116. ) && "bary must be Dynamic or size of Ele.cols()");
  117. BaryPoint tmp_bary;
  118. c = (const Derivedc &)ClosestBaryPtPointTriangle(
  119. p,
  120. V.row(Ele(primitive,0)),
  121. // modulo is a HACK to handle points, segments and triangles. Because of
  122. // this, we need 3d buffer for bary
  123. V.row(Ele(primitive,1%Ele.cols())),
  124. V.row(Ele(primitive,2%Ele.cols())),
  125. tmp_bary);
  126. bary.resize( Derivedb::RowsAtCompileTime == 1 ? 1 : Ele.cols(), Derivedb::ColsAtCompileTime == 1 ? 1 : Ele.cols());
  127. bary.head(Ele.cols()) = tmp_bary.head(Ele.cols());
  128. sqr_d = (p-c).squaredNorm();
  129. }
  130. template <
  131. int DIM,
  132. typename Derivedp,
  133. typename DerivedV,
  134. typename DerivedEle,
  135. typename Derivedsqr_d,
  136. typename Derivedc>
  137. IGL_INLINE void igl::point_simplex_squared_distance(
  138. const Eigen::MatrixBase<Derivedp> & p,
  139. const Eigen::MatrixBase<DerivedV> & V,
  140. const Eigen::MatrixBase<DerivedEle> & Ele,
  141. const typename DerivedEle::Index primitive,
  142. Derivedsqr_d & sqr_d,
  143. Eigen::PlainObjectBase<Derivedc> & c)
  144. {
  145. // DerivedEle::ColsAtCompileTime will fallback to Eigen::Dynamic if unknown.
  146. Eigen::Matrix<typename Derivedc::Scalar,1,DerivedEle::ColsAtCompileTime> b;
  147. point_simplex_squared_distance<DIM>( p, V, Ele, primitive, sqr_d, c, b );
  148. }
  149. #ifdef IGL_STATIC_LIBRARY
  150. // Explicit template instantiation
  151. // generated by autoexplicit.sh
  152. template void igl::point_simplex_squared_distance<3, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
  153. // generated by autoexplicit.sh
  154. template void igl::point_simplex_squared_distance<2, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, double, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, Eigen::Matrix<int, -1, 2, 0, -1, 2>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&);
  155. template void igl::point_simplex_squared_distance<3, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(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<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
  156. template void igl::point_simplex_squared_distance<3, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(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<int, -1, 3, 1, -1, 3> > const&, Eigen::Matrix<int, -1, 3, 1, -1, 3>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
  157. template void igl::point_simplex_squared_distance<3, Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, float, Eigen::Matrix<float, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, float&, Eigen::PlainObjectBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> >&);
  158. template void igl::point_simplex_squared_distance<3, Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, float, Eigen::Matrix<float, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::Matrix<int, -1, 3, 1, -1, 3>::Index, float&, Eigen::PlainObjectBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> >&);
  159. template void igl::point_simplex_squared_distance<3, Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, float, Eigen::Matrix<float, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, float&, Eigen::PlainObjectBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> >&);
  160. template void igl::point_simplex_squared_distance<3, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
  161. template void igl::point_simplex_squared_distance<2, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&);
  162. template void igl::point_simplex_squared_distance<3, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
  163. template void igl::point_simplex_squared_distance<3, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 1, 1, 3> >&);
  164. template void igl::point_simplex_squared_distance<2, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&);
  165. template void igl::point_simplex_squared_distance<2, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 2, 1, 1, 1, 2> >&);
  166. template void igl::point_simplex_squared_distance<2, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, double, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&);
  167. template void igl::point_simplex_squared_distance<3, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
  168. #endif