shape_diameter_function.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2017 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 "shape_diameter_function.h"
  9. #include "random_dir.h"
  10. #include "barycenter.h"
  11. #include "ray_mesh_intersect.h"
  12. #include "per_vertex_normals.h"
  13. #include "PlainMatrix.h"
  14. #include "per_face_normals.h"
  15. #include "EPS.h"
  16. #include "Hit.h"
  17. #include "parallel_for.h"
  18. #include <functional>
  19. #include <vector>
  20. #include <algorithm>
  21. template <
  22. typename DerivedP,
  23. typename DerivedN,
  24. typename DerivedS >
  25. IGL_INLINE void igl::shape_diameter_function(
  26. const std::function<
  27. typename DerivedP::Scalar(
  28. const Eigen::Matrix<typename DerivedP::Scalar,3,1> &,
  29. const Eigen::Matrix<typename DerivedP::Scalar,3,1> &)
  30. > & shoot_ray,
  31. const Eigen::MatrixBase<DerivedP> & P,
  32. const Eigen::MatrixBase<DerivedN> & N,
  33. const int num_samples,
  34. Eigen::PlainObjectBase<DerivedS> & S)
  35. {
  36. using Scalar = typename DerivedP::Scalar;
  37. using Vector3S = Eigen::Matrix<typename DerivedP::Scalar,3,1>;
  38. const int n = P.rows();
  39. // Resize output
  40. S.resize(n,1);
  41. // Embree seems to be parallel when constructing but not when tracing rays
  42. const Eigen::Matrix<Scalar,Eigen::Dynamic,3> D = random_dir_stratified(num_samples).cast<Scalar>();
  43. const auto & inner = [&P,&N,&num_samples,&D,&S,&shoot_ray](const int p)
  44. {
  45. const Vector3S origin = P.row(p);
  46. const Vector3S normal = N.row(p);
  47. int num_hits = 0;
  48. double total_distance = 0;
  49. for(int s = 0;s<num_samples;s++)
  50. {
  51. Vector3S d = D.row(s);
  52. // Shoot _inward_
  53. if(d.dot(normal) > 0)
  54. {
  55. // reverse ray
  56. d *= -1;
  57. }
  58. const double dist = shoot_ray(origin,d);
  59. if(std::isfinite(dist))
  60. {
  61. total_distance += dist;
  62. num_hits++;
  63. }
  64. }
  65. S(p) = total_distance/(double)num_hits;
  66. };
  67. parallel_for(n,inner,1000);
  68. }
  69. template <
  70. typename DerivedV,
  71. int DIM,
  72. typename DerivedF,
  73. typename DerivedP,
  74. typename DerivedN,
  75. typename DerivedS >
  76. IGL_INLINE void igl::shape_diameter_function(
  77. const igl::AABB<DerivedV,DIM> & aabb,
  78. const Eigen::MatrixBase<DerivedV> & V,
  79. const Eigen::MatrixBase<DerivedF> & F,
  80. const Eigen::MatrixBase<DerivedP> & P,
  81. const Eigen::MatrixBase<DerivedN> & N,
  82. const int num_samples,
  83. Eigen::PlainObjectBase<DerivedS> & S)
  84. {
  85. using Scalar = typename DerivedP::Scalar;
  86. using Vector3S = Eigen::Matrix<typename DerivedP::Scalar,3,1>;
  87. const auto & shoot_ray = [&aabb,&V,&F](
  88. const Vector3S& _s,
  89. const Vector3S& dir)->double
  90. {
  91. Vector3S s = _s+1e-4*dir;
  92. igl::Hit<Scalar> hit;
  93. if(aabb.intersect_ray(
  94. V,
  95. F,
  96. s ,
  97. dir,
  98. hit))
  99. {
  100. return hit.t;
  101. }else
  102. {
  103. return std::numeric_limits<double>::infinity();
  104. }
  105. };
  106. return shape_diameter_function(shoot_ray,P,N,num_samples,S);
  107. }
  108. template <
  109. typename DerivedV,
  110. typename DerivedF,
  111. typename DerivedP,
  112. typename DerivedN,
  113. typename DerivedS >
  114. IGL_INLINE void igl::shape_diameter_function(
  115. const Eigen::MatrixBase<DerivedV> & V,
  116. const Eigen::MatrixBase<DerivedF> & F,
  117. const Eigen::MatrixBase<DerivedP> & P,
  118. const Eigen::MatrixBase<DerivedN> & N,
  119. const int num_samples,
  120. Eigen::PlainObjectBase<DerivedS> & S)
  121. {
  122. using Scalar = typename DerivedP::Scalar;
  123. using Vector3S = Eigen::Matrix<typename DerivedP::Scalar,3,1>;
  124. if(F.rows() < 100)
  125. {
  126. // Super naive
  127. const auto & shoot_ray = [&V,&F](
  128. const Vector3S& _s,
  129. const Vector3S& dir)->double
  130. {
  131. Vector3S s = _s+1e-4*dir;
  132. igl::Hit<Scalar> hit;
  133. if(ray_mesh_intersect(s,dir,V,F,hit))
  134. {
  135. return hit.t;
  136. }else
  137. {
  138. return std::numeric_limits<double>::infinity();
  139. }
  140. };
  141. return shape_diameter_function(shoot_ray,P,N,num_samples,S);
  142. }
  143. AABB<DerivedV,3> aabb;
  144. aabb.init(V,F);
  145. return shape_diameter_function(aabb,V,F,P,N,num_samples,S);
  146. }
  147. template <
  148. typename DerivedV,
  149. typename DerivedF,
  150. typename DerivedS>
  151. IGL_INLINE void igl::shape_diameter_function(
  152. const Eigen::MatrixBase<DerivedV> & V,
  153. const Eigen::MatrixBase<DerivedF> & F,
  154. const bool per_face,
  155. const int num_samples,
  156. Eigen::PlainObjectBase<DerivedS> & S)
  157. {
  158. if (per_face)
  159. {
  160. PlainMatrix<DerivedV> N;
  161. igl::per_face_normals(V, F, N);
  162. PlainMatrix<DerivedV> P;
  163. igl::barycenter(V, F, P);
  164. return igl::shape_diameter_function(V, F, P, N, num_samples, S);
  165. }
  166. else
  167. {
  168. PlainMatrix<DerivedV> N;
  169. igl::per_vertex_normals(V, F, N);
  170. return igl::shape_diameter_function(V, F, V, N, num_samples, S);
  171. }
  172. }
  173. #ifdef IGL_STATIC_LIBRARY
  174. // Explicit template instantiation
  175. template void igl::shape_diameter_function<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::function<double (Eigen::Matrix<double, 3, 1, 0, 3, 1> const&, Eigen::Matrix<double, 3, 1, 0, 3, 1> const&)> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
  176. template void igl::shape_diameter_function<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::function<double (Eigen::Matrix<double, 3, 1, 0, 3, 1> const&, Eigen::Matrix<double, 3, 1, 0, 3, 1> const&)> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
  177. template void igl::shape_diameter_function<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::function<double (Eigen::Matrix<double, 3, 1, 0, 3, 1> const&, Eigen::Matrix<double, 3, 1, 0, 3, 1> const&)> const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
  178. template void igl::shape_diameter_function<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(std::function<double (Eigen::Matrix<double, 3, 1, 0, 3, 1> const&, Eigen::Matrix<double, 3, 1, 0, 3, 1> const&)> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
  179. template void igl::shape_diameter_function<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -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<int, -1, -1, 0, -1, -1> > const&, bool, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
  180. #endif