WindingNumberAABB.h 11 KB

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