WindingNumberAABB.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2014 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. // # MUTUAL DEPENDENCY ISSUE FOR HEADER ONLY VERSION
  9. // MUST INCLUDE winding_number.h first before guard:
  10. #include "winding_number.h"
  11. #ifndef IGL_WINDINGNUMBERAABB_H
  12. #define IGL_WINDINGNUMBERAABB_H
  13. #include "WindingNumberTree.h"
  14. #include "PlainMatrix.h"
  15. namespace igl
  16. {
  17. /// Class for building an AABB tree to implement the divide and conquer
  18. /// algorithm described in [Jacobson et al. 2013].
  19. template <
  20. typename Scalar,
  21. typename Index>
  22. class WindingNumberAABB : public WindingNumberTree<Scalar,Index>
  23. {
  24. protected:
  25. // WindingNumberTree defines Point
  26. using Point = typename WindingNumberTree<Scalar,Index>::Point;
  27. using MatrixXF = typename WindingNumberTree<Scalar,Index>::MatrixXF;
  28. Point min_corner;
  29. Point max_corner;
  30. Scalar total_positive_area;
  31. public:
  32. enum SplitMethod
  33. {
  34. CENTER_ON_LONGEST_AXIS = 0,
  35. MEDIAN_ON_LONGEST_AXIS = 1,
  36. NUM_SPLIT_METHODS = 2
  37. } split_method;
  38. public:
  39. inline WindingNumberAABB():
  40. total_positive_area(std::numeric_limits<Scalar>::infinity()),
  41. split_method(MEDIAN_ON_LONGEST_AXIS)
  42. {}
  43. /// Constructor
  44. ///
  45. /// @param[in] V #V by 3 list of vertex positions
  46. /// @param[in] F #F by 3 list of triangle indices into V
  47. template <typename DerivedV, typename DerivedF>
  48. inline WindingNumberAABB(
  49. const Eigen::MatrixBase<DerivedV> & V,
  50. const Eigen::MatrixBase<DerivedF> & F);
  51. inline WindingNumberAABB(
  52. const WindingNumberTree<Scalar,Index> & parent,
  53. const typename WindingNumberTree<Scalar,Index>::MatrixXF & F);
  54. /// Initialize the hierarchy to a given mesh
  55. ///
  56. /// @param[in] V #V by 3 list of vertex positions
  57. /// @param[in] F #F by 3 list of triangle indices into V
  58. template <typename DerivedV, typename DerivedF>
  59. inline void set_mesh(
  60. const Eigen::MatrixBase<DerivedV> & V,
  61. const Eigen::MatrixBase<DerivedF> & F);
  62. inline void init();
  63. inline bool inside(const Point & p) const;
  64. inline virtual void grow();
  65. // Compute min and max corners
  66. inline void compute_min_max_corners();
  67. inline Scalar max_abs_winding_number(const Point & p) const;
  68. inline Scalar max_simple_abs_winding_number(const Point & p) const;
  69. };
  70. }
  71. // Implementation
  72. #include "winding_number.h"
  73. #include "barycenter.h"
  74. #include "median.h"
  75. #include "doublearea.h"
  76. #include "per_face_normals.h"
  77. #include <limits>
  78. #include <vector>
  79. #include <iostream>
  80. // Minimum number of faces in a hierarchy element (this is probably dependent
  81. // on speed of machine and compiler optimization)
  82. #ifndef WindingNumberAABB_MIN_F
  83. # define WindingNumberAABB_MIN_F 100
  84. #endif
  85. template <typename Scalar, typename Index>
  86. template <typename DerivedV, typename DerivedF>
  87. inline void igl::WindingNumberAABB<Scalar,Index>::set_mesh(
  88. const Eigen::MatrixBase<DerivedV> & V,
  89. const Eigen::MatrixBase<DerivedF> & F)
  90. {
  91. // static assert that DerivedF::ColsAtCompileTime == 3 or Eigen::Dynamic
  92. static_assert(
  93. DerivedF::ColsAtCompileTime == 3 || DerivedF::ColsAtCompileTime == Eigen::Dynamic,
  94. "F should have 3 or Dynamic columns");
  95. igl::WindingNumberTree<Scalar,Index>::set_mesh(V,F);
  96. init();
  97. }
  98. template <typename Scalar, typename Index>
  99. inline void igl::WindingNumberAABB<Scalar,Index>::init()
  100. {
  101. assert(max_corner.size() == 3);
  102. assert(min_corner.size() == 3);
  103. compute_min_max_corners();
  104. Eigen::Matrix<Scalar,Eigen::Dynamic,1> dblA;
  105. doublearea((*this->Vptr),(this->F),dblA);
  106. total_positive_area = dblA.sum()/2.0;
  107. }
  108. template <typename Scalar, typename Index>
  109. template <typename DerivedV, typename DerivedF>
  110. inline igl::WindingNumberAABB<Scalar,Index>::WindingNumberAABB(
  111. const Eigen::MatrixBase<DerivedV> & V,
  112. const Eigen::MatrixBase<DerivedF> & F):
  113. WindingNumberTree<Scalar,Index>(V,F),
  114. min_corner(),
  115. max_corner(),
  116. total_positive_area(
  117. std::numeric_limits<Scalar>::infinity()),
  118. split_method(MEDIAN_ON_LONGEST_AXIS)
  119. {
  120. init();
  121. }
  122. template <typename Scalar, typename Index>
  123. inline igl::WindingNumberAABB<Scalar,Index>::WindingNumberAABB(
  124. const WindingNumberTree<Scalar,Index> & parent,
  125. const typename WindingNumberTree<Scalar,Index>::MatrixXF & F):
  126. WindingNumberTree<Scalar,Index>(parent,F),
  127. min_corner(),
  128. max_corner(),
  129. total_positive_area(
  130. std::numeric_limits<Scalar>::infinity()),
  131. split_method(MEDIAN_ON_LONGEST_AXIS)
  132. {
  133. init();
  134. }
  135. template <typename Scalar, typename Index>
  136. inline void igl::WindingNumberAABB<Scalar,Index>::grow()
  137. {
  138. // Clear anything that already exists
  139. this->delete_children();
  140. //cout<<"cap.rows(): "<<(this->cap).rows()<<endl;
  141. //cout<<"F.rows(): "<<(this->F).rows()<<endl;
  142. // Base cases
  143. if(
  144. (this->F).rows() <= (WindingNumberAABB_MIN_F>0?WindingNumberAABB_MIN_F:0) ||
  145. ((this->cap).rows() - 2) >= (this->F).rows())
  146. {
  147. // Don't grow
  148. return;
  149. }
  150. // Compute longest direction
  151. int max_d = -1;
  152. Scalar max_len =
  153. -std::numeric_limits<Scalar>::infinity();
  154. for(int d = 0;d<min_corner.size();d++)
  155. {
  156. if( (max_corner[d] - min_corner[d]) > max_len )
  157. {
  158. max_len = (max_corner[d] - min_corner[d]);
  159. max_d = d;
  160. }
  161. }
  162. // Compute facet barycenters
  163. Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> BC;
  164. barycenter((*this->Vptr),(this->F),BC);
  165. // Blerg, why is selecting rows so difficult
  166. Scalar split_value;
  167. // Split in longest direction
  168. switch(split_method)
  169. {
  170. case MEDIAN_ON_LONGEST_AXIS:
  171. // Determine median
  172. median(BC.col(max_d),split_value);
  173. break;
  174. default:
  175. assert(false);
  176. case CENTER_ON_LONGEST_AXIS:
  177. split_value = 0.5*(max_corner[max_d] + min_corner[max_d]);
  178. break;
  179. }
  180. //cout<<"c: "<<0.5*(max_corner[max_d] + min_corner[max_d])<<" "<<
  181. // "m: "<<split_value<<endl;;
  182. std::vector<int> id( (this->F).rows());
  183. for(int i = 0;i<(this->F).rows();i++)
  184. {
  185. if(BC(i,max_d) <= split_value)
  186. {
  187. id[i] = 0; //left
  188. }else
  189. {
  190. id[i] = 1; //right
  191. }
  192. }
  193. const int lefts = (int) count(id.begin(),id.end(),0);
  194. const int rights = (int) count(id.begin(),id.end(),1);
  195. if(lefts == 0 || rights == 0)
  196. {
  197. // badly balanced base case (could try to recut)
  198. return;
  199. }
  200. assert(lefts+rights == (this->F).rows());
  201. MatrixXF leftF(lefts, (this->F).cols());
  202. MatrixXF rightF(rights,(this->F).cols());
  203. int left_i = 0;
  204. int right_i = 0;
  205. for(int i = 0;i<(this->F).rows();i++)
  206. {
  207. if(id[i] == 0)
  208. {
  209. leftF.row(left_i++) = (this->F).row(i);
  210. }else if(id[i] == 1)
  211. {
  212. rightF.row(right_i++) = (this->F).row(i);
  213. }else
  214. {
  215. assert(false);
  216. }
  217. }
  218. assert(right_i == rightF.rows());
  219. assert(left_i == leftF.rows());
  220. // Finally actually grow children and Recursively grow
  221. WindingNumberAABB<Scalar,Index> * leftWindingNumberAABB =
  222. new WindingNumberAABB<Scalar,Index>(*this,leftF);
  223. leftWindingNumberAABB->grow();
  224. this->children.push_back(leftWindingNumberAABB);
  225. WindingNumberAABB<Scalar,Index> * rightWindingNumberAABB =
  226. new WindingNumberAABB<Scalar,Index>(*this,rightF);
  227. rightWindingNumberAABB->grow();
  228. this->children.push_back(rightWindingNumberAABB);
  229. }
  230. template <typename Scalar, typename Index>
  231. inline bool igl::WindingNumberAABB<Scalar,Index>::inside(const Point & p) const
  232. {
  233. assert(p.size() == max_corner.size());
  234. assert(p.size() == min_corner.size());
  235. for(int i = 0;i<p.size();i++)
  236. {
  237. //// Perfect matching is **not** robust
  238. //if( p(i) < min_corner(i) || p(i) >= max_corner(i))
  239. // **MUST** be conservative
  240. if( p(i) < min_corner(i) || p(i) > max_corner(i))
  241. {
  242. return false;
  243. }
  244. }
  245. return true;
  246. }
  247. template <typename Scalar, typename Index>
  248. inline void igl::WindingNumberAABB<Scalar,Index>::compute_min_max_corners()
  249. {
  250. // initialize corners
  251. for(int d = 0;d<min_corner.size();d++)
  252. {
  253. min_corner[d] = std::numeric_limits<typename Point::Scalar>::infinity();
  254. max_corner[d] = -std::numeric_limits<typename Point::Scalar>::infinity();
  255. }
  256. this->center = Point(0,0,0);
  257. // Loop over facets
  258. for(int i = 0;i<(this->F).rows();i++)
  259. {
  260. for(int j = 0;j<(this->F).cols();j++)
  261. {
  262. for(int d = 0;d<min_corner.size();d++)
  263. {
  264. min_corner[d] =
  265. (*this->Vptr)((this->F)(i,j),d) < min_corner[d] ?
  266. (*this->Vptr)((this->F)(i,j),d) : min_corner[d];
  267. max_corner[d] =
  268. (*this->Vptr)((this->F)(i,j),d) > max_corner[d] ?
  269. (*this->Vptr)((this->F)(i,j),d) : max_corner[d];
  270. }
  271. // This is biased toward vertices incident on more than one face, but
  272. // perhaps that's good
  273. this->center += (*this->Vptr).row((this->F)(i,j));
  274. }
  275. }
  276. // Average
  277. this->center.array() /= (this->F).size();
  278. //cout<<"min_corner: "<<this->min_corner.transpose()<<endl;
  279. //cout<<"Center: "<<this->center.transpose()<<endl;
  280. //cout<<"max_corner: "<<this->max_corner.transpose()<<endl;
  281. //cout<<"Diag center: "<<((this->max_corner + this->min_corner)*0.5).transpose()<<endl;
  282. //cout<<endl;
  283. this->radius = (max_corner-min_corner).norm()/2.0;
  284. }
  285. template <typename Scalar, typename Index>
  286. inline Scalar
  287. igl::WindingNumberAABB<Scalar,Index>::max_abs_winding_number(const Point & p) const
  288. {
  289. // Only valid if not inside
  290. if(inside(p))
  291. {
  292. return std::numeric_limits<Scalar>::infinity();
  293. }
  294. // Q: we know the total positive area so what's the most this could project
  295. // to? Remember it could be layered in the same direction.
  296. return std::numeric_limits<Scalar>::infinity();
  297. }
  298. template <typename Scalar, typename Index>
  299. inline Scalar
  300. igl::WindingNumberAABB<Scalar,Index>::max_simple_abs_winding_number(
  301. const Point & p) const
  302. {
  303. // Only valid if not inside
  304. if(inside(p))
  305. {
  306. return std::numeric_limits<Scalar>::infinity();
  307. }
  308. // Max simple is the same as sum of positive winding number contributions of
  309. // bounding box
  310. // begin precomputation
  311. //MatrixXd BV((int)pow(2,3),3);
  312. typedef
  313. Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>
  314. MatrixXS;
  315. typedef
  316. Eigen::Matrix<Index,Eigen::Dynamic,Eigen::Dynamic>
  317. MatrixXF;
  318. MatrixXS BV((int)(1<<3),3);
  319. BV <<
  320. min_corner[0],min_corner[1],min_corner[2],
  321. min_corner[0],min_corner[1],max_corner[2],
  322. min_corner[0],max_corner[1],min_corner[2],
  323. min_corner[0],max_corner[1],max_corner[2],
  324. max_corner[0],min_corner[1],min_corner[2],
  325. max_corner[0],min_corner[1],max_corner[2],
  326. max_corner[0],max_corner[1],min_corner[2],
  327. max_corner[0],max_corner[1],max_corner[2];
  328. MatrixXF BF(2*2*3,3);
  329. BF <<
  330. 0,6,4,
  331. 0,2,6,
  332. 0,3,2,
  333. 0,1,3,
  334. 2,7,6,
  335. 2,3,7,
  336. 4,6,7,
  337. 4,7,5,
  338. 0,4,5,
  339. 0,5,1,
  340. 1,5,7,
  341. 1,7,3;
  342. MatrixXS BFN;
  343. per_face_normals(BV,BF,BFN);
  344. // end of precomputation
  345. // Only keep those with positive dot products
  346. MatrixXF PBF(BF.rows(),BF.cols());
  347. int pbfi = 0;
  348. Point p2c = 0.5*(min_corner+max_corner)-p;
  349. for(int i = 0;i<BFN.rows();i++)
  350. {
  351. if(p2c.dot(BFN.row(i)) > 0)
  352. {
  353. PBF.row(pbfi++) = BF.row(i);
  354. }
  355. }
  356. PBF.conservativeResize(pbfi,PBF.cols());
  357. return igl::winding_number(BV,PBF,p);
  358. }
  359. #endif