AABB.h 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142
  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. // Implementation of semi-general purpose axis-aligned bounding box hierarchy.
  11. // The mesh (V,Ele) is stored and managed by the caller and each routine here
  12. // simply takes it as references (it better not change between calls).
  13. //
  14. // It's a little annoying that the Dimension is a template parameter and not
  15. // picked up at run time from V. This leads to duplicated code for 2d/3d (up to
  16. // dim).
  17. #include <Eigen/Core>
  18. #include <Eigen/Geometry>
  19. #include <vector>
  20. namespace igl
  21. {
  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. template <int SS>
  259. static
  260. inline void barycentric_coordinates(
  261. const RowVectorDIMS & p,
  262. const RowVectorDIMS & a,
  263. const RowVectorDIMS & b,
  264. const RowVectorDIMS & c,
  265. Eigen::Matrix<Scalar,1,SS> & bary);
  266. public:
  267. EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  268. };
  269. }
  270. // Implementation
  271. #include "EPS.h"
  272. #include "barycenter.h"
  273. #include "colon.h"
  274. #include "colon.h"
  275. #include "doublearea.h"
  276. #include "matlab_format.h"
  277. #include "project_to_line_segment.h"
  278. #include "sort.h"
  279. #include "volume.h"
  280. #include <iostream>
  281. #include <iomanip>
  282. #include <limits>
  283. #include <list>
  284. template <typename DerivedV, int DIM>
  285. template <typename Derivedbb_mins, typename Derivedbb_maxs>
  286. inline void igl::AABB<DerivedV,DIM>::init(
  287. const Eigen::PlainObjectBase<DerivedV> & V,
  288. const Eigen::MatrixXi & Ele,
  289. const Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
  290. const Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
  291. const Eigen::VectorXi & elements,
  292. const int i)
  293. {
  294. using namespace std;
  295. using namespace Eigen;
  296. if(bb_mins.size() > 0)
  297. {
  298. assert(bb_mins.rows() == bb_maxs.rows() && "Serial tree arrays must match");
  299. assert(bb_mins.cols() == V.cols() && "Serial tree array dim must match V");
  300. assert(bb_mins.cols() == bb_maxs.cols() && "Serial tree arrays must match");
  301. assert(bb_mins.rows() == elements.rows() &&
  302. "Serial tree arrays must match");
  303. // construct from serialization
  304. m_box.extend(bb_mins.row(i).transpose());
  305. m_box.extend(bb_maxs.row(i).transpose());
  306. m_primitive = elements(i);
  307. // Not leaf then recurse
  308. if(m_primitive == -1)
  309. {
  310. m_left = new AABB();
  311. m_left->init( V,Ele,bb_mins,bb_maxs,elements,2*i+1);
  312. m_right = new AABB();
  313. m_right->init( V,Ele,bb_mins,bb_maxs,elements,2*i+2);
  314. //m_depth = std::max( m_left->m_depth, m_right->m_depth)+1;
  315. }
  316. }else
  317. {
  318. VectorXi allI = colon<int>(0,Ele.rows()-1);
  319. MatrixXDIMS BC;
  320. if(Ele.cols() == 1)
  321. {
  322. // points
  323. BC = V;
  324. }else
  325. {
  326. // Simplices
  327. barycenter(V,Ele,BC);
  328. }
  329. MatrixXi SI(BC.rows(),BC.cols());
  330. {
  331. MatrixXDIMS _;
  332. MatrixXi IS;
  333. igl::sort(BC,1,true,_,IS);
  334. // Need SI(i) to tell which place i would be sorted into
  335. const int dim = IS.cols();
  336. for(int i = 0;i<IS.rows();i++)
  337. {
  338. for(int d = 0;d<dim;d++)
  339. {
  340. SI(IS(i,d),d) = i;
  341. }
  342. }
  343. }
  344. init(V,Ele,SI,allI);
  345. }
  346. }
  347. template <typename DerivedV, int DIM>
  348. inline void igl::AABB<DerivedV,DIM>::init(
  349. const Eigen::PlainObjectBase<DerivedV> & V,
  350. const Eigen::MatrixXi & Ele)
  351. {
  352. using namespace Eigen;
  353. return init(V,Ele,MatrixXDIMS(),MatrixXDIMS(),VectorXi(),0);
  354. }
  355. template <typename DerivedV, int DIM>
  356. inline void igl::AABB<DerivedV,DIM>::init(
  357. const Eigen::PlainObjectBase<DerivedV> & V,
  358. const Eigen::MatrixXi & Ele,
  359. const Eigen::MatrixXi & SI,
  360. const Eigen::VectorXi & I)
  361. {
  362. using namespace Eigen;
  363. using namespace std;
  364. assert(DIM == V.cols() && "V.cols() should matched declared dimension");
  365. const Scalar inf = numeric_limits<Scalar>::infinity();
  366. m_box = AlignedBox<Scalar,DIM>();
  367. // Compute bounding box
  368. for(int i = 0;i<I.rows();i++)
  369. {
  370. for(int c = 0;c<Ele.cols();c++)
  371. {
  372. m_box.extend(V.row(Ele(I(i),c)).transpose());
  373. m_box.extend(V.row(Ele(I(i),c)).transpose());
  374. }
  375. }
  376. switch(I.size())
  377. {
  378. case 0:
  379. {
  380. assert(false);
  381. }
  382. case 1:
  383. {
  384. m_primitive = I(0);
  385. break;
  386. }
  387. default:
  388. {
  389. // Compute longest direction
  390. int max_d = -1;
  391. m_box.diagonal().maxCoeff(&max_d);
  392. // Can't use median on BC directly because many may have same value,
  393. // but can use median on sorted BC indices
  394. VectorXi SIdI(I.rows());
  395. for(int i = 0;i<I.rows();i++)
  396. {
  397. SIdI(i) = SI(I(i),max_d);
  398. }
  399. // Since later I use <= I think I don't need to worry about odd/even
  400. // Pass by copy to avoid changing input
  401. const auto median = [](VectorXi A)->Scalar
  402. {
  403. size_t n = A.size()/2;
  404. nth_element(A.data(),A.data()+n,A.data()+A.size());
  405. if(A.rows() % 2 == 1)
  406. {
  407. return A(n);
  408. }else
  409. {
  410. nth_element(A.data(),A.data()+n-1,A.data()+A.size());
  411. return 0.5*(A(n)+A(n-1));
  412. }
  413. };
  414. const Scalar med = median(SIdI);
  415. VectorXi LI((I.rows()+1)/2),RI(I.rows()/2);
  416. assert(LI.rows()+RI.rows() == I.rows());
  417. // Distribute left and right
  418. {
  419. int li = 0;
  420. int ri = 0;
  421. for(int i = 0;i<I.rows();i++)
  422. {
  423. if(SIdI(i)<=med)
  424. {
  425. LI(li++) = I(i);
  426. }else
  427. {
  428. RI(ri++) = I(i);
  429. }
  430. }
  431. }
  432. //m_depth = 0;
  433. if(LI.rows()>0)
  434. {
  435. m_left = new AABB();
  436. m_left->init(V,Ele,SI,LI);
  437. //m_depth = std::max(m_depth, m_left->m_depth+1);
  438. }
  439. if(RI.rows()>0)
  440. {
  441. m_right = new AABB();
  442. m_right->init(V,Ele,SI,RI);
  443. //m_depth = std::max(m_depth, m_right->m_depth+1);
  444. }
  445. }
  446. }
  447. }
  448. template <typename DerivedV, int DIM>
  449. inline bool igl::AABB<DerivedV,DIM>::is_leaf() const
  450. {
  451. return m_primitive != -1;
  452. }
  453. template <typename DerivedV, int DIM>
  454. template <typename Derivedq>
  455. inline std::vector<int> igl::AABB<DerivedV,DIM>::find(
  456. const Eigen::PlainObjectBase<DerivedV> & V,
  457. const Eigen::MatrixXi & Ele,
  458. const Eigen::PlainObjectBase<Derivedq> & q,
  459. const bool first) const
  460. {
  461. using namespace std;
  462. using namespace Eigen;
  463. assert(q.size() == DIM &&
  464. "Query dimension should match aabb dimension");
  465. assert(Ele.cols() == V.cols()+1 &&
  466. "AABB::find only makes sense for (d+1)-simplices");
  467. const Scalar epsilon = igl::EPS<Scalar>();
  468. // Check if outside bounding box
  469. bool inside = m_box.contains(q.transpose());
  470. if(!inside)
  471. {
  472. return std::vector<int>();
  473. }
  474. assert(m_primitive==-1 || (m_left == NULL && m_right == NULL));
  475. if(is_leaf())
  476. {
  477. // Initialize to some value > -epsilon
  478. Scalar a1=1,a2=1,a3=1,a4=1;
  479. switch(DIM)
  480. {
  481. case 3:
  482. {
  483. // Barycentric coordinates
  484. typedef Eigen::Matrix<Scalar,1,3> RowVector3S;
  485. const RowVector3S V1 = V.row(Ele(m_primitive,0));
  486. const RowVector3S V2 = V.row(Ele(m_primitive,1));
  487. const RowVector3S V3 = V.row(Ele(m_primitive,2));
  488. const RowVector3S V4 = V.row(Ele(m_primitive,3));
  489. a1 = volume_single(V2,V4,V3,(RowVector3S)q);
  490. a2 = volume_single(V1,V3,V4,(RowVector3S)q);
  491. a3 = volume_single(V1,V4,V2,(RowVector3S)q);
  492. a4 = volume_single(V1,V2,V3,(RowVector3S)q);
  493. break;
  494. }
  495. case 2:
  496. {
  497. // Barycentric coordinates
  498. typedef Eigen::Matrix<Scalar,2,1> Vector2S;
  499. const Vector2S V1 = V.row(Ele(m_primitive,0));
  500. const Vector2S V2 = V.row(Ele(m_primitive,1));
  501. const Vector2S V3 = V.row(Ele(m_primitive,2));
  502. // Hack for now to keep templates simple. If becomes bottleneck
  503. // consider using std::enable_if_t
  504. const Vector2S q2 = q.head(2);
  505. Scalar a0 = doublearea_single(V1,V2,V3);
  506. a1 = doublearea_single(V1,V2,q2);
  507. a2 = doublearea_single(V2,V3,q2);
  508. a3 = doublearea_single(V3,V1,q2);
  509. break;
  510. }
  511. default:assert(false);
  512. }
  513. if(
  514. a1>=-epsilon &&
  515. a2>=-epsilon &&
  516. a3>=-epsilon &&
  517. a4>=-epsilon)
  518. {
  519. return std::vector<int>(1,m_primitive);
  520. }else
  521. {
  522. return std::vector<int>();
  523. }
  524. }
  525. std::vector<int> left = m_left->find(V,Ele,q,first);
  526. if(first && !left.empty())
  527. {
  528. return left;
  529. }
  530. std::vector<int> right = m_right->find(V,Ele,q,first);
  531. if(first)
  532. {
  533. return right;
  534. }
  535. left.insert(left.end(),right.begin(),right.end());
  536. return left;
  537. }
  538. template <typename DerivedV, int DIM>
  539. inline int igl::AABB<DerivedV,DIM>::subtree_size() const
  540. {
  541. // 1 for self
  542. int n = 1;
  543. int n_left = 0,n_right = 0;
  544. if(m_left != NULL)
  545. {
  546. n_left = m_left->subtree_size();
  547. }
  548. if(m_right != NULL)
  549. {
  550. n_right = m_right->subtree_size();
  551. }
  552. n += 2*std::max(n_left,n_right);
  553. return n;
  554. }
  555. template <typename DerivedV, int DIM>
  556. template <typename Derivedbb_mins, typename Derivedbb_maxs>
  557. inline void igl::AABB<DerivedV,DIM>::serialize(
  558. Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
  559. Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
  560. Eigen::VectorXi & elements,
  561. const int i) const
  562. {
  563. using namespace std;
  564. using namespace Eigen;
  565. // Calling for root then resize output
  566. if(i==0)
  567. {
  568. const int m = subtree_size();
  569. //cout<<"m: "<<m<<endl;
  570. bb_mins.resize(m,DIM);
  571. bb_maxs.resize(m,DIM);
  572. elements.resize(m,1);
  573. }
  574. //cout<<i<<" ";
  575. bb_mins.row(i) = m_box.min();
  576. bb_maxs.row(i) = m_box.max();
  577. elements(i) = m_primitive;
  578. if(m_left != NULL)
  579. {
  580. m_left->serialize(bb_mins,bb_maxs,elements,2*i+1);
  581. }
  582. if(m_right != NULL)
  583. {
  584. m_right->serialize(bb_mins,bb_maxs,elements,2*i+2);
  585. }
  586. }
  587. template <typename DerivedV, int DIM>
  588. inline typename igl::AABB<DerivedV,DIM>::Scalar
  589. igl::AABB<DerivedV,DIM>::squared_distance(
  590. const Eigen::PlainObjectBase<DerivedV> & V,
  591. const Eigen::MatrixXi & Ele,
  592. const RowVectorDIMS & p,
  593. int & i,
  594. RowVectorDIMS & c) const
  595. {
  596. return squared_distance(V,Ele,p,std::numeric_limits<Scalar>::infinity(),i,c);
  597. }
  598. template <typename DerivedV, int DIM>
  599. inline typename igl::AABB<DerivedV,DIM>::Scalar
  600. igl::AABB<DerivedV,DIM>::squared_distance(
  601. const Eigen::PlainObjectBase<DerivedV> & V,
  602. const Eigen::MatrixXi & Ele,
  603. const RowVectorDIMS & p,
  604. Scalar min_sqr_d,
  605. int & i,
  606. RowVectorDIMS & c) const
  607. {
  608. using namespace Eigen;
  609. using namespace std;
  610. using namespace igl;
  611. Scalar sqr_d = min_sqr_d;
  612. assert(DIM == 3 && "Code has only been tested for DIM == 3");
  613. assert((Ele.cols() == 3 || Ele.cols() == 2 || Ele.cols() == 1)
  614. && "Code has only been tested for simplex sizes 3,2,1");
  615. assert(m_primitive==-1 || (m_left == NULL && m_right == NULL));
  616. if(is_leaf())
  617. {
  618. leaf_squared_distance(V,Ele,p,sqr_d,i,c);
  619. }else
  620. {
  621. bool looked_left = false;
  622. bool looked_right = false;
  623. const auto & look_left = [&]()
  624. {
  625. int i_left;
  626. RowVectorDIMS c_left = c;
  627. Scalar sqr_d_left = m_left->squared_distance(V,Ele,p,sqr_d,i_left,c_left);
  628. set_min(p,sqr_d_left,i_left,c_left,sqr_d,i,c);
  629. looked_left = true;
  630. };
  631. const auto & look_right = [&]()
  632. {
  633. int i_right;
  634. RowVectorDIMS c_right = c;
  635. Scalar sqr_d_right = m_right->squared_distance(V,Ele,p,sqr_d,i_right,c_right);
  636. set_min(p,sqr_d_right,i_right,c_right,sqr_d,i,c);
  637. looked_right = true;
  638. };
  639. // must look left or right if in box
  640. if(m_left->m_box.contains(p.transpose()))
  641. {
  642. look_left();
  643. }
  644. if(m_right->m_box.contains(p.transpose()))
  645. {
  646. look_right();
  647. }
  648. // if haven't looked left and could be less than current min, then look
  649. Scalar left_min_sqr_d = m_left->m_box.squaredExteriorDistance(p.transpose());
  650. Scalar right_min_sqr_d = m_right->m_box.squaredExteriorDistance(p.transpose());
  651. if(left_min_sqr_d < right_min_sqr_d)
  652. {
  653. if(!looked_left && left_min_sqr_d<sqr_d)
  654. {
  655. look_left();
  656. }
  657. if( !looked_right && right_min_sqr_d<sqr_d)
  658. {
  659. look_right();
  660. }
  661. }else
  662. {
  663. if( !looked_right && right_min_sqr_d<sqr_d)
  664. {
  665. look_right();
  666. }
  667. if(!looked_left && left_min_sqr_d<sqr_d)
  668. {
  669. look_left();
  670. }
  671. }
  672. }
  673. return sqr_d;
  674. }
  675. template <typename DerivedV, int DIM>
  676. template <
  677. typename DerivedP,
  678. typename DerivedsqrD,
  679. typename DerivedI,
  680. typename DerivedC>
  681. inline void igl::AABB<DerivedV,DIM>::squared_distance(
  682. const Eigen::PlainObjectBase<DerivedV> & V,
  683. const Eigen::MatrixXi & Ele,
  684. const Eigen::PlainObjectBase<DerivedP> & P,
  685. Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
  686. Eigen::PlainObjectBase<DerivedI> & I,
  687. Eigen::PlainObjectBase<DerivedC> & C) const
  688. {
  689. assert(P.cols() == V.cols() && "cols in P should match dim of cols in V");
  690. sqrD.resize(P.rows(),1);
  691. I.resize(P.rows(),1);
  692. C.resize(P.rows(),P.cols());
  693. for(int p = 0;p<P.rows();p++)
  694. {
  695. RowVectorDIMS Pp = P.row(p), c;
  696. int Ip;
  697. sqrD(p) = squared_distance(V,Ele,Pp,Ip,c);
  698. I(p) = Ip;
  699. C.row(p) = c;
  700. }
  701. }
  702. template <typename DerivedV, int DIM>
  703. template <
  704. typename Derivedother_V,
  705. typename DerivedsqrD,
  706. typename DerivedI,
  707. typename DerivedC>
  708. inline void igl::AABB<DerivedV,DIM>::squared_distance(
  709. const Eigen::PlainObjectBase<DerivedV> & V,
  710. const Eigen::MatrixXi & Ele,
  711. const AABB<Derivedother_V,DIM> & other,
  712. const Eigen::PlainObjectBase<Derivedother_V> & other_V,
  713. const Eigen::MatrixXi & other_Ele,
  714. Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
  715. Eigen::PlainObjectBase<DerivedI> & I,
  716. Eigen::PlainObjectBase<DerivedC> & C) const
  717. {
  718. assert(other_Ele.cols() == 1 &&
  719. "Only implemented for other as list of points");
  720. assert(other_V.cols() == V.cols() && "other must match this dimension");
  721. sqrD.setConstant(other_Ele.rows(),1,std::numeric_limits<double>::infinity());
  722. I.resize(other_Ele.rows(),1);
  723. C.resize(other_Ele.rows(),other_V.cols());
  724. // All points in other_V currently think they need to check against root of
  725. // this. The point of using another AABB is to quickly prune chunks of
  726. // other_V so that most points just check some subtree of this.
  727. // This holds a conservative estimate of max(sqr_D) where sqr_D is the
  728. // current best minimum squared distance for all points in this subtree
  729. double min_sqr_d = std::numeric_limits<double>::infinity();
  730. squared_distance_helper(
  731. V,Ele,&other,other_V,other_Ele,min_sqr_d,sqrD,I,C);
  732. }
  733. template <typename DerivedV, int DIM>
  734. template <
  735. typename Derivedother_V,
  736. typename DerivedsqrD,
  737. typename DerivedI,
  738. typename DerivedC>
  739. inline typename igl::AABB<DerivedV,DIM>::Scalar igl::AABB<DerivedV,DIM>::squared_distance_helper(
  740. const Eigen::PlainObjectBase<DerivedV> & V,
  741. const Eigen::MatrixXi & Ele,
  742. const AABB<Derivedother_V,DIM> * other,
  743. const Eigen::PlainObjectBase<Derivedother_V> & other_V,
  744. const Eigen::MatrixXi & other_Ele,
  745. const Scalar min_sqr_d,
  746. Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
  747. Eigen::PlainObjectBase<DerivedI> & I,
  748. Eigen::PlainObjectBase<DerivedC> & C) const
  749. {
  750. using namespace std;
  751. using namespace Eigen;
  752. // This implementation is a bit disappointing. There's no major speed up. Any
  753. // performance gains seem to come from accidental cache coherency and
  754. // diminish for larger "other" (the opposite of what was intended).
  755. // Base case
  756. if(other->is_leaf() && this->is_leaf())
  757. {
  758. Scalar sqr_d = sqrD(other->m_primitive);
  759. int i = I(other->m_primitive);
  760. RowVectorDIMS c = C.row( other->m_primitive);
  761. RowVectorDIMS p = other_V.row(other->m_primitive);
  762. leaf_squared_distance(V,Ele,p,sqr_d,i,c);
  763. sqrD( other->m_primitive) = sqr_d;
  764. I( other->m_primitive) = i;
  765. C.row(other->m_primitive) = c;
  766. //cout<<"leaf: "<<sqr_d<<endl;
  767. //other->m_max_sqr_d = sqr_d;
  768. return sqr_d;
  769. }
  770. if(other->is_leaf())
  771. {
  772. Scalar sqr_d = sqrD(other->m_primitive);
  773. int i = I(other->m_primitive);
  774. RowVectorDIMS c = C.row( other->m_primitive);
  775. RowVectorDIMS p = other_V.row(other->m_primitive);
  776. sqr_d = squared_distance(V,Ele,p,sqr_d,i,c);
  777. sqrD( other->m_primitive) = sqr_d;
  778. I( other->m_primitive) = i;
  779. C.row(other->m_primitive) = c;
  780. //other->m_max_sqr_d = sqr_d;
  781. return sqr_d;
  782. }
  783. //// Exact minimum squared distance between arbitary primitives inside this and
  784. //// othre's bounding boxes
  785. //const auto & min_squared_distance = [&](
  786. // const AABB<DerivedV,DIM> * A,
  787. // const AABB<Derivedother_V,DIM> * B)->Scalar
  788. //{
  789. // return A->m_box.squaredExteriorDistance(B->m_box);
  790. //};
  791. if(this->is_leaf())
  792. {
  793. //if(min_squared_distance(this,other) < other->m_max_sqr_d)
  794. if(true)
  795. {
  796. this->squared_distance_helper(
  797. V,Ele,other->m_left,other_V,other_Ele,0,sqrD,I,C);
  798. this->squared_distance_helper(
  799. V,Ele,other->m_right,other_V,other_Ele,0,sqrD,I,C);
  800. }else
  801. {
  802. // This is never reached...
  803. }
  804. //// we know other is not a leaf
  805. //other->m_max_sqr_d = std::max(other->m_left->m_max_sqr_d,other->m_right->m_max_sqr_d);
  806. return 0;
  807. }
  808. // FORCE DOWN TO OTHER LEAF EVAL
  809. //if(min_squared_distance(this,other) < other->m_max_sqr_d)
  810. if(true)
  811. {
  812. if(true)
  813. {
  814. this->squared_distance_helper(
  815. V,Ele,other->m_left,other_V,other_Ele,0,sqrD,I,C);
  816. this->squared_distance_helper(
  817. V,Ele,other->m_right,other_V,other_Ele,0,sqrD,I,C);
  818. }else // this direction never seems to be faster
  819. {
  820. this->m_left->squared_distance_helper(
  821. V,Ele,other,other_V,other_Ele,0,sqrD,I,C);
  822. this->m_right->squared_distance_helper(
  823. V,Ele,other,other_V,other_Ele,0,sqrD,I,C);
  824. }
  825. }else
  826. {
  827. // this is never reached ... :-(
  828. }
  829. //// we know other is not a leaf
  830. //other->m_max_sqr_d = std::max(other->m_left->m_max_sqr_d,other->m_right->m_max_sqr_d);
  831. return 0;
  832. #if false
  833. // _Very_ conservative approximation of maximum squared distance between
  834. // primitives inside this and other's bounding boxes
  835. const auto & max_squared_distance = [](
  836. const AABB<DerivedV,DIM> * A,
  837. const AABB<Derivedother_V,DIM> * B)->Scalar
  838. {
  839. AlignedBox<Scalar,DIM> combo = A->m_box;
  840. combo.extend(B->m_box);
  841. return combo.diagonal().squaredNorm();
  842. };
  843. //// other base-case
  844. //if(other->is_leaf())
  845. //{
  846. // double sqr_d = sqrD(other->m_primitive);
  847. // int i = I(other->m_primitive);
  848. // RowVectorDIMS c = C.row(m_primitive);
  849. // RowVectorDIMS p = other_V.row(m_primitive);
  850. // leaf_squared_distance(V,Ele,p,sqr_d,i,c);
  851. // sqrD(other->m_primitive) = sqr_d;
  852. // I(other->m_primitive) = i;
  853. // C.row(m_primitive) = c;
  854. // return;
  855. //}
  856. std::vector<const AABB<DerivedV,DIM> * > this_list;
  857. if(this->is_leaf())
  858. {
  859. this_list.push_back(this);
  860. }else
  861. {
  862. assert(this->m_left);
  863. this_list.push_back(this->m_left);
  864. assert(this->m_right);
  865. this_list.push_back(this->m_right);
  866. }
  867. std::vector<AABB<Derivedother_V,DIM> *> other_list;
  868. if(other->is_leaf())
  869. {
  870. other_list.push_back(other);
  871. }else
  872. {
  873. assert(other->m_left);
  874. other_list.push_back(other->m_left);
  875. assert(other->m_right);
  876. other_list.push_back(other->m_right);
  877. }
  878. //const std::function<Scalar(
  879. // const AABB<Derivedother_V,DIM> * other)
  880. // > max_sqr_d = [&sqrD,&max_sqr_d](const AABB<Derivedother_V,DIM> * other)->Scalar
  881. // {
  882. // if(other->is_leaf())
  883. // {
  884. // return sqrD(other->m_primitive);
  885. // }else
  886. // {
  887. // return std::max(max_sqr_d(other->m_left),max_sqr_d(other->m_right));
  888. // }
  889. // };
  890. //// Potentially recurse on all pairs, if minimum distance is less than running
  891. //// bound
  892. //Eigen::Matrix<Scalar,Eigen::Dynamic,1> other_max_sqr_d =
  893. // Eigen::Matrix<Scalar,Eigen::Dynamic,1>::Constant(other_list.size(),1,min_sqr_d);
  894. for(size_t child = 0;child<other_list.size();child++)
  895. {
  896. auto other_tree = other_list[child];
  897. Eigen::Matrix<Scalar,Eigen::Dynamic,1> this_max_sqr_d(this_list.size(),1);
  898. for(size_t t = 0;t<this_list.size();t++)
  899. {
  900. const auto this_tree = this_list[t];
  901. this_max_sqr_d(t) = max_squared_distance(this_tree,other_tree);
  902. }
  903. if(this_list.size() ==2 &&
  904. ( this_max_sqr_d(0) > this_max_sqr_d(1))
  905. )
  906. {
  907. std::swap(this_list[0],this_list[1]);
  908. //std::swap(this_max_sqr_d(0),this_max_sqr_d(1));
  909. }
  910. const Scalar sqr_d = this_max_sqr_d.minCoeff();
  911. for(size_t t = 0;t<this_list.size();t++)
  912. {
  913. const auto this_tree = this_list[t];
  914. //const auto mm = max_sqr_d(other_tree);
  915. //const Scalar mc = other_max_sqr_d(child);
  916. //assert(mc == mm);
  917. // Only look left/right in this_list if can possible decrease somebody's
  918. // distance in this_tree.
  919. const Scalar min_this_other = min_squared_distance(this_tree,other_tree);
  920. if(
  921. min_this_other < sqr_d &&
  922. min_this_other < other_tree->m_max_sqr_d)
  923. {
  924. //cout<<"before: "<<other_max_sqr_d(child)<<endl;
  925. //other_max_sqr_d(child) = std::min(
  926. // other_max_sqr_d(child),
  927. // this_tree->squared_distance_helper(
  928. // V,Ele,other_tree,other_V,other_Ele,other_max_sqr_d(child),sqrD,I,C));
  929. //cout<<"after: "<<other_max_sqr_d(child)<<endl;
  930. this_tree->squared_distance_helper(
  931. V,Ele,other_tree,other_V,other_Ele,0,sqrD,I,C);
  932. }
  933. }
  934. }
  935. //const Scalar ret = other_max_sqr_d.maxCoeff();
  936. //const auto mm = max_sqr_d(other);
  937. //assert(mm == ret);
  938. //cout<<"non-leaf: "<<ret<<endl;
  939. //return ret;
  940. if(!other->is_leaf())
  941. {
  942. other->m_max_sqr_d = std::max(other->m_left->m_max_sqr_d,other->m_right->m_max_sqr_d);
  943. }
  944. return 0;
  945. #endif
  946. }
  947. template <typename DerivedV, int DIM>
  948. inline void igl::AABB<DerivedV,DIM>::leaf_squared_distance(
  949. const Eigen::PlainObjectBase<DerivedV> & V,
  950. const Eigen::MatrixXi & Ele,
  951. const RowVectorDIMS & p,
  952. Scalar & sqr_d,
  953. int & i,
  954. RowVectorDIMS & c) const
  955. {
  956. using namespace Eigen;
  957. using namespace igl;
  958. using namespace std;
  959. // Simplex size
  960. const size_t ss = Ele.cols();
  961. // Only one element per node
  962. // plane unit normal
  963. bool inside_triangle = false;
  964. Scalar d_j = std::numeric_limits<Scalar>::infinity();
  965. RowVectorDIMS pp;
  966. // Only consider triangles, and non-degenerate triangles at that
  967. if(ss == 3 &&
  968. Ele(m_primitive,0) != Ele(m_primitive,1) &&
  969. Ele(m_primitive,1) != Ele(m_primitive,2) &&
  970. Ele(m_primitive,2) != Ele(m_primitive,0))
  971. {
  972. const RowVectorDIMS v10 = (V.row(Ele(m_primitive,1))- V.row(Ele(m_primitive,0)));
  973. const RowVectorDIMS v20 = (V.row(Ele(m_primitive,2))- V.row(Ele(m_primitive,0)));
  974. const RowVectorDIMS n = v10.cross(v20);
  975. Scalar n_norm = n.norm();
  976. if(n_norm > 0)
  977. {
  978. const RowVectorDIMS un = n/n.norm();
  979. // vector to plane
  980. const RowVectorDIMS bc =
  981. 1./3.*
  982. ( V.row(Ele(m_primitive,0))+
  983. V.row(Ele(m_primitive,1))+
  984. V.row(Ele(m_primitive,2)));
  985. const auto & v = p-bc;
  986. // projected point on plane
  987. d_j = v.dot(un);
  988. pp = p - d_j*un;
  989. // determine if pp is inside triangle
  990. Eigen::Matrix<Scalar,1,3> b;
  991. barycentric_coordinates(
  992. pp,
  993. V.row(Ele(m_primitive,0)),
  994. V.row(Ele(m_primitive,1)),
  995. V.row(Ele(m_primitive,2)),
  996. b);
  997. inside_triangle = fabs(fabs(b(0)) + fabs(b(1)) + fabs(b(2)) - 1.) <= 1e-10;
  998. }
  999. }
  1000. const auto & point_point_squared_distance = [&](const RowVectorDIMS & s)
  1001. {
  1002. cout<<"pp"<<endl;
  1003. const Scalar sqr_d_s = (p-s).squaredNorm();
  1004. set_min(p,sqr_d_s,m_primitive,s,sqr_d,i,c);
  1005. };
  1006. if(inside_triangle)
  1007. {
  1008. // point-triangle squared distance
  1009. const Scalar sqr_d_j = d_j*d_j;
  1010. //cout<<"point-triangle..."<<endl;
  1011. set_min(p,sqr_d_j,m_primitive,pp,sqr_d,i,c);
  1012. }else
  1013. {
  1014. if(ss >= 2)
  1015. {
  1016. // point-segment distance
  1017. // number of edges
  1018. size_t ne = ss==3?3:1;
  1019. for(size_t x = 0;x<ne;x++)
  1020. {
  1021. const size_t e1 = Ele(m_primitive,(x+1)%ss);
  1022. const size_t e2 = Ele(m_primitive,(x+2)%ss);
  1023. const RowVectorDIMS & s = V.row(e1);
  1024. const RowVectorDIMS & d = V.row(e2);
  1025. // Degenerate edge
  1026. if(e1 == e2 || (s-d).squaredNorm()==0)
  1027. {
  1028. // only consider once
  1029. if(e1 < e2)
  1030. {
  1031. point_point_squared_distance(s);
  1032. }
  1033. continue;
  1034. }
  1035. Matrix<Scalar,1,1> sqr_d_j_x(1,1);
  1036. Matrix<Scalar,1,1> t(1,1);
  1037. project_to_line_segment(p,s,d,t,sqr_d_j_x);
  1038. const RowVectorDIMS q = s+t(0)*(d-s);
  1039. set_min(p,sqr_d_j_x(0),m_primitive,q,sqr_d,i,c);
  1040. }
  1041. }else
  1042. {
  1043. // So then Ele is just a list of points...
  1044. assert(ss == 1);
  1045. const RowVectorDIMS & s = V.row(Ele(m_primitive,0));
  1046. point_point_squared_distance(s);
  1047. }
  1048. }
  1049. }
  1050. template <typename DerivedV, int DIM>
  1051. inline void igl::AABB<DerivedV,DIM>::set_min(
  1052. const RowVectorDIMS & p,
  1053. const Scalar sqr_d_candidate,
  1054. const int i_candidate,
  1055. const RowVectorDIMS & c_candidate,
  1056. Scalar & sqr_d,
  1057. int & i,
  1058. RowVectorDIMS & c) const
  1059. {
  1060. #ifndef NDEBUG
  1061. //std::cout<<matlab_format(c_candidate,"c_candidate")<<std::endl;
  1062. const Scalar pc_norm = (p-c_candidate).squaredNorm();
  1063. const Scalar diff = fabs(sqr_d_candidate - pc_norm);
  1064. assert(diff<=1e-10 && "distance should match norm of difference");
  1065. #endif
  1066. if(sqr_d_candidate < sqr_d)
  1067. {
  1068. i = i_candidate;
  1069. c = c_candidate;
  1070. sqr_d = sqr_d_candidate;
  1071. }
  1072. }
  1073. template <typename DerivedV, int DIM>
  1074. template <int SS>
  1075. inline void
  1076. igl::AABB<DerivedV,DIM>::barycentric_coordinates(
  1077. const RowVectorDIMS & p,
  1078. const RowVectorDIMS & a,
  1079. const RowVectorDIMS & b,
  1080. const RowVectorDIMS & c,
  1081. Eigen::Matrix<Scalar,1,SS> & bary)
  1082. {
  1083. assert(SS==3);
  1084. // http://gamedev.stackexchange.com/a/23745
  1085. const RowVectorDIMS v0 = b - a;
  1086. const RowVectorDIMS v1 = c - a;
  1087. const RowVectorDIMS v2 = p - a;
  1088. Scalar d00 = v0.dot(v0);
  1089. Scalar d01 = v0.dot(v1);
  1090. Scalar d11 = v1.dot(v1);
  1091. Scalar d20 = v2.dot(v0);
  1092. Scalar d21 = v2.dot(v1);
  1093. Scalar denom = d00 * d11 - d01 * d01;
  1094. bary(1) = (d11 * d20 - d01 * d21) / denom;
  1095. bary(2) = (d00 * d21 - d01 * d20) / denom;
  1096. bary(0) = 1.0f - bary(1) - bary(2);
  1097. };
  1098. #endif