AABB.h 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2015 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. #ifndef IGL_AABB_H
  9. #define IGL_AABB_H
  10. #include <Eigen/Core>
  11. #include <Eigen/Geometry>
  12. #include <vector>
  13. namespace igl
  14. {
  15. // Implementation of semi-general purpose axis-aligned bounding box hierarchy.
  16. // The mesh (V,Ele) is stored and managed by the caller and each routine here
  17. // simply takes it as references (it better not change between calls).
  18. //
  19. // It's a little annoying that the Dimension is a template parameter and not
  20. // picked up at run time from V. This leads to duplicated code for 2d/3d (up to
  21. // dim).
  22. template <typename DerivedV, int DIM>
  23. class AABB
  24. {
  25. public:
  26. typedef typename DerivedV::Scalar Scalar;
  27. typedef Eigen::Matrix<Scalar,1,DIM> RowVectorDIMS;
  28. typedef Eigen::Matrix<Scalar,DIM,1> VectorDIMS;
  29. typedef Eigen::Matrix<Scalar,Eigen::Dynamic,DIM> MatrixXDIMS;
  30. // Shared pointers are slower...
  31. AABB * m_left;
  32. AABB * m_right;
  33. Eigen::AlignedBox<Scalar,DIM> m_box;
  34. // -1 non-leaf
  35. int m_primitive;
  36. //Scalar m_max_sqr_d;
  37. //int m_depth;
  38. AABB():
  39. m_left(NULL), m_right(NULL),
  40. m_box(), m_primitive(-1)
  41. //m_max_sqr_d(std::numeric_limits<double>::infinity()),
  42. //m_depth(0)
  43. {}
  44. // http://stackoverflow.com/a/3279550/148668
  45. AABB(const AABB& other):
  46. m_left(other.m_left ? new AABB(*other.m_left) : NULL),
  47. m_right(other.m_right ? new AABB(*other.m_right) : NULL),
  48. m_box(other.m_box),
  49. m_primitive(other.m_primitive)
  50. //m_max_sqr_d(other.m_max_sqr_d),
  51. //m_depth(std::max(
  52. // m_left ? m_left->m_depth + 1 : 0,
  53. // m_right ? m_right->m_depth + 1 : 0))
  54. {
  55. }
  56. // copy-swap idiom
  57. friend void swap(AABB& first, AABB& second)
  58. {
  59. // Enable ADL
  60. using std::swap;
  61. swap(first.m_left,second.m_left);
  62. swap(first.m_right,second.m_right);
  63. swap(first.m_box,second.m_box);
  64. swap(first.m_primitive,second.m_primitive);
  65. //swap(first.m_max_sqr_d,second.m_max_sqr_d);
  66. //swap(first.m_depth,second.m_depth);
  67. }
  68. // Pass-by-value (aka copy)
  69. AABB& operator=(AABB other)
  70. {
  71. swap(*this,other);
  72. return *this;
  73. }
  74. AABB(AABB&& other):
  75. // initialize via default constructor
  76. AABB()
  77. {
  78. swap(*this,other);
  79. }
  80. // Seems like there should have been an elegant solution to this using
  81. // the copy-swap idiom above:
  82. inline void deinit()
  83. {
  84. m_primitive = -1;
  85. m_box = Eigen::AlignedBox<Scalar,DIM>();
  86. delete m_left;
  87. m_left = NULL;
  88. delete m_right;
  89. m_right = NULL;
  90. }
  91. ~AABB()
  92. {
  93. deinit();
  94. }
  95. // Build an Axis-Aligned Bounding Box tree for a given mesh and given
  96. // serialization of a previous AABB tree.
  97. //
  98. // Inputs:
  99. // V #V by dim list of mesh vertex positions.
  100. // Ele #Ele by dim+1 list of mesh indices into #V.
  101. // bb_mins max_tree by dim list of bounding box min corner positions
  102. // bb_maxs max_tree by dim list of bounding box max corner positions
  103. // elements max_tree list of element or (not leaf id) indices into Ele
  104. // i recursive call index {0}
  105. template <typename Derivedbb_mins, typename Derivedbb_maxs>
  106. inline void init(
  107. const Eigen::PlainObjectBase<DerivedV> & V,
  108. const Eigen::MatrixXi & Ele,
  109. const Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
  110. const Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
  111. const Eigen::VectorXi & elements,
  112. const int i = 0);
  113. // Wrapper for root with empty serialization
  114. inline void init(
  115. const Eigen::PlainObjectBase<DerivedV> & V,
  116. const Eigen::MatrixXi & Ele);
  117. // Build an Axis-Aligned Bounding Box tree for a given mesh.
  118. //
  119. // Inputs:
  120. // V #V by dim list of mesh vertex positions.
  121. // Ele #Ele by dim+1 list of mesh indices into #V.
  122. // SI #Ele by dim list revealing for each coordinate where Ele's
  123. // barycenters would be sorted: SI(e,d) = i --> the dth coordinate of
  124. // the barycenter of the eth element would be placed at position i in a
  125. // sorted list.
  126. // I #I list of indices into Ele of elements to include (for recursive
  127. // calls)
  128. //
  129. inline void init(
  130. const Eigen::PlainObjectBase<DerivedV> & V,
  131. const Eigen::MatrixXi & Ele,
  132. const Eigen::MatrixXi & SI,
  133. const Eigen::VectorXi & I);
  134. // Return whether at leaf node
  135. inline bool is_leaf() const;
  136. // Find the indices of elements containing given point.
  137. //
  138. // Inputs:
  139. // V #V by dim list of mesh vertex positions. **Should be same as used to
  140. // construct mesh.**
  141. // Ele #Ele by dim+1 list of mesh indices into #V. **Should be same as used to
  142. // construct mesh.**
  143. // q dim row-vector query position
  144. // first whether to only return first element containing q
  145. // Returns:
  146. // list of indices of elements containing q
  147. template <typename Derivedq>
  148. inline std::vector<int> find(
  149. const Eigen::PlainObjectBase<DerivedV> & V,
  150. const Eigen::MatrixXi & Ele,
  151. const Eigen::PlainObjectBase<Derivedq> & q,
  152. const bool first=false) const;
  153. // If number of elements m then total tree size should be 2*h where h is
  154. // the deepest depth 2^ceil(log(#Ele*2-1))
  155. inline int subtree_size() const;
  156. // Serialize this class into 3 arrays (so we can pass it pack to matlab)
  157. //
  158. // Outputs:
  159. // bb_mins max_tree by dim list of bounding box min corner positions
  160. // bb_maxs max_tree by dim list of bounding box max corner positions
  161. // elements max_tree list of element or (not leaf id) indices into Ele
  162. // i recursive call index into these arrays {0}
  163. template <typename Derivedbb_mins, typename Derivedbb_maxs>
  164. inline void serialize(
  165. Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
  166. Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
  167. Eigen::VectorXi & elements,
  168. const int i = 0) const;
  169. // Compute squared distance to a query point
  170. //
  171. // Inputs:
  172. // V #V by dim list of vertex positions
  173. // Ele #Ele by dim list of simplex indices
  174. // P 3 list of query point coordinates
  175. // min_sqr_d current minimum squared distance (only find distances
  176. // less than this)
  177. // Outputs:
  178. // I #P list of facet indices corresponding to smallest distances
  179. // C #P by 3 list of closest points
  180. // Returns squared distance
  181. //
  182. // Known bugs: currently assumes Elements are triangles regardless of
  183. // dimension.
  184. inline Scalar squared_distance(
  185. const Eigen::PlainObjectBase<DerivedV> & V,
  186. const Eigen::MatrixXi & Ele,
  187. const RowVectorDIMS & p,
  188. int & i,
  189. RowVectorDIMS & c) const;
  190. //private:
  191. inline Scalar squared_distance(
  192. const Eigen::PlainObjectBase<DerivedV> & V,
  193. const Eigen::MatrixXi & Ele,
  194. const RowVectorDIMS & p,
  195. const Scalar min_sqr_d,
  196. int & i,
  197. RowVectorDIMS & c) const;
  198. public:
  199. template <
  200. typename DerivedP,
  201. typename DerivedsqrD,
  202. typename DerivedI,
  203. typename DerivedC>
  204. inline void squared_distance(
  205. const Eigen::PlainObjectBase<DerivedV> & V,
  206. const Eigen::MatrixXi & Ele,
  207. const Eigen::PlainObjectBase<DerivedP> & P,
  208. Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
  209. Eigen::PlainObjectBase<DerivedI> & I,
  210. Eigen::PlainObjectBase<DerivedC> & C) const;
  211. template <
  212. typename Derivedother_V,
  213. typename DerivedsqrD,
  214. typename DerivedI,
  215. typename DerivedC>
  216. inline void squared_distance(
  217. const Eigen::PlainObjectBase<DerivedV> & V,
  218. const Eigen::MatrixXi & Ele,
  219. const AABB<Derivedother_V,DIM> & other,
  220. const Eigen::PlainObjectBase<Derivedother_V> & other_V,
  221. const Eigen::MatrixXi & other_Ele,
  222. Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
  223. Eigen::PlainObjectBase<DerivedI> & I,
  224. Eigen::PlainObjectBase<DerivedC> & C) const;
  225. private:
  226. template <
  227. typename Derivedother_V,
  228. typename DerivedsqrD,
  229. typename DerivedI,
  230. typename DerivedC>
  231. inline Scalar squared_distance_helper(
  232. const Eigen::PlainObjectBase<DerivedV> & V,
  233. const Eigen::MatrixXi & Ele,
  234. const AABB<Derivedother_V,DIM> * other,
  235. const Eigen::PlainObjectBase<Derivedother_V> & other_V,
  236. const Eigen::MatrixXi & other_Ele,
  237. const Scalar min_sqr_d,
  238. Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
  239. Eigen::PlainObjectBase<DerivedI> & I,
  240. Eigen::PlainObjectBase<DerivedC> & C) const;
  241. // Helper function for leaves: works in-place on sqr_d
  242. inline void leaf_squared_distance(
  243. const Eigen::PlainObjectBase<DerivedV> & V,
  244. const Eigen::MatrixXi & Ele,
  245. const RowVectorDIMS & p,
  246. Scalar & sqr_d,
  247. int & i,
  248. RowVectorDIMS & c) const;
  249. inline void set_min(
  250. const RowVectorDIMS & p,
  251. const Scalar sqr_d_candidate,
  252. const int i_candidate,
  253. const RowVectorDIMS & c_candidate,
  254. Scalar & sqr_d,
  255. int & i,
  256. RowVectorDIMS & c) const;
  257. public:
  258. static
  259. inline void barycentric_coordinates(
  260. const RowVectorDIMS & p,
  261. const RowVectorDIMS & a,
  262. const RowVectorDIMS & b,
  263. const RowVectorDIMS & c,
  264. Eigen::Matrix<Scalar,1,3> & bary);
  265. public:
  266. EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  267. };
  268. }
  269. // Implementation
  270. #include "EPS.h"
  271. #include "barycenter.h"
  272. #include "colon.h"
  273. #include "colon.h"
  274. #include "doublearea.h"
  275. #include "matlab_format.h"
  276. #include "project_to_line_segment.h"
  277. #include "sort.h"
  278. #include "volume.h"
  279. #include <iostream>
  280. #include <iomanip>
  281. #include <limits>
  282. #include <list>
  283. template <typename DerivedV, int DIM>
  284. template <typename Derivedbb_mins, typename Derivedbb_maxs>
  285. inline void igl::AABB<DerivedV,DIM>::init(
  286. const Eigen::PlainObjectBase<DerivedV> & V,
  287. const Eigen::MatrixXi & Ele,
  288. const Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
  289. const Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
  290. const Eigen::VectorXi & elements,
  291. const int i)
  292. {
  293. using namespace std;
  294. using namespace Eigen;
  295. if(bb_mins.size() > 0)
  296. {
  297. assert(bb_mins.rows() == bb_maxs.rows() && "Serial tree arrays must match");
  298. assert(bb_mins.cols() == V.cols() && "Serial tree array dim must match V");
  299. assert(bb_mins.cols() == bb_maxs.cols() && "Serial tree arrays must match");
  300. assert(bb_mins.rows() == elements.rows() &&
  301. "Serial tree arrays must match");
  302. // construct from serialization
  303. m_box.extend(bb_mins.row(i).transpose());
  304. m_box.extend(bb_maxs.row(i).transpose());
  305. m_primitive = elements(i);
  306. // Not leaf then recurse
  307. if(m_primitive == -1)
  308. {
  309. m_left = new AABB();
  310. m_left->init( V,Ele,bb_mins,bb_maxs,elements,2*i+1);
  311. m_right = new AABB();
  312. m_right->init( V,Ele,bb_mins,bb_maxs,elements,2*i+2);
  313. //m_depth = std::max( m_left->m_depth, m_right->m_depth)+1;
  314. }
  315. }else
  316. {
  317. VectorXi allI = colon<int>(0,Ele.rows()-1);
  318. MatrixXDIMS BC;
  319. if(Ele.cols() == 1)
  320. {
  321. // points
  322. BC = V;
  323. }else
  324. {
  325. // Simplices
  326. barycenter(V,Ele,BC);
  327. }
  328. MatrixXi SI(BC.rows(),BC.cols());
  329. {
  330. MatrixXDIMS _;
  331. MatrixXi IS;
  332. igl::sort(BC,1,true,_,IS);
  333. // Need SI(i) to tell which place i would be sorted into
  334. const int dim = IS.cols();
  335. for(int i = 0;i<IS.rows();i++)
  336. {
  337. for(int d = 0;d<dim;d++)
  338. {
  339. SI(IS(i,d),d) = i;
  340. }
  341. }
  342. }
  343. init(V,Ele,SI,allI);
  344. }
  345. }
  346. template <typename DerivedV, int DIM>
  347. inline void igl::AABB<DerivedV,DIM>::init(
  348. const Eigen::PlainObjectBase<DerivedV> & V,
  349. const Eigen::MatrixXi & Ele)
  350. {
  351. using namespace Eigen;
  352. return init(V,Ele,MatrixXDIMS(),MatrixXDIMS(),VectorXi(),0);
  353. }
  354. template <typename DerivedV, int DIM>
  355. inline void igl::AABB<DerivedV,DIM>::init(
  356. const Eigen::PlainObjectBase<DerivedV> & V,
  357. const Eigen::MatrixXi & Ele,
  358. const Eigen::MatrixXi & SI,
  359. const Eigen::VectorXi & I)
  360. {
  361. using namespace Eigen;
  362. using namespace std;
  363. assert(DIM == V.cols() && "V.cols() should matched declared dimension");
  364. //const Scalar inf = numeric_limits<Scalar>::infinity();
  365. m_box = AlignedBox<Scalar,DIM>();
  366. // Compute bounding box
  367. for(int i = 0;i<I.rows();i++)
  368. {
  369. for(int c = 0;c<Ele.cols();c++)
  370. {
  371. m_box.extend(V.row(Ele(I(i),c)).transpose());
  372. m_box.extend(V.row(Ele(I(i),c)).transpose());
  373. }
  374. }
  375. switch(I.size())
  376. {
  377. case 0:
  378. {
  379. assert(false);
  380. }
  381. case 1:
  382. {
  383. m_primitive = I(0);
  384. break;
  385. }
  386. default:
  387. {
  388. // Compute longest direction
  389. int max_d = -1;
  390. m_box.diagonal().maxCoeff(&max_d);
  391. // Can't use median on BC directly because many may have same value,
  392. // but can use median on sorted BC indices
  393. VectorXi SIdI(I.rows());
  394. for(int i = 0;i<I.rows();i++)
  395. {
  396. SIdI(i) = SI(I(i),max_d);
  397. }
  398. // Since later I use <= I think I don't need to worry about odd/even
  399. // Pass by copy to avoid changing input
  400. const auto median = [](VectorXi A)->Scalar
  401. {
  402. size_t n = A.size()/2;
  403. nth_element(A.data(),A.data()+n,A.data()+A.size());
  404. if(A.rows() % 2 == 1)
  405. {
  406. return A(n);
  407. }else
  408. {
  409. nth_element(A.data(),A.data()+n-1,A.data()+A.size());
  410. return 0.5*(A(n)+A(n-1));
  411. }
  412. };
  413. const Scalar med = median(SIdI);
  414. VectorXi LI((I.rows()+1)/2),RI(I.rows()/2);
  415. assert(LI.rows()+RI.rows() == I.rows());
  416. // Distribute left and right
  417. {
  418. int li = 0;
  419. int ri = 0;
  420. for(int i = 0;i<I.rows();i++)
  421. {
  422. if(SIdI(i)<=med)
  423. {
  424. LI(li++) = I(i);
  425. }else
  426. {
  427. RI(ri++) = I(i);
  428. }
  429. }
  430. }
  431. //m_depth = 0;
  432. if(LI.rows()>0)
  433. {
  434. m_left = new AABB();
  435. m_left->init(V,Ele,SI,LI);
  436. //m_depth = std::max(m_depth, m_left->m_depth+1);
  437. }
  438. if(RI.rows()>0)
  439. {
  440. m_right = new AABB();
  441. m_right->init(V,Ele,SI,RI);
  442. //m_depth = std::max(m_depth, m_right->m_depth+1);
  443. }
  444. }
  445. }
  446. }
  447. template <typename DerivedV, int DIM>
  448. inline bool igl::AABB<DerivedV,DIM>::is_leaf() const
  449. {
  450. return m_primitive != -1;
  451. }
  452. template <typename DerivedV, int DIM>
  453. template <typename Derivedq>
  454. inline std::vector<int> igl::AABB<DerivedV,DIM>::find(
  455. const Eigen::PlainObjectBase<DerivedV> & V,
  456. const Eigen::MatrixXi & Ele,
  457. const Eigen::PlainObjectBase<Derivedq> & q,
  458. const bool first) const
  459. {
  460. using namespace std;
  461. using namespace Eigen;
  462. assert(q.size() == DIM &&
  463. "Query dimension should match aabb dimension");
  464. assert(Ele.cols() == V.cols()+1 &&
  465. "AABB::find only makes sense for (d+1)-simplices");
  466. const Scalar epsilon = igl::EPS<Scalar>();
  467. // Check if outside bounding box
  468. bool inside = m_box.contains(q.transpose());
  469. if(!inside)
  470. {
  471. return std::vector<int>();
  472. }
  473. assert(m_primitive==-1 || (m_left == NULL && m_right == NULL));
  474. if(is_leaf())
  475. {
  476. // Initialize to some value > -epsilon
  477. Scalar a1=0,a2=0,a3=0,a4=0;
  478. switch(DIM)
  479. {
  480. case 3:
  481. {
  482. // Barycentric coordinates
  483. typedef Eigen::Matrix<Scalar,1,3> RowVector3S;
  484. const RowVector3S V1 = V.row(Ele(m_primitive,0));
  485. const RowVector3S V2 = V.row(Ele(m_primitive,1));
  486. const RowVector3S V3 = V.row(Ele(m_primitive,2));
  487. const RowVector3S V4 = V.row(Ele(m_primitive,3));
  488. a1 = volume_single(V2,V4,V3,(RowVector3S)q);
  489. a2 = volume_single(V1,V3,V4,(RowVector3S)q);
  490. a3 = volume_single(V1,V4,V2,(RowVector3S)q);
  491. a4 = volume_single(V1,V2,V3,(RowVector3S)q);
  492. break;
  493. }
  494. case 2:
  495. {
  496. // Barycentric coordinates
  497. typedef Eigen::Matrix<Scalar,2,1> Vector2S;
  498. const Vector2S V1 = V.row(Ele(m_primitive,0));
  499. const Vector2S V2 = V.row(Ele(m_primitive,1));
  500. const Vector2S V3 = V.row(Ele(m_primitive,2));
  501. // Hack for now to keep templates simple. If becomes bottleneck
  502. // consider using std::enable_if_t
  503. const Vector2S q2 = q.head(2);
  504. a1 = doublearea_single(V1,V2,q2);
  505. a2 = doublearea_single(V2,V3,q2);
  506. a3 = doublearea_single(V3,V1,q2);
  507. break;
  508. }
  509. default:assert(false);
  510. }
  511. // Normalization is important for correcting sign
  512. Scalar sum = a1+a2+a3+a4;
  513. a1 /= sum;
  514. a2 /= sum;
  515. a3 /= sum;
  516. a4 /= sum;
  517. if(
  518. a1>=-epsilon &&
  519. a2>=-epsilon &&
  520. a3>=-epsilon &&
  521. a4>=-epsilon)
  522. {
  523. return std::vector<int>(1,m_primitive);
  524. }else
  525. {
  526. return std::vector<int>();
  527. }
  528. }
  529. std::vector<int> left = m_left->find(V,Ele,q,first);
  530. if(first && !left.empty())
  531. {
  532. return left;
  533. }
  534. std::vector<int> right = m_right->find(V,Ele,q,first);
  535. if(first)
  536. {
  537. return right;
  538. }
  539. left.insert(left.end(),right.begin(),right.end());
  540. return left;
  541. }
  542. template <typename DerivedV, int DIM>
  543. inline int igl::AABB<DerivedV,DIM>::subtree_size() const
  544. {
  545. // 1 for self
  546. int n = 1;
  547. int n_left = 0,n_right = 0;
  548. if(m_left != NULL)
  549. {
  550. n_left = m_left->subtree_size();
  551. }
  552. if(m_right != NULL)
  553. {
  554. n_right = m_right->subtree_size();
  555. }
  556. n += 2*std::max(n_left,n_right);
  557. return n;
  558. }
  559. template <typename DerivedV, int DIM>
  560. template <typename Derivedbb_mins, typename Derivedbb_maxs>
  561. inline void igl::AABB<DerivedV,DIM>::serialize(
  562. Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
  563. Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
  564. Eigen::VectorXi & elements,
  565. const int i) const
  566. {
  567. using namespace std;
  568. using namespace Eigen;
  569. // Calling for root then resize output
  570. if(i==0)
  571. {
  572. const int m = subtree_size();
  573. //cout<<"m: "<<m<<endl;
  574. bb_mins.resize(m,DIM);
  575. bb_maxs.resize(m,DIM);
  576. elements.resize(m,1);
  577. }
  578. //cout<<i<<" ";
  579. bb_mins.row(i) = m_box.min();
  580. bb_maxs.row(i) = m_box.max();
  581. elements(i) = m_primitive;
  582. if(m_left != NULL)
  583. {
  584. m_left->serialize(bb_mins,bb_maxs,elements,2*i+1);
  585. }
  586. if(m_right != NULL)
  587. {
  588. m_right->serialize(bb_mins,bb_maxs,elements,2*i+2);
  589. }
  590. }
  591. template <typename DerivedV, int DIM>
  592. inline typename igl::AABB<DerivedV,DIM>::Scalar
  593. igl::AABB<DerivedV,DIM>::squared_distance(
  594. const Eigen::PlainObjectBase<DerivedV> & V,
  595. const Eigen::MatrixXi & Ele,
  596. const RowVectorDIMS & p,
  597. int & i,
  598. RowVectorDIMS & c) const
  599. {
  600. return squared_distance(V,Ele,p,std::numeric_limits<Scalar>::infinity(),i,c);
  601. }
  602. template <typename DerivedV, int DIM>
  603. inline typename igl::AABB<DerivedV,DIM>::Scalar
  604. igl::AABB<DerivedV,DIM>::squared_distance(
  605. const Eigen::PlainObjectBase<DerivedV> & V,
  606. const Eigen::MatrixXi & Ele,
  607. const RowVectorDIMS & p,
  608. Scalar min_sqr_d,
  609. int & i,
  610. RowVectorDIMS & c) const
  611. {
  612. using namespace Eigen;
  613. using namespace std;
  614. using namespace igl;
  615. Scalar sqr_d = min_sqr_d;
  616. //assert(DIM == 3 && "Code has only been tested for DIM == 3");
  617. assert((Ele.cols() == 3 || Ele.cols() == 2 || Ele.cols() == 1)
  618. && "Code has only been tested for simplex sizes 3,2,1");
  619. assert(m_primitive==-1 || (m_left == NULL && m_right == NULL));
  620. if(is_leaf())
  621. {
  622. leaf_squared_distance(V,Ele,p,sqr_d,i,c);
  623. }else
  624. {
  625. bool looked_left = false;
  626. bool looked_right = false;
  627. const auto & look_left = [&]()
  628. {
  629. int i_left;
  630. RowVectorDIMS c_left = c;
  631. Scalar sqr_d_left = m_left->squared_distance(V,Ele,p,sqr_d,i_left,c_left);
  632. set_min(p,sqr_d_left,i_left,c_left,sqr_d,i,c);
  633. looked_left = true;
  634. };
  635. const auto & look_right = [&]()
  636. {
  637. int i_right;
  638. RowVectorDIMS c_right = c;
  639. Scalar sqr_d_right = m_right->squared_distance(V,Ele,p,sqr_d,i_right,c_right);
  640. set_min(p,sqr_d_right,i_right,c_right,sqr_d,i,c);
  641. looked_right = true;
  642. };
  643. // must look left or right if in box
  644. if(m_left->m_box.contains(p.transpose()))
  645. {
  646. look_left();
  647. }
  648. if(m_right->m_box.contains(p.transpose()))
  649. {
  650. look_right();
  651. }
  652. // if haven't looked left and could be less than current min, then look
  653. Scalar left_min_sqr_d = m_left->m_box.squaredExteriorDistance(p.transpose());
  654. Scalar right_min_sqr_d = m_right->m_box.squaredExteriorDistance(p.transpose());
  655. if(left_min_sqr_d < right_min_sqr_d)
  656. {
  657. if(!looked_left && left_min_sqr_d<sqr_d)
  658. {
  659. look_left();
  660. }
  661. if( !looked_right && right_min_sqr_d<sqr_d)
  662. {
  663. look_right();
  664. }
  665. }else
  666. {
  667. if( !looked_right && right_min_sqr_d<sqr_d)
  668. {
  669. look_right();
  670. }
  671. if(!looked_left && left_min_sqr_d<sqr_d)
  672. {
  673. look_left();
  674. }
  675. }
  676. }
  677. return sqr_d;
  678. }
  679. template <typename DerivedV, int DIM>
  680. template <
  681. typename DerivedP,
  682. typename DerivedsqrD,
  683. typename DerivedI,
  684. typename DerivedC>
  685. inline void igl::AABB<DerivedV,DIM>::squared_distance(
  686. const Eigen::PlainObjectBase<DerivedV> & V,
  687. const Eigen::MatrixXi & Ele,
  688. const Eigen::PlainObjectBase<DerivedP> & P,
  689. Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
  690. Eigen::PlainObjectBase<DerivedI> & I,
  691. Eigen::PlainObjectBase<DerivedC> & C) const
  692. {
  693. assert(P.cols() == V.cols() && "cols in P should match dim of cols in V");
  694. sqrD.resize(P.rows(),1);
  695. I.resize(P.rows(),1);
  696. C.resize(P.rows(),P.cols());
  697. for(int p = 0;p<P.rows();p++)
  698. {
  699. RowVectorDIMS Pp = P.row(p), c;
  700. int Ip;
  701. sqrD(p) = squared_distance(V,Ele,Pp,Ip,c);
  702. I(p) = Ip;
  703. C.row(p).head(DIM) = c;
  704. }
  705. }
  706. template <typename DerivedV, int DIM>
  707. template <
  708. typename Derivedother_V,
  709. typename DerivedsqrD,
  710. typename DerivedI,
  711. typename DerivedC>
  712. inline void igl::AABB<DerivedV,DIM>::squared_distance(
  713. const Eigen::PlainObjectBase<DerivedV> & V,
  714. const Eigen::MatrixXi & Ele,
  715. const AABB<Derivedother_V,DIM> & other,
  716. const Eigen::PlainObjectBase<Derivedother_V> & other_V,
  717. const Eigen::MatrixXi & other_Ele,
  718. Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
  719. Eigen::PlainObjectBase<DerivedI> & I,
  720. Eigen::PlainObjectBase<DerivedC> & C) const
  721. {
  722. assert(other_Ele.cols() == 1 &&
  723. "Only implemented for other as list of points");
  724. assert(other_V.cols() == V.cols() && "other must match this dimension");
  725. sqrD.setConstant(other_Ele.rows(),1,std::numeric_limits<double>::infinity());
  726. I.resize(other_Ele.rows(),1);
  727. C.resize(other_Ele.rows(),other_V.cols());
  728. // All points in other_V currently think they need to check against root of
  729. // this. The point of using another AABB is to quickly prune chunks of
  730. // other_V so that most points just check some subtree of this.
  731. // This holds a conservative estimate of max(sqr_D) where sqr_D is the
  732. // current best minimum squared distance for all points in this subtree
  733. double min_sqr_d = std::numeric_limits<double>::infinity();
  734. squared_distance_helper(
  735. V,Ele,&other,other_V,other_Ele,min_sqr_d,sqrD,I,C);
  736. }
  737. template <typename DerivedV, int DIM>
  738. template <
  739. typename Derivedother_V,
  740. typename DerivedsqrD,
  741. typename DerivedI,
  742. typename DerivedC>
  743. inline typename igl::AABB<DerivedV,DIM>::Scalar igl::AABB<DerivedV,DIM>::squared_distance_helper(
  744. const Eigen::PlainObjectBase<DerivedV> & V,
  745. const Eigen::MatrixXi & Ele,
  746. const AABB<Derivedother_V,DIM> * other,
  747. const Eigen::PlainObjectBase<Derivedother_V> & other_V,
  748. const Eigen::MatrixXi & other_Ele,
  749. const Scalar /*min_sqr_d*/,
  750. Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
  751. Eigen::PlainObjectBase<DerivedI> & I,
  752. Eigen::PlainObjectBase<DerivedC> & C) const
  753. {
  754. using namespace std;
  755. using namespace Eigen;
  756. // This implementation is a bit disappointing. There's no major speed up. Any
  757. // performance gains seem to come from accidental cache coherency and
  758. // diminish for larger "other" (the opposite of what was intended).
  759. // Base case
  760. if(other->is_leaf() && this->is_leaf())
  761. {
  762. Scalar sqr_d = sqrD(other->m_primitive);
  763. int i = I(other->m_primitive);
  764. RowVectorDIMS c = C.row( other->m_primitive);
  765. RowVectorDIMS p = other_V.row(other->m_primitive);
  766. leaf_squared_distance(V,Ele,p,sqr_d,i,c);
  767. sqrD( other->m_primitive) = sqr_d;
  768. I( other->m_primitive) = i;
  769. C.row(other->m_primitive) = c;
  770. //cout<<"leaf: "<<sqr_d<<endl;
  771. //other->m_max_sqr_d = sqr_d;
  772. return sqr_d;
  773. }
  774. if(other->is_leaf())
  775. {
  776. Scalar sqr_d = sqrD(other->m_primitive);
  777. int i = I(other->m_primitive);
  778. RowVectorDIMS c = C.row( other->m_primitive);
  779. RowVectorDIMS p = other_V.row(other->m_primitive);
  780. sqr_d = squared_distance(V,Ele,p,sqr_d,i,c);
  781. sqrD( other->m_primitive) = sqr_d;
  782. I( other->m_primitive) = i;
  783. C.row(other->m_primitive) = c;
  784. //other->m_max_sqr_d = sqr_d;
  785. return sqr_d;
  786. }
  787. //// Exact minimum squared distance between arbitary primitives inside this and
  788. //// othre's bounding boxes
  789. //const auto & min_squared_distance = [&](
  790. // const AABB<DerivedV,DIM> * A,
  791. // const AABB<Derivedother_V,DIM> * B)->Scalar
  792. //{
  793. // return A->m_box.squaredExteriorDistance(B->m_box);
  794. //};
  795. if(this->is_leaf())
  796. {
  797. //if(min_squared_distance(this,other) < other->m_max_sqr_d)
  798. if(true)
  799. {
  800. this->squared_distance_helper(
  801. V,Ele,other->m_left,other_V,other_Ele,0,sqrD,I,C);
  802. this->squared_distance_helper(
  803. V,Ele,other->m_right,other_V,other_Ele,0,sqrD,I,C);
  804. }else
  805. {
  806. // This is never reached...
  807. }
  808. //// we know other is not a leaf
  809. //other->m_max_sqr_d = std::max(other->m_left->m_max_sqr_d,other->m_right->m_max_sqr_d);
  810. return 0;
  811. }
  812. // FORCE DOWN TO OTHER LEAF EVAL
  813. //if(min_squared_distance(this,other) < other->m_max_sqr_d)
  814. if(true)
  815. {
  816. if(true)
  817. {
  818. this->squared_distance_helper(
  819. V,Ele,other->m_left,other_V,other_Ele,0,sqrD,I,C);
  820. this->squared_distance_helper(
  821. V,Ele,other->m_right,other_V,other_Ele,0,sqrD,I,C);
  822. }else // this direction never seems to be faster
  823. {
  824. this->m_left->squared_distance_helper(
  825. V,Ele,other,other_V,other_Ele,0,sqrD,I,C);
  826. this->m_right->squared_distance_helper(
  827. V,Ele,other,other_V,other_Ele,0,sqrD,I,C);
  828. }
  829. }else
  830. {
  831. // this is never reached ... :-(
  832. }
  833. //// we know other is not a leaf
  834. //other->m_max_sqr_d = std::max(other->m_left->m_max_sqr_d,other->m_right->m_max_sqr_d);
  835. return 0;
  836. #if 0 // False
  837. // _Very_ conservative approximation of maximum squared distance between
  838. // primitives inside this and other's bounding boxes
  839. const auto & max_squared_distance = [](
  840. const AABB<DerivedV,DIM> * A,
  841. const AABB<Derivedother_V,DIM> * B)->Scalar
  842. {
  843. AlignedBox<Scalar,DIM> combo = A->m_box;
  844. combo.extend(B->m_box);
  845. return combo.diagonal().squaredNorm();
  846. };
  847. //// other base-case
  848. //if(other->is_leaf())
  849. //{
  850. // double sqr_d = sqrD(other->m_primitive);
  851. // int i = I(other->m_primitive);
  852. // RowVectorDIMS c = C.row(m_primitive);
  853. // RowVectorDIMS p = other_V.row(m_primitive);
  854. // leaf_squared_distance(V,Ele,p,sqr_d,i,c);
  855. // sqrD(other->m_primitive) = sqr_d;
  856. // I(other->m_primitive) = i;
  857. // C.row(m_primitive) = c;
  858. // return;
  859. //}
  860. std::vector<const AABB<DerivedV,DIM> * > this_list;
  861. if(this->is_leaf())
  862. {
  863. this_list.push_back(this);
  864. }else
  865. {
  866. assert(this->m_left);
  867. this_list.push_back(this->m_left);
  868. assert(this->m_right);
  869. this_list.push_back(this->m_right);
  870. }
  871. std::vector<AABB<Derivedother_V,DIM> *> other_list;
  872. if(other->is_leaf())
  873. {
  874. other_list.push_back(other);
  875. }else
  876. {
  877. assert(other->m_left);
  878. other_list.push_back(other->m_left);
  879. assert(other->m_right);
  880. other_list.push_back(other->m_right);
  881. }
  882. //const std::function<Scalar(
  883. // const AABB<Derivedother_V,DIM> * other)
  884. // > max_sqr_d = [&sqrD,&max_sqr_d](const AABB<Derivedother_V,DIM> * other)->Scalar
  885. // {
  886. // if(other->is_leaf())
  887. // {
  888. // return sqrD(other->m_primitive);
  889. // }else
  890. // {
  891. // return std::max(max_sqr_d(other->m_left),max_sqr_d(other->m_right));
  892. // }
  893. // };
  894. //// Potentially recurse on all pairs, if minimum distance is less than running
  895. //// bound
  896. //Eigen::Matrix<Scalar,Eigen::Dynamic,1> other_max_sqr_d =
  897. // Eigen::Matrix<Scalar,Eigen::Dynamic,1>::Constant(other_list.size(),1,min_sqr_d);
  898. for(size_t child = 0;child<other_list.size();child++)
  899. {
  900. auto other_tree = other_list[child];
  901. Eigen::Matrix<Scalar,Eigen::Dynamic,1> this_max_sqr_d(this_list.size(),1);
  902. for(size_t t = 0;t<this_list.size();t++)
  903. {
  904. const auto this_tree = this_list[t];
  905. this_max_sqr_d(t) = max_squared_distance(this_tree,other_tree);
  906. }
  907. if(this_list.size() ==2 &&
  908. ( this_max_sqr_d(0) > this_max_sqr_d(1))
  909. )
  910. {
  911. std::swap(this_list[0],this_list[1]);
  912. //std::swap(this_max_sqr_d(0),this_max_sqr_d(1));
  913. }
  914. const Scalar sqr_d = this_max_sqr_d.minCoeff();
  915. for(size_t t = 0;t<this_list.size();t++)
  916. {
  917. const auto this_tree = this_list[t];
  918. //const auto mm = max_sqr_d(other_tree);
  919. //const Scalar mc = other_max_sqr_d(child);
  920. //assert(mc == mm);
  921. // Only look left/right in this_list if can possible decrease somebody's
  922. // distance in this_tree.
  923. const Scalar min_this_other = min_squared_distance(this_tree,other_tree);
  924. if(
  925. min_this_other < sqr_d &&
  926. min_this_other < other_tree->m_max_sqr_d)
  927. {
  928. //cout<<"before: "<<other_max_sqr_d(child)<<endl;
  929. //other_max_sqr_d(child) = std::min(
  930. // other_max_sqr_d(child),
  931. // this_tree->squared_distance_helper(
  932. // V,Ele,other_tree,other_V,other_Ele,other_max_sqr_d(child),sqrD,I,C));
  933. //cout<<"after: "<<other_max_sqr_d(child)<<endl;
  934. this_tree->squared_distance_helper(
  935. V,Ele,other_tree,other_V,other_Ele,0,sqrD,I,C);
  936. }
  937. }
  938. }
  939. //const Scalar ret = other_max_sqr_d.maxCoeff();
  940. //const auto mm = max_sqr_d(other);
  941. //assert(mm == ret);
  942. //cout<<"non-leaf: "<<ret<<endl;
  943. //return ret;
  944. if(!other->is_leaf())
  945. {
  946. other->m_max_sqr_d = std::max(other->m_left->m_max_sqr_d,other->m_right->m_max_sqr_d);
  947. }
  948. return 0;
  949. #endif
  950. }
  951. template <typename DerivedV, int DIM>
  952. inline void igl::AABB<DerivedV,DIM>::leaf_squared_distance(
  953. const Eigen::PlainObjectBase<DerivedV> & V,
  954. const Eigen::MatrixXi & Ele,
  955. const RowVectorDIMS & p,
  956. Scalar & sqr_d,
  957. int & i,
  958. RowVectorDIMS & c) const
  959. {
  960. using namespace Eigen;
  961. using namespace igl;
  962. using namespace std;
  963. // Simplex size
  964. const size_t ss = Ele.cols();
  965. // Only one element per node
  966. // plane unit normal
  967. bool inside_triangle = false;
  968. Scalar d_j = std::numeric_limits<Scalar>::infinity();
  969. RowVectorDIMS pp;
  970. // Only consider triangles, and non-degenerate triangles at that
  971. if(ss == 3 &&
  972. Ele(m_primitive,0) != Ele(m_primitive,1) &&
  973. Ele(m_primitive,1) != Ele(m_primitive,2) &&
  974. Ele(m_primitive,2) != Ele(m_primitive,0))
  975. {
  976. assert(DIM == 3 && "Only implemented for 3D triangles");
  977. typedef Eigen::Matrix<Scalar,1,3> RowVector3S;
  978. // can't be const because of annoying DIM template
  979. RowVector3S v10(0,0,0);
  980. v10.head(DIM) = (V.row(Ele(m_primitive,1))- V.row(Ele(m_primitive,0)));
  981. RowVector3S v20(0,0,0);
  982. v20.head(DIM) = (V.row(Ele(m_primitive,2))- V.row(Ele(m_primitive,0)));
  983. const RowVectorDIMS n = (v10.cross(v20)).head(DIM);
  984. Scalar n_norm = n.norm();
  985. if(n_norm > 0)
  986. {
  987. const RowVectorDIMS un = n/n.norm();
  988. // vector to plane
  989. const RowVectorDIMS bc =
  990. 1./3.*
  991. ( V.row(Ele(m_primitive,0))+
  992. V.row(Ele(m_primitive,1))+
  993. V.row(Ele(m_primitive,2)));
  994. const auto & v = p-bc;
  995. // projected point on plane
  996. d_j = v.dot(un);
  997. pp = p - d_j*un;
  998. // determine if pp is inside triangle
  999. Eigen::Matrix<Scalar,1,3> b;
  1000. barycentric_coordinates(
  1001. pp,
  1002. V.row(Ele(m_primitive,0)),
  1003. V.row(Ele(m_primitive,1)),
  1004. V.row(Ele(m_primitive,2)),
  1005. b);
  1006. inside_triangle = fabs(fabs(b(0)) + fabs(b(1)) + fabs(b(2)) - 1.) <= 1e-10;
  1007. }
  1008. }
  1009. const auto & point_point_squared_distance = [&](const RowVectorDIMS & s)
  1010. {
  1011. const Scalar sqr_d_s = (p-s).squaredNorm();
  1012. set_min(p,sqr_d_s,m_primitive,s,sqr_d,i,c);
  1013. };
  1014. if(inside_triangle)
  1015. {
  1016. // point-triangle squared distance
  1017. const Scalar sqr_d_j = d_j*d_j;
  1018. //cout<<"point-triangle..."<<endl;
  1019. set_min(p,sqr_d_j,m_primitive,pp,sqr_d,i,c);
  1020. }else
  1021. {
  1022. if(ss >= 2)
  1023. {
  1024. // point-segment distance
  1025. // number of edges
  1026. size_t ne = ss==3?3:1;
  1027. for(size_t x = 0;x<ne;x++)
  1028. {
  1029. const size_t e1 = Ele(m_primitive,(x+1)%ss);
  1030. const size_t e2 = Ele(m_primitive,(x+2)%ss);
  1031. const RowVectorDIMS & s = V.row(e1);
  1032. const RowVectorDIMS & d = V.row(e2);
  1033. // Degenerate edge
  1034. if(e1 == e2 || (s-d).squaredNorm()==0)
  1035. {
  1036. // only consider once
  1037. if(e1 < e2)
  1038. {
  1039. point_point_squared_distance(s);
  1040. }
  1041. continue;
  1042. }
  1043. Matrix<Scalar,1,1> sqr_d_j_x(1,1);
  1044. Matrix<Scalar,1,1> t(1,1);
  1045. project_to_line_segment(p,s,d,t,sqr_d_j_x);
  1046. const RowVectorDIMS q = s+t(0)*(d-s);
  1047. set_min(p,sqr_d_j_x(0),m_primitive,q,sqr_d,i,c);
  1048. }
  1049. }else
  1050. {
  1051. // So then Ele is just a list of points...
  1052. assert(ss == 1);
  1053. const RowVectorDIMS & s = V.row(Ele(m_primitive,0));
  1054. point_point_squared_distance(s);
  1055. }
  1056. }
  1057. }
  1058. template <typename DerivedV, int DIM>
  1059. inline void igl::AABB<DerivedV,DIM>::set_min(
  1060. const RowVectorDIMS &
  1061. #ifndef NDEBUG
  1062. p
  1063. #endif
  1064. ,
  1065. const Scalar sqr_d_candidate,
  1066. const int i_candidate,
  1067. const RowVectorDIMS & c_candidate,
  1068. Scalar & sqr_d,
  1069. int & i,
  1070. RowVectorDIMS & c) const
  1071. {
  1072. #ifndef NDEBUG
  1073. //std::cout<<matlab_format(c_candidate,"c_candidate")<<std::endl;
  1074. const Scalar pc_norm = (p-c_candidate).squaredNorm();
  1075. const Scalar diff = fabs(sqr_d_candidate - pc_norm);
  1076. assert(diff<=1e-10 && "distance should match norm of difference");
  1077. #endif
  1078. if(sqr_d_candidate < sqr_d)
  1079. {
  1080. i = i_candidate;
  1081. c = c_candidate;
  1082. sqr_d = sqr_d_candidate;
  1083. }
  1084. }
  1085. template <typename DerivedV, int DIM>
  1086. inline void
  1087. igl::AABB<DerivedV,DIM>::barycentric_coordinates(
  1088. const RowVectorDIMS & p,
  1089. const RowVectorDIMS & a,
  1090. const RowVectorDIMS & b,
  1091. const RowVectorDIMS & c,
  1092. Eigen::Matrix<Scalar,1,3> & bary)
  1093. {
  1094. // http://gamedev.stackexchange.com/a/23745
  1095. const RowVectorDIMS v0 = b - a;
  1096. const RowVectorDIMS v1 = c - a;
  1097. const RowVectorDIMS v2 = p - a;
  1098. Scalar d00 = v0.dot(v0);
  1099. Scalar d01 = v0.dot(v1);
  1100. Scalar d11 = v1.dot(v1);
  1101. Scalar d20 = v2.dot(v0);
  1102. Scalar d21 = v2.dot(v1);
  1103. Scalar denom = d00 * d11 - d01 * d01;
  1104. bary(1) = (d11 * d20 - d01 * d21) / denom;
  1105. bary(2) = (d00 * d21 - d01 * d20) / denom;
  1106. bary(0) = 1.0f - bary(1) - bary(2);
  1107. }
  1108. #endif