AABB.h 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139
  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. 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=1,a2=1,a3=1,a4=1;
  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. Scalar a0 = doublearea_single(V1,V2,V3);
  505. a1 = doublearea_single(V1,V2,q2);
  506. a2 = doublearea_single(V2,V3,q2);
  507. a3 = doublearea_single(V3,V1,q2);
  508. break;
  509. }
  510. default:assert(false);
  511. }
  512. if(
  513. a1>=-epsilon &&
  514. a2>=-epsilon &&
  515. a3>=-epsilon &&
  516. a4>=-epsilon)
  517. {
  518. return std::vector<int>(1,m_primitive);
  519. }else
  520. {
  521. return std::vector<int>();
  522. }
  523. }
  524. std::vector<int> left = m_left->find(V,Ele,q,first);
  525. if(first && !left.empty())
  526. {
  527. return left;
  528. }
  529. std::vector<int> right = m_right->find(V,Ele,q,first);
  530. if(first)
  531. {
  532. return right;
  533. }
  534. left.insert(left.end(),right.begin(),right.end());
  535. return left;
  536. }
  537. template <typename DerivedV, int DIM>
  538. inline int igl::AABB<DerivedV,DIM>::subtree_size() const
  539. {
  540. // 1 for self
  541. int n = 1;
  542. int n_left = 0,n_right = 0;
  543. if(m_left != NULL)
  544. {
  545. n_left = m_left->subtree_size();
  546. }
  547. if(m_right != NULL)
  548. {
  549. n_right = m_right->subtree_size();
  550. }
  551. n += 2*std::max(n_left,n_right);
  552. return n;
  553. }
  554. template <typename DerivedV, int DIM>
  555. template <typename Derivedbb_mins, typename Derivedbb_maxs>
  556. inline void igl::AABB<DerivedV,DIM>::serialize(
  557. Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
  558. Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
  559. Eigen::VectorXi & elements,
  560. const int i) const
  561. {
  562. using namespace std;
  563. using namespace Eigen;
  564. // Calling for root then resize output
  565. if(i==0)
  566. {
  567. const int m = subtree_size();
  568. //cout<<"m: "<<m<<endl;
  569. bb_mins.resize(m,DIM);
  570. bb_maxs.resize(m,DIM);
  571. elements.resize(m,1);
  572. }
  573. //cout<<i<<" ";
  574. bb_mins.row(i) = m_box.min();
  575. bb_maxs.row(i) = m_box.max();
  576. elements(i) = m_primitive;
  577. if(m_left != NULL)
  578. {
  579. m_left->serialize(bb_mins,bb_maxs,elements,2*i+1);
  580. }
  581. if(m_right != NULL)
  582. {
  583. m_right->serialize(bb_mins,bb_maxs,elements,2*i+2);
  584. }
  585. }
  586. template <typename DerivedV, int DIM>
  587. inline typename igl::AABB<DerivedV,DIM>::Scalar
  588. igl::AABB<DerivedV,DIM>::squared_distance(
  589. const Eigen::PlainObjectBase<DerivedV> & V,
  590. const Eigen::MatrixXi & Ele,
  591. const RowVectorDIMS & p,
  592. int & i,
  593. RowVectorDIMS & c) const
  594. {
  595. return squared_distance(V,Ele,p,std::numeric_limits<Scalar>::infinity(),i,c);
  596. }
  597. template <typename DerivedV, int DIM>
  598. inline typename igl::AABB<DerivedV,DIM>::Scalar
  599. igl::AABB<DerivedV,DIM>::squared_distance(
  600. const Eigen::PlainObjectBase<DerivedV> & V,
  601. const Eigen::MatrixXi & Ele,
  602. const RowVectorDIMS & p,
  603. Scalar min_sqr_d,
  604. int & i,
  605. RowVectorDIMS & c) const
  606. {
  607. using namespace Eigen;
  608. using namespace std;
  609. using namespace igl;
  610. Scalar sqr_d = min_sqr_d;
  611. assert(DIM == 3 && "Code has only been tested for DIM == 3");
  612. assert((Ele.cols() == 3 || Ele.cols() == 2 || Ele.cols() == 1)
  613. && "Code has only been tested for simplex sizes 3,2,1");
  614. assert(m_primitive==-1 || (m_left == NULL && m_right == NULL));
  615. if(is_leaf())
  616. {
  617. leaf_squared_distance(V,Ele,p,sqr_d,i,c);
  618. }else
  619. {
  620. bool looked_left = false;
  621. bool looked_right = false;
  622. const auto & look_left = [&]()
  623. {
  624. int i_left;
  625. RowVectorDIMS c_left = c;
  626. Scalar sqr_d_left = m_left->squared_distance(V,Ele,p,sqr_d,i_left,c_left);
  627. set_min(p,sqr_d_left,i_left,c_left,sqr_d,i,c);
  628. looked_left = true;
  629. };
  630. const auto & look_right = [&]()
  631. {
  632. int i_right;
  633. RowVectorDIMS c_right = c;
  634. Scalar sqr_d_right = m_right->squared_distance(V,Ele,p,sqr_d,i_right,c_right);
  635. set_min(p,sqr_d_right,i_right,c_right,sqr_d,i,c);
  636. looked_right = true;
  637. };
  638. // must look left or right if in box
  639. if(m_left->m_box.contains(p.transpose()))
  640. {
  641. look_left();
  642. }
  643. if(m_right->m_box.contains(p.transpose()))
  644. {
  645. look_right();
  646. }
  647. // if haven't looked left and could be less than current min, then look
  648. Scalar left_min_sqr_d = m_left->m_box.squaredExteriorDistance(p.transpose());
  649. Scalar right_min_sqr_d = m_right->m_box.squaredExteriorDistance(p.transpose());
  650. if(left_min_sqr_d < right_min_sqr_d)
  651. {
  652. if(!looked_left && left_min_sqr_d<sqr_d)
  653. {
  654. look_left();
  655. }
  656. if( !looked_right && right_min_sqr_d<sqr_d)
  657. {
  658. look_right();
  659. }
  660. }else
  661. {
  662. if( !looked_right && right_min_sqr_d<sqr_d)
  663. {
  664. look_right();
  665. }
  666. if(!looked_left && left_min_sqr_d<sqr_d)
  667. {
  668. look_left();
  669. }
  670. }
  671. }
  672. return sqr_d;
  673. }
  674. template <typename DerivedV, int DIM>
  675. template <
  676. typename DerivedP,
  677. typename DerivedsqrD,
  678. typename DerivedI,
  679. typename DerivedC>
  680. inline void igl::AABB<DerivedV,DIM>::squared_distance(
  681. const Eigen::PlainObjectBase<DerivedV> & V,
  682. const Eigen::MatrixXi & Ele,
  683. const Eigen::PlainObjectBase<DerivedP> & P,
  684. Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
  685. Eigen::PlainObjectBase<DerivedI> & I,
  686. Eigen::PlainObjectBase<DerivedC> & C) const
  687. {
  688. assert(P.cols() == V.cols() && "cols in P should match dim of cols in V");
  689. sqrD.resize(P.rows(),1);
  690. I.resize(P.rows(),1);
  691. C.resize(P.rows(),P.cols());
  692. for(int p = 0;p<P.rows();p++)
  693. {
  694. RowVectorDIMS Pp = P.row(p), c;
  695. int Ip;
  696. sqrD(p) = squared_distance(V,Ele,Pp,Ip,c);
  697. I(p) = Ip;
  698. C.row(p) = c;
  699. }
  700. }
  701. template <typename DerivedV, int DIM>
  702. template <
  703. typename Derivedother_V,
  704. typename DerivedsqrD,
  705. typename DerivedI,
  706. typename DerivedC>
  707. inline void igl::AABB<DerivedV,DIM>::squared_distance(
  708. const Eigen::PlainObjectBase<DerivedV> & V,
  709. const Eigen::MatrixXi & Ele,
  710. const AABB<Derivedother_V,DIM> & other,
  711. const Eigen::PlainObjectBase<Derivedother_V> & other_V,
  712. const Eigen::MatrixXi & other_Ele,
  713. Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
  714. Eigen::PlainObjectBase<DerivedI> & I,
  715. Eigen::PlainObjectBase<DerivedC> & C) const
  716. {
  717. assert(other_Ele.cols() == 1 &&
  718. "Only implemented for other as list of points");
  719. assert(other_V.cols() == V.cols() && "other must match this dimension");
  720. sqrD.setConstant(other_Ele.rows(),1,std::numeric_limits<double>::infinity());
  721. I.resize(other_Ele.rows(),1);
  722. C.resize(other_Ele.rows(),other_V.cols());
  723. // All points in other_V currently think they need to check against root of
  724. // this. The point of using another AABB is to quickly prune chunks of
  725. // other_V so that most points just check some subtree of this.
  726. // This holds a conservative estimate of max(sqr_D) where sqr_D is the
  727. // current best minimum squared distance for all points in this subtree
  728. double min_sqr_d = std::numeric_limits<double>::infinity();
  729. squared_distance_helper(
  730. V,Ele,&other,other_V,other_Ele,min_sqr_d,sqrD,I,C);
  731. }
  732. template <typename DerivedV, int DIM>
  733. template <
  734. typename Derivedother_V,
  735. typename DerivedsqrD,
  736. typename DerivedI,
  737. typename DerivedC>
  738. inline typename igl::AABB<DerivedV,DIM>::Scalar igl::AABB<DerivedV,DIM>::squared_distance_helper(
  739. const Eigen::PlainObjectBase<DerivedV> & V,
  740. const Eigen::MatrixXi & Ele,
  741. const AABB<Derivedother_V,DIM> * other,
  742. const Eigen::PlainObjectBase<Derivedother_V> & other_V,
  743. const Eigen::MatrixXi & other_Ele,
  744. const Scalar min_sqr_d,
  745. Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
  746. Eigen::PlainObjectBase<DerivedI> & I,
  747. Eigen::PlainObjectBase<DerivedC> & C) const
  748. {
  749. using namespace std;
  750. using namespace Eigen;
  751. // This implementation is a bit disappointing. There's no major speed up. Any
  752. // performance gains seem to come from accidental cache coherency and
  753. // diminish for larger "other" (the opposite of what was intended).
  754. // Base case
  755. if(other->is_leaf() && this->is_leaf())
  756. {
  757. Scalar sqr_d = sqrD(other->m_primitive);
  758. int i = I(other->m_primitive);
  759. RowVectorDIMS c = C.row( other->m_primitive);
  760. RowVectorDIMS p = other_V.row(other->m_primitive);
  761. leaf_squared_distance(V,Ele,p,sqr_d,i,c);
  762. sqrD( other->m_primitive) = sqr_d;
  763. I( other->m_primitive) = i;
  764. C.row(other->m_primitive) = c;
  765. //cout<<"leaf: "<<sqr_d<<endl;
  766. //other->m_max_sqr_d = sqr_d;
  767. return sqr_d;
  768. }
  769. if(other->is_leaf())
  770. {
  771. Scalar sqr_d = sqrD(other->m_primitive);
  772. int i = I(other->m_primitive);
  773. RowVectorDIMS c = C.row( other->m_primitive);
  774. RowVectorDIMS p = other_V.row(other->m_primitive);
  775. sqr_d = squared_distance(V,Ele,p,sqr_d,i,c);
  776. sqrD( other->m_primitive) = sqr_d;
  777. I( other->m_primitive) = i;
  778. C.row(other->m_primitive) = c;
  779. //other->m_max_sqr_d = sqr_d;
  780. return sqr_d;
  781. }
  782. //// Exact minimum squared distance between arbitary primitives inside this and
  783. //// othre's bounding boxes
  784. //const auto & min_squared_distance = [&](
  785. // const AABB<DerivedV,DIM> * A,
  786. // const AABB<Derivedother_V,DIM> * B)->Scalar
  787. //{
  788. // return A->m_box.squaredExteriorDistance(B->m_box);
  789. //};
  790. if(this->is_leaf())
  791. {
  792. //if(min_squared_distance(this,other) < other->m_max_sqr_d)
  793. if(true)
  794. {
  795. this->squared_distance_helper(
  796. V,Ele,other->m_left,other_V,other_Ele,0,sqrD,I,C);
  797. this->squared_distance_helper(
  798. V,Ele,other->m_right,other_V,other_Ele,0,sqrD,I,C);
  799. }else
  800. {
  801. // This is never reached...
  802. }
  803. //// we know other is not a leaf
  804. //other->m_max_sqr_d = std::max(other->m_left->m_max_sqr_d,other->m_right->m_max_sqr_d);
  805. return 0;
  806. }
  807. // FORCE DOWN TO OTHER LEAF EVAL
  808. //if(min_squared_distance(this,other) < other->m_max_sqr_d)
  809. if(true)
  810. {
  811. if(true)
  812. {
  813. this->squared_distance_helper(
  814. V,Ele,other->m_left,other_V,other_Ele,0,sqrD,I,C);
  815. this->squared_distance_helper(
  816. V,Ele,other->m_right,other_V,other_Ele,0,sqrD,I,C);
  817. }else // this direction never seems to be faster
  818. {
  819. this->m_left->squared_distance_helper(
  820. V,Ele,other,other_V,other_Ele,0,sqrD,I,C);
  821. this->m_right->squared_distance_helper(
  822. V,Ele,other,other_V,other_Ele,0,sqrD,I,C);
  823. }
  824. }else
  825. {
  826. // this is never reached ... :-(
  827. }
  828. //// we know other is not a leaf
  829. //other->m_max_sqr_d = std::max(other->m_left->m_max_sqr_d,other->m_right->m_max_sqr_d);
  830. return 0;
  831. #if 0 // False
  832. // _Very_ conservative approximation of maximum squared distance between
  833. // primitives inside this and other's bounding boxes
  834. const auto & max_squared_distance = [](
  835. const AABB<DerivedV,DIM> * A,
  836. const AABB<Derivedother_V,DIM> * B)->Scalar
  837. {
  838. AlignedBox<Scalar,DIM> combo = A->m_box;
  839. combo.extend(B->m_box);
  840. return combo.diagonal().squaredNorm();
  841. };
  842. //// other base-case
  843. //if(other->is_leaf())
  844. //{
  845. // double sqr_d = sqrD(other->m_primitive);
  846. // int i = I(other->m_primitive);
  847. // RowVectorDIMS c = C.row(m_primitive);
  848. // RowVectorDIMS p = other_V.row(m_primitive);
  849. // leaf_squared_distance(V,Ele,p,sqr_d,i,c);
  850. // sqrD(other->m_primitive) = sqr_d;
  851. // I(other->m_primitive) = i;
  852. // C.row(m_primitive) = c;
  853. // return;
  854. //}
  855. std::vector<const AABB<DerivedV,DIM> * > this_list;
  856. if(this->is_leaf())
  857. {
  858. this_list.push_back(this);
  859. }else
  860. {
  861. assert(this->m_left);
  862. this_list.push_back(this->m_left);
  863. assert(this->m_right);
  864. this_list.push_back(this->m_right);
  865. }
  866. std::vector<AABB<Derivedother_V,DIM> *> other_list;
  867. if(other->is_leaf())
  868. {
  869. other_list.push_back(other);
  870. }else
  871. {
  872. assert(other->m_left);
  873. other_list.push_back(other->m_left);
  874. assert(other->m_right);
  875. other_list.push_back(other->m_right);
  876. }
  877. //const std::function<Scalar(
  878. // const AABB<Derivedother_V,DIM> * other)
  879. // > max_sqr_d = [&sqrD,&max_sqr_d](const AABB<Derivedother_V,DIM> * other)->Scalar
  880. // {
  881. // if(other->is_leaf())
  882. // {
  883. // return sqrD(other->m_primitive);
  884. // }else
  885. // {
  886. // return std::max(max_sqr_d(other->m_left),max_sqr_d(other->m_right));
  887. // }
  888. // };
  889. //// Potentially recurse on all pairs, if minimum distance is less than running
  890. //// bound
  891. //Eigen::Matrix<Scalar,Eigen::Dynamic,1> other_max_sqr_d =
  892. // Eigen::Matrix<Scalar,Eigen::Dynamic,1>::Constant(other_list.size(),1,min_sqr_d);
  893. for(size_t child = 0;child<other_list.size();child++)
  894. {
  895. auto other_tree = other_list[child];
  896. Eigen::Matrix<Scalar,Eigen::Dynamic,1> this_max_sqr_d(this_list.size(),1);
  897. for(size_t t = 0;t<this_list.size();t++)
  898. {
  899. const auto this_tree = this_list[t];
  900. this_max_sqr_d(t) = max_squared_distance(this_tree,other_tree);
  901. }
  902. if(this_list.size() ==2 &&
  903. ( this_max_sqr_d(0) > this_max_sqr_d(1))
  904. )
  905. {
  906. std::swap(this_list[0],this_list[1]);
  907. //std::swap(this_max_sqr_d(0),this_max_sqr_d(1));
  908. }
  909. const Scalar sqr_d = this_max_sqr_d.minCoeff();
  910. for(size_t t = 0;t<this_list.size();t++)
  911. {
  912. const auto this_tree = this_list[t];
  913. //const auto mm = max_sqr_d(other_tree);
  914. //const Scalar mc = other_max_sqr_d(child);
  915. //assert(mc == mm);
  916. // Only look left/right in this_list if can possible decrease somebody's
  917. // distance in this_tree.
  918. const Scalar min_this_other = min_squared_distance(this_tree,other_tree);
  919. if(
  920. min_this_other < sqr_d &&
  921. min_this_other < other_tree->m_max_sqr_d)
  922. {
  923. //cout<<"before: "<<other_max_sqr_d(child)<<endl;
  924. //other_max_sqr_d(child) = std::min(
  925. // other_max_sqr_d(child),
  926. // this_tree->squared_distance_helper(
  927. // V,Ele,other_tree,other_V,other_Ele,other_max_sqr_d(child),sqrD,I,C));
  928. //cout<<"after: "<<other_max_sqr_d(child)<<endl;
  929. this_tree->squared_distance_helper(
  930. V,Ele,other_tree,other_V,other_Ele,0,sqrD,I,C);
  931. }
  932. }
  933. }
  934. //const Scalar ret = other_max_sqr_d.maxCoeff();
  935. //const auto mm = max_sqr_d(other);
  936. //assert(mm == ret);
  937. //cout<<"non-leaf: "<<ret<<endl;
  938. //return ret;
  939. if(!other->is_leaf())
  940. {
  941. other->m_max_sqr_d = std::max(other->m_left->m_max_sqr_d,other->m_right->m_max_sqr_d);
  942. }
  943. return 0;
  944. #endif
  945. }
  946. template <typename DerivedV, int DIM>
  947. inline void igl::AABB<DerivedV,DIM>::leaf_squared_distance(
  948. const Eigen::PlainObjectBase<DerivedV> & V,
  949. const Eigen::MatrixXi & Ele,
  950. const RowVectorDIMS & p,
  951. Scalar & sqr_d,
  952. int & i,
  953. RowVectorDIMS & c) const
  954. {
  955. using namespace Eigen;
  956. using namespace igl;
  957. using namespace std;
  958. // Simplex size
  959. const size_t ss = Ele.cols();
  960. // Only one element per node
  961. // plane unit normal
  962. bool inside_triangle = false;
  963. Scalar d_j = std::numeric_limits<Scalar>::infinity();
  964. RowVectorDIMS pp;
  965. // Only consider triangles, and non-degenerate triangles at that
  966. if(ss == 3 &&
  967. Ele(m_primitive,0) != Ele(m_primitive,1) &&
  968. Ele(m_primitive,1) != Ele(m_primitive,2) &&
  969. Ele(m_primitive,2) != Ele(m_primitive,0))
  970. {
  971. const RowVectorDIMS v10 = (V.row(Ele(m_primitive,1))- V.row(Ele(m_primitive,0)));
  972. const RowVectorDIMS v20 = (V.row(Ele(m_primitive,2))- V.row(Ele(m_primitive,0)));
  973. const RowVectorDIMS n = v10.cross(v20);
  974. Scalar n_norm = n.norm();
  975. if(n_norm > 0)
  976. {
  977. const RowVectorDIMS un = n/n.norm();
  978. // vector to plane
  979. const RowVectorDIMS bc =
  980. 1./3.*
  981. ( V.row(Ele(m_primitive,0))+
  982. V.row(Ele(m_primitive,1))+
  983. V.row(Ele(m_primitive,2)));
  984. const auto & v = p-bc;
  985. // projected point on plane
  986. d_j = v.dot(un);
  987. pp = p - d_j*un;
  988. // determine if pp is inside triangle
  989. Eigen::Matrix<Scalar,1,3> b;
  990. barycentric_coordinates(
  991. pp,
  992. V.row(Ele(m_primitive,0)),
  993. V.row(Ele(m_primitive,1)),
  994. V.row(Ele(m_primitive,2)),
  995. b);
  996. inside_triangle = fabs(fabs(b(0)) + fabs(b(1)) + fabs(b(2)) - 1.) <= 1e-10;
  997. }
  998. }
  999. const auto & point_point_squared_distance = [&](const RowVectorDIMS & s)
  1000. {
  1001. cout<<"pp"<<endl;
  1002. const Scalar sqr_d_s = (p-s).squaredNorm();
  1003. set_min(p,sqr_d_s,m_primitive,s,sqr_d,i,c);
  1004. };
  1005. if(inside_triangle)
  1006. {
  1007. // point-triangle squared distance
  1008. const Scalar sqr_d_j = d_j*d_j;
  1009. //cout<<"point-triangle..."<<endl;
  1010. set_min(p,sqr_d_j,m_primitive,pp,sqr_d,i,c);
  1011. }else
  1012. {
  1013. if(ss >= 2)
  1014. {
  1015. // point-segment distance
  1016. // number of edges
  1017. size_t ne = ss==3?3:1;
  1018. for(size_t x = 0;x<ne;x++)
  1019. {
  1020. const size_t e1 = Ele(m_primitive,(x+1)%ss);
  1021. const size_t e2 = Ele(m_primitive,(x+2)%ss);
  1022. const RowVectorDIMS & s = V.row(e1);
  1023. const RowVectorDIMS & d = V.row(e2);
  1024. // Degenerate edge
  1025. if(e1 == e2 || (s-d).squaredNorm()==0)
  1026. {
  1027. // only consider once
  1028. if(e1 < e2)
  1029. {
  1030. point_point_squared_distance(s);
  1031. }
  1032. continue;
  1033. }
  1034. Matrix<Scalar,1,1> sqr_d_j_x(1,1);
  1035. Matrix<Scalar,1,1> t(1,1);
  1036. project_to_line_segment(p,s,d,t,sqr_d_j_x);
  1037. const RowVectorDIMS q = s+t(0)*(d-s);
  1038. set_min(p,sqr_d_j_x(0),m_primitive,q,sqr_d,i,c);
  1039. }
  1040. }else
  1041. {
  1042. // So then Ele is just a list of points...
  1043. assert(ss == 1);
  1044. const RowVectorDIMS & s = V.row(Ele(m_primitive,0));
  1045. point_point_squared_distance(s);
  1046. }
  1047. }
  1048. }
  1049. template <typename DerivedV, int DIM>
  1050. inline void igl::AABB<DerivedV,DIM>::set_min(
  1051. const RowVectorDIMS & p,
  1052. const Scalar sqr_d_candidate,
  1053. const int i_candidate,
  1054. const RowVectorDIMS & c_candidate,
  1055. Scalar & sqr_d,
  1056. int & i,
  1057. RowVectorDIMS & c) const
  1058. {
  1059. #ifndef NDEBUG
  1060. //std::cout<<matlab_format(c_candidate,"c_candidate")<<std::endl;
  1061. const Scalar pc_norm = (p-c_candidate).squaredNorm();
  1062. const Scalar diff = fabs(sqr_d_candidate - pc_norm);
  1063. assert(diff<=1e-10 && "distance should match norm of difference");
  1064. #endif
  1065. if(sqr_d_candidate < sqr_d)
  1066. {
  1067. i = i_candidate;
  1068. c = c_candidate;
  1069. sqr_d = sqr_d_candidate;
  1070. }
  1071. }
  1072. template <typename DerivedV, int DIM>
  1073. inline void
  1074. igl::AABB<DerivedV,DIM>::barycentric_coordinates(
  1075. const RowVectorDIMS & p,
  1076. const RowVectorDIMS & a,
  1077. const RowVectorDIMS & b,
  1078. const RowVectorDIMS & c,
  1079. Eigen::Matrix<Scalar,1,3> & bary)
  1080. {
  1081. // http://gamedev.stackexchange.com/a/23745
  1082. const RowVectorDIMS v0 = b - a;
  1083. const RowVectorDIMS v1 = c - a;
  1084. const RowVectorDIMS v2 = p - a;
  1085. Scalar d00 = v0.dot(v0);
  1086. Scalar d01 = v0.dot(v1);
  1087. Scalar d11 = v1.dot(v1);
  1088. Scalar d20 = v2.dot(v0);
  1089. Scalar d21 = v2.dot(v1);
  1090. Scalar denom = d00 * d11 - d01 * d01;
  1091. bary(1) = (d11 * d20 - d01 * d21) / denom;
  1092. bary(2) = (d00 * d21 - d01 * d20) / denom;
  1093. bary(0) = 1.0f - bary(1) - bary(2);
  1094. }
  1095. #endif