point_simplex_squared_distance.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2016 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 "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. typedef typename Derivedp::Scalar Scalar;
  32. typedef typename Eigen::Matrix<Scalar,1,DIM> Vector;
  33. typedef Vector Point;
  34. typedef Eigen::PlainObjectBase<Derivedb> BaryPoint;
  35. const auto & Dot = [](const Point & a, const Point & b)->Scalar
  36. {
  37. return a.dot(b);
  38. };
  39. // Real-time collision detection, Ericson, Chapter 5
  40. const auto & ClosestBaryPtPointTriangle =
  41. [&Dot](Point p, Point a, Point b, Point c, BaryPoint& bary_out )->Point
  42. {
  43. // Check if P in vertex region outside A
  44. Vector ab = b - a;
  45. Vector ac = c - a;
  46. Vector ap = p - a;
  47. Scalar d1 = Dot(ab, ap);
  48. Scalar d2 = Dot(ac, ap);
  49. if (d1 <= 0.0 && d2 <= 0.0) {
  50. // barycentric coordinates (1,0,0)
  51. bary_out << 1, 0, 0;
  52. return a;
  53. }
  54. // Check if P in vertex region outside B
  55. Vector bp = p - b;
  56. Scalar d3 = Dot(ab, bp);
  57. Scalar d4 = Dot(ac, bp);
  58. if (d3 >= 0.0 && d4 <= d3) {
  59. // barycentric coordinates (0,1,0)
  60. bary_out << 0, 1, 0;
  61. return b;
  62. }
  63. // Check if P in edge region of AB, if so return projection of P onto AB
  64. Scalar vc = d1*d4 - d3*d2;
  65. if( a != b)
  66. {
  67. if (vc <= 0.0 && d1 >= 0.0 && d3 <= 0.0) {
  68. Scalar v = d1 / (d1 - d3);
  69. // barycentric coordinates (1-v,v,0)
  70. bary_out << 1-v, v, 0;
  71. return a + v * ab;
  72. }
  73. }
  74. // Check if P in vertex region outside C
  75. Vector cp = p - c;
  76. Scalar d5 = Dot(ab, cp);
  77. Scalar d6 = Dot(ac, cp);
  78. if (d6 >= 0.0 && d5 <= d6) {
  79. // barycentric coordinates (0,0,1)
  80. bary_out << 0, 0, 1;
  81. return c;
  82. }
  83. // Check if P in edge region of AC, if so return projection of P onto AC
  84. Scalar vb = d5*d2 - d1*d6;
  85. if (vb <= 0.0 && d2 >= 0.0 && d6 <= 0.0) {
  86. Scalar w = d2 / (d2 - d6);
  87. // barycentric coordinates (1-w,0,w)
  88. bary_out << 1-w, 0, w;
  89. return a + w * ac;
  90. }
  91. // Check if P in edge region of BC, if so return projection of P onto BC
  92. Scalar va = d3*d6 - d5*d4;
  93. if (va <= 0.0 && (d4 - d3) >= 0.0 && (d5 - d6) >= 0.0) {
  94. Scalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
  95. // barycentric coordinates (0,1-w,w)
  96. bary_out << 0, 1-w, w;
  97. return b + w * (c - b);
  98. }
  99. // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
  100. Scalar denom = 1.0 / (va + vb + vc);
  101. Scalar v = vb * denom;
  102. Scalar w = vc * denom;
  103. bary_out << 1.0-v-w, v, w;
  104. return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = 1.0-v-w
  105. };
  106. assert(p.size() == DIM);
  107. assert(V.cols() == DIM);
  108. assert(Ele.cols() <= DIM+1);
  109. assert(Ele.cols() <= 3 && "Only simplices up to triangles are considered");
  110. assert((Derivedb::RowsAtCompileTime == 1 || Derivedb::ColsAtCompileTime == 1) && "bary must be Eigen Vector or Eigen RowVector");
  111. bary.resize( Derivedb::RowsAtCompileTime == 1 ? 1 : DIM, Derivedb::ColsAtCompileTime == 1 ? 1 : DIM );
  112. c = ClosestBaryPtPointTriangle(
  113. p,
  114. V.row(Ele(primitive,0)),
  115. V.row(Ele(primitive,1%Ele.cols())),
  116. V.row(Ele(primitive,2%Ele.cols())),
  117. bary);
  118. sqr_d = (p-c).squaredNorm();
  119. }
  120. template <
  121. int DIM,
  122. typename Derivedp,
  123. typename DerivedV,
  124. typename DerivedEle,
  125. typename Derivedsqr_d,
  126. typename Derivedc>
  127. IGL_INLINE void igl::point_simplex_squared_distance(
  128. const Eigen::MatrixBase<Derivedp> & p,
  129. const Eigen::MatrixBase<DerivedV> & V,
  130. const Eigen::MatrixBase<DerivedEle> & Ele,
  131. const typename DerivedEle::Index primitive,
  132. Derivedsqr_d & sqr_d,
  133. Eigen::PlainObjectBase<Derivedc> & c)
  134. {
  135. Eigen::PlainObjectBase<Derivedc> b;
  136. point_simplex_squared_distance<DIM>( p, V, Ele, primitive, sqr_d, c, b );
  137. }
  138. #ifdef IGL_STATIC_LIBRARY
  139. // Explicit template instanciation
  140. 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> >&);
  141. 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> >&);
  142. 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> >&);
  143. 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> >&);
  144. 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> >&);
  145. 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> >&);
  146. #endif