WindingNumberAABB.h 8.8 KB

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