point_mesh_squared_distance.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2014 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_mesh_squared_distance.h"
  9. #include "mesh_to_cgal_triangle_list.h"
  10. template <typename Kernel>
  11. IGL_INLINE void igl::cgal::point_mesh_squared_distance(
  12. const Eigen::MatrixXd & P,
  13. const Eigen::MatrixXd & V,
  14. const Eigen::MatrixXi & F,
  15. Eigen::VectorXd & sqrD,
  16. Eigen::VectorXi & I,
  17. Eigen::MatrixXd & C)
  18. {
  19. using namespace std;
  20. typedef CGAL::Triangle_3<Kernel> Triangle_3;
  21. typedef typename std::vector<Triangle_3>::iterator Iterator;
  22. typedef CGAL::AABB_triangle_primitive<Kernel, Iterator> Primitive;
  23. typedef CGAL::AABB_traits<Kernel, Primitive> AABB_triangle_traits;
  24. typedef CGAL::AABB_tree<AABB_triangle_traits> Tree;
  25. Tree tree;
  26. vector<Triangle_3> T;
  27. point_mesh_squared_distance_precompute(V,F,tree,T);
  28. return point_mesh_squared_distance(P,tree,T,sqrD,I,C);
  29. }
  30. template <typename Kernel>
  31. IGL_INLINE void igl::cgal::point_mesh_squared_distance_precompute(
  32. const Eigen::MatrixXd & V,
  33. const Eigen::MatrixXi & F,
  34. CGAL::AABB_tree<
  35. CGAL::AABB_traits<Kernel,
  36. CGAL::AABB_triangle_primitive<Kernel,
  37. typename std::vector<CGAL::Triangle_3<Kernel> >::iterator
  38. >
  39. >
  40. > & tree,
  41. std::vector<CGAL::Triangle_3<Kernel> > & T)
  42. {
  43. using namespace std;
  44. typedef CGAL::Triangle_3<Kernel> Triangle_3;
  45. typedef CGAL::Point_3<Kernel> Point_3;
  46. typedef typename std::vector<Triangle_3>::iterator Iterator;
  47. typedef CGAL::AABB_triangle_primitive<Kernel, Iterator> Primitive;
  48. typedef CGAL::AABB_traits<Kernel, Primitive> AABB_triangle_traits;
  49. typedef CGAL::AABB_tree<AABB_triangle_traits> Tree;
  50. // Must be 3D
  51. assert(V.cols() == 3);
  52. // Must be triangles
  53. assert(F.cols() == 3);
  54. // WTF ALERT!!!!
  55. //
  56. // There's a bug in clang probably or at least in cgal. Without calling this
  57. // line (I guess invoking some compilation from <vector>), clang will vomit
  58. // errors inside CGAL.
  59. //
  60. // http://stackoverflow.com/questions/27748442/is-clangs-c11-support-reliable
  61. T.reserve(0);
  62. // Make list of cgal triangles
  63. mesh_to_cgal_triangle_list(V,F,T);
  64. tree.clear();
  65. tree.insert(T.begin(),T.end());
  66. tree.accelerate_distance_queries();
  67. // accelerate_distance_queries doesn't seem actually to do _all_ of the
  68. // precomputation. the tree (despite being const) will still do more
  69. // precomputation and reorganizing on the first call of `closest_point` or
  70. // `closest_point_and_primitive`. Therefor, call it once here.
  71. tree.closest_point_and_primitive(Point_3(0,0,0));
  72. }
  73. template <typename Kernel>
  74. IGL_INLINE void igl::cgal::point_mesh_squared_distance(
  75. const Eigen::MatrixXd & P,
  76. const CGAL::AABB_tree<
  77. CGAL::AABB_traits<Kernel,
  78. CGAL::AABB_triangle_primitive<Kernel,
  79. typename std::vector<CGAL::Triangle_3<Kernel> >::iterator
  80. >
  81. >
  82. > & tree,
  83. const std::vector<CGAL::Triangle_3<Kernel> > & T,
  84. Eigen::VectorXd & sqrD,
  85. Eigen::VectorXi & I,
  86. Eigen::MatrixXd & C)
  87. {
  88. typedef CGAL::Triangle_3<Kernel> Triangle_3;
  89. typedef typename std::vector<Triangle_3>::iterator Iterator;
  90. typedef CGAL::AABB_triangle_primitive<Kernel, Iterator> Primitive;
  91. typedef CGAL::AABB_traits<Kernel, Primitive> AABB_triangle_traits;
  92. typedef CGAL::AABB_tree<AABB_triangle_traits> Tree;
  93. typedef typename Tree::Point_and_primitive_id Point_and_primitive_id;
  94. typedef CGAL::Point_3<Kernel> Point_3;
  95. assert(P.cols() == 3);
  96. const int n = P.rows();
  97. sqrD.resize(n,1);
  98. I.resize(n,1);
  99. C.resize(n,P.cols());
  100. for(int p = 0;p < n;p++)
  101. {
  102. Point_3 query(P(p,0),P(p,1),P(p,2));
  103. // Find closest point and primitive id
  104. Point_and_primitive_id pp = tree.closest_point_and_primitive(query);
  105. Point_3 closest_point = pp.first;
  106. C(p,0) = CGAL::to_double(closest_point[0]);
  107. C(p,1) = CGAL::to_double(closest_point[1]);
  108. C(p,2) = CGAL::to_double(closest_point[2]);
  109. sqrD(p) = CGAL::to_double((closest_point-query).squared_length());
  110. I(p) = pp.second - T.begin();
  111. }
  112. }
  113. #ifdef IGL_STATIC_LIBRARY
  114. // Explicit template specialization
  115. template void igl::cgal::point_mesh_squared_distance_precompute<CGAL::Epick>(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, CGAL::AABB_tree<CGAL::AABB_traits<CGAL::Epick, CGAL::AABB_triangle_primitive<CGAL::Epick, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > >::iterator, CGAL::Boolean_tag<false> > > >&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > >&);
  116. template void igl::cgal::point_mesh_squared_distance<CGAL::Epeck>( const Eigen::MatrixXd & P, const Eigen::MatrixXd & V, const Eigen::MatrixXi & F, Eigen::VectorXd & sqrD, Eigen::VectorXi & I, Eigen::MatrixXd & C);
  117. template void igl::cgal::point_mesh_squared_distance<CGAL::Epick>(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1>&, Eigen::Matrix<int, -1, 1, 0, -1, 1>&, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
  118. template void igl::cgal::point_mesh_squared_distance<CGAL::Simple_cartesian<double> >(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1>&, Eigen::Matrix<int, -1, 1, 0, -1, 1>&, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
  119. #endif