AABB.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2015 Alec Jacobson <[email protected]>
  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 "Hit.h"
  11. #include "igl_inline.h"
  12. #include <Eigen/Core>
  13. #include <Eigen/Geometry>
  14. #include <vector>
  15. namespace igl
  16. {
  17. /// Implementation of semi-general purpose axis-aligned bounding box hierarchy.
  18. /// The mesh (V,Ele) is stored and managed by the caller and each routine here
  19. /// simply takes it as references (it better not change between calls).
  20. ///
  21. /// It's a little annoying that the Dimension is a template parameter and not
  22. /// picked up at run time from V. This leads to duplicated code for 2d/3d (up to
  23. /// dim).
  24. ///
  25. /// @tparam DerivedV Matrix type of vertex positions (e.g., `Eigen::MatrixXd`)
  26. /// @tparam DIM Dimension of mesh vertex positions (2 or 3)
  27. template <typename DerivedV, int DIM>
  28. class AABB
  29. {
  30. public:
  31. /// Scalar type of vertex positions (e.g., `double`)
  32. typedef typename DerivedV::Scalar Scalar;
  33. /// Fixed-size (`DIM`) RowVector type using `Scalar`
  34. typedef Eigen::Matrix<Scalar,1,DIM> RowVectorDIMS;
  35. /// Fixed-size (`DIM`) (Column)Vector type using `Scalar`
  36. typedef Eigen::Matrix<Scalar,DIM,1> VectorDIMS;
  37. /// Fixed-width (`DIM`) Matrix type using `Scalar`
  38. typedef Eigen::Matrix<Scalar,Eigen::Dynamic,DIM> MatrixXDIMS;
  39. /// Pointer to "left" child node (`nullptr` if leaf)
  40. // Shared pointers are slower...
  41. AABB * m_left;
  42. /// Pointer to "right" child node (`nullptr` if leaf)
  43. AABB * m_right;
  44. /// Axis-Aligned Bounding Box containing this node
  45. Eigen::AlignedBox<Scalar,DIM> m_box;
  46. /// Index of single primitive in this node if full leaf, otherwise -1 for non-leaf
  47. int m_primitive;
  48. //Scalar m_low_sqr_d;
  49. //int m_depth;
  50. /// @private
  51. AABB():
  52. m_left(NULL), m_right(NULL),
  53. m_box(), m_primitive(-1)
  54. //m_low_sqr_d(std::numeric_limits<double>::infinity()),
  55. //m_depth(0)
  56. {}
  57. /// @private
  58. // http://stackoverflow.com/a/3279550/148668
  59. AABB(const AABB& other):
  60. m_left(other.m_left ? new AABB(*other.m_left) : NULL),
  61. m_right(other.m_right ? new AABB(*other.m_right) : NULL),
  62. m_box(other.m_box),
  63. m_primitive(other.m_primitive)
  64. //m_low_sqr_d(other.m_low_sqr_d),
  65. //m_depth(std::max(
  66. // m_left ? m_left->m_depth + 1 : 0,
  67. // m_right ? m_right->m_depth + 1 : 0))
  68. {
  69. }
  70. /// @private
  71. // copy-swap idiom
  72. friend void swap(AABB& first, AABB& second)
  73. {
  74. // Enable ADL
  75. using std::swap;
  76. swap(first.m_left,second.m_left);
  77. swap(first.m_right,second.m_right);
  78. swap(first.m_box,second.m_box);
  79. swap(first.m_primitive,second.m_primitive);
  80. //swap(first.m_low_sqr_d,second.m_low_sqr_d);
  81. //swap(first.m_depth,second.m_depth);
  82. }
  83. /// @private
  84. // Pass-by-value (aka copy)
  85. AABB& operator=(AABB other)
  86. {
  87. swap(*this,other);
  88. return *this;
  89. }
  90. /// @private
  91. AABB(AABB&& other):
  92. // initialize via default constructor
  93. AABB()
  94. {
  95. swap(*this,other);
  96. }
  97. /// @private
  98. // Seems like there should have been an elegant solution to this using
  99. // the copy-swap idiom above:
  100. IGL_INLINE void deinit()
  101. {
  102. m_primitive = -1;
  103. m_box = Eigen::AlignedBox<Scalar,DIM>();
  104. delete m_left;
  105. m_left = NULL;
  106. delete m_right;
  107. m_right = NULL;
  108. }
  109. /// @private
  110. ~AABB()
  111. {
  112. deinit();
  113. }
  114. /// Build an Axis-Aligned Bounding Box tree for a given mesh and given
  115. /// serialization of a previous AABB tree.
  116. ///
  117. /// @param[in] V #V by dim list of mesh vertex positions.
  118. /// @param[in] Ele #Ele by dim+1 list of mesh indices into #V.
  119. /// @param[in] bb_mins max_tree by dim list of bounding box min corner positions
  120. /// @param[in] bb_maxs max_tree by dim list of bounding box max corner positions
  121. /// @param[in] elements max_tree list of element or (not leaf id) indices into Ele
  122. /// @param[in] i recursive call index {0}
  123. template <
  124. typename DerivedEle,
  125. typename Derivedbb_mins,
  126. typename Derivedbb_maxs,
  127. typename Derivedelements>
  128. IGL_INLINE void init(
  129. const Eigen::MatrixBase<DerivedV> & V,
  130. const Eigen::MatrixBase<DerivedEle> & Ele,
  131. const Eigen::MatrixBase<Derivedbb_mins> & bb_mins,
  132. const Eigen::MatrixBase<Derivedbb_maxs> & bb_maxs,
  133. const Eigen::MatrixBase<Derivedelements> & elements,
  134. const int i = 0);
  135. /// Build an Axis-Aligned Bounding Box tree for a given mesh and given
  136. /// serialization of a previous AABB tree.
  137. ///
  138. /// @param[in] V #V by dim list of mesh vertex positions.
  139. /// @param[in] Ele #Ele by dim+1 list of mesh indices into #V.
  140. template <typename DerivedEle>
  141. IGL_INLINE void init(
  142. const Eigen::MatrixBase<DerivedV> & V,
  143. const Eigen::MatrixBase<DerivedEle> & Ele);
  144. /// Build an Axis-Aligned Bounding Box tree for a given mesh.
  145. ///
  146. /// @param[in] V #V by dim list of mesh vertex positions.
  147. /// @param[in] Ele #Ele by dim+1 list of mesh indices into #V.
  148. /// @param[in] SI #Ele by dim list revealing for each coordinate where Ele's
  149. /// barycenters would be sorted: SI(e,d) = i --> the dth coordinate of
  150. /// the barycenter of the eth element would be placed at position i in a
  151. /// sorted list.
  152. /// @param[in] I #I list of indices into Ele of elements to include (for recursive
  153. /// calls)
  154. ///
  155. template <typename DerivedEle, typename DerivedSI, typename DerivedI>
  156. IGL_INLINE void init(
  157. const Eigen::MatrixBase<DerivedV> & V,
  158. const Eigen::MatrixBase<DerivedEle> & Ele,
  159. const Eigen::MatrixBase<DerivedSI> & SI,
  160. const Eigen::MatrixBase<DerivedI>& I);
  161. /// Return whether at leaf node
  162. IGL_INLINE bool is_leaf() const;
  163. /// Find the indices of elements containing given point: this makes sense
  164. /// when Ele is a co-dimension 0 simplex (tets in 3D, triangles in 2D).
  165. ///
  166. /// @param[in] V #V by dim list of mesh vertex positions. **Should be same as used to
  167. /// construct mesh.**
  168. /// @param[in] Ele #Ele by dim+1 list of mesh indices into #V. **Should be same as used to
  169. /// construct mesh.**
  170. /// @param[in] q dim row-vector query position
  171. /// @param[in] first whether to only return first element containing q
  172. /// @return list of indices of elements containing q
  173. template <typename DerivedEle, typename Derivedq>
  174. IGL_INLINE std::vector<int> find(
  175. const Eigen::MatrixBase<DerivedV> & V,
  176. const Eigen::MatrixBase<DerivedEle> & Ele,
  177. const Eigen::MatrixBase<Derivedq> & q,
  178. const bool first=false) const;
  179. /// Number of nodes contained in subtree
  180. ///
  181. /// @return Number of elements m then total tree size should be 2*h where h is
  182. /// the deepest depth 2^ceil(log(#Ele*2-1))
  183. IGL_INLINE int subtree_size() const;
  184. /// Serialize this class into 3 arrays (so we can pass it pack to matlab)
  185. ///
  186. /// @param[out] bb_mins max_tree by dim list of bounding box min corner positions
  187. /// @param[out] bb_maxs max_tree by dim list of bounding box max corner positions
  188. /// @param[out] elements max_tree list of element or (not leaf id) indices into Ele
  189. /// @param[in] i recursive call index into these arrays {0}
  190. template <
  191. typename Derivedbb_mins,
  192. typename Derivedbb_maxs,
  193. typename Derivedelements>
  194. IGL_INLINE void serialize(
  195. Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
  196. Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
  197. Eigen::PlainObjectBase<Derivedelements> & elements,
  198. const int i = 0) const;
  199. /// Compute squared distance to a query point
  200. ///
  201. /// @param[in] V #V by dim list of vertex positions
  202. /// @param[in] Ele #Ele by dim list of simplex indices
  203. /// @param[in] p dim-long query point
  204. /// @param[out] i facet index corresponding to smallest distances
  205. /// @param[out] c closest point
  206. /// @return squared distance
  207. ///
  208. /// \pre Currently assumes Elements are triangles regardless of
  209. /// dimension.
  210. template <typename DerivedEle>
  211. IGL_INLINE Scalar squared_distance(
  212. const Eigen::MatrixBase<DerivedV> & V,
  213. const Eigen::MatrixBase<DerivedEle> & Ele,
  214. const RowVectorDIMS & p,
  215. int & i,
  216. Eigen::PlainObjectBase<RowVectorDIMS> & c) const;
  217. /// Compute squared distance to a query point if within `low_sqr_d` and
  218. /// `up_sqr_d`.
  219. ///
  220. /// @param[in] V #V by dim list of vertex positions
  221. /// @param[in] Ele #Ele by dim list of simplex indices
  222. /// @param[in] p dim-long query point
  223. /// @param[in] low_sqr_d lower bound on squared distance, specified maximum squared
  224. /// distance
  225. /// @param[in] up_sqr_d current upper bounded on squared distance, current minimum
  226. /// squared distance (only consider distances less than this), see
  227. /// output.
  228. /// @param[out] i facet index corresponding to smallest distances
  229. /// @param[out] c closest point
  230. /// @return squared distance
  231. ///
  232. /// \pre currently assumes Elements are triangles regardless of
  233. /// dimension.
  234. template <typename DerivedEle>
  235. IGL_INLINE Scalar squared_distance(
  236. const Eigen::MatrixBase<DerivedV> & V,
  237. const Eigen::MatrixBase<DerivedEle> & Ele,
  238. const RowVectorDIMS & p,
  239. const Scalar low_sqr_d,
  240. const Scalar up_sqr_d,
  241. int & i,
  242. Eigen::PlainObjectBase<RowVectorDIMS> & c) const;
  243. /// Compute squared distance to a query point (default `low_sqr_d`)
  244. ///
  245. /// @param[in] V #V by dim list of vertex positions
  246. /// @param[in] Ele #Ele by dim list of simplex indices
  247. /// @param[in] p dim-long query point
  248. /// @param[in] up_sqr_d current upper bounded on squared distance, current minimum
  249. /// squared distance (only consider distances less than this), see
  250. /// output.
  251. /// @param[out] i facet index corresponding to smallest distances
  252. /// @param[out] c closest point
  253. /// @return squared distance
  254. ///
  255. template <typename DerivedEle>
  256. IGL_INLINE Scalar squared_distance(
  257. const Eigen::MatrixBase<DerivedV> & V,
  258. const Eigen::MatrixBase<DerivedEle> & Ele,
  259. const RowVectorDIMS & p,
  260. const Scalar up_sqr_d,
  261. int & i,
  262. Eigen::PlainObjectBase<RowVectorDIMS> & c) const;
  263. /// Intersect a ray with the mesh return all hits
  264. ///
  265. /// @param[in] V #V by dim list of vertex positions
  266. /// @param[in] Ele #Ele by dim list of simplex indices
  267. /// @param[in] origin dim-long ray origin
  268. /// @param[in] dir dim-long ray direction
  269. /// @param[out] hits list of hits
  270. /// @return true if any hits
  271. template <typename DerivedEle>
  272. IGL_INLINE bool intersect_ray(
  273. const Eigen::MatrixBase<DerivedV> & V,
  274. const Eigen::MatrixBase<DerivedEle> & Ele,
  275. const RowVectorDIMS & origin,
  276. const RowVectorDIMS & dir,
  277. std::vector<igl::Hit> & hits) const;
  278. /// Intersect a ray with the mesh return first hit
  279. ///
  280. /// @param[in] V #V by dim list of vertex positions
  281. /// @param[in] Ele #Ele by dim list of simplex indices
  282. /// @param[in] origin dim-long ray origin
  283. /// @param[in] dir dim-long ray direction
  284. /// @param[out] hit first hit
  285. /// @return true if any hit
  286. template <typename DerivedEle>
  287. IGL_INLINE bool intersect_ray(
  288. const Eigen::MatrixBase<DerivedV> & V,
  289. const Eigen::MatrixBase<DerivedEle> & Ele,
  290. const RowVectorDIMS & origin,
  291. const RowVectorDIMS & dir,
  292. igl::Hit & hit) const;
  293. /// Intersect a ray with the mesh return first hit farther than `min_t`
  294. ///
  295. /// @param[in] V #V by dim list of vertex positions
  296. /// @param[in] Ele #Ele by dim list of simplex indices
  297. /// @param[in] origin dim-long ray origin
  298. /// @param[in] dir dim-long ray direction
  299. /// @param[in] min_t minimum t value to consider
  300. /// @param[out] hit first hit
  301. /// @return true if any hit
  302. template <typename DerivedEle>
  303. IGL_INLINE bool intersect_ray(
  304. const Eigen::MatrixBase<DerivedV> & V,
  305. const Eigen::MatrixBase<DerivedEle> & Ele,
  306. const RowVectorDIMS & origin,
  307. const RowVectorDIMS & dir,
  308. const Scalar min_t,
  309. igl::Hit & hit) const;
  310. public:
  311. /// Compute the squared distance from all query points in P to the
  312. /// _closest_ points on the primitives stored in the AABB hierarchy for
  313. /// the mesh (V,Ele).
  314. ///
  315. /// @param[in] V #V by dim list of vertex positions
  316. /// @param[in] Ele #Ele by dim list of simplex indices
  317. /// @param[in] P #P by dim list of query points
  318. /// @param[out] sqrD #P list of squared distances
  319. /// @param[out] I #P list of indices into Ele of closest primitives
  320. /// @param[out] C #P by dim list of closest points
  321. template <
  322. typename DerivedEle,
  323. typename DerivedP,
  324. typename DerivedsqrD,
  325. typename DerivedI,
  326. typename DerivedC>
  327. IGL_INLINE void squared_distance(
  328. const Eigen::MatrixBase<DerivedV> & V,
  329. const Eigen::MatrixBase<DerivedEle> & Ele,
  330. const Eigen::MatrixBase<DerivedP> & P,
  331. Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
  332. Eigen::PlainObjectBase<DerivedI> & I,
  333. Eigen::PlainObjectBase<DerivedC> & C) const;
  334. /// Compute the squared distance from all query points in P already stored
  335. /// in its own AABB hierarchy to the _closest_ points on the primitives
  336. /// stored in the AABB hierarchy for the mesh (V,Ele).
  337. ///
  338. /// @param[in] V #V by dim list of vertex positions
  339. /// @param[in] Ele #Ele by dim list of simplex indices
  340. /// @param[in] other AABB hierarchy of another set of primitives (must be points)
  341. /// @param[in] other_V #other_V by dim list of query points
  342. /// @param[in] other_Ele #other_Ele by ss list of simplex indices into other_V
  343. /// (must be simple list of points: ss == 1)
  344. /// @param[out] sqrD #P list of squared distances
  345. /// @param[out] I #P list of indices into Ele of closest primitives
  346. /// @param[out] C #P by dim list of closest points
  347. template <
  348. typename DerivedEle,
  349. typename Derivedother_V,
  350. typename Derivedother_Ele,
  351. typename DerivedsqrD,
  352. typename DerivedI,
  353. typename DerivedC>
  354. IGL_INLINE void squared_distance(
  355. const Eigen::MatrixBase<DerivedV> & V,
  356. const Eigen::MatrixBase<DerivedEle> & Ele,
  357. const AABB<Derivedother_V,DIM> & other,
  358. const Eigen::MatrixBase<Derivedother_V> & other_V,
  359. const Eigen::MatrixBase<Derivedother_Ele> & other_Ele,
  360. Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
  361. Eigen::PlainObjectBase<DerivedI> & I,
  362. Eigen::PlainObjectBase<DerivedC> & C) const;
  363. private:
  364. template <
  365. typename DerivedEle,
  366. typename Derivedother_V,
  367. typename Derivedother_Ele,
  368. typename DerivedsqrD,
  369. typename DerivedI,
  370. typename DerivedC>
  371. IGL_INLINE Scalar squared_distance_helper(
  372. const Eigen::MatrixBase<DerivedV> & V,
  373. const Eigen::MatrixBase<DerivedEle> & Ele,
  374. const AABB<Derivedother_V,DIM> * other,
  375. const Eigen::MatrixBase<Derivedother_V> & other_V,
  376. const Eigen::MatrixBase<Derivedother_Ele>& other_Ele,
  377. const Scalar up_sqr_d,
  378. Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
  379. Eigen::PlainObjectBase<DerivedI> & I,
  380. Eigen::PlainObjectBase<DerivedC> & C) const;
  381. // Compute the squared distance to the primitive in this node: assumes
  382. // that this is indeed a leaf node.
  383. //
  384. // Inputs:
  385. // V #V by dim list of vertex positions
  386. // Ele #Ele by dim list of simplex indices
  387. // p dim-long query point
  388. // sqr_d current minimum distance for this query, see output
  389. // i current index into Ele of closest point, see output
  390. // c dim-long current closest point, see output
  391. // Outputs:
  392. // sqr_d minimum of initial value and squared distance to this
  393. // primitive
  394. // i possibly updated index into Ele of closest point
  395. // c dim-long possibly updated closest point
  396. template <typename DerivedEle>
  397. IGL_INLINE void leaf_squared_distance(
  398. const Eigen::MatrixBase<DerivedV> & V,
  399. const Eigen::MatrixBase<DerivedEle> & Ele,
  400. const RowVectorDIMS & p,
  401. const Scalar low_sqr_d,
  402. Scalar & sqr_d,
  403. int & i,
  404. Eigen::PlainObjectBase<RowVectorDIMS> & c) const;
  405. // Default low_sqr_d
  406. template <typename DerivedEle>
  407. IGL_INLINE void leaf_squared_distance(
  408. const Eigen::MatrixBase<DerivedV> & V,
  409. const Eigen::MatrixBase<DerivedEle> & Ele,
  410. const RowVectorDIMS & p,
  411. Scalar & sqr_d,
  412. int & i,
  413. Eigen::PlainObjectBase<RowVectorDIMS> & c) const;
  414. // If new distance (sqr_d_candidate) is less than current distance
  415. // (sqr_d), then update this distance and its associated values
  416. // _in-place_:
  417. //
  418. // Inputs:
  419. // p dim-long query point (only used in DEBUG mode)
  420. // sqr_d candidate minimum distance for this query, see output
  421. // i candidate index into Ele of closest point, see output
  422. // c dim-long candidate closest point, see output
  423. // sqr_d current minimum distance for this query, see output
  424. // i current index into Ele of closest point, see output
  425. // c dim-long current closest point, see output
  426. // Outputs:
  427. // sqr_d minimum of initial value and squared distance to this
  428. // primitive
  429. // i possibly updated index into Ele of closest point
  430. // c dim-long possibly updated closest point
  431. IGL_INLINE void set_min(
  432. const RowVectorDIMS & p,
  433. const Scalar sqr_d_candidate,
  434. const int i_candidate,
  435. const RowVectorDIMS & c_candidate,
  436. Scalar & sqr_d,
  437. int & i,
  438. Eigen::PlainObjectBase<RowVectorDIMS> & c) const;
  439. public:
  440. EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  441. };
  442. }
  443. #ifndef IGL_STATIC_LIBRARY
  444. # include "AABB.cpp"
  445. #endif
  446. #endif