| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855 |
- // This file is part of libigl, a simple c++ geometry processing library.
- //
- // Copyright (C) 2015 Alec Jacobson <[email protected]>
- //
- // This Source Code Form is subject to the terms of the Mozilla Public License
- // v. 2.0. If a copy of the MPL was not distributed with this file, You can
- // obtain one at http://mozilla.org/MPL/2.0/.
- #ifndef IGL_AABB_H
- #define IGL_AABB_H
- #include "Hit.h"
- #include "igl_inline.h"
- #include <cassert>
- #include <Eigen/Core>
- #include <Eigen/Geometry>
- #include <vector>
- namespace igl
- {
- /// Implementation of semi-general purpose axis-aligned bounding box hierarchy.
- /// The mesh (V,Ele) is stored and managed by the caller and each routine here
- /// simply takes it as references (it better not change between calls).
- ///
- /// It's a little annoying that the Dimension is a template parameter and not
- /// picked up at run time from V. This leads to duplicated code for 2d/3d (up to
- /// dim).
- ///
- /// @tparam DerivedV Matrix type of vertex positions (e.g., `Eigen::MatrixXd`)
- /// @tparam DIM Dimension of mesh vertex positions (2 or 3)
- template <typename DerivedV, int DIM>
- class AABB
- {
- public:
- ///////////////////////////////////////////////////////////////////////////////
- // Member variables
- ///////////////////////////////////////////////////////////////////////////////
- /// Scalar type of vertex positions (e.g., `double`)
- typedef typename DerivedV::Scalar Scalar;
- /// Fixed-size (`DIM`) RowVector type using `Scalar`
- typedef Eigen::Matrix<Scalar,1,DIM> RowVectorDIMS;
- /// Fixed-size (`DIM`) (Column)Vector type using `Scalar`
- typedef Eigen::Matrix<Scalar,DIM,1> VectorDIMS;
- /// Fixed-width (`DIM`) Matrix type using `Scalar`
- typedef Eigen::Matrix<Scalar,Eigen::Dynamic,DIM> MatrixXDIMS;
- /// Pointer to "left" child node (`nullptr` if leaf)
- // Shared pointers are slower...
- AABB * m_left;
- /// Pointer to "right" child node (`nullptr` if leaf)
- AABB * m_right;
- /// Pointer to "parent" node (`nullptr` if root)
- AABB * m_parent;
- /// Axis-Aligned Bounding Box containing this node
- Eigen::AlignedBox<Scalar,DIM> m_box;
- /// Index of single primitive in this node if full leaf, otherwise -1 for non-leaf
- int m_primitive;
- ///////////////////////////////////////////////////////////////////////////////
- // Non-templated member functions
- ///////////////////////////////////////////////////////////////////////////////
- //Scalar m_low_sqr_d;
- //int m_depth;
- /// @private
- AABB():
- m_left(nullptr), m_right(nullptr),m_parent(nullptr),
- m_box(), m_primitive(-1)
- //m_low_sqr_d(std::numeric_limits<double>::infinity()),
- //m_depth(0)
- {
- static_assert(DerivedV::ColsAtCompileTime == DIM || DerivedV::ColsAtCompileTime == Eigen::Dynamic,"DerivedV::ColsAtCompileTime == DIM || DerivedV::ColsAtCompileTime == Eigen::Dynamic");
- }
- /// @private
- // http://stackoverflow.com/a/3279550/148668
- AABB(const AABB& other):
- m_left (other.m_left ? new AABB(*other.m_left) : nullptr),
- m_right(other.m_right ? new AABB(*other.m_right) : nullptr),
- m_parent(other.m_parent),
- m_box(other.m_box),
- m_primitive(other.m_primitive)
- //m_low_sqr_d(other.m_low_sqr_d),
- //m_depth(std::max(
- // m_left ? m_left->m_depth + 1 : 0,
- // m_right ? m_right->m_depth + 1 : 0))
- {
- if(m_left) { m_left->m_parent = this; }
- if(m_right) { m_right->m_parent = this; }
- }
- /// @private
- // copy-swap idiom
- friend void swap(AABB& first, AABB& second)
- {
- // Enable ADL
- using std::swap;
- swap(first.m_left,second.m_left);
- swap(first.m_right,second.m_right);
- swap(first.m_parent,second.m_parent);
- swap(first.m_box,second.m_box);
- swap(first.m_primitive,second.m_primitive);
- //swap(first.m_low_sqr_d,second.m_low_sqr_d);
- //swap(first.m_depth,second.m_depth);
- }
- /// @private
- // Pass-by-value (aka copy)
- AABB& operator=(AABB other)
- {
- swap(*this,other);
- return *this;
- }
- /// @private
- AABB(AABB&& other):
- // initialize via default constructor
- AABB()
- {
- swap(*this,other);
- }
- /// @private
- // Seems like there should have been an elegant solution to this using
- // the copy-swap idiom above:
- IGL_INLINE void clear()
- {
- m_primitive = -1;
- m_box = Eigen::AlignedBox<Scalar,DIM>();
- delete m_left;
- m_left = nullptr;
- delete m_right;
- m_right = nullptr;
- // Tell my parent I'm dead
- if(m_parent)
- {
- if(m_parent->m_left == this)
- {
- m_parent->m_left = nullptr;
- }else if(m_parent->m_right == this)
- {
- m_parent->m_right = nullptr;
- }else
- {
- assert(false && "I'm not my parent's child");
- }
- auto * grandparent = m_parent->m_parent;
- if(grandparent)
- {
- // Before
- // grandparent
- // ╱ ╲
- // parent pibling
- // ╱ ╲
- // sibling this
- //
- // After
- // grandparent
- // ╱ ╲
- // sibling® pibling
- }else
- {
- // Before
- // parent=root
- // ╱ ╲
- // sibling this
- //
- // After
- // grandparent
- // ╱ ╲
- // sibling® pibling
- }
- }
- // Now my parent is dead to me.
- m_parent = nullptr;
- }
- /// @private
- ~AABB()
- {
- clear();
- }
- /// Return whether at leaf node
- IGL_INLINE bool is_leaf() const;
- /// Return whether at root node
- IGL_INLINE bool is_root() const;
- /// Return the root node of this node's tree by following its parent
- IGL_INLINE AABB<DerivedV,DIM>* root() const;
- IGL_INLINE AABB<DerivedV,DIM>* detach();
- IGL_INLINE void refit_lineage();
- /// Get a vector of leaves indexed by their m_primitive id (these better
- /// be non-negative and tightly packed.
- /// @param[in] m number of leaves/elements (Ele.rows())
- /// @returns leaves m list of pointers to leaves
- IGL_INLINE std::vector<AABB<DerivedV,DIM>*> gather_leaves(const int m);
- /// \overload where m is the max m_primitive id in the tree.
- IGL_INLINE std::vector<AABB<DerivedV,DIM>*> gather_leaves();
- /// Pad leaves by `pad` in each dimension
- /// @param[in] pad padding amount
- /// @param[in] polish_rotate_passes number of passes to polish rotations
- /// @returns pointer to (potentially new) root
- IGL_INLINE AABB<DerivedV,DIM>* pad(
- const std::vector<AABB<DerivedV,DIM>*> & leaves,
- const Scalar pad,
- const int polish_rotate_passes=0);
- /// @returns `this` if no update was needed, otherwise returns pointer to
- /// (potentially new) root
- ///
- /// Example:
- /// ```cpp
- /// auto * up = leaf->update(new_box);
- /// if(up != leaf)
- /// {
- /// tree = up->root();
- /// }else
- /// {
- /// printf("no update occurred\n");
- /// }
- ///
- /// // or simply
- /// tree = leaf->update(new_box)->root();
- /// ```
- IGL_INLINE AABB<DerivedV,DIM>* update(
- const Eigen::AlignedBox<Scalar,DIM> & new_box,
- const Scalar pad=0);
- /// Insert a (probably a leaf) AABB `other` into this AABB tree. If
- /// `other`'s box is contained in this AABB's box then insert it as a child recursively.
- ///
- /// If `other`'s box is not contained in this AABB's box then insert it as a
- /// sibling.
- ///
- /// It's a very good idea to call either `rotate` (faster, less good) or `rotate_lineage` (slower, better)
- /// after insertion. Rotating continues to improve the tree's quality so
- /// after doing a bunch of insertions you might even consider calling
- /// `rotate` on all nodes.
- ///
- /// `insert` attempts to minimize total internal surface area. Where as
- /// `init` is top-down and splits boxes based on the median along the
- /// longest dimension. When initializing a tree, `init` seems to result in
- /// great trees (small height and small total internal surface area).
- ///
- /// @param[in] other pointer to another AABB node
- /// @returns pointer to the parent of `other` or `other` itself. This
- /// could be == to a `new`ly created internal node or to `other` if
- /// `this==other`. Calling ->root() on this returned node will give you
- /// the root of the tree.
- ///
- /// ##### Example
- ///
- /// ```cpp
- /// // Create a tree (use pointer to track changes to root)
- /// auto * tree = new igl::AABB<DerivedV,3>::AABB();
- /// // Fill the tree (e.g., using ->init())
- /// …
- /// // Create a new leafe node
- /// auto * leaf = new igl::AABB<DerivedV,3>::AABB();
- /// // Fill the leaf node with a primitive and box
- /// …
- /// // Insert into the tree and find the possibly new root
- /// tree = tree->insert(leaf)->root();
- /// ```
- IGL_INLINE AABB<DerivedV,DIM>* insert(AABB * other);
- /// Insert `other` as a sibling to `this` by creating a new internal node
- /// to be their shared parent.
- ///
- /// Before
- /// parent
- /// ╱ ╲
- /// this(C) sibling
- /// ╱ ╲
- /// left right
- ///
- /// After
- /// parent
- /// ╱ ╲
- /// newbie sibling
- /// ╱ ╲
- /// this other
- /// ╱ ╲
- /// left right
- ///
- ///
- /// @param[in] other pointer to another AABB node
- /// @returns pointer to the new shared parent.
- IGL_INLINE AABB<DerivedV,DIM>* insert_as_sibling(AABB * other);
- /// Try to swap this node with its close relatives if it will decrease
- /// total internal surface area.
- ///
- ///
- /// grandparent
- /// ╱ ╲
- /// parent pibling°
- /// ╱ ╲ ╱ ╲
- /// sibling this cuz1° cuz2°
- /// ╱ ╲
- /// nib1° nib2°
- ///
- /// °Swap Candidates
- ///
- /// @param[in] dry_run if true then don't actually swap
- /// @return[in] the change in total internal surface area, 0 if no
- /// improvement and rotate won't be carried out.
- IGL_INLINE Scalar rotate(const bool dry_run = false);
- /// Try to swap this node with its cousins if it will decrease
- /// total internal surface area.
- ///
- /// @param[in] dry_run if true then don't actually swap
- /// @return[in] the change in total internal surface area, 0 if no
- /// improvement and rotate won't be carried out.
- ///
- /// Before
- /// grandparent
- /// ╱ ╲
- /// parent pibling
- /// ╱ ╲ ╱ ╲
- /// sibling this cuz1 cuz2
- ///
- ///
- /// Candidates
- /// grandparent
- /// ╱ ╲
- /// parent pibling
- /// ╱ ╲ ╱ ╲
- /// sibling cuz1 this cuz2
- ///
- /// Or
- /// grandparent
- /// ╱ ╲
- /// parent pibling
- /// ╱ ╲ ╱ ╲
- /// sibling cuz2 cuz1 this
- IGL_INLINE Scalar rotate_across(const bool dry_run = false);
- /// Try to swap this node with its pibling if it will decrease
- /// total internal surface area.
- ///
- /// @param[in] dry_run if true then don't actually swap
- /// @return[in] the change in total internal surface area, 0 if no
- /// improvement and rotate won't be carried out.
- ///
- /// Before
- /// grandparent
- /// ╱ ╲
- /// other parent
- /// ╱ ╲
- /// this sibling
- ///
- ///
- /// Candidate
- /// grandparent
- /// ╱ ╲
- /// this parent
- /// ╱ ╲
- /// other sibling
- IGL_INLINE Scalar rotate_up(const bool dry_run = false);
- /// Try to swap this node with one of its niblings if it will decrease
- /// total internal surface area.
- ///
- /// @param[in] dry_run if true then don't actually swap
- /// @return[in] the change in total internal surface area, 0 if no
- /// improvement and rotate won't be carried out.
- ///
- /// Before
- /// parent
- /// ╱ ╲
- /// this sibling
- /// ╱ ╲
- /// left right
- ///
- ///
- /// Candidates
- /// parent
- /// ╱ ╲
- /// left sibling
- /// ╱ ╲
- /// this right
- ///
- /// Or
- ///
- /// parent
- /// ╱ ╲
- /// right sibling
- /// ╱ ╲
- /// left this
- IGL_INLINE Scalar rotate_down(const bool dry_run = false);
- /// "Rotate" (swap) `reining` with `challenger`.
- ///
- /// Before
- /// grandparent
- /// ╱ ╲
- /// reining parent
- /// ╱ ╲
- /// challenger sibling
- ///
- ///
- /// Candidate
- /// grandparent
- /// ╱ ╲
- /// challenger parent
- /// ╱ ╲
- /// reining sibling
- /// @param[in] reining pointer to AABB node to be rotated
- /// @param[in] grandparent pointer to challenger's grandparent
- /// @param[in] parent pointer to challenger's parent
- /// @param[in] challenger pointer to AABB node to be rotated
- /// @param[in] sibling pointer to challenger's sibling
- /// @returns true only if rotation was possible and successfully carried
- /// out.
- static IGL_INLINE Scalar rotate_up(
- const bool dry_run,
- AABB<DerivedV,DIM>* reining,
- AABB<DerivedV,DIM>* grandparent,
- AABB<DerivedV,DIM>* parent,
- AABB<DerivedV,DIM>* challenger,
- AABB<DerivedV,DIM>* sibling);
- // Should this be a static function with an argument?
- IGL_INLINE void rotate_lineage();
- /// Number of nodes contained in subtree (is it?)
- ///
- /// \note At best, this function has a dubious name. This is really an
- /// internal helper function for the serialization.
- ///
- /// \see size()
- ///
- /// @return Number of elements m then total tree size should be 2*h where h is
- /// the deepest depth 2^ceil(log(#Ele*2-1))
- IGL_INLINE int subtree_size() const;
- /// @param[in] box query box
- /// @param[in,out] leaves list of leaves to append to
- IGL_INLINE bool append_intersecting_leaves(
- const Eigen::AlignedBox<Scalar,DIM> & box,
- std::vector<const AABB<DerivedV,DIM>*> & leaves) const;
- /// Compute sum of surface area of all internal (non-root, non-leaf) boxes
- IGL_INLINE typename DerivedV::Scalar internal_surface_area() const;
- /// Validate the subtree under this node by running a bunch of assertions.
- /// Does nothing when not in debug mode
- IGL_INLINE void validate() const;
- /// print the memory addresses of the tree in a somewhat legible way
- IGL_INLINE void print(const int depth = 0) const;
- /// @returns Actual size of tree. Total number of nodes in tree. A singleton root
- /// has size 1.
- ///
- /// \see subtree_size
- IGL_INLINE int size() const;
- /// @returns Height of the tree. A singleton root has height 1.
- IGL_INLINE int height() const;
- private:
- /// If new distance (sqr_d_candidate) is less than current distance
- /// (sqr_d), then update this distance and its associated values
- /// _in-place_:
- ///
- /// @param[in] p dim-long query point (only used in DEBUG mode)
- /// @param[in] sqr_d candidate minimum distance for this query, see
- /// output
- /// @param[in] i candidate index into Ele of closest point, see output
- /// @param[in] c dim-long candidate closest point, see output
- /// @param[in] sqr_d current minimum distance for this query, see output
- /// @param[in] i current index into Ele of closest point, see output
- /// @param[in] c dim-long current closest point, see output
- /// @param[out] sqr_d minimum of initial value and squared distance to
- /// this primitive
- /// @param[out] i possibly updated index into Ele of closest point
- /// @param[out] c dim-long possibly updated closest point
- IGL_INLINE void set_min(
- const RowVectorDIMS & p,
- const Scalar sqr_d_candidate,
- const int & i_candidate,
- const RowVectorDIMS & c_candidate,
- Scalar & sqr_d,
- int & i,
- Eigen::PlainObjectBase<RowVectorDIMS> & c) const;
- public:
- ///////////////////////////////////////////////////////////////////////////////
- // Templated member functions
- ///////////////////////////////////////////////////////////////////////////////
- /// Build an Axis-Aligned Bounding Box tree for a given mesh and given
- /// serialization of a previous AABB tree.
- ///
- /// @param[in] V #V by dim list of mesh vertex positions.
- /// @param[in] Ele #Ele by dim+1 list of mesh indices into #V.
- /// @param[in] bb_mins max_tree by dim list of bounding box min corner
- /// positions
- /// @param[in] bb_maxs max_tree by dim list of bounding box max corner
- /// positions
- /// @param[in] elements max_tree list of element or (not leaf id) indices
- /// into Ele
- /// @param[in] i recursive call index {0}
- template <
- typename DerivedEle,
- typename Derivedbb_mins,
- typename Derivedbb_maxs,
- typename Derivedelements>
- IGL_INLINE void init(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele,
- const Eigen::MatrixBase<Derivedbb_mins> & bb_mins,
- const Eigen::MatrixBase<Derivedbb_maxs> & bb_maxs,
- const Eigen::MatrixBase<Derivedelements> & elements,
- const int i = 0);
- /// Build an Axis-Aligned Bounding Box tree for a given mesh and given
- /// serialization of a previous AABB tree.
- ///
- /// @param[in] V #V by dim list of mesh vertex positions.
- /// @param[in] Ele #Ele by dim+1 list of mesh indices into #V.
- template <typename DerivedEle>
- IGL_INLINE void init(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele);
- /// Build an Axis-Aligned Bounding Box tree for a given mesh.
- ///
- /// @param[in] V #V by dim list of mesh vertex positions.
- /// @param[in] Ele #Ele by dim+1 list of mesh indices into #V.
- /// @param[in] SI #Ele by dim list revealing for each coordinate where
- /// Ele's barycenters would be sorted: SI(e,d) = i --> the dth
- /// coordinate of the barycenter of the eth element would be placed at
- /// position i in a sorted list.
- /// @param[in] I #I list of indices into Ele of elements to include (for
- /// recursive calls)
- ///
- template <typename DerivedEle, typename DerivedSI, typename DerivedI>
- IGL_INLINE void init(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele,
- const Eigen::MatrixBase<DerivedSI> & SI,
- const Eigen::MatrixBase<DerivedI>& I);
- /// @returns `this` if no update was needed, otherwise returns pointer to
- /// (potentially new) root
- template <typename DerivedEle>
- IGL_INLINE AABB<DerivedV,DIM>* update_primitive(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele,
- const Scalar pad=0);
- /// Find the indices of elements containing given point: this makes sense
- /// when Ele is a co-dimension 0 simplex (tets in 3D, triangles in 2D).
- ///
- /// @param[in] V #V by dim list of mesh vertex positions. **Should be
- /// same as used to construct mesh.**
- /// @param[in] Ele #Ele by dim+1 list of mesh indices into #V. **Should
- /// be same as used to construct mesh.**
- /// @param[in] q dim row-vector query position
- /// @param[in] first whether to only return first element containing q
- /// @return list of indices of elements containing q
- template <typename DerivedEle, typename Derivedq>
- IGL_INLINE std::vector<int> find(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele,
- const Eigen::MatrixBase<Derivedq> & q,
- const bool first=false) const;
- /// Serialize this class into 3 arrays (so we can pass it pack to matlab)
- ///
- /// @param[out] bb_mins max_tree by dim list of bounding box min corner
- /// positions
- /// @param[out] bb_maxs max_tree by dim list of bounding box max corner
- /// positions
- /// @param[out] elements max_tree list of element or (not leaf id)
- /// indices into Ele
- /// @param[in] i recursive call index into these arrays {0}
- template <
- typename Derivedbb_mins,
- typename Derivedbb_maxs,
- typename Derivedelements>
- IGL_INLINE void serialize(
- Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
- Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
- Eigen::PlainObjectBase<Derivedelements> & elements,
- const int i = 0) const;
- /// Compute squared distance to a query point
- ///
- /// @param[in] V #V by dim list of vertex positions
- /// @param[in] Ele #Ele by dim list of simplex indices
- /// @param[in] p dim-long query point
- /// @param[out] i facet index corresponding to smallest distances
- /// @param[out] c closest point
- /// @return squared distance
- ///
- /// \pre Currently assumes Elements are triangles regardless of
- /// dimension.
- template <typename DerivedEle>
- IGL_INLINE Scalar squared_distance(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele,
- const RowVectorDIMS & p,
- int & i,
- Eigen::PlainObjectBase<RowVectorDIMS> & c) const;
- /// Compute squared distance to a query point if within `low_sqr_d` and
- /// `up_sqr_d`.
- ///
- /// @param[in] V #V by dim list of vertex positions
- /// @param[in] Ele #Ele by dim list of simplex indices
- /// @param[in] p dim-long query point
- /// @param[in] low_sqr_d lower bound on squared distance, specified
- /// maximum squared distance
- /// @param[in] up_sqr_d current upper bounded on squared distance,
- /// current minimum squared distance (only consider distances less than
- /// this), see output.
- /// @param[out] i facet index corresponding to smallest distances
- /// @param[out] c closest point
- /// @return squared distance
- ///
- /// \pre currently assumes Elements are triangles regardless of
- /// dimension.
- template <typename DerivedEle>
- IGL_INLINE Scalar squared_distance(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele,
- const RowVectorDIMS & p,
- const Scalar low_sqr_d,
- const Scalar up_sqr_d,
- int & i,
- Eigen::PlainObjectBase<RowVectorDIMS> & c) const;
- /// Compute squared distance to a query point (default `low_sqr_d`)
- ///
- /// @param[in] V #V by dim list of vertex positions
- /// @param[in] Ele #Ele by dim list of simplex indices
- /// @param[in] p dim-long query point
- /// @param[in] up_sqr_d current upper bounded on squared distance,
- /// current minimum squared distance (only consider distances less than
- /// this), see output.
- /// @param[out] i facet index corresponding to smallest distances
- /// @param[out] c closest point
- /// @return squared distance
- ///
- template <typename DerivedEle>
- IGL_INLINE Scalar squared_distance(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele,
- const RowVectorDIMS & p,
- const Scalar up_sqr_d,
- int & i,
- Eigen::PlainObjectBase<RowVectorDIMS> & c) const;
- /// Intersect a ray with the mesh return all hits
- ///
- /// @param[in] V #V by dim list of vertex positions
- /// @param[in] Ele #Ele by dim list of simplex indices
- /// @param[in] origin dim-long ray origin
- /// @param[in] dir dim-long ray direction
- /// @param[out] hits list of hits
- /// @return true if any hits
- template <typename DerivedEle>
- IGL_INLINE bool intersect_ray(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele,
- const RowVectorDIMS & origin,
- const RowVectorDIMS & dir,
- std::vector<igl::Hit<typename DerivedV::Scalar>> & hits) const;
- /// Intersect a ray with the mesh return first hit
- ///
- /// @param[in] V #V by dim list of vertex positions
- /// @param[in] Ele #Ele by dim list of simplex indices
- /// @param[in] origin dim-long ray origin
- /// @param[in] dir dim-long ray direction
- /// @param[out] hit first hit
- /// @return true if any hit
- template <typename DerivedEle>
- IGL_INLINE bool intersect_ray(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele,
- const RowVectorDIMS & origin,
- const RowVectorDIMS & dir,
- igl::Hit<typename DerivedV::Scalar> & hit) const;
- /// Intersect a ray with the mesh return first hit farther than `min_t`
- ///
- /// @param[in] V #V by dim list of vertex positions
- /// @param[in] Ele #Ele by dim list of simplex indices
- /// @param[in] origin dim-long ray origin
- /// @param[in] dir dim-long ray direction
- /// @param[in] min_t minimum t value to consider
- /// @param[out] hit first hit
- /// @return true if any hit
- template <typename DerivedEle>
- IGL_INLINE bool intersect_ray(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele,
- const RowVectorDIMS & origin,
- const RowVectorDIMS & dir,
- const Scalar min_t,
- igl::Hit<typename DerivedV::Scalar> & hit) const;
- /// Intersect a rays with the mesh return first hit for each
- ///
- /// @param[in] V #V by dim list of vertex positions
- /// @param[in] Ele #Ele by dim list of simplex indices
- /// @param[in] origin #ray by dim+1 list of ray origins
- /// @param[in] dir #ray by dim list of ray directions
- /// @param[in] min_t minimum t value to consider
- /// @param[out] I #ray list of indices into Ele of closest primitives
- /// (-1 indicates no hit)
- /// @param[out] T #ray list of t values (nan indicates no hit)
- /// @param[out] UV #ray by dim list of barycentric coordinates
- template <
- typename DerivedEle,
- typename DerivedOrigin,
- typename DerivedDir,
- typename DerivedI,
- typename DerivedT,
- typename DerivedUV>
- IGL_INLINE void intersect_ray(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele,
- const Eigen::MatrixBase<DerivedOrigin> & origin,
- const Eigen::MatrixBase<DerivedDir> & dir,
- const Scalar min_t,
- Eigen::PlainObjectBase<DerivedI> & I,
- Eigen::PlainObjectBase<DerivedT> & T,
- Eigen::PlainObjectBase<DerivedUV> & UV);
- template <
- typename DerivedEle,
- typename DerivedOrigin,
- typename DerivedDir>
- IGL_INLINE void intersect_ray(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele,
- const Eigen::MatrixBase<DerivedOrigin> & origin,
- const Eigen::MatrixBase<DerivedDir> & dir,
- std::vector<std::vector<igl::Hit<typename DerivedV::Scalar>>> & hits);
- /// Compute the squared distance from all query points in P to the
- /// _closest_ points on the primitives stored in the AABB hierarchy for
- /// the mesh (V,Ele).
- ///
- /// @param[in] V #V by dim list of vertex positions
- /// @param[in] Ele #Ele by dim list of simplex indices
- /// @param[in] P #P by dim list of query points
- /// @param[out] sqrD #P list of squared distances
- /// @param[out] I #P list of indices into Ele of closest primitives
- /// @param[out] C #P by dim list of closest points
- template <
- typename DerivedEle,
- typename DerivedP,
- typename DerivedsqrD,
- typename DerivedI,
- typename DerivedC>
- IGL_INLINE void squared_distance(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele,
- const Eigen::MatrixBase<DerivedP> & P,
- Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
- Eigen::PlainObjectBase<DerivedI> & I,
- Eigen::PlainObjectBase<DerivedC> & C) const;
- /// Compute the squared distance from all query points in P already stored
- /// in its own AABB hierarchy to the _closest_ points on the primitives
- /// stored in the AABB hierarchy for the mesh (V,Ele).
- ///
- /// @param[in] V #V by dim list of vertex positions
- /// @param[in] Ele #Ele by dim list of simplex indices
- /// @param[in] other AABB hierarchy of another set of primitives (must be points)
- /// @param[in] other_V #other_V by dim list of query points
- /// @param[in] other_Ele #other_Ele by ss list of simplex indices into other_V
- /// (must be simple list of points: ss == 1)
- /// @param[out] sqrD #P list of squared distances
- /// @param[out] I #P list of indices into Ele of closest primitives
- /// @param[out] C #P by dim list of closest points
- template <
- typename DerivedEle,
- typename Derivedother_V,
- typename Derivedother_Ele,
- typename DerivedsqrD,
- typename DerivedI,
- typename DerivedC>
- IGL_INLINE void squared_distance(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele,
- const AABB<Derivedother_V,DIM> & other,
- const Eigen::MatrixBase<Derivedother_V> & other_V,
- const Eigen::MatrixBase<Derivedother_Ele> & other_Ele,
- Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
- Eigen::PlainObjectBase<DerivedI> & I,
- Eigen::PlainObjectBase<DerivedC> & C) const;
- private:
- template <
- typename DerivedEle,
- typename Derivedother_V,
- typename Derivedother_Ele,
- typename DerivedsqrD,
- typename DerivedI,
- typename DerivedC>
- IGL_INLINE Scalar squared_distance_helper(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele,
- const AABB<Derivedother_V,DIM> * other,
- const Eigen::MatrixBase<Derivedother_V> & other_V,
- const Eigen::MatrixBase<Derivedother_Ele>& other_Ele,
- const Scalar up_sqr_d,
- Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
- Eigen::PlainObjectBase<DerivedI> & I,
- Eigen::PlainObjectBase<DerivedC> & C) const;
- // Compute the squared distance to the primitive in this node: assumes
- // that this is indeed a leaf node.
- //
- // Inputs:
- // V #V by dim list of vertex positions
- // Ele #Ele by dim list of simplex indices
- // p dim-long query point
- // sqr_d current minimum distance for this query, see output
- // i current index into Ele of closest point, see output
- // c dim-long current closest point, see output
- // Outputs:
- // sqr_d minimum of initial value and squared distance to this
- // primitive
- // i possibly updated index into Ele of closest point
- // c dim-long possibly updated closest point
- template <typename DerivedEle>
- IGL_INLINE void leaf_squared_distance(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele,
- const RowVectorDIMS & p,
- const Scalar low_sqr_d,
- Scalar & sqr_d,
- int & i,
- Eigen::PlainObjectBase<RowVectorDIMS> & c) const;
- // Default low_sqr_d
- template <typename DerivedEle>
- IGL_INLINE void leaf_squared_distance(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele,
- const RowVectorDIMS & p,
- Scalar & sqr_d,
- int & i,
- Eigen::PlainObjectBase<RowVectorDIMS> & c) const;
- /// Intersect a ray with the mesh return all hits
- ///
- /// @param[in] V #V by dim list of vertex positions
- /// @param[in] Ele #Ele by dim list of simplex indices
- /// @param[in] origin dim-long ray origin
- /// @param[in] dir dim-long ray direction
- /// @param[out] hits list of hits
- /// @return true if any hits
- template <typename DerivedEle>
- IGL_INLINE bool intersect_ray_opt(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele,
- const RowVectorDIMS & origin,
- const RowVectorDIMS & dir,
- const RowVectorDIMS & inv_dir,
- const RowVectorDIMS & inv_dir_pad,
- std::vector<igl::Hit<typename DerivedV::Scalar>> & hits) const;
- /// Intersect a ray with the mesh return first hit farther than `min_t`
- ///
- /// @param[in] V #V by dim list of vertex positions
- /// @param[in] Ele #Ele by dim list of simplex indices
- /// @param[in] origin dim-long ray origin
- /// @param[in] dir dim-long ray direction
- /// @param[in] min_t minimum t value to consider
- /// @param[out] hit first hit
- /// @return true if any hit
- template <typename DerivedEle>
- IGL_INLINE bool intersect_ray_opt(
- const Eigen::MatrixBase<DerivedV> & V,
- const Eigen::MatrixBase<DerivedEle> & Ele,
- const RowVectorDIMS & origin,
- const RowVectorDIMS & dir,
- const RowVectorDIMS & inv_dir,
- const RowVectorDIMS & inv_dir_pad,
- const Scalar min_t,
- igl::Hit<typename DerivedV::Scalar> & hit) const;
- public:
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW
- };
- }
- #ifndef IGL_STATIC_LIBRARY
- # include "AABB.cpp"
- #endif
- #endif
|