Doxygen based documentation (#2233)
* basic config file * documentation for two funcs * better theme; subnamespace * A-c * documentation for all core headers * more documentation * documentation for all headers (except a few classes) * rm accidental comment on igl * just h * typo * accidental delete * fix compile issues * add main page [ci skip]
This commit is contained in:
File diff suppressed because it is too large
Load Diff
+2728
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,21 @@
|
||||
# libigl - A simple C++ geometry processing library
|
||||
|
||||
This detailed documentation browser is automatically generated from the comments
|
||||
in libigl header (.h) files.
|
||||
|
||||
In general, each function (e.g., `igl::func`) will be defined in a
|
||||
correspondingly named header file (e.g., `#include <igl/func.h>`).
|
||||
|
||||
The _core_ library only depends on the standard template library (`std::`) and
|
||||
Eigen. These functions reside directly the [`igl::` namespace](./namespaceigl.html)
|
||||
|
||||
Functions with further dependencies reside in a corresonding sub-namespace. For
|
||||
example, the function `igl::spectra::lscm` depends on the Spectra library so it
|
||||
resides in the [`igl::spectra::` namespace](./namespaceigl_1_1spectra.html).
|
||||
|
||||
Functions which depend on external code under a copyleft license reside in the
|
||||
[`igl::copyleft::` namepsace](file:///Users/alecjacobson/Repos/libigl/dox/namespaceigl_1_1copyleft.html).
|
||||
|
||||
https://libigl.github.io/
|
||||
|
||||
https://github.com/libigl/libigl/
|
||||
+160
-119
@@ -15,35 +15,47 @@
|
||||
#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).
|
||||
/// 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:
|
||||
/// 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;
|
||||
AABB * m_left;
|
||||
/// Pointer to "right" child node (`nullptr` if leaf)
|
||||
AABB * m_right;
|
||||
/// Axis-Aligned Bounding Box containing this node
|
||||
Eigen::AlignedBox<Scalar,DIM> m_box;
|
||||
// -1 non-leaf
|
||||
/// Index of single primitive in this node if full leaf, otherwise -1 for non-leaf
|
||||
int m_primitive;
|
||||
//Scalar m_low_sqr_d;
|
||||
//int m_depth;
|
||||
/// @private
|
||||
AABB():
|
||||
m_left(NULL), m_right(NULL),
|
||||
m_box(), m_primitive(-1)
|
||||
//m_low_sqr_d(std::numeric_limits<double>::infinity()),
|
||||
//m_depth(0)
|
||||
{}
|
||||
/// @private
|
||||
// http://stackoverflow.com/a/3279550/148668
|
||||
AABB(const AABB& other):
|
||||
m_left(other.m_left ? new AABB(*other.m_left) : NULL),
|
||||
@@ -56,6 +68,7 @@ public:
|
||||
// m_right ? m_right->m_depth + 1 : 0))
|
||||
{
|
||||
}
|
||||
/// @private
|
||||
// copy-swap idiom
|
||||
friend void swap(AABB& first, AABB& second)
|
||||
{
|
||||
@@ -68,18 +81,21 @@ public:
|
||||
//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 deinit()
|
||||
@@ -91,20 +107,20 @@ public:
|
||||
delete m_right;
|
||||
m_right = NULL;
|
||||
}
|
||||
/// @private
|
||||
~AABB()
|
||||
{
|
||||
deinit();
|
||||
}
|
||||
// Build an Axis-Aligned Bounding Box tree for a given mesh and given
|
||||
// serialization of a previous AABB tree.
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by dim list of mesh vertex positions.
|
||||
// Ele #Ele by dim+1 list of mesh indices into #V.
|
||||
// bb_mins max_tree by dim list of bounding box min corner positions
|
||||
// bb_maxs max_tree by dim list of bounding box max corner positions
|
||||
// elements max_tree list of element or (not leaf id) indices into Ele
|
||||
// i recursive call index {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.
|
||||
/// @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,
|
||||
@@ -117,43 +133,44 @@ public:
|
||||
const Eigen::MatrixBase<Derivedbb_maxs> & bb_maxs,
|
||||
const Eigen::MatrixBase<Derivedelements> & elements,
|
||||
const int i = 0);
|
||||
// Wrapper for root with empty serialization
|
||||
/// 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.
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by dim list of mesh vertex positions.
|
||||
// Ele #Ele by dim+1 list of mesh indices into #V.
|
||||
// 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.
|
||||
// I #I list of indices into Ele of elements to include (for recursive
|
||||
// calls)
|
||||
//
|
||||
/// 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);
|
||||
// Return whether at leaf node
|
||||
/// Return whether at leaf node
|
||||
IGL_INLINE bool is_leaf() const;
|
||||
// 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).
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by dim list of mesh vertex positions. **Should be same as used to
|
||||
// construct mesh.**
|
||||
// Ele #Ele by dim+1 list of mesh indices into #V. **Should be same as used to
|
||||
// construct mesh.**
|
||||
// q dim row-vector query position
|
||||
// first whether to only return first element containing q
|
||||
// Returns:
|
||||
// list of indices of elements containing q
|
||||
/// 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,
|
||||
@@ -161,17 +178,18 @@ public:
|
||||
const Eigen::MatrixBase<Derivedq> & q,
|
||||
const bool first=false) const;
|
||||
|
||||
// If number of elements m then total tree size should be 2*h where h is
|
||||
// the deepest depth 2^ceil(log(#Ele*2-1))
|
||||
/// Number of nodes contained in subtree
|
||||
///
|
||||
/// @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;
|
||||
|
||||
// Serialize this class into 3 arrays (so we can pass it pack to matlab)
|
||||
//
|
||||
// Outputs:
|
||||
// bb_mins max_tree by dim list of bounding box min corner positions
|
||||
// bb_maxs max_tree by dim list of bounding box max corner positions
|
||||
// elements max_tree list of element or (not leaf id) indices into Ele
|
||||
// i recursive call index into these arrays {0}
|
||||
/// 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,
|
||||
@@ -181,19 +199,17 @@ public:
|
||||
Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
|
||||
Eigen::PlainObjectBase<Derivedelements> & elements,
|
||||
const int i = 0) const;
|
||||
// Compute squared distance to a query point
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by dim list of vertex positions
|
||||
// Ele #Ele by dim list of simplex indices
|
||||
// p dim-long query point
|
||||
// Outputs:
|
||||
// i facet index corresponding to smallest distances
|
||||
// c closest point
|
||||
// Returns squared distance
|
||||
//
|
||||
// Known bugs: currently assumes Elements are triangles regardless of
|
||||
// dimension.
|
||||
/// 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,
|
||||
@@ -201,26 +217,23 @@ public:
|
||||
const RowVectorDIMS & p,
|
||||
int & i,
|
||||
Eigen::PlainObjectBase<RowVectorDIMS> & c) const;
|
||||
//private:
|
||||
// Compute squared distance to a query point
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by dim list of vertex positions
|
||||
// Ele #Ele by dim list of simplex indices
|
||||
// p dim-long query point
|
||||
// low_sqr_d lower bound on squared distance, specified maximum squared
|
||||
// distance
|
||||
// up_sqr_d current upper bounded on squared distance, current minimum
|
||||
// squared distance (only consider distances less than this), see
|
||||
// output.
|
||||
// Outputs:
|
||||
// up_sqr_d updated current minimum squared distance
|
||||
// i facet index corresponding to smallest distances
|
||||
// c closest point
|
||||
// Returns squared distance
|
||||
//
|
||||
// Known bugs: currently assumes Elements are triangles regardless of
|
||||
// dimension.
|
||||
/// 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,
|
||||
@@ -230,7 +243,18 @@ public:
|
||||
const Scalar up_sqr_d,
|
||||
int & i,
|
||||
Eigen::PlainObjectBase<RowVectorDIMS> & c) const;
|
||||
// Default low_sqr_d
|
||||
/// 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,
|
||||
@@ -239,7 +263,14 @@ public:
|
||||
const Scalar up_sqr_d,
|
||||
int & i,
|
||||
Eigen::PlainObjectBase<RowVectorDIMS> & c) const;
|
||||
// All hits
|
||||
/// 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,
|
||||
@@ -247,7 +278,14 @@ public:
|
||||
const RowVectorDIMS & origin,
|
||||
const RowVectorDIMS & dir,
|
||||
std::vector<igl::Hit> & hits) const;
|
||||
// First hit
|
||||
/// 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,
|
||||
@@ -255,7 +293,15 @@ public:
|
||||
const RowVectorDIMS & origin,
|
||||
const RowVectorDIMS & dir,
|
||||
igl::Hit & hit) const;
|
||||
//private:
|
||||
/// 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,
|
||||
@@ -265,20 +311,17 @@ public:
|
||||
const Scalar min_t,
|
||||
igl::Hit & hit) const;
|
||||
|
||||
|
||||
public:
|
||||
// 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).
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by dim list of vertex positions
|
||||
// Ele #Ele by dim list of simplex indices
|
||||
// P #P by dim list of query points
|
||||
// Outputs:
|
||||
// sqrD #P list of squared distances
|
||||
// I #P list of indices into Ele of closest primitives
|
||||
// C #P by dim list of closest points
|
||||
/// 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,
|
||||
@@ -293,21 +336,19 @@ public:
|
||||
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).
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by dim list of vertex positions
|
||||
// Ele #Ele by dim list of simplex indices
|
||||
// other AABB hierarchy of another set of primitives (must be points)
|
||||
// other_V #other_V by dim list of query points
|
||||
// other_Ele #other_Ele by ss list of simplex indices into other_V
|
||||
// (must be simple list of points: ss == 1)
|
||||
// Outputs:
|
||||
// sqrD #P list of squared distances
|
||||
// I #P list of indices into Ele of closest primitives
|
||||
// C #P by dim list of closest points
|
||||
/// 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,
|
||||
|
||||
@@ -9,27 +9,24 @@
|
||||
#define IGL_ARAPENERGYTYPE_H
|
||||
namespace igl
|
||||
{
|
||||
// ARAP_ENERGY_TYPE_SPOKES "As-rigid-as-possible Surface Modeling" by [Sorkine and
|
||||
// Alexa 2007], rotations defined at vertices affecting incident edges,
|
||||
// default
|
||||
// ARAP_ENERGY_TYPE_SPOKES-AND-RIMS Adapted version of "As-rigid-as-possible Surface
|
||||
// Modeling" by [Sorkine and Alexa 2007] presented in section 4.2 of or
|
||||
// "A simple geometric model for elastic deformation" by [Chao et al.
|
||||
// 2010], rotations defined at vertices affecting incident edges and
|
||||
// opposite edges
|
||||
// ARAP_ENERGY_TYPE_ELEMENTS "A local-global approach to mesh parameterization" by
|
||||
// [Liu et al. 2010] or "A simple geometric model for elastic
|
||||
// deformation" by [Chao et al. 2010], rotations defined at elements
|
||||
// (triangles or tets)
|
||||
// ARAP_ENERGY_TYPE_DEFAULT Choose one automatically: spokes and rims
|
||||
// for surfaces, elements for planar meshes and tets (not fully
|
||||
// supported)
|
||||
/// Enum for choosing ARAP energy type
|
||||
enum ARAPEnergyType
|
||||
{
|
||||
/// "As-rigid-as-possible Surface Modeling" by [Sorkine and Alexa 2007],
|
||||
/// rotations defined at vertices affecting incident edges, default
|
||||
ARAP_ENERGY_TYPE_SPOKES = 0,
|
||||
/// Adapted version of "As-rigid-as-possible Surface Modeling" by [Sorkine
|
||||
/// and Alexa 2007] presented in section 4.2 of or "A simple geometric model
|
||||
/// for elastic deformation" by [Chao et al.\ 2010], rotations defined at
|
||||
/// vertices affecting incident edges and opposite edges
|
||||
ARAP_ENERGY_TYPE_SPOKES_AND_RIMS = 1,
|
||||
/// "A local-global approach to mesh parameterization" by [Liu et al.\ 2010]
|
||||
/// or "A simple geometric model for elastic deformation" by [Chao et al.\ 2010], rotations defined at elements (triangles or tets)
|
||||
ARAP_ENERGY_TYPE_ELEMENTS = 2,
|
||||
/// Choose one automatically: spokes and rims for surfaces, elements for
|
||||
/// planar meshes and tets (not fully supported)
|
||||
ARAP_ENERGY_TYPE_DEFAULT = 3,
|
||||
/// Total number of types
|
||||
NUM_ARAP_ENERGY_TYPES = 4
|
||||
};
|
||||
}
|
||||
|
||||
+32
-20
@@ -13,40 +13,47 @@
|
||||
#include <Eigen/Sparse>
|
||||
namespace igl
|
||||
{
|
||||
/// Hold precomputed data for AtA_cached
|
||||
struct AtA_cached_data
|
||||
{
|
||||
// Weights
|
||||
/// Weights (diagonal of W)
|
||||
Eigen::VectorXd W;
|
||||
|
||||
// Flatten composition rules
|
||||
/// @private
|
||||
std::vector<int> I_row;
|
||||
/// @private
|
||||
std::vector<int> I_col;
|
||||
/// @private
|
||||
std::vector<int> I_w;
|
||||
|
||||
// For each entry of AtA, points to the beginning
|
||||
// of the composition rules
|
||||
/// @private
|
||||
std::vector<int> I_outer;
|
||||
};
|
||||
|
||||
// Computes At * W * A, where A is sparse and W is diagonal. Divides the
|
||||
// construction in two phases, one
|
||||
// for fixing the sparsity pattern, and one to populate it with values. Compared to
|
||||
// evaluating it directly, this version is slower for the first time (since it requires a
|
||||
// precomputation), but faster to the subsequent evaluations.
|
||||
//
|
||||
// Input:
|
||||
// A m x n sparse matrix
|
||||
// data stores the precomputed sparsity pattern, data.W contains the optional diagonal weights (stored as a dense vector). If W is not provided, it is replaced by the identity.
|
||||
// Outputs:
|
||||
// AtA m by m matrix computed as AtA * W * A
|
||||
//
|
||||
// Example:
|
||||
// AtA_data = igl::AtA_cached_data();
|
||||
// AtA_data.W = W;
|
||||
// if (s.AtA.rows() == 0)
|
||||
// igl::AtA_cached_precompute(s.A,s.AtA_data,s.AtA);
|
||||
// else
|
||||
// igl::AtA_cached(s.A,s.AtA_data,s.AtA);
|
||||
/// Computes At * W * A, where A is sparse and W is diagonal.
|
||||
///
|
||||
/// Divides the construction in two phases, one for fixing the sparsity
|
||||
/// pattern, and one to populate it with values. Compared to evaluating it
|
||||
/// directly, this version is slower for the first time (since it requires a
|
||||
/// precomputation), but faster to the subsequent evaluations.
|
||||
///
|
||||
/// @param[in] A m x n sparse matrix
|
||||
/// @param[in,out] data stores the precomputed sparsity pattern, data.W contains the optional diagonal weights (stored as a dense vector). If W is not provided, it is replaced by the identity.
|
||||
/// @param[out] AtA m by m matrix computed as AtA * W * A
|
||||
///
|
||||
/// #### Example:
|
||||
///
|
||||
/// \code{cpp}
|
||||
/// AtA_data = igl::AtA_cached_data();
|
||||
/// AtA_data.W = W;
|
||||
/// if (s.AtA.rows() == 0)
|
||||
/// igl::AtA_cached_precompute(s.A,s.AtA_data,s.AtA);
|
||||
/// else
|
||||
/// igl::AtA_cached(s.A,s.AtA_data,s.AtA);
|
||||
/// \endcode
|
||||
template <typename Scalar>
|
||||
IGL_INLINE void AtA_cached_precompute(
|
||||
const Eigen::SparseMatrix<Scalar>& A,
|
||||
@@ -54,6 +61,11 @@ namespace igl
|
||||
Eigen::SparseMatrix<Scalar>& AtA
|
||||
);
|
||||
|
||||
/// Computes At * W * A, where A is sparse and W is diagonal precomputed into data.
|
||||
///
|
||||
/// @param[in] A m x n sparse matrix
|
||||
/// @param[in] data stores the precomputed sparsity pattern, data.W contains the optional diagonal weights (stored as a dense vector). If W is not provided, it is replaced by the identity.
|
||||
/// @param[out] AtA m by m matrix computed as AtA * W * A
|
||||
template <typename Scalar>
|
||||
IGL_INLINE void AtA_cached(
|
||||
const Eigen::SparseMatrix<Scalar>& A,
|
||||
|
||||
+16
-5
@@ -7,12 +7,23 @@
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_C_STR_H
|
||||
#define IGL_C_STR_H
|
||||
// http://stackoverflow.com/a/2433143/148668
|
||||
// Suppose you have a function:
|
||||
// void func(const char * c);
|
||||
// Then you can write:
|
||||
// func(C_STR("foo"<<1<<"bar"));
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
/// Convert a stream of things to a const char *.
|
||||
///
|
||||
/// Suppose you have a function:
|
||||
/// \code{cpp}
|
||||
/// void func(const char * c);
|
||||
/// \endcode
|
||||
/// Then you can write:
|
||||
/// \code{cpp}
|
||||
/// func(C_STR("foo"<<1<<"bar"));
|
||||
/// \endcode
|
||||
/// which is equivalent to:
|
||||
/// \code{cpp}
|
||||
/// func("foo1bar");
|
||||
/// \endcode
|
||||
///
|
||||
// http://stackoverflow.com/a/2433143/148668
|
||||
#define C_STR(X) static_cast<std::ostringstream&>(std::ostringstream().flush() << X).str().c_str()
|
||||
#endif
|
||||
|
||||
@@ -22,10 +22,13 @@
|
||||
namespace igl
|
||||
{
|
||||
|
||||
// A simple camera class. The camera stores projection parameters (field of
|
||||
// view angle, aspect ratio, near and far clips) as well as a rigid
|
||||
// transformation *of the camera as if it were also a scene object*. Thus, the
|
||||
// **inverse** of this rigid transformation is the modelview transformation.
|
||||
/// A simple camera class. The camera stores projection parameters (field of
|
||||
/// view angle, aspect ratio, near and far clips) as well as a rigid
|
||||
/// transformation *of the camera as if it were also a scene object*. Thus, the
|
||||
/// **inverse** of this rigid transformation is the modelview transformation.
|
||||
///
|
||||
/// \deprecated This is not maintained.
|
||||
/// @private
|
||||
class Camera
|
||||
{
|
||||
public:
|
||||
|
||||
+6
-2
@@ -10,13 +10,17 @@
|
||||
#include "igl_inline.h"
|
||||
namespace igl
|
||||
{
|
||||
// Define a standard value for double epsilon
|
||||
/// Standard value for double epsilon
|
||||
const double DOUBLE_EPS = 1.0e-14;
|
||||
/// Standard value for double epsilon²
|
||||
const double DOUBLE_EPS_SQ = 1.0e-28;
|
||||
/// Standard value for single epsilon
|
||||
const float FLOAT_EPS = 1.0e-7f;
|
||||
/// Standard value for single epsilon²
|
||||
const float FLOAT_EPS_SQ = 1.0e-14f;
|
||||
// Function returning EPS for corresponding type
|
||||
/// Function returning EPS for corresponding type
|
||||
template <typename S_type> IGL_INLINE S_type EPS();
|
||||
/// Function returning EPS_SQ for corresponding type
|
||||
template <typename S_type> IGL_INLINE S_type EPS_SQ();
|
||||
// Template specializations for float and double
|
||||
template <> IGL_INLINE float EPS<float>();
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
|
||||
/// File encoding types for writing files.
|
||||
enum class FileEncoding {
|
||||
Binary,
|
||||
Ascii
|
||||
|
||||
@@ -50,6 +50,7 @@ namespace igl {
|
||||
}
|
||||
};
|
||||
|
||||
/// Class to convert a FILE * to an std::istream
|
||||
struct FileMemoryStream : virtual FileMemoryBuffer, public std::istream
|
||||
{
|
||||
FileMemoryStream( char const *first_elem, size_t size)
|
||||
|
||||
@@ -13,33 +13,22 @@
|
||||
#include <vector>
|
||||
#include <igl/igl_inline.h>
|
||||
|
||||
// This file violates many of the libigl style guidelines.
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// HalfEdgeIterator - Fake halfedge for fast and easy navigation
|
||||
// on triangle meshes with vertex_triangle_adjacency and
|
||||
// triangle_triangle adjacency
|
||||
//
|
||||
// Note: this is different to classical Half Edge data structure.
|
||||
// Instead, it follows cell-tuple in [Brisson, 1989]
|
||||
// "Representing geometric structures in d dimensions: topology and order."
|
||||
// This class can achieve local navigation similar to half edge in OpenMesh
|
||||
// But the logic behind each atom operation is different.
|
||||
// So this should be more properly called TriangleTupleIterator.
|
||||
//
|
||||
// Each tuple contains information on (face, edge, vertex)
|
||||
// and encoded by (face, edge \in {0,1,2}, bool reverse)
|
||||
//
|
||||
// Inputs:
|
||||
// F #F by 3 list of "faces"
|
||||
// FF #F by 3 list of triangle-triangle adjacency.
|
||||
// FFi #F by 3 list of FF inverse. For FF and FFi, refer to
|
||||
// "triangle_triangle_adjacency.h"
|
||||
// Usages:
|
||||
// FlipF/E/V changes solely one actual face/edge/vertex resp.
|
||||
// NextFE iterates through one-ring of a vertex robustly.
|
||||
//
|
||||
/// Fake halfedge for fast and easy navigation
|
||||
/// on triangle meshes with vertex_triangle_adjacency and
|
||||
/// triangle_triangle adjacency
|
||||
///
|
||||
/// Note: this is different to classical Half Edge data structure.
|
||||
/// Instead, it follows cell-tuple in [Brisson, 1989]
|
||||
/// "Representing geometric structures in d dimensions: topology and order."
|
||||
/// This class can achieve local navigation similar to half edge in OpenMesh
|
||||
/// But the logic behind each atom operation is different.
|
||||
/// So this should be more properly called TriangleTupleIterator.
|
||||
///
|
||||
/// Each tuple contains information on (face, edge, vertex)
|
||||
/// and encoded by (face, edge \in {0,1,2}, bool reverse)
|
||||
template <
|
||||
typename DerivedF,
|
||||
typename DerivedFF,
|
||||
@@ -47,7 +36,15 @@ namespace igl
|
||||
class HalfEdgeIterator
|
||||
{
|
||||
public:
|
||||
// Init the HalfEdgeIterator by specifying Face,Edge Index and Orientation
|
||||
/// Init the HalfEdgeIterator by specifying Face,Edge Index and Orientation
|
||||
///
|
||||
/// @param[in] F #F by 3 list of "faces"
|
||||
/// @param[in] FF #F by 3 list of triangle-triangle adjacency.
|
||||
/// @param[in] FFi #F by 3 list of FF inverse. For FF and FFi, refer to
|
||||
/// "triangle_triangle_adjacency.h"
|
||||
/// @param[in] _fi index of the selected face
|
||||
/// @param[in] _ii index of the selected face
|
||||
/// @param[in] _reverse orientation of the selected face
|
||||
IGL_INLINE HalfEdgeIterator(
|
||||
const Eigen::MatrixBase<DerivedF>& _F,
|
||||
const Eigen::MatrixBase<DerivedFF>& _FF,
|
||||
@@ -57,41 +54,48 @@ namespace igl
|
||||
bool _reverse = false
|
||||
);
|
||||
|
||||
// Change Face
|
||||
/// Change Face
|
||||
IGL_INLINE void flipF();
|
||||
|
||||
// Change Edge
|
||||
/// Change Edge
|
||||
IGL_INLINE void flipE();
|
||||
|
||||
// Change Vertex
|
||||
/// Change Vertex
|
||||
IGL_INLINE void flipV();
|
||||
|
||||
/// Determine if on border.
|
||||
/// @returns true if the current edge is on the border
|
||||
IGL_INLINE bool isBorder();
|
||||
|
||||
/*!
|
||||
* Returns the next edge skipping the border
|
||||
* _________
|
||||
* /\ c | b /\
|
||||
* / \ | / \
|
||||
* / d \ | / a \
|
||||
* /______\|/______\
|
||||
* v
|
||||
* In this example, if a and d are of-border and the pos is iterating
|
||||
counterclockwise, this method iterate through the faces incident on vertex
|
||||
v,
|
||||
* producing the sequence a, b, c, d, a, b, c, ...
|
||||
*/
|
||||
/// Change to next edge skipping the border
|
||||
/// _________
|
||||
/// /\ c | b /\
|
||||
/// / \ | / \
|
||||
/// / d \ | / a \
|
||||
/// /______\|/______\
|
||||
/// v
|
||||
/// In this example, if a and d are of-border and the pos is iterating
|
||||
/// counterclockwise, this method iterate through the faces incident on vertex
|
||||
/// v,
|
||||
/// producing the sequence a, b, c, d, a, b, c, ...
|
||||
///
|
||||
/// @returns true if the next edge is not on the border
|
||||
IGL_INLINE bool NextFE();
|
||||
|
||||
// Get vertex index
|
||||
/// Get vertex index
|
||||
/// @return vertex index
|
||||
IGL_INLINE int Vi();
|
||||
|
||||
// Get face index
|
||||
/// Get face index
|
||||
/// @return face index
|
||||
IGL_INLINE int Fi();
|
||||
|
||||
// Get edge index
|
||||
/// Get edge index
|
||||
/// @return edge index
|
||||
IGL_INLINE int Ei();
|
||||
|
||||
/// Check if two HalfEdgeIterator are the same
|
||||
/// @return true if two HalfEdgeIterator are the same
|
||||
IGL_INLINE bool operator==(HalfEdgeIterator& p2);
|
||||
|
||||
private:
|
||||
|
||||
+10
-8
@@ -11,18 +11,20 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// Reimplementation of the embree::Hit struct from embree1.0
|
||||
//
|
||||
/// Reimplementation of the embree::Hit struct from embree1.0
|
||||
///
|
||||
// TODO: template on floating point type
|
||||
struct Hit
|
||||
{
|
||||
int id; // primitive id
|
||||
int gid; // geometry id (not used)
|
||||
// barycentric coordinates so that
|
||||
// pos = V.row(F(id,0))*(1-u-v)+V.row(F(id,1))*u+V.row(F(id,2))*v;
|
||||
/// primitive id
|
||||
int id;
|
||||
/// geometry id (not used)
|
||||
int gid;
|
||||
/// barycentric coordinates so that
|
||||
/// pos = V.row(F(id,0))*(1-u-v)+V.row(F(id,1))*u+V.row(F(id,2))*v;
|
||||
float u,v;
|
||||
// parametric distance so that
|
||||
// pos = origin + t * dir
|
||||
/// parametric distance so that
|
||||
/// pos = origin + t * dir
|
||||
float t;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,10 +8,8 @@
|
||||
#ifndef IGL_INDEXCOMPARISON_H
|
||||
#define IGL_INDEXCOMPARISON_H
|
||||
namespace igl{
|
||||
// Comparison struct used by sort
|
||||
// http://bytes.com/topic/c/answers/132045-sort-get-index
|
||||
|
||||
// For use with functions like std::sort
|
||||
/// Comparison struct used by sort
|
||||
/// http://bytes.com/topic/c/answers/132045-sort-get-index
|
||||
template<class T> struct IndexLessThan
|
||||
{
|
||||
IndexLessThan(const T arr) : arr(arr) {}
|
||||
@@ -22,7 +20,7 @@ namespace igl{
|
||||
const T arr;
|
||||
};
|
||||
|
||||
// For use with functions like std::unique
|
||||
/// Comparison struct used by unique
|
||||
template<class T> struct IndexEquals
|
||||
{
|
||||
IndexEquals(const T arr) : arr(arr) {}
|
||||
@@ -33,7 +31,7 @@ namespace igl{
|
||||
const T arr;
|
||||
};
|
||||
|
||||
// For use with functions like std::sort
|
||||
/// Comparison struct for vectors for use with functions like std::sort
|
||||
template<class T> struct IndexVectorLessThan
|
||||
{
|
||||
IndexVectorLessThan(const T & vec) : vec ( vec) {}
|
||||
@@ -44,7 +42,7 @@ namespace igl{
|
||||
const T & vec;
|
||||
};
|
||||
|
||||
// For use with functions like std::sort
|
||||
/// Comparison struct for use with functions like std::sort
|
||||
template<class T> struct IndexDimLessThan
|
||||
{
|
||||
IndexDimLessThan(const T & mat,const int & dim, const int & j) :
|
||||
@@ -67,7 +65,7 @@ namespace igl{
|
||||
const int & j;
|
||||
};
|
||||
|
||||
// For use with functions like std::sort
|
||||
/// Comparison struct For use with functions like std::sort
|
||||
template<class T> struct IndexRowLessThan
|
||||
{
|
||||
IndexRowLessThan(const T & mat) : mat ( mat) {}
|
||||
@@ -91,7 +89,7 @@ namespace igl{
|
||||
const T & mat;
|
||||
};
|
||||
|
||||
// For use with functions like std::sort
|
||||
/// Comparison struct for use with functions like std::sort
|
||||
template<class T> struct IndexRowEquals
|
||||
{
|
||||
IndexRowEquals(const T & mat) : mat ( mat) {}
|
||||
|
||||
+34
-25
@@ -1,33 +1,42 @@
|
||||
#ifndef IGL_LINSPACED_H
|
||||
#define IGL_LINSPACED_H
|
||||
#include <Eigen/Core>
|
||||
// This function is not intended to be a permanent function of libigl. Rather
|
||||
// it is a "drop-in" workaround for documented bug in Eigen:
|
||||
// http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1383
|
||||
//
|
||||
// Replace:
|
||||
//
|
||||
// Eigen::VectorXi::LinSpaced(size,low,high);
|
||||
//
|
||||
// With:
|
||||
//
|
||||
// igl::LinSpaced<Eigen::VectorXi>(size,low,high);
|
||||
//
|
||||
// Specifcally, this version will _always_ return an empty vector if size==0,
|
||||
// regardless of the values for low and high. If size != 0, then this simply
|
||||
// returns the result of Eigen::Derived::LinSpaced.
|
||||
//
|
||||
// Until this bug is fixed, we should also avoid calls to the member function
|
||||
// `.setLinSpaced`. This means replacing:
|
||||
//
|
||||
// a.setLinSpaced(size,low,high);
|
||||
//
|
||||
// with
|
||||
//
|
||||
// a = igl::LinSpaced<decltype(a) >(size,low,high);
|
||||
//
|
||||
/// @file LinSpaced.h
|
||||
///
|
||||
/// This function is not intended to be a permanent function of libigl. Rather
|
||||
/// it is a "drop-in" workaround for documented bug in Eigen:
|
||||
/// http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1383
|
||||
///
|
||||
/// Replace:
|
||||
///
|
||||
/// Eigen::VectorXi::LinSpaced(size,low,high);
|
||||
///
|
||||
/// With:
|
||||
///
|
||||
/// igl::LinSpaced<Eigen::VectorXi>(size,low,high);
|
||||
///
|
||||
/// Specifcally, this version will _always_ return an empty vector if size==0,
|
||||
/// regardless of the values for low and high. If size != 0, then this simply
|
||||
/// returns the result of Eigen::Derived::LinSpaced.
|
||||
///
|
||||
/// Until this bug is fixed, we should also avoid calls to the member function
|
||||
/// `.setLinSpaced`. This means replacing:
|
||||
///
|
||||
/// a.setLinSpaced(size,low,high);
|
||||
///
|
||||
/// with
|
||||
///
|
||||
/// a = igl::LinSpaced<decltype(a) >(size,low,high);
|
||||
///
|
||||
namespace igl
|
||||
{
|
||||
/// Replacement for Eigen::DenseBase::LinSpaced
|
||||
/// @param[in] size number of elements
|
||||
/// @param[in] low first element
|
||||
/// @param[in] high last element
|
||||
/// @return vector of size elements linearly spaced between low and
|
||||
///
|
||||
/// \fileinfo
|
||||
template <typename Derived>
|
||||
//inline typename Eigen::DenseBase< Derived >::RandomAccessLinSpacedReturnType
|
||||
inline Derived LinSpaced(
|
||||
|
||||
@@ -9,10 +9,9 @@
|
||||
#define IGL_MAPPINGENERGYTYPE_H
|
||||
namespace igl
|
||||
{
|
||||
// Energy Types used for Parameterization/Mapping.
|
||||
// Refer to SLIM [Rabinovich et al. 2017] for more details
|
||||
/// Energy Types used for Parameterization/Mapping.
|
||||
/// Refer to SLIM [Rabinovich et al. 2017] for more details
|
||||
// Todo: Integrate with ARAPEnergyType
|
||||
|
||||
enum MappingEnergyType
|
||||
{
|
||||
ARAP = 0,
|
||||
|
||||
@@ -9,13 +9,20 @@
|
||||
#define IGL_MESH_BOOLEAN_TYPE_H
|
||||
namespace igl
|
||||
{
|
||||
/// Boolean operation types
|
||||
enum MeshBooleanType
|
||||
{
|
||||
/// A ∪ B
|
||||
MESH_BOOLEAN_TYPE_UNION = 0,
|
||||
/// A ∩ B
|
||||
MESH_BOOLEAN_TYPE_INTERSECT = 1,
|
||||
/// A \ B
|
||||
MESH_BOOLEAN_TYPE_MINUS = 2,
|
||||
/// A ⊕ B
|
||||
MESH_BOOLEAN_TYPE_XOR = 3,
|
||||
/// Resolve intersections without removing any non-coplanar faces
|
||||
MESH_BOOLEAN_TYPE_RESOLVE = 4,
|
||||
/// Total number of Boolean options
|
||||
NUM_MESH_BOOLEAN_TYPES = 5
|
||||
};
|
||||
};
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
|
||||
namespace igl {
|
||||
|
||||
// Class for loading information from .msh file
|
||||
// depends only on c++stl library
|
||||
/// Class for loading information from .msh file
|
||||
/// depends only on c++stl library
|
||||
class MshLoader {
|
||||
public:
|
||||
|
||||
@@ -60,6 +60,8 @@ class MshLoader {
|
||||
// other elements
|
||||
ELEMENT_POINT=15 };
|
||||
public:
|
||||
/// Load a .msh file from a given path
|
||||
/// @param[in] filename path to .msh
|
||||
MshLoader(const std::string &filename);
|
||||
|
||||
public:
|
||||
@@ -187,4 +189,4 @@ class MshLoader {
|
||||
# include "MshLoader.cpp"
|
||||
#endif
|
||||
|
||||
#endif //IGL_MSH_LOADER_H
|
||||
#endif //IGL_MSH_LOADER_H
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
namespace igl {
|
||||
|
||||
// Class for dumping information to .msh file
|
||||
// depends only on c++stl library
|
||||
// current implementation works only with 3D information
|
||||
/// Class for dumping information to .msh file
|
||||
/// depends only on c++stl library
|
||||
/// current implementation works only with 3D information
|
||||
class MshSaver {
|
||||
public:
|
||||
typedef double Float;
|
||||
@@ -30,6 +30,9 @@ class MshSaver {
|
||||
typedef std::vector<IntVector> IntField;
|
||||
typedef std::vector<std::string> FieldNames;
|
||||
|
||||
/// Write a .msh to a given path
|
||||
/// @param[in] filename path to output file
|
||||
/// @param[in] binary whether to write in binary format
|
||||
MshSaver(const std::string& filename, bool binary=true);
|
||||
~MshSaver();
|
||||
|
||||
|
||||
@@ -10,14 +10,15 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// PER_VERTEX_NORMALS Normals computed per vertex based on incident faces
|
||||
// PER_FACE_NORMALS Normals computed per face
|
||||
// PER_CORNER_NORMALS Normals computed per corner (aka wedge) based on
|
||||
// incident faces without sharp edge
|
||||
/// Type of mesh normal computation method
|
||||
enum NormalType
|
||||
{
|
||||
/// Normals computed per vertex based on incident faces
|
||||
PER_VERTEX_NORMALS,
|
||||
/// Normals computed per face
|
||||
PER_FACE_NORMALS,
|
||||
/// Normals computed per corner (aka wedge) based on incident faces without
|
||||
/// sharp edge
|
||||
PER_CORNER_NORMALS
|
||||
};
|
||||
# define NUM_NORMAL_TYPE 3
|
||||
|
||||
+3
-3
@@ -9,9 +9,9 @@
|
||||
#define IGL_ONE_H
|
||||
namespace igl
|
||||
{
|
||||
// Often one needs a reference to a dummy variable containing one as its
|
||||
// value, for example when using AntTweakBar's
|
||||
// TwSetParam( "3D View", "opened", TW_PARAM_INT32, 1, &INT_ONE);
|
||||
/// Often one needs a reference to a dummy variable containing one as its
|
||||
/// value, for example when using AntTweakBar's
|
||||
/// TwSetParam( "3D View", "opened", TW_PARAM_INT32, 1, &INT_ONE);
|
||||
const char CHAR_ONE = 1;
|
||||
const int INT_ONE = 1;
|
||||
const unsigned int UNSIGNED_INT_ONE = 1;
|
||||
|
||||
@@ -11,8 +11,10 @@ namespace igl
|
||||
{
|
||||
// Use standard mathematical constants' M_PI if available
|
||||
#ifdef M_PI
|
||||
/// π
|
||||
constexpr double PI = M_PI;
|
||||
#else
|
||||
/// π
|
||||
constexpr double PI = 3.1415926535897932384626433832795;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -35,9 +35,17 @@
|
||||
|
||||
#else
|
||||
|
||||
/// Bold red colored text
|
||||
/// @param[in] X text to color
|
||||
/// @returns colored text as "stream"
|
||||
/// #### Example:
|
||||
///
|
||||
/// \code{cpp}
|
||||
/// std::cout<<REDRUM("File "<<filename<<" not found.")<<std::endl;
|
||||
/// \endcode
|
||||
#define REDRUM(X) "\e[1m\e[31m"<<X<<"\e[m"
|
||||
// Bold Red, etc.
|
||||
#define NORUM(X) ""<<X<<""
|
||||
#define REDRUM(X) "\e[1m\e[31m"<<X<<"\e[m"
|
||||
#define GREENRUM(X) "\e[1m\e[32m"<<X<<"\e[m"
|
||||
#define YELLOWRUM(X) "\e[1m\e[33m"<<X<<"\e[m"
|
||||
#define BLUERUM(X) "\e[1m\e[34m"<<X<<"\e[m"
|
||||
|
||||
+16
-5
@@ -7,12 +7,23 @@
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_STR_H
|
||||
#define IGL_STR_H
|
||||
// http://stackoverflow.com/a/2433143/148668
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
// Suppose you have a function:
|
||||
// void func(std::string c);
|
||||
// Then you can write:
|
||||
// func(STR("foo"<<1<<"bar"));
|
||||
/// Convert a stream of things to std:;string
|
||||
///
|
||||
/// Suppose you have a function:
|
||||
/// \code{cpp}
|
||||
/// void func(std::string s);
|
||||
/// \endcode
|
||||
/// Then you can write:
|
||||
/// \code{cpp}
|
||||
/// func(C_STR("foo"<<1<<"bar"));
|
||||
/// \endcode
|
||||
/// which is equivalent to:
|
||||
/// \code{cpp}
|
||||
/// func("foo1bar");
|
||||
/// \endcode
|
||||
///
|
||||
// http://stackoverflow.com/a/2433143/148668
|
||||
#define STR(X) static_cast<std::ostringstream&>(std::ostringstream().flush() << X).str()
|
||||
#endif
|
||||
|
||||
@@ -9,14 +9,16 @@
|
||||
#define IGL_SOLVER_STATUS_H
|
||||
namespace igl
|
||||
{
|
||||
/// Solver status type used by min_quad_with_fixed
|
||||
enum SolverStatus
|
||||
{
|
||||
// Good
|
||||
// Good. Solver declared convergence
|
||||
SOLVER_STATUS_CONVERGED = 0,
|
||||
// OK
|
||||
// OK. Solver reached max iterations
|
||||
SOLVER_STATUS_MAX_ITER = 1,
|
||||
// Bad
|
||||
// Bad. Solver reported failure
|
||||
SOLVER_STATUS_ERROR = 2,
|
||||
// Total number of solver types
|
||||
NUM_SOLVER_STATUSES = 3,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -14,16 +14,23 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// Templates:
|
||||
// T should be a matrix that implements .size(), and operator(int i)
|
||||
/// A row of things that can be sorted against other rows
|
||||
/// @tparam T should be a vector/matrix/array that implements .size(), and operator(int i)
|
||||
template <typename T>
|
||||
class SortableRow
|
||||
{
|
||||
public:
|
||||
/// The data
|
||||
T data;
|
||||
public:
|
||||
/// Default constructor
|
||||
SortableRow():data(){};
|
||||
/// Constructor
|
||||
/// @param[in] data the data
|
||||
SortableRow(const T & data):data(data){};
|
||||
/// Less than comparison
|
||||
/// @param[in] that the other row
|
||||
/// @returns true if this row is less than that row
|
||||
bool operator<(const SortableRow & that) const
|
||||
{
|
||||
// Lexicographical
|
||||
@@ -41,6 +48,9 @@ namespace igl
|
||||
// All characters the same, comes done to length
|
||||
return this->data.size()<that.data.size();
|
||||
};
|
||||
/// Equality comparison
|
||||
/// @param[in] that the other row
|
||||
/// @returns true if this row is equal to that row
|
||||
bool operator==(const SortableRow & that) const
|
||||
{
|
||||
if(this->data.size() != that.data.size())
|
||||
@@ -56,6 +66,9 @@ namespace igl
|
||||
}
|
||||
return true;
|
||||
};
|
||||
/// Inequality comparison
|
||||
/// @param[in] that the other row
|
||||
/// @returns true if this row is not equal to that row
|
||||
bool operator!=(const SortableRow & that) const
|
||||
{
|
||||
return !(*this == that);
|
||||
|
||||
+16
-8
@@ -25,10 +25,11 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
/// Simple timer class
|
||||
class Timer
|
||||
{
|
||||
public:
|
||||
// default constructor
|
||||
/// default constructor
|
||||
Timer():
|
||||
stopped(0),
|
||||
#ifdef WIN32
|
||||
@@ -64,7 +65,10 @@ namespace igl
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
//Raw mach_absolute_times going in, difference in seconds out
|
||||
/// Raw mach_absolute_times going in, difference in seconds out
|
||||
/// @param[in] endTime end time
|
||||
/// @param[in] startTime start time
|
||||
/// @return time
|
||||
double subtractTimes( uint64_t endTime, uint64_t startTime )
|
||||
{
|
||||
uint64_t difference = endTime - startTime;
|
||||
@@ -84,7 +88,7 @@ namespace igl
|
||||
}
|
||||
#endif
|
||||
|
||||
// start timer
|
||||
/// start timer
|
||||
void start()
|
||||
{
|
||||
stopped = 0; // reset stop flag
|
||||
@@ -98,7 +102,7 @@ namespace igl
|
||||
|
||||
}
|
||||
|
||||
// stop the timer
|
||||
/// stop the timer
|
||||
void stop()
|
||||
{
|
||||
stopped = 1; // set timer stopped flag
|
||||
@@ -112,23 +116,27 @@ namespace igl
|
||||
#endif
|
||||
|
||||
}
|
||||
// get elapsed time in second
|
||||
/// get elapsed time in second
|
||||
/// @return time in seconds
|
||||
double getElapsedTime()
|
||||
{
|
||||
return this->getElapsedTimeInSec();
|
||||
}
|
||||
// get elapsed time in second (same as getElapsedTime)
|
||||
/// get elapsed time in second (same as getElapsedTime)
|
||||
/// @return time
|
||||
double getElapsedTimeInSec()
|
||||
{
|
||||
return this->getElapsedTimeInMicroSec() * 0.000001;
|
||||
}
|
||||
|
||||
// get elapsed time in milli-second
|
||||
/// get elapsed time in milli-second
|
||||
/// @return time
|
||||
double getElapsedTimeInMilliSec()
|
||||
{
|
||||
return this->getElapsedTimeInMicroSec() * 0.001;
|
||||
}
|
||||
// get elapsed time in micro-second
|
||||
/// get elapsed time in micro-second
|
||||
/// @return time
|
||||
double getElapsedTimeInMicroSec()
|
||||
{
|
||||
double startTimeInMicroSec = 0;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
/// @private
|
||||
// Simple Viewport class for an opengl context. Handles reshaping and mouse.
|
||||
struct Viewport
|
||||
{
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
/// Class for building an AABB tree to implement the divide and conquer
|
||||
/// algorithm described in [Jacobson et al. 2013].
|
||||
template <
|
||||
typename Point,
|
||||
typename DerivedV,
|
||||
@@ -38,13 +40,20 @@ namespace igl
|
||||
total_positive_area(std::numeric_limits<typename DerivedV::Scalar>::infinity()),
|
||||
split_method(MEDIAN_ON_LONGEST_AXIS)
|
||||
{}
|
||||
/// Constructor
|
||||
///
|
||||
/// @param[in] V #V by 3 list of vertex positions
|
||||
/// @param[in] F #F by 3 list of triangle indices into V
|
||||
inline WindingNumberAABB(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F);
|
||||
inline WindingNumberAABB(
|
||||
const WindingNumberTree<Point,DerivedV,DerivedF> & parent,
|
||||
const Eigen::MatrixBase<DerivedF> & F);
|
||||
// Initialize some things
|
||||
/// Initialize the hierarchy to a given mesh
|
||||
///
|
||||
/// @param[in] V #V by 3 list of vertex positions
|
||||
/// @param[in] F #F by 3 list of triangle indices into V
|
||||
inline void set_mesh(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F);
|
||||
|
||||
@@ -9,14 +9,15 @@
|
||||
#define IGL_WINDINGNUMBERMETHOD_H
|
||||
namespace igl
|
||||
{
|
||||
// EXACT_WINDING_NUMBER_METHOD exact hierarchical evaluation
|
||||
// APPROX_SIMPLE_WINDING_NUMBER_METHOD poor approximation
|
||||
// APPROX_CACHE_WINDING_NUMBER_METHOD another poor approximation
|
||||
enum WindingNumberMethod
|
||||
{
|
||||
// exact hierarchical evaluation
|
||||
EXACT_WINDING_NUMBER_METHOD = 0,
|
||||
// poor approximation
|
||||
APPROX_SIMPLE_WINDING_NUMBER_METHOD = 1,
|
||||
// another poor approximation
|
||||
APPROX_CACHE_WINDING_NUMBER_METHOD = 2,
|
||||
/// Number of winding number methods
|
||||
NUM_WINDING_NUMBER_METHODS = 3
|
||||
};
|
||||
}
|
||||
|
||||
@@ -14,10 +14,9 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// Space partitioning tree for computing winding number hierarchically.
|
||||
//
|
||||
// Templates:
|
||||
// Point type for points in space, e.g. Eigen::Vector3d
|
||||
/// Space partitioning tree for computing winding number hierarchically.
|
||||
///
|
||||
/// @tparam Point type for points in space, e.g. Eigen::Vector3d
|
||||
template <
|
||||
typename Point,
|
||||
typename DerivedV,
|
||||
|
||||
+10
-13
@@ -11,14 +11,11 @@
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
// ACCUMARRY Like Matlab's accumarray. Accumulate values in V using subscripts
|
||||
// in S.
|
||||
//
|
||||
// Inputs:
|
||||
// S #S list of subscripts
|
||||
// V #V list of values
|
||||
// Outputs:
|
||||
// A max(subs)+1 list of accumulated values
|
||||
/// Accumulate values in V using subscripts in S. Like Matlab's accumarray.
|
||||
///
|
||||
/// @param[in] S #S list of subscripts
|
||||
/// @param[in] V #V list of values
|
||||
/// @param[out] A max(subs)+1 list of accumulated values
|
||||
template <
|
||||
typename DerivedS,
|
||||
typename DerivedV,
|
||||
@@ -28,11 +25,11 @@ namespace igl
|
||||
const Eigen::MatrixBase<DerivedS> & S,
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
Eigen::PlainObjectBase<DerivedA> & A);
|
||||
// Inputs:
|
||||
// S #S list of subscripts
|
||||
// V single value used for all
|
||||
// Outputs:
|
||||
// A max(subs)+1 list of accumulated values
|
||||
/// Accumulate constant value `V` using subscripts in S. Like Matlab's accumarray.
|
||||
///
|
||||
/// @param[in] S #S list of subscripts
|
||||
/// @param[in] V single value used for all
|
||||
/// @param[out] A max(subs)+1 list of accumulated values
|
||||
template <
|
||||
typename DerivedS,
|
||||
typename DerivedA
|
||||
|
||||
+47
-42
@@ -16,39 +16,41 @@
|
||||
namespace igl
|
||||
{
|
||||
struct active_set_params;
|
||||
// Known Bugs: rows of [Aeq;Aieq] **must** be linearly independent. Should be
|
||||
// using QR decomposition otherwise:
|
||||
// https://v8doc.sas.com/sashtml/ormp/chap5/sect32.htm
|
||||
//
|
||||
// ACTIVE_SET Minimize quadratic energy
|
||||
//
|
||||
// 0.5*Z'*A*Z + Z'*B + C with constraints
|
||||
//
|
||||
// that Z(known) = Y, optionally also subject to the constraints Aeq*Z = Beq,
|
||||
// and further optionally subject to the linear inequality constraints that
|
||||
// Aieq*Z <= Bieq and constant inequality constraints lx <= x <= ux
|
||||
//
|
||||
// Inputs:
|
||||
// A n by n matrix of quadratic coefficients
|
||||
// B n by 1 column of linear coefficients
|
||||
// known list of indices to known rows in Z
|
||||
// Y list of fixed values corresponding to known rows in Z
|
||||
// Aeq meq by n list of linear equality constraint coefficients
|
||||
// Beq meq by 1 list of linear equality constraint constant values
|
||||
// Aieq mieq by n list of linear inequality constraint coefficients
|
||||
// Bieq mieq by 1 list of linear inequality constraint constant values
|
||||
// lx n by 1 list of lower bounds [] implies -Inf
|
||||
// ux n by 1 list of upper bounds [] implies Inf
|
||||
// params struct of additional parameters (see below)
|
||||
// Z if not empty, is taken to be an n by 1 list of initial guess values
|
||||
// (see output)
|
||||
// Outputs:
|
||||
// Z n by 1 list of solution values
|
||||
// Returns true on success, false on error
|
||||
//
|
||||
// Benchmark: For a harmonic solve on a mesh with 325K facets, matlab 2.2
|
||||
// secs, igl/min_quad_with_fixed.h 7.1 secs
|
||||
//
|
||||
///
|
||||
/// Minimize convex quadratic energy subject to linear inequality constraints
|
||||
///
|
||||
/// min ½ Zᵀ A Z + Zᵀ B + constant
|
||||
/// Z
|
||||
/// subject to
|
||||
/// Aeq Z = Beq
|
||||
/// Aieq Z <= Bieq
|
||||
/// lx <= Z <= ux
|
||||
/// Z(known) = Y
|
||||
///
|
||||
/// that Z(known) = Y, optionally also subject to the constraints Aeq*Z = Beq,
|
||||
/// and further optionally subject to the linear inequality constraints that
|
||||
/// Aieq*Z <= Bieq and constant inequality constraints lx <= x <= ux
|
||||
///
|
||||
/// @param[in] A n by n matrix of quadratic coefficients
|
||||
/// @param[in] B n by 1 column of linear coefficients
|
||||
/// @param[in] known list of indices to known rows in Z
|
||||
/// @param[in] Y list of fixed values corresponding to known rows in Z
|
||||
/// @param[in] Aeq meq by n list of linear equality constraint coefficients
|
||||
/// @param[in] Beq meq by 1 list of linear equality constraint constant values
|
||||
/// @param[in] Aieq mieq by n list of linear inequality constraint coefficients
|
||||
/// @param[in] Bieq mieq by 1 list of linear inequality constraint constant values
|
||||
/// @param[in] lx n by 1 list of lower bounds [] implies -Inf
|
||||
/// @param[in] ux n by 1 list of upper bounds [] implies Inf
|
||||
/// @param[in] params struct of additional parameters (see below)
|
||||
/// @param[in,out] Z if not empty, is taken to be an n by 1 list of initial guess values. Set to solution on output.
|
||||
/// @return true on success, false on error
|
||||
///
|
||||
/// \note Benchmark: For a harmonic solve on a mesh with 325K facets, matlab 2.2
|
||||
/// secs, igl/min_quad_with_fixed.h 7.1 secs
|
||||
///
|
||||
/// \pre rows of [Aeq;Aieq] **must** be linearly independent. Should be
|
||||
/// using QR decomposition otherwise:
|
||||
/// https://v8doc.sas.com/sashtml/ormp/chap5/sect32.htm
|
||||
template <
|
||||
typename AT,
|
||||
typename DerivedB,
|
||||
@@ -79,22 +81,25 @@ namespace igl
|
||||
};
|
||||
|
||||
#include "EPS.h"
|
||||
/// Input parameters controling active_set
|
||||
///
|
||||
/// \fileinfo
|
||||
struct igl::active_set_params
|
||||
{
|
||||
// Input parameters for active_set:
|
||||
// Auu_pd whether Auu is positive definite {false}
|
||||
// max_iter Maximum number of iterations (0 = Infinity, {100})
|
||||
// inactive_threshold Threshold on Lagrange multiplier values to determine
|
||||
// whether to keep constraints active {EPS}
|
||||
// constraint_threshold Threshold on whether constraints are violated (0
|
||||
// is perfect) {EPS}
|
||||
// solution_diff_threshold Threshold on the squared norm of the difference
|
||||
// between two consecutive solutions {EPS}
|
||||
/// Auu_pd whether Auu is positive definite {false}
|
||||
bool Auu_pd;
|
||||
/// max_iter Maximum number of iterations (0 = Infinity, {100})
|
||||
int max_iter;
|
||||
/// inactive_threshold Threshold on Lagrange multiplier values to determine
|
||||
/// whether to keep constraints active {EPS}
|
||||
double inactive_threshold;
|
||||
/// constraint_threshold Threshold on whether constraints are violated (0
|
||||
/// is perfect) {EPS}
|
||||
double constraint_threshold;
|
||||
/// solution_diff_threshold Threshold on the squared norm of the difference
|
||||
/// between two consecutive solutions {EPS}
|
||||
double solution_diff_threshold;
|
||||
/// @private
|
||||
active_set_params():
|
||||
Auu_pd(false),
|
||||
max_iter(100),
|
||||
|
||||
@@ -14,29 +14,35 @@
|
||||
#include <vector>
|
||||
namespace igl
|
||||
{
|
||||
// Constructs the graph adjacency list of a given mesh (V,F)
|
||||
// Templates:
|
||||
// T should be a eigen sparse matrix primitive type like int or double
|
||||
// Inputs:
|
||||
// F #F by dim list of mesh faces (must be triangles)
|
||||
// sorted flag that indicates if the list should be sorted counter-clockwise
|
||||
// Outputs:
|
||||
// A vector<vector<T> > containing at row i the adjacent vertices of vertex i
|
||||
//
|
||||
// Example:
|
||||
// // Mesh in (V,F)
|
||||
// vector<vector<double> > A;
|
||||
// adjacency_list(F,A);
|
||||
//
|
||||
// See also: edges, cotmatrix, diag
|
||||
/// Constructs the graph adjacency list of a given mesh (V,F)
|
||||
///
|
||||
/// @tparam T should be a eigen sparse matrix primitive type like int or double
|
||||
/// @param[in] F #F by dim list of mesh faces (must be triangles)
|
||||
/// @param[out] A vector<vector<T> > containing at row i the adjacent vertices of vertex i
|
||||
/// @param[in] sorted flag that indicates if the list should be sorted counter-clockwise
|
||||
///
|
||||
/// Example:
|
||||
/// \code{.cpp}
|
||||
/// // Mesh in (V,F)
|
||||
/// vector<vector<double> > A;
|
||||
/// adjacency_list(F,A);
|
||||
/// \endcode
|
||||
///
|
||||
/// \see
|
||||
/// adjacency_matrix
|
||||
/// edges,
|
||||
/// cotmatrix,
|
||||
/// diag
|
||||
template <typename Index, typename IndexVector>
|
||||
IGL_INLINE void adjacency_list(
|
||||
const Eigen::MatrixBase<Index> & F,
|
||||
std::vector<std::vector<IndexVector> >& A,
|
||||
bool sorted = false);
|
||||
|
||||
// Variant that accepts polygonal faces.
|
||||
// Each element of F is a set of indices of a polygonal face.
|
||||
/// Constructs the graph adjacency list of a given _polygon_ mesh (V,F)
|
||||
///
|
||||
/// @tparam T should be a eigen sparse matrix primitive type like int or double
|
||||
/// @param[in] F #F list of polygon face index lists
|
||||
/// @param[out] A vector<vector<T> > containing at row i the adjacent vertices of vertex i
|
||||
template <typename Index>
|
||||
IGL_INLINE void adjacency_list(
|
||||
const std::vector<std::vector<Index> > & F,
|
||||
|
||||
@@ -15,43 +15,44 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// Constructs the graph adjacency matrix of a given mesh (V,F)
|
||||
// Templates:
|
||||
// T should be a eigen sparse matrix primitive type like int or double
|
||||
// Inputs:
|
||||
// F #F by dim list of mesh simplices
|
||||
// Outputs:
|
||||
// A max(F)+1 by max(F)+1 adjacency matrix, each row i corresponding to V(i,:)
|
||||
//
|
||||
// Example:
|
||||
// // Mesh in (V,F)
|
||||
// Eigen::SparseMatrix<double> A;
|
||||
// adjacency_matrix(F,A);
|
||||
// // sum each row
|
||||
// SparseVector<double> Asum;
|
||||
// sum(A,1,Asum);
|
||||
// // Convert row sums into diagonal of sparse matrix
|
||||
// SparseMatrix<double> Adiag;
|
||||
// diag(Asum,Adiag);
|
||||
// // Build uniform laplacian
|
||||
// SparseMatrix<double> U;
|
||||
// U = A-Adiag;
|
||||
//
|
||||
// See also: edges, cotmatrix, diag
|
||||
/// Constructs the graph adjacency matrix of a given mesh (V,F)
|
||||
///
|
||||
/// @tparam T should be a eigen sparse matrix primitive type like `int` or `double`
|
||||
/// @param[in] F #F by dim list of mesh simplices
|
||||
/// @param[out] A max(F)+1 by max(F)+1 adjacency matrix, each row i corresponding to V(i,:)
|
||||
///
|
||||
/// #### Example
|
||||
/// \code{.cpp}
|
||||
/// // Mesh in (V,F)
|
||||
/// Eigen::SparseMatrix<double> A;
|
||||
/// adjacency_matrix(F,A);
|
||||
/// // sum each row
|
||||
/// SparseVector<double> Asum;
|
||||
/// sum(A,1,Asum);
|
||||
/// // Convert row sums into diagonal of sparse matrix
|
||||
/// SparseMatrix<double> Adiag;
|
||||
/// diag(Asum,Adiag);
|
||||
/// // Build uniform laplacian
|
||||
/// SparseMatrix<double> U;
|
||||
/// U = A-Adiag;
|
||||
/// \endcode
|
||||
///
|
||||
/// \see
|
||||
/// edges,
|
||||
/// cotmatrix,
|
||||
/// diag
|
||||
template <typename DerivedF, typename T>
|
||||
IGL_INLINE void adjacency_matrix(
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
Eigen::SparseMatrix<T>& A);
|
||||
// Constructs an vertex adjacency for a polygon mesh.
|
||||
//
|
||||
// Inputs:
|
||||
// I #I vectorized list of polygon corner indices into rows of some matrix V
|
||||
// C #polygons+1 list of cumulative polygon sizes so that C(i+1)-C(i) =
|
||||
// size of the ith polygon, and so I(C(i)) through I(C(i+1)-1) are the
|
||||
// indices of the ith polygon
|
||||
// Outputs:
|
||||
// A max(I)+1 by max(I)+1 adjacency matrix, each row i corresponding to V(i,:)
|
||||
//
|
||||
/// Constructs an vertex adjacency for a polygon mesh.
|
||||
///
|
||||
/// @param[in] I #I vectorized list of polygon corner indices into rows of some matrix V
|
||||
/// @param[in] C #polygons+1 list of cumulative polygon sizes so that C(i+1)-C(i) =
|
||||
/// size of the ith polygon, and so I(C(i)) through I(C(i+1)-1) are the
|
||||
/// indices of the ith polygon
|
||||
/// @param[out] A max(I)+1 by max(I)+1 adjacency matrix, each row i corresponding to V(i,:)
|
||||
///
|
||||
template <typename DerivedI, typename DerivedC, typename T>
|
||||
IGL_INLINE void adjacency_matrix(
|
||||
const Eigen::MatrixBase<DerivedI> & I,
|
||||
|
||||
+9
-10
@@ -12,16 +12,15 @@
|
||||
#include <Eigen/Sparse>
|
||||
namespace igl
|
||||
{
|
||||
// For Dense matrices use: A.rowwise().all() or A.colwise().all()
|
||||
//
|
||||
// Inputs:
|
||||
// A m by n sparse matrix
|
||||
// dim dimension along which to check for all (1 or 2)
|
||||
// Output:
|
||||
// B n-long vector (if dim == 1)
|
||||
// or
|
||||
// B m-long vector (if dim == 2)
|
||||
//
|
||||
/// Check whether all values are logically true along a dimension.
|
||||
///
|
||||
/// \note For Dense matrices use: A.rowwise().all() or A.colwise().all()
|
||||
///
|
||||
/// @param[in] A m by n sparse matrix
|
||||
/// @param[in] dim dimension along which to check for all (1 or 2)
|
||||
/// @param[out] B n-long vector (if dim == 1)
|
||||
/// or m-long vector (if dim == 2)
|
||||
///
|
||||
template <typename AType, typename DerivedB>
|
||||
IGL_INLINE void all(
|
||||
const Eigen::SparseMatrix<AType> & A,
|
||||
|
||||
@@ -11,21 +11,16 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// ALL_PAIRS_DISTANCES compute distances between each point i in V and point j
|
||||
// in U
|
||||
//
|
||||
// D = all_pairs_distances(V,U)
|
||||
//
|
||||
// Templates:
|
||||
// Mat matrix class like MatrixXd
|
||||
// Inputs:
|
||||
// V #V by dim list of points
|
||||
// U #U by dim list of points
|
||||
// squared whether to return squared distances
|
||||
// Outputs:
|
||||
// D #V by #U matrix of distances, where D(i,j) gives the distance or
|
||||
// squareed distance between V(i,:) and U(j,:)
|
||||
//
|
||||
/// Compute distances between each point i in V and point j in U
|
||||
///
|
||||
/// D = all_pairs_distances(V,U)
|
||||
///
|
||||
/// @tparam matrix class like MatrixXd
|
||||
/// @param[in] V #V by dim list of points
|
||||
/// @param[in] U #U by dim list of points
|
||||
/// @param[in] squared whether to return squared distances
|
||||
/// @param[out] D #V by #U matrix of distances, where D(i,j) gives the distance or
|
||||
/// squareed distance between V(i,:) and U(j,:)
|
||||
template <typename Mat>
|
||||
IGL_INLINE void all_pairs_distances(
|
||||
const Mat & V,
|
||||
|
||||
@@ -13,17 +13,17 @@
|
||||
#include <functional>
|
||||
namespace igl
|
||||
{
|
||||
// Compute ambient occlusion per given point
|
||||
//
|
||||
// Inputs:
|
||||
// shoot_ray function handle that outputs hits of a given ray against a
|
||||
// mesh (embedded in function handles as captured variable/data)
|
||||
// P #P by 3 list of origin points
|
||||
// N #P by 3 list of origin normals
|
||||
// Outputs:
|
||||
// S #P list of ambient occlusion values between 1 (fully occluded) and
|
||||
// 0 (not occluded)
|
||||
//
|
||||
/// Compute ambient occlusion per given point using ray-mesh intersection
|
||||
/// function handle.
|
||||
///
|
||||
/// @param[in] shoot_ray function handle that outputs hits of a given ray against a
|
||||
/// mesh (embedded in function handles as captured variable/data)
|
||||
/// @param[in] P #P by 3 list of origin points
|
||||
/// @param[in] N #P by 3 list of origin normals
|
||||
/// @param[in] num_samples number of samples to use (e.g., 1000)
|
||||
/// @param[out] S #P list of ambient occlusion values between 1 (fully occluded) and
|
||||
/// 0 (not occluded)
|
||||
///
|
||||
template <
|
||||
typename DerivedP,
|
||||
typename DerivedN,
|
||||
@@ -38,8 +38,18 @@ namespace igl
|
||||
const Eigen::MatrixBase<DerivedN> & N,
|
||||
const int num_samples,
|
||||
Eigen::PlainObjectBase<DerivedS> & S);
|
||||
// Inputs:
|
||||
// AABB axis-aligned bounding box hierarchy around (V,F)
|
||||
/// Compute ambient occlusion per given point for mesh (V,F) with precomputed
|
||||
/// AABB tree.
|
||||
///
|
||||
// @param[in] AABB axis-aligned bounding box hierarchy around (V,F)
|
||||
/// @param[in] V #V by 3 list of mesh vertex positions
|
||||
/// @param[in] F #F by 3 list of mesh face indices into V
|
||||
/// @param[in] P #P by 3 list of origin points
|
||||
/// @param[in] N #P by 3 list of origin normals
|
||||
/// @param[in] num_samples number of samples to use (e.g., 1000)
|
||||
/// @param[out] S #P list of ambient occlusion values between 1 (fully occluded) and
|
||||
/// 0 (not occluded)
|
||||
///
|
||||
template <
|
||||
typename DerivedV,
|
||||
int DIM,
|
||||
@@ -55,9 +65,15 @@ namespace igl
|
||||
const Eigen::MatrixBase<DerivedN> & N,
|
||||
const int num_samples,
|
||||
Eigen::PlainObjectBase<DerivedS> & S);
|
||||
// Inputs:
|
||||
// V #V by 3 list of mesh vertex positions
|
||||
// F #F by 3 list of mesh face indices into V
|
||||
/// Compute ambient occlusion per given point for mesh (V,F)
|
||||
///
|
||||
/// @param[in] V #V by 3 list of mesh vertex positions
|
||||
/// @param[in] F #F by 3 list of mesh face indices into V
|
||||
/// @param[in] P #P by 3 list of origin points
|
||||
/// @param[in] N #P by 3 list of origin normals
|
||||
/// @param[in] num_samples number of samples to use (e.g., 1000)
|
||||
/// @param[out] S #P list of ambient occlusion values between 1 (fully occluded) and
|
||||
/// 0 (not occluded)
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
|
||||
@@ -11,13 +11,12 @@
|
||||
#include <Eigen/Geometry>
|
||||
namespace igl
|
||||
{
|
||||
// The "angular distance" between two unit quaternions is the angle of the
|
||||
// smallest rotation (treated as an Axis and Angle) that takes A to B.
|
||||
//
|
||||
// Inputs:
|
||||
// A unit quaternion
|
||||
// B unit quaternion
|
||||
// Returns angular distance
|
||||
/// The "angular distance" between two unit quaternions is the angle of the
|
||||
/// smallest rotation (treated as an Axis and Angle) that takes A to B.
|
||||
///
|
||||
/// @param[in] A unit quaternion
|
||||
/// @param[in] B unit quaternion
|
||||
/// @return angular distance
|
||||
IGL_INLINE double angular_distance(
|
||||
const Eigen::Quaterniond & A,
|
||||
const Eigen::Quaterniond & B);
|
||||
|
||||
+9
-10
@@ -12,16 +12,15 @@
|
||||
#include <Eigen/Sparse>
|
||||
namespace igl
|
||||
{
|
||||
// For Dense matrices use: A.rowwise().any() or A.colwise().any()
|
||||
//
|
||||
// Inputs:
|
||||
// A m by n sparse matrix
|
||||
// dim dimension along which to check for any (1 or 2)
|
||||
// Output:
|
||||
// B n-long vector (if dim == 1)
|
||||
// or
|
||||
// B m-long vector (if dim == 2)
|
||||
//
|
||||
/// Check whether any values are logically true along a dimension.
|
||||
///
|
||||
/// \note Dense matrices use: A.rowwise().any() or A.colwise().any()
|
||||
///
|
||||
/// @param[in] A m by n sparse matrix
|
||||
/// @param[in] dim dimension along which to check for any (1 or 2)
|
||||
/// @param[out] B n-long vector (if dim == 1)
|
||||
/// or m-long vector (if dim == 2)
|
||||
///
|
||||
template <typename AType, typename DerivedB>
|
||||
IGL_INLINE void any(
|
||||
const Eigen::SparseMatrix<AType> & A,
|
||||
|
||||
@@ -10,13 +10,14 @@
|
||||
#include "igl_inline.h"
|
||||
namespace igl
|
||||
{
|
||||
// Wrapper for STL `any_of` for matrix types
|
||||
//
|
||||
// Inputs:
|
||||
// S matrix
|
||||
// Returns whether any entries are true
|
||||
//
|
||||
// Seems that Eigen (now) implements this for `Eigen::Array`
|
||||
/// Wrapper for STL `any_of` for matrix types
|
||||
///
|
||||
/// @param[in] S matrix
|
||||
/// @return whether any entries are true
|
||||
///
|
||||
/// \deprecated Seems that Eigen (now) implements this for `Eigen::Array`
|
||||
///
|
||||
/// \see any
|
||||
template <typename Mat>
|
||||
IGL_INLINE bool any_of(const Mat & S);
|
||||
}
|
||||
|
||||
+51
-40
@@ -15,36 +15,41 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
/// Parameters and precomputed values for arap solver.
|
||||
///
|
||||
/// \fileinfo
|
||||
struct ARAPData
|
||||
{
|
||||
// n #V
|
||||
// G #V list of group indices (1 to k) for each vertex, such that vertex i
|
||||
// is assigned to group G(i)
|
||||
// energy type of energy to use
|
||||
// with_dynamics whether using dynamics (need to call arap_precomputation
|
||||
// after changing)
|
||||
// f_ext #V by dim list of external forces
|
||||
// vel #V by dim list of velocities
|
||||
// h dynamics time step
|
||||
// ym ~Young's modulus smaller is softer, larger is more rigid/stiff
|
||||
// max_iter maximum inner iterations
|
||||
// K rhs pre-multiplier
|
||||
// M mass matrix
|
||||
// solver_data quadratic solver data
|
||||
// b list of boundary indices into V
|
||||
// dim dimension being used for solving
|
||||
/// #V size of mesh
|
||||
int n;
|
||||
/// #V list of group indices (1 to k) for each vertex, such that vertex i
|
||||
/// is assigned to group G(i)
|
||||
Eigen::VectorXi G;
|
||||
/// type of energy to use
|
||||
ARAPEnergyType energy;
|
||||
/// whether using dynamics (need to call arap_precomputation after changing)
|
||||
bool with_dynamics;
|
||||
Eigen::MatrixXd f_ext,vel;
|
||||
/// #V by dim list of external forces
|
||||
Eigen::MatrixXd f_ext;
|
||||
/// #V by dim list of velocities
|
||||
Eigen::MatrixXd vel;
|
||||
/// dynamics time step
|
||||
double h;
|
||||
/// "Young's modulus" smaller is softer, larger is more rigid/stiff
|
||||
double ym;
|
||||
/// maximum inner iterations
|
||||
int max_iter;
|
||||
Eigen::SparseMatrix<double> K,M;
|
||||
/// @private rhs pre-multiplier
|
||||
Eigen::SparseMatrix<double> K;
|
||||
/// @private mass matrix
|
||||
Eigen::SparseMatrix<double> M;
|
||||
/// @private covariance scatter matrix
|
||||
Eigen::SparseMatrix<double> CSM;
|
||||
/// @private quadratic solver data
|
||||
min_quad_with_fixed_data<double> solver_data;
|
||||
/// @private list of boundary indices into V
|
||||
Eigen::VectorXi b;
|
||||
/// @private dimension being used for solving
|
||||
int dim;
|
||||
ARAPData():
|
||||
n(0),
|
||||
@@ -64,16 +69,19 @@ namespace igl
|
||||
};
|
||||
};
|
||||
|
||||
// Compute necessary information to start using an ARAP deformation
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by dim list of mesh positions
|
||||
// F #F by simplex-size list of triangle|tet indices into V
|
||||
// dim dimension being used at solve time. For deformation usually dim =
|
||||
// V.cols(), for surface parameterization V.cols() = 3 and dim = 2
|
||||
// b #b list of "boundary" fixed vertex indices into V
|
||||
// Outputs:
|
||||
// data struct containing necessary precomputation
|
||||
/// Compute necessary information to start using an ARAP deformation using
|
||||
/// local-global solver as described in "As-rigid-as-possible surface
|
||||
/// modeling" [Sorkine and Alexa 2007].
|
||||
///
|
||||
/// @param[in] V #V by dim list of mesh positions
|
||||
/// @param[in] F #F by simplex-size list of triangle|tet indices into V
|
||||
/// @param[in] dim dimension being used at solve time. For deformation usually dim =
|
||||
/// V.cols(), for surface parameterization V.cols() = 3 and dim = 2
|
||||
/// @param[in] b #b list of "boundary" fixed vertex indices into V
|
||||
/// @param[out] data struct containing necessary precomputation
|
||||
/// @return whether initialization succeeded
|
||||
///
|
||||
/// \fileinfo
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
@@ -84,18 +92,21 @@ namespace igl
|
||||
const int dim,
|
||||
const Eigen::MatrixBase<Derivedb> & b,
|
||||
ARAPData & data);
|
||||
// Inputs:
|
||||
// bc #b by dim list of boundary conditions
|
||||
// data struct containing necessary precomputation and parameters
|
||||
// U #V by dim initial guess
|
||||
//
|
||||
// NOTE: While the libigl guidelines require outputs to be of type
|
||||
// PlainObjectBase so that the user does not need to worry about allocating
|
||||
// memory for the output, in this case, the user is required to give an initial
|
||||
// guess and hence fix the size of the problem domain.
|
||||
// Taking a reference to MatrixBase in this case thus allows the user to provide e.g.
|
||||
// a map to the position data, allowing seamless interoperability with user-defined
|
||||
// datastructures without requiring a copy.
|
||||
/// Conduct arap solve.
|
||||
///
|
||||
/// @param[in] bc #b by dim list of boundary conditions
|
||||
/// @param[in] data struct containing necessary precomputation and parameters
|
||||
/// @param[in,out] U #V by dim initial guess
|
||||
///
|
||||
/// \fileinfo
|
||||
///
|
||||
/// \note While the libigl guidelines require outputs to be of type
|
||||
/// PlainObjectBase so that the user does not need to worry about allocating
|
||||
/// memory for the output, in this case, the user is required to give an initial
|
||||
/// guess and hence fix the size of the problem domain.
|
||||
/// Taking a reference to MatrixBase in this case thus allows the user to provide e.g.
|
||||
/// a map to the position data, allowing seamless interoperability with user-defined
|
||||
/// datastructures without requiring a copy.
|
||||
template <
|
||||
typename Derivedbc,
|
||||
typename DerivedU>
|
||||
|
||||
+136
-134
@@ -14,75 +14,76 @@
|
||||
#include "ARAPEnergyType.h"
|
||||
#include <vector>
|
||||
|
||||
/// @file arap_dof.h
|
||||
/// @brief "Fast Automatic Skinning Transformations" [Jacobson et al.\ 2012]
|
||||
///
|
||||
/// Arap DOF precomputation consists of two parts the computation. The first is
|
||||
/// that which depends solely on the mesh (V,F), the linear blend skinning
|
||||
/// weights (M) and the groups G. Then there's the part that depends on the
|
||||
/// previous precomputation and the list of free and fixed vertices.
|
||||
///
|
||||
///
|
||||
/// #### Caller example:
|
||||
///
|
||||
/// Once:
|
||||
/// arap_dof_precomputation(...)
|
||||
///
|
||||
/// Each frame:
|
||||
/// while(not satisfied)
|
||||
/// arap_dof_update(...)
|
||||
/// end
|
||||
/// The code and variables differ from the description in Section 3 of "Fast
|
||||
/// Automatic Skinning Transformations" by [Jacobson et al. 2012]
|
||||
///
|
||||
/// Here is a useful conversion table:
|
||||
///
|
||||
/// [article] [code]
|
||||
/// S = \tilde{K} T S = CSM * Lsep
|
||||
/// S --> R S --> R --shuffled--> Rxyz
|
||||
/// Gamma_solve RT = Pi_1 \tilde{K} RT L_part1xyz = CSolveBlock1 * Rxyz
|
||||
/// Pi_1 \tilde{K} CSolveBlock1
|
||||
/// Peq = [T_full; P_pos]
|
||||
/// T_full B_eq_fix <--- L0
|
||||
/// P_pos B_eq
|
||||
/// Pi_2 * P_eq = Lpart2and3 = Lpart2 + Lpart3
|
||||
/// Pi_2_left T_full + Lpart3 = M_fullsolve(right) * B_eq_fix
|
||||
/// Pi_2_right P_pos Lpart2 = M_fullsolve(left) * B_eq
|
||||
/// T = [Pi_1 Pi_2] [\tilde{K}TRT P_eq] L = Lpart1 + Lpart2and3
|
||||
///
|
||||
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// Caller example:
|
||||
//
|
||||
// Once:
|
||||
// arap_dof_precomputation(...)
|
||||
//
|
||||
// Each frame:
|
||||
// while(not satisfied)
|
||||
// arap_dof_update(...)
|
||||
// end
|
||||
|
||||
template <typename LbsMatrixType, typename SSCALAR>
|
||||
struct ArapDOFData;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Arap DOF precomputation consists of two parts the computation. The first is
|
||||
// that which depends solely on the mesh (V,F), the linear blend skinning
|
||||
// weights (M) and the groups G. Then there's the part that depends on the
|
||||
// previous precomputation and the list of free and fixed vertices.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// The code and variables differ from the description in Section 3 of "Fast
|
||||
// Automatic Skinning Transformations" by [Jacobson et al. 2012]
|
||||
//
|
||||
// Here is a useful conversion table:
|
||||
//
|
||||
// [article] [code]
|
||||
// S = \tilde{K} T S = CSM * Lsep
|
||||
// S --> R S --> R --shuffled--> Rxyz
|
||||
// Gamma_solve RT = Pi_1 \tilde{K} RT L_part1xyz = CSolveBlock1 * Rxyz
|
||||
// Pi_1 \tilde{K} CSolveBlock1
|
||||
// Peq = [T_full; P_pos]
|
||||
// T_full B_eq_fix <--- L0
|
||||
// P_pos B_eq
|
||||
// Pi_2 * P_eq = Lpart2and3 = Lpart2 + Lpart3
|
||||
// Pi_2_left T_full + Lpart3 = M_fullsolve(right) * B_eq_fix
|
||||
// Pi_2_right P_pos Lpart2 = M_fullsolve(left) * B_eq
|
||||
// T = [Pi_1 Pi_2] [\tilde{K}TRT P_eq] L = Lpart1 + Lpart2and3
|
||||
//
|
||||
|
||||
// Precomputes the system we are going to optimize. This consists of building
|
||||
// constructor matrices (to compute covariance matrices from transformations
|
||||
// and to build the poisson solve right hand side from rotation matrix entries)
|
||||
// and also prefactoring the poisson system.
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by dim list of vertex positions
|
||||
// F #F by {3|4} list of face indices
|
||||
// M #V * dim by #handles * dim * (dim+1) matrix such that
|
||||
// new_V(:) = LBS(V,W,A) = reshape(M * A,size(V)), where A is a column
|
||||
// vectors formed by the entries in each handle's dim by dim+1
|
||||
// transformation matrix. Specifcally, A =
|
||||
// reshape(permute(Astack,[3 1 2]),n*dim*(dim+1),1)
|
||||
// or A = [Lxx;Lyx;Lxy;Lyy;tx;ty], and likewise for other dim
|
||||
// if Astack(:,:,i) is the dim by (dim+1) transformation at handle i
|
||||
// handles are ordered according to P then BE (point handles before bone
|
||||
// handles)
|
||||
// G #V list of group indices (1 to k) for each vertex, such that vertex i
|
||||
// is assigned to group G(i)
|
||||
// Outputs:
|
||||
// data structure containing all necessary precomputation for calling
|
||||
// arap_dof_update
|
||||
// Returns true on success, false on error
|
||||
//
|
||||
// See also: lbs_matrix_column
|
||||
/// Precomputes the system to optimize for "Fast Automatic Skinning
|
||||
/// Transformations" [Jacobson et al.\ 2012] skinning degrees of freedom
|
||||
/// optimization using as-rigid-as-possible energy. This consists of building
|
||||
/// constructor matrices (to compute covariance matrices from transformations
|
||||
/// and to build the poisson solve right hand side from rotation matrix entries)
|
||||
/// and also prefactoring the poisson system.
|
||||
///
|
||||
/// @param[in] V #V by dim list of vertex positions
|
||||
/// @param[in] F #F by {3|4} list of face indices
|
||||
/// @param[in] M #V * dim by #handles * dim * (dim+1) matrix such that
|
||||
/// new_V(:) = LBS(V,W,A) = reshape(M * A,size(V)), where A is a column
|
||||
/// vectors formed by the entries in each handle's dim by dim+1
|
||||
/// transformation matrix. Specifcally, A =
|
||||
/// reshape(permute(Astack,[3 1 2]),n*dim*(dim+1),1)
|
||||
/// or A = [Lxx;Lyx;Lxy;Lyy;tx;ty], and likewise for other dim
|
||||
/// if Astack(:,:,i) is the dim by (dim+1) transformation at handle i
|
||||
/// handles are ordered according to P then BE (point handles before bone
|
||||
/// handles)
|
||||
/// @param[in] G #V list of group indices (1 to k) for each vertex, such that vertex i
|
||||
/// is assigned to group G(i)
|
||||
/// @param[out] data structure containing all necessary precomputation for calling
|
||||
/// arap_dof_update
|
||||
/// @return true on success, false on error
|
||||
///
|
||||
/// \see lbs_matrix_column
|
||||
///
|
||||
/// \fileinfo
|
||||
template <typename LbsMatrixType, typename SSCALAR>
|
||||
IGL_INLINE bool arap_dof_precomputation(
|
||||
const Eigen::MatrixXd & V,
|
||||
@@ -91,49 +92,49 @@ namespace igl
|
||||
const Eigen::Matrix<int,Eigen::Dynamic,1> & G,
|
||||
ArapDOFData<LbsMatrixType, SSCALAR> & data);
|
||||
|
||||
// Should always be called after arap_dof_precomputation, but may be called in
|
||||
// between successive calls to arap_dof_update, recomputes precomputation
|
||||
// given that there are only changes in free and fixed
|
||||
//
|
||||
// Inputs:
|
||||
// fixed_dim list of transformation element indices for fixed (or partailly
|
||||
// fixed) handles: not necessarily the complement of 'free'
|
||||
// NOTE: the constraints for fixed transformations still need to be
|
||||
// present in A_eq
|
||||
// A_eq dim*#constraint_points by m*dim*(dim+1) matrix of linear equality
|
||||
// constraint coefficients. Each row corresponds to a linear constraint,
|
||||
// so that A_eq * L = Beq says that the linear transformation entries in
|
||||
// the column L should produce the user supplied positional constraints
|
||||
// for each handle in Beq. The row A_eq(i*dim+d) corresponds to the
|
||||
// constrain on coordinate d of position i
|
||||
// Outputs:
|
||||
// data structure containing all necessary precomputation for calling
|
||||
// arap_dof_update
|
||||
// Returns true on success, false on error
|
||||
//
|
||||
// See also: lbs_matrix_column
|
||||
/// Should always be called after arap_dof_precomputation, but may be called in
|
||||
/// between successive calls to arap_dof_update, recomputes precomputation
|
||||
/// given that there are only changes in free and fixed
|
||||
///
|
||||
/// @param[in] fixed_dim list of transformation element indices for fixed (or partailly
|
||||
/// fixed) handles: not necessarily the complement of 'free'
|
||||
/// NOTE: the constraints for fixed transformations still need to be
|
||||
/// present in A_eq
|
||||
/// @param[in] A_eq dim*#constraint_points by m*dim*(dim+1) matrix of linear equality
|
||||
/// constraint coefficients. Each row corresponds to a linear constraint,
|
||||
/// so that A_eq * L = Beq says that the linear transformation entries in
|
||||
/// the column L should produce the user supplied positional constraints
|
||||
/// for each handle in Beq. The row A_eq(i*dim+d) corresponds to the
|
||||
/// constrain on coordinate d of position i
|
||||
/// @param[out] data structure containing all necessary precomputation for calling
|
||||
/// arap_dof_update
|
||||
/// @return true on success, false on error
|
||||
///
|
||||
/// \see lbs_matrix_column
|
||||
///
|
||||
/// \fileinfo
|
||||
template <typename LbsMatrixType, typename SSCALAR>
|
||||
IGL_INLINE bool arap_dof_recomputation(
|
||||
const Eigen::Matrix<int,Eigen::Dynamic,1> & fixed_dim,
|
||||
const Eigen::SparseMatrix<double> & A_eq,
|
||||
ArapDOFData<LbsMatrixType, SSCALAR> & data);
|
||||
|
||||
// Optimizes the transformations attached to each weight function based on
|
||||
// precomputed system.
|
||||
//
|
||||
// Inputs:
|
||||
// data precomputation data struct output from arap_dof_precomputation
|
||||
// Beq dim*#constraint_points constraint values.
|
||||
// L0 #handles * dim * dim+1 list of initial guess transformation entries,
|
||||
// also holds fixed transformation entries for fixed handles
|
||||
// max_iters maximum number of iterations
|
||||
// tol stopping criteria parameter. If variables (linear transformation
|
||||
// matrix entries) change by less than 'tol' the optimization terminates,
|
||||
// 0.75 (weak tolerance)
|
||||
// 0.0 (extreme tolerance)
|
||||
// Outputs:
|
||||
// L #handles * dim * dim+1 list of final optimized transformation entries,
|
||||
// allowed to be the same as L
|
||||
/// Optimizes the transformations attached to each weight function based on
|
||||
/// precomputed system.
|
||||
///
|
||||
/// @param[in] data precomputation data struct output from arap_dof_precomputation
|
||||
/// @param[in] Beq dim*#constraint_points constraint values.
|
||||
/// @param[in] L0 #handles * dim * dim+1 list of initial guess transformation entries,
|
||||
/// also holds fixed transformation entries for fixed handles
|
||||
/// @param[in] max_iters maximum number of iterations
|
||||
/// @param[in] tol stopping criteria parameter. If variables (linear transformation
|
||||
/// matrix entries) change by less than 'tol' the optimization terminates,
|
||||
/// 0.75 (weak tolerance)
|
||||
/// 0.0 (extreme tolerance)
|
||||
/// @param[out] L #handles * dim * dim+1 list of final optimized transformation entries,
|
||||
/// allowed to be the same as L
|
||||
///
|
||||
/// \fileinfo
|
||||
template <typename LbsMatrixType, typename SSCALAR>
|
||||
IGL_INLINE bool arap_dof_update(
|
||||
const ArapDOFData<LbsMatrixType,SSCALAR> & data,
|
||||
@@ -144,88 +145,89 @@ namespace igl
|
||||
Eigen::MatrixXd & L
|
||||
);
|
||||
|
||||
// Structure that contains fields for all precomputed data or data that needs
|
||||
// to be remembered at update
|
||||
/// Structure that contains fields for all precomputed data or data that needs
|
||||
/// to be remembered at update
|
||||
///
|
||||
/// \fileinfo
|
||||
template <typename LbsMatrixType, typename SSCALAR>
|
||||
struct ArapDOFData
|
||||
{
|
||||
/// Matrix with SSCALAR type
|
||||
typedef Eigen::Matrix<SSCALAR, Eigen::Dynamic, Eigen::Dynamic> MatrixXS;
|
||||
// Type of arap energy we're solving
|
||||
/// Type of arap energy we're solving
|
||||
igl::ARAPEnergyType energy;
|
||||
//// LU decomposition precomptation data; note: not used by araf_dop_update
|
||||
//// any more, replaced by M_FullSolve
|
||||
//igl::min_quad_with_fixed_data<double> lu_data;
|
||||
// List of indices of fixed transformation entries
|
||||
/// List of indices of fixed transformation entries
|
||||
Eigen::Matrix<int,Eigen::Dynamic,1> fixed_dim;
|
||||
// List of precomputed covariance scatter matrices multiplied by lbs
|
||||
// matrices
|
||||
//std::vector<Eigen::SparseMatrix<double> > CSM_M;
|
||||
/// List of precomputed covariance scatter matrices multiplied by lbs
|
||||
/// matrices
|
||||
std::vector<Eigen::MatrixXd> CSM_M;
|
||||
/// @private
|
||||
LbsMatrixType M_KG;
|
||||
// Number of mesh vertices
|
||||
/// Number of mesh vertices
|
||||
int n;
|
||||
// Number of weight functions
|
||||
/// Number of weight functions
|
||||
int m;
|
||||
// Number of dimensions
|
||||
/// Number of dimensions
|
||||
int dim;
|
||||
// Effective dimensions
|
||||
/// Effective dimensions
|
||||
int effective_dim;
|
||||
// List of indices into C of positional constraints
|
||||
/// List of indices into C of positional constraints
|
||||
Eigen::Matrix<int,Eigen::Dynamic,1> interpolated;
|
||||
/// Mask of free variables
|
||||
std::vector<bool> free_mask;
|
||||
// Full quadratic coefficients matrix before lagrangian (should be dense)
|
||||
/// Full quadratic coefficients matrix before lagrangian (should be dense)
|
||||
LbsMatrixType Q;
|
||||
|
||||
|
||||
//// Solve matrix for the global step
|
||||
//Eigen::MatrixXd M_Solve; // TODO: remove from here
|
||||
|
||||
// Full solve matrix that contains also conversion from rotations to the right hand side,
|
||||
// i.e., solves Poisson transformations just from rotations and positional constraints
|
||||
/// Full solve matrix that contains also conversion from rotations to the right hand side,
|
||||
/// i.e., solves Poisson transformations just from rotations and positional constraints
|
||||
MatrixXS M_FullSolve;
|
||||
|
||||
// Precomputed condensed matrices (3x3 commutators folded to 1x1):
|
||||
/// Precomputed condensed matrices (3x3 commutators folded to 1x1):
|
||||
MatrixXS CSM;
|
||||
/// @private
|
||||
MatrixXS CSolveBlock1;
|
||||
|
||||
// Print timings at each update
|
||||
/// Print timings at each update
|
||||
bool print_timings;
|
||||
|
||||
// Dynamics
|
||||
/// dynamics
|
||||
bool with_dynamics;
|
||||
// I'm hiding the extra dynamics stuff in this struct, which sort of defeats
|
||||
// the purpose of this function-based coding style...
|
||||
|
||||
// Time step
|
||||
/// Time step
|
||||
double h;
|
||||
|
||||
// L0 #handles * dim * dim+1 list of transformation entries from
|
||||
// previous solve
|
||||
/// #handles * dim * dim+1 list of transformation entries from
|
||||
/// previous solve
|
||||
MatrixXS L0;
|
||||
//// Lm1 #handles * dim * dim+1 list of transformation entries from
|
||||
//// previous-previous solve
|
||||
//MatrixXS Lm1;
|
||||
// "Velocity"
|
||||
/// "Velocity"
|
||||
MatrixXS Lvel0;
|
||||
|
||||
// #V by dim matrix of external forces
|
||||
// fext
|
||||
/// #V by dim matrix of external forces
|
||||
MatrixXS fext;
|
||||
|
||||
// Mass_tilde: MT * Mass * M
|
||||
/// Mass_tilde: MT * Mass * M
|
||||
LbsMatrixType Mass_tilde;
|
||||
|
||||
// Force due to gravity (premultiplier)
|
||||
/// Force due to gravity (premultiplier)
|
||||
Eigen::MatrixXd fgrav;
|
||||
// Direction of gravity
|
||||
/// Direction of gravity
|
||||
Eigen::Vector3d grav_dir;
|
||||
// Magnitude of gravity
|
||||
/// Magnitude of gravity
|
||||
double grav_mag;
|
||||
|
||||
// Π1 from the paper
|
||||
/// Π1 from the paper
|
||||
MatrixXS Pi_1;
|
||||
|
||||
// Default values
|
||||
// @private Default values
|
||||
ArapDOFData():
|
||||
energy(igl::ARAP_ENERGY_TYPE_SPOKES),
|
||||
with_dynamics(false),
|
||||
|
||||
@@ -14,35 +14,35 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// ARAP_LINEAR_BLOCK constructs a block of the matrix which constructs the
|
||||
// linear terms of a given arap energy. When treating rotations as knowns
|
||||
// (arranged in a column) then this constructs Kd of K such that the linear
|
||||
// portion of the energy is as a column:
|
||||
// K * R = [Kx Z ... Ky Z ...
|
||||
// Z Kx ... Z Ky ...
|
||||
// ... ]
|
||||
// These blocks are also used to build the "covariance scatter matrices".
|
||||
// Here we want to build a scatter matrix that multiplies against positions
|
||||
// (treated as known) producing covariance matrices to fit each rotation.
|
||||
// Notice that in the case of the RHS of the poisson solve the rotations are
|
||||
// known and the positions unknown, and vice versa for rotation fitting.
|
||||
// These linear block just relate the rotations to the positions, linearly in
|
||||
// each.
|
||||
//
|
||||
// Templates:
|
||||
// MatV vertex position matrix, e.g. Eigen::MatrixXd
|
||||
// MatF face index matrix, e.g. Eigen::MatrixXd
|
||||
// Scalar e.g. double
|
||||
// Inputs:
|
||||
// V #V by dim list of initial domain positions
|
||||
// F #F by #simplex size list of triangle indices into V
|
||||
// d coordinate of linear constructor to build
|
||||
// energy ARAPEnergyType enum value defining which energy is being used.
|
||||
// See ARAPEnergyType.h for valid options and explanations.
|
||||
// Outputs:
|
||||
// Kd #V by #V/#F block of the linear constructor matrix corresponding to
|
||||
// coordinate d
|
||||
//
|
||||
/// Constructs a block of the matrix which constructs the
|
||||
/// linear terms of a given arap energy. When treating rotations as knowns
|
||||
/// (arranged in a column) then this constructs Kd of K such that the linear
|
||||
/// portion of the energy is as a column:
|
||||
///
|
||||
/// K * R = [Kx Z ... Ky Z ...
|
||||
/// Z Kx ... Z Ky ...
|
||||
/// ... ]
|
||||
///
|
||||
/// These blocks are also used to build the "covariance scatter matrices".
|
||||
/// Here we want to build a scatter matrix that multiplies against positions
|
||||
/// (treated as known) producing covariance matrices to fit each rotation.
|
||||
/// Notice that in the case of the RHS of the poisson solve the rotations are
|
||||
/// known and the positions unknown, and vice versa for rotation fitting.
|
||||
/// These linear block just relate the rotations to the positions, linearly in
|
||||
/// each.
|
||||
///
|
||||
/// @tparam MatV vertex position matrix, e.g. Eigen::MatrixXd
|
||||
/// @tparam MatF face index matrix, e.g. Eigen::MatrixXd
|
||||
/// @tparam Scalar e.g. double
|
||||
/// @param[in] V #V by dim list of initial domain positions
|
||||
/// @param[in] F #F by #simplex size list of triangle indices into V
|
||||
/// @param[in] d coordinate of linear constructor to build
|
||||
/// @param[in] energy ARAPEnergyType enum value defining which energy is being used.
|
||||
/// See ARAPEnergyType.h for valid options and explanations.
|
||||
/// @param[out] Kd #V by #V/#F block of the linear constructor matrix
|
||||
/// corresponding to coordinate d
|
||||
///
|
||||
/// \see ARAPEnergyType
|
||||
template <typename MatV, typename MatF, typename MatK>
|
||||
IGL_INLINE void arap_linear_block(
|
||||
const MatV & V,
|
||||
@@ -50,19 +50,54 @@ namespace igl
|
||||
const int d,
|
||||
const igl::ARAPEnergyType energy,
|
||||
MatK & Kd);
|
||||
// Helper functions for each energy type
|
||||
/// Constructs a block of the matrix which constructs the linear terms for
|
||||
/// spokes energy.
|
||||
///
|
||||
/// @tparam MatV vertex position matrix, e.g. Eigen::MatrixXd
|
||||
/// @tparam MatF face index matrix, e.g. Eigen::MatrixXd
|
||||
/// @tparam Scalar e.g. double
|
||||
/// @param[in] V #V by dim list of initial domain positions
|
||||
/// @param[in] F #F by #simplex size list of triangle indices into V
|
||||
/// @param[in] d coordinate of linear constructor to build (0 index)
|
||||
/// See ARAPEnergyType.h for valid options and explanations.
|
||||
/// @param[out] Kd #V by #V block of the linear constructor matrix
|
||||
/// corresponding to coordinate d
|
||||
template <typename MatV, typename MatF, typename MatK>
|
||||
IGL_INLINE void arap_linear_block_spokes(
|
||||
const MatV & V,
|
||||
const MatF & F,
|
||||
const int d,
|
||||
MatK & Kd);
|
||||
/// Constructs a block of the matrix which constructs the linear terms for
|
||||
/// spokes and rims energy.
|
||||
///
|
||||
/// @tparam MatV vertex position matrix, e.g. Eigen::MatrixXd
|
||||
/// @tparam MatF face index matrix, e.g. Eigen::MatrixXd
|
||||
/// @tparam Scalar e.g. double
|
||||
/// @param[in] V #V by dim list of initial domain positions
|
||||
/// @param[in] F #F by #simplex size list of triangle indices into V
|
||||
/// @param[in] d coordinate of linear constructor to build (0 index)
|
||||
/// See ARAPEnergyType.h for valid options and explanations.
|
||||
/// @param[out] Kd #V by #V block of the linear constructor matrix
|
||||
/// corresponding to coordinate d
|
||||
template <typename MatV, typename MatF, typename MatK>
|
||||
IGL_INLINE void arap_linear_block_spokes_and_rims(
|
||||
const MatV & V,
|
||||
const MatF & F,
|
||||
const int d,
|
||||
MatK & Kd);
|
||||
/// Constructs a block of the matrix which constructs the linear terms for
|
||||
/// per element energy.
|
||||
///
|
||||
/// @tparam MatV vertex position matrix, e.g. Eigen::MatrixXd
|
||||
/// @tparam MatF face index matrix, e.g. Eigen::MatrixXd
|
||||
/// @tparam Scalar e.g. double
|
||||
/// @param[in] V #V by dim list of initial domain positions
|
||||
/// @param[in] F #F by #simplex size list of triangle indices into V
|
||||
/// @param[in] d coordinate of linear constructor to build (0 index)
|
||||
/// See ARAPEnergyType.h for valid options and explanations.
|
||||
/// @param[out] Kd #V by #F block of the linear constructor matrix
|
||||
/// corresponding to coordinate d
|
||||
template <typename MatV, typename MatF, typename MatK>
|
||||
IGL_INLINE void arap_linear_block_elements(
|
||||
const MatV & V,
|
||||
|
||||
+13
-14
@@ -15,20 +15,19 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// ARAP_RHS build right-hand side constructor of global poisson solve for
|
||||
// various Arap energies
|
||||
// Inputs:
|
||||
// V #V by Vdim list of initial domain positions
|
||||
// F #F by 3 list of triangle indices into V
|
||||
// dim dimension being used at solve time. For deformation usually dim =
|
||||
// V.cols(), for surface parameterization V.cols() = 3 and dim = 2
|
||||
// energy igl::ARAPEnergyType enum value defining which energy is being
|
||||
// used. See igl::ARAPEnergyType.h for valid options and explanations.
|
||||
// Outputs:
|
||||
// K #V*dim by #(F|V)*dim*dim matrix such that:
|
||||
// b = K * reshape(permute(R,[3 1 2]),size(V|F,1)*size(V,2)*size(V,2),1);
|
||||
//
|
||||
// See also: arap_linear_block
|
||||
/// Right-hand side constructor of global poisson solve for various Arap
|
||||
/// energies
|
||||
///
|
||||
/// @param[in] V #V by Vdim list of initial domain positions
|
||||
/// @param[in] F #F by 3 list of triangle indices into V
|
||||
/// @param[in] dim dimension being used at solve time. For deformation usually dim =
|
||||
/// V.cols(), for surface parameterization V.cols() = 3 and dim = 2
|
||||
/// @param[in] energy igl::ARAPEnergyType enum value defining which energy is being
|
||||
/// used. See igl::ARAPEnergyType.h for valid options and explanations.
|
||||
/// @param[out] K #V*dim by #(F|V)*dim*dim matrix such that:
|
||||
/// b = K * reshape(permute(R,[3 1 2]),size(V|F,1)*size(V,2)*size(V,2),1);
|
||||
///
|
||||
/// \see arap_linear_block
|
||||
template<typename DerivedV, typename DerivedF, typename DerivedK>
|
||||
IGL_INLINE void arap_rhs(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
|
||||
@@ -12,16 +12,15 @@
|
||||
#include <Eigen/Dense>
|
||||
namespace igl
|
||||
{
|
||||
// Move a scalar field defined on edges to vertices by averaging
|
||||
//
|
||||
// Input:
|
||||
// F: triangle mesh connectivity
|
||||
// E, oE: mapping from halfedges to edges and orientation as generated by
|
||||
// orient_halfedges
|
||||
// uE: scalar field defined on edges, one per edge
|
||||
//
|
||||
// Output:
|
||||
// uV: scalar field defined on vertices
|
||||
/// Move a scalar field defined on edges to vertices by averaging
|
||||
///
|
||||
/// @param[in] F #F by 3 triangle mesh connectivity
|
||||
/// @param[in] E #E by 3 mapping from each halfedge to each edge
|
||||
/// @param[in] oE #E by 3 orientation as generated by orient_halfedges
|
||||
/// @param[in] uE #E by 1 list of scalars
|
||||
/// @param[out] uV #V by 1 list of scalar defined on vertices
|
||||
///
|
||||
/// \see orient_halfedges
|
||||
template<typename DerivedF,typename DerivedE,typename DerivedoE,
|
||||
typename DeriveduE,typename DeriveduV>
|
||||
IGL_INLINE void average_from_edges_onto_vertices(
|
||||
|
||||
@@ -12,13 +12,11 @@
|
||||
#include <Eigen/Dense>
|
||||
namespace igl
|
||||
{
|
||||
// Move a scalar field defined on vertices to faces by averaging
|
||||
//
|
||||
// Input:
|
||||
// F #F by ss list of simples/faces
|
||||
// S #V by dim list of per-vertex values
|
||||
// Output:
|
||||
// SF #F by dim list of per-face values
|
||||
/// Move a scalar field defined on vertices to faces by averaging
|
||||
///
|
||||
/// @param[in] F #F by ss list of simples/faces
|
||||
/// @param[in] S #V by dim list of per-vertex values
|
||||
/// @param[out] SF #F by dim list of per-face values
|
||||
template <typename DerivedF, typename DerivedS, typename DerivedSF>
|
||||
IGL_INLINE void average_onto_faces(
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
|
||||
@@ -12,15 +12,12 @@
|
||||
#include <Eigen/Dense>
|
||||
namespace igl
|
||||
{
|
||||
// average_onto_vertices
|
||||
// Move a scalar field defined on faces to vertices by averaging
|
||||
//
|
||||
// Input:
|
||||
// V,F: mesh
|
||||
// S: scalar field defined on faces, Fx1
|
||||
//
|
||||
// Output:
|
||||
// SV: scalar field defined on vertices
|
||||
/// Move a scalar field defined on faces to vertices by averaging
|
||||
///
|
||||
/// @param[in] V #V by 3 list of mesh vertex positions
|
||||
/// @param[in] F #F by 3 list of mesh face indices into rows of V
|
||||
/// @param[in] S #F by 1 scalar field defined on faces
|
||||
/// @param[out] SV #V by 1 scalar field defined on vertices
|
||||
template<typename DerivedV,typename DerivedF,typename DerivedS,typename DerivedSV>
|
||||
IGL_INLINE void average_onto_vertices(const Eigen::MatrixBase<DerivedV> &V,
|
||||
const Eigen::MatrixBase<DerivedF> &F,
|
||||
|
||||
@@ -15,18 +15,16 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// Compute the average edge length for the given triangle mesh
|
||||
// Templates:
|
||||
// DerivedV derived from vertex positions matrix type: i.e. MatrixXd
|
||||
// DerivedF derived from face indices matrix type: i.e. MatrixXi
|
||||
// DerivedL derived from edge lengths matrix type: i.e. MatrixXd
|
||||
// Inputs:
|
||||
// V eigen matrix #V by 3
|
||||
// F #F by simplex-size list of mesh faces (must be simplex)
|
||||
// Outputs:
|
||||
// l average edge length
|
||||
//
|
||||
// See also: adjacency_matrix
|
||||
/// Compute the average edge length for the given triangle mesh
|
||||
///
|
||||
/// @tparam DerivedV derived from vertex positions matrix type: i.e. MatrixXd
|
||||
/// @tparam DerivedF derived from face indices matrix type: i.e. MatrixXi
|
||||
/// @tparam DerivedL derived from edge lengths matrix type: i.e. MatrixXd
|
||||
/// @param[in] V #V by dim list of mesh vertex positions
|
||||
/// @param[in] F #F by simplex-size list of mesh faces (must be simplex)
|
||||
/// @return average edge length
|
||||
///
|
||||
/// \see adjacency_matrix
|
||||
template <typename DerivedV, typename DerivedF>
|
||||
IGL_INLINE double avg_edge_length(
|
||||
const Eigen::MatrixBase<DerivedV>& V,
|
||||
|
||||
@@ -11,14 +11,15 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// Convert axis angle representation of a rotation to a quaternion
|
||||
// A Quaternion, q, is defined here as an arrays of four scalars (x,y,z,w),
|
||||
// such that q = x*i + y*j + z*k + w
|
||||
// Inputs:
|
||||
// axis 3d vector
|
||||
// angle scalar
|
||||
// Outputs:
|
||||
// quaternion
|
||||
/// Convert axis angle representation of a rotation to a quaternion.
|
||||
/// A Quaternion, q, is defined here as an arrays of four scalars (x,y,z,w),
|
||||
///
|
||||
/// such that q = x*i + y*j + z*k + w
|
||||
/// @param[in] axis 3d vector
|
||||
/// @param[in] angle scalar
|
||||
/// @param[out] out pointer to new quaternion
|
||||
///
|
||||
/// \deprecated Use `Eigen::AngleAxisd` instead
|
||||
template <typename Q_type>
|
||||
IGL_INLINE void axis_angle_to_quat(
|
||||
const Q_type *axis,
|
||||
|
||||
@@ -11,14 +11,12 @@
|
||||
#include <Eigen/Dense>
|
||||
namespace igl
|
||||
{
|
||||
// Computes the barycenter of every simplex
|
||||
//
|
||||
// Inputs:
|
||||
// V #V x dim matrix of vertex coordinates
|
||||
// F #F x simplex_size matrix of indices of simplex corners into V
|
||||
// Output:
|
||||
// BC #F x dim matrix of 3d vertices
|
||||
//
|
||||
/// Computes the barycenter of every simplex.
|
||||
///
|
||||
/// @param[in] V #V x dim matrix of vertex coordinates
|
||||
/// @param[in] F #F x simplex_size matrix of indices of simplex corners into V
|
||||
/// @param[out] BC #F x dim matrix of 3d vertices
|
||||
///
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
|
||||
@@ -11,17 +11,15 @@
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
// Compute barycentric coordinates in a tet
|
||||
//
|
||||
// Inputs:
|
||||
// P #P by 3 Query points in 3d
|
||||
// A #P by 3 Tet corners in 3d
|
||||
// B #P by 3 Tet corners in 3d
|
||||
// C #P by 3 Tet corners in 3d
|
||||
// D #P by 3 Tet corners in 3d
|
||||
// Outputs:
|
||||
// L #P by 4 list of barycentric coordinates
|
||||
//
|
||||
/// Compute barycentric coordinates of each point in a corresponding tetrahedron.
|
||||
///
|
||||
/// @param[in] P #P by 3 Query points in 3d
|
||||
/// @param[in] A #P by 3 Tet corners in 3d
|
||||
/// @param[in] B #P by 3 Tet corners in 3d
|
||||
/// @param[in] C #P by 3 Tet corners in 3d
|
||||
/// @param[in] D #P by 3 Tet corners in 3d
|
||||
/// @param[out] L #P by 4 list of barycentric coordinates
|
||||
///
|
||||
template <
|
||||
typename DerivedP,
|
||||
typename DerivedA,
|
||||
@@ -36,16 +34,14 @@ namespace igl
|
||||
const Eigen::MatrixBase<DerivedC> & C,
|
||||
const Eigen::MatrixBase<DerivedD> & D,
|
||||
Eigen::PlainObjectBase<DerivedL> & L);
|
||||
// Compute barycentric coordinates in a triangle
|
||||
//
|
||||
// Inputs:
|
||||
// P #P by dim Query points
|
||||
// A #P by dim Triangle corners
|
||||
// B #P by dim Triangle corners
|
||||
// C #P by dim Triangle corners
|
||||
// Outputs:
|
||||
// L #P by 3 list of barycentric coordinates
|
||||
//
|
||||
/// Compute barycentric coordinates in a triangle
|
||||
///
|
||||
/// @param[in] P #P by dim Query points
|
||||
/// @param[in] A #P by dim Triangle corners
|
||||
/// @param[in] B #P by dim Triangle corners
|
||||
/// @param[in] C #P by dim Triangle corners
|
||||
/// @param[out] L #P by 3 list of barycentric coordinates
|
||||
///
|
||||
template <
|
||||
typename DerivedP,
|
||||
typename DerivedA,
|
||||
|
||||
@@ -11,15 +11,13 @@
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
// Interpolate data on a triangle mesh using barycentric coordinates
|
||||
//
|
||||
// Inputs:
|
||||
// D #D by dim list of per-vertex data
|
||||
// F #F by 3 list of triangle indices
|
||||
// B #X by 3 list of barycentric corodinates
|
||||
// I #X list of triangle indices
|
||||
// Outputs:
|
||||
// X #X by dim list of interpolated data
|
||||
/// Interpolate data on a triangle mesh using barycentric coordinates
|
||||
///
|
||||
/// @param[in] D #D by dim list of per-vertex data
|
||||
/// @param[in] F #F by 3 list of triangle indices
|
||||
/// @param[in] B #X by 3 list of barycentric corodinates
|
||||
/// @param[in] I #X list of triangle indices
|
||||
/// @param[out] X #X by dim list of interpolated data
|
||||
template <
|
||||
typename DerivedD,
|
||||
typename DerivedF,
|
||||
|
||||
@@ -13,12 +13,14 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// Function like PHP's basename: /etc/sudoers.d --> sudoers.d
|
||||
// Input:
|
||||
// path string containing input path
|
||||
// Returns string containing basename (see php's basename)
|
||||
//
|
||||
// See also: dirname, pathinfo
|
||||
/// Extract basename of file path (like PHP's basename). E.g., /etc/sudoers.d → sudoers.d
|
||||
///
|
||||
/// @param[in] path string containing input path
|
||||
/// @return string containing basename (see php's basename)
|
||||
///
|
||||
/// \see
|
||||
/// dirname,
|
||||
/// pathinfo
|
||||
IGL_INLINE std::string basename(const std::string & path);
|
||||
}
|
||||
|
||||
|
||||
+27
-28
@@ -14,46 +14,45 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// Container for BBW computation related data and flags
|
||||
/// Container for BBW computation related data and flags
|
||||
class BBWData
|
||||
{
|
||||
public:
|
||||
// Enforce partition of unity during optimization (optimize all weight
|
||||
// simultaneously)
|
||||
/// Enforce partition of unity during optimization (optimize all weight
|
||||
/// simultaneously)
|
||||
bool partition_unity;
|
||||
// Initial guess
|
||||
/// Initial guess
|
||||
Eigen::MatrixXd W0;
|
||||
/// Parameters for active set solver \see active_set
|
||||
igl::active_set_params active_set_params;
|
||||
// Verbosity level
|
||||
// 0: quiet
|
||||
// 1: loud
|
||||
// 2: louder
|
||||
/// Verbosity level
|
||||
/// 0: quiet
|
||||
/// 1: loud
|
||||
/// 2: louder
|
||||
int verbosity;
|
||||
public:
|
||||
/// @private
|
||||
IGL_INLINE BBWData();
|
||||
// Print current state of object
|
||||
/// Print current state of object
|
||||
IGL_INLINE void print();
|
||||
};
|
||||
|
||||
// Compute Bounded Biharmonic Weights on a given domain (V,Ele) with a given
|
||||
// set of boundary conditions
|
||||
//
|
||||
// Templates
|
||||
// DerivedV derived type of eigen matrix for V (e.g. MatrixXd)
|
||||
// DerivedF derived type of eigen matrix for F (e.g. MatrixXi)
|
||||
// Derivedb derived type of eigen matrix for b (e.g. VectorXi)
|
||||
// Derivedbc derived type of eigen matrix for bc (e.g. MatrixXd)
|
||||
// DerivedW derived type of eigen matrix for W (e.g. MatrixXd)
|
||||
// Inputs:
|
||||
// V #V by dim vertex positions
|
||||
// Ele #Elements by simplex-size list of element indices
|
||||
// b #b boundary indices into V
|
||||
// bc #b by #W list of boundary values
|
||||
// data object containing options, initial guess --> solution and results
|
||||
// Outputs:
|
||||
// W #V by #W list of *unnormalized* weights to normalize use
|
||||
// igl::normalize_row_sums(W,W);
|
||||
// Returns true on success, false on failure
|
||||
/// Compute Bounded Biharmonic Weights on a given domain (V,Ele) with a given
|
||||
/// set of boundary conditions
|
||||
///
|
||||
/// @tparam DerivedV derived type of eigen matrix for V (e.g. MatrixXd)
|
||||
/// @tparam DerivedF derived type of eigen matrix for F (e.g. MatrixXi)
|
||||
/// @tparam Derivedb derived type of eigen matrix for b (e.g. VectorXi)
|
||||
/// @tparam Derivedbc derived type of eigen matrix for bc (e.g. MatrixXd)
|
||||
/// @tparam DerivedW derived type of eigen matrix for W (e.g. MatrixXd)
|
||||
/// @param[in] V #V by dim vertex positions
|
||||
/// @param[in] Ele #Elements by simplex-size list of element indices
|
||||
/// @param[in] b #b boundary indices into V
|
||||
/// @param[in] bc #b by #W list of boundary values
|
||||
/// @param[in,out] data object containing options, initial guess --> solution and results
|
||||
/// @param[out] W #V by #W list of *unnormalized* weights to normalize use
|
||||
/// igl::normalize_row_sums(W,W);
|
||||
/// @return true on success, false on failure
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedEle,
|
||||
|
||||
+19
-22
@@ -5,38 +5,35 @@
|
||||
#include <vector>
|
||||
namespace igl
|
||||
{
|
||||
// Evaluate a polynomial Bezier Curve.
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by dim list of Bezier control points
|
||||
// t evaluation parameter within [0,1]
|
||||
// Outputs:
|
||||
// P 1 by dim output point
|
||||
/// Evaluate a polynomial Bezier Curve at single parameter value.
|
||||
///
|
||||
/// @param[in] V #V by dim list of Bezier control points
|
||||
/// @param[in] t evaluation parameter within [0,1]
|
||||
/// @param[out] P 1 by dim output point
|
||||
template <typename DerivedV, typename DerivedP>
|
||||
IGL_INLINE void bezier(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const typename DerivedV::Scalar t,
|
||||
Eigen::PlainObjectBase<DerivedP> & P);
|
||||
// Evaluate a polynomial Bezier Curve.
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by dim list of Bezier control points
|
||||
// T #T evaluation parameters within [0,1]
|
||||
// Outputs:
|
||||
// P #T by dim output points
|
||||
/// Evaluate a polynomial Bezier Curve at many parameter values.
|
||||
///
|
||||
/// @param[in] V #V by dim list of Bezier control points
|
||||
/// @param[in] T #T evaluation parameters within [0,1]
|
||||
/// @param[out] P #T by dim output points
|
||||
template <typename DerivedV, typename DerivedT, typename DerivedP>
|
||||
IGL_INLINE void bezier(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedT> & T,
|
||||
Eigen::PlainObjectBase<DerivedP> & P);
|
||||
// Evaluate a polynomial Bezier spline with a fixed parameter set for each
|
||||
// sub-curve
|
||||
//
|
||||
// Inputs:
|
||||
// spline #curves list of lists of Bezier control points
|
||||
// T #T evaluation parameters within [0,1] to use for each spline
|
||||
// Outputs:
|
||||
// P #curves*#T by dim output points
|
||||
/// Evaluate a polynomial Bezier spline with a fixed parameter set for each
|
||||
/// sub-curve.
|
||||
///
|
||||
/// @tparam VMat type of matrix of each list of control points
|
||||
/// @tparam DerivedT Derived type of evaluation parameters
|
||||
/// @tparam DerivedP Derived type of output points
|
||||
/// @param[in] spline #curves list of lists of Bezier control points
|
||||
/// @param[in] T #T evaluation parameters within [0,1] to use for each spline
|
||||
/// @param[out] P #curves*#T by dim output points
|
||||
template <typename VMat, typename DerivedT, typename DerivedP>
|
||||
IGL_INLINE void bezier(
|
||||
const std::vector<VMat> & spline,
|
||||
|
||||
+21
-12
@@ -6,18 +6,16 @@
|
||||
#include <Eigen/Sparse>
|
||||
namespace igl
|
||||
{
|
||||
// Traverse a **directed** graph represented by an adjacency list using
|
||||
// breadth first search
|
||||
//
|
||||
// Inputs:
|
||||
// A #V list of adjacency lists or #V by #V adjacency matrix
|
||||
// s starting node (index into A)
|
||||
// Outputs:
|
||||
// D #V list of indices into rows of A in the order in which graph nodes
|
||||
// are discovered.
|
||||
// P #V list of indices into rows of A of predecessor in resulting
|
||||
// spanning tree {-1 indicates root/not discovered), order corresponds to
|
||||
// V **not** D.
|
||||
/// Traverse a **directed** graph represented by an adjacency list using.
|
||||
/// breadth first search; outputs Eigen types.
|
||||
///
|
||||
/// @param[in] A #V list of adjacency lists or #V by #V adjacency matrix
|
||||
/// @param[in] s starting node (index into A)
|
||||
/// @param[out] D #V list of indices into rows of A in the order in which graph nodes
|
||||
/// are discovered.
|
||||
/// @param[out] P #V list of indices into rows of A of predecessor in resulting
|
||||
/// spanning tree {-1 indicates root/not discovered), order corresponds to
|
||||
/// V **not** D.
|
||||
template <
|
||||
typename AType,
|
||||
typename DerivedD,
|
||||
@@ -28,6 +26,16 @@ namespace igl
|
||||
Eigen::PlainObjectBase<DerivedD> & D,
|
||||
Eigen::PlainObjectBase<DerivedP> & P);
|
||||
|
||||
/// Traverse a **directed** graph represented by an adjacency list using.
|
||||
/// breadth first search; inputs adjacency lists, outputs lists.
|
||||
///
|
||||
/// @param[in] A #V list of adjacency lists
|
||||
/// @param[in] s starting node (index into A)
|
||||
/// @param[out] D #V list of indices into rows of A in the order in which graph nodes
|
||||
/// are discovered.
|
||||
/// @param[out] P #V list of indices into rows of A of predecessor in resulting
|
||||
/// spanning tree {-1 indicates root/not discovered), order corresponds to
|
||||
/// V **not** D.
|
||||
template <
|
||||
typename AType,
|
||||
typename DType,
|
||||
@@ -37,6 +45,7 @@ namespace igl
|
||||
const size_t s,
|
||||
std::vector<DType> & D,
|
||||
std::vector<PType> & P);
|
||||
/// \overload
|
||||
template <
|
||||
typename AType,
|
||||
typename DType,
|
||||
|
||||
@@ -12,17 +12,12 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// Consistently orient faces in orientable patches using BFS
|
||||
//
|
||||
// F = bfs_orient(F,V);
|
||||
//
|
||||
// Inputs:
|
||||
// F #F by 3 list of faces
|
||||
// Outputs:
|
||||
// FF #F by 3 list of faces (OK if same as F)
|
||||
// C #F list of component ids
|
||||
//
|
||||
//
|
||||
/// Consistently orient faces in orientable patches using BFS.
|
||||
///
|
||||
/// @param[in] F #F by 3 list of faces
|
||||
/// @param[out] FF #F by 3 list of faces (OK if same as F)
|
||||
/// @param[out] C #F list of component ids
|
||||
///
|
||||
template <typename DerivedF, typename DerivedFF, typename DerivedC>
|
||||
IGL_INLINE void bfs_orient(
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
|
||||
@@ -12,54 +12,53 @@
|
||||
#include <vector>
|
||||
namespace igl
|
||||
{
|
||||
// Compute "discrete biharmonic generalized barycentric coordinates" as
|
||||
// described in "Linear Subspace Design for Real-Time Shape Deformation"
|
||||
// [Wang et al. 2015]. Not to be confused with "Bounded Biharmonic Weights
|
||||
// for Real-Time Deformation" [Jacobson et al. 2011] or "Biharmonic
|
||||
// Coordinates" (2D complex barycentric coordinates) [Weber et al. 2012].
|
||||
// These weights minimize a discrete version of the squared Laplacian energy
|
||||
// subject to positional interpolation constraints at selected vertices
|
||||
// (point handles) and transformation interpolation constraints at regions
|
||||
// (region handles).
|
||||
//
|
||||
// Templates:
|
||||
// HType should be a simple index type e.g. `int`,`size_t`
|
||||
// Inputs:
|
||||
// V #V by dim list of mesh vertex positions
|
||||
// T #T by dim+1 list of / triangle indices into V if dim=2
|
||||
// \ tetrahedron indices into V if dim=3
|
||||
// S #point-handles+#region-handles list of lists of selected vertices for
|
||||
// each handle. Point handles should have singleton lists and region
|
||||
// handles should have lists of size at least dim+1 (and these points
|
||||
// should be in general position).
|
||||
// Outputs:
|
||||
// W #V by #points-handles+(#region-handles * dim+1) matrix of weights so
|
||||
// that columns correspond to each handles generalized barycentric
|
||||
// coordinates (for point-handles) or animation space weights (for region
|
||||
// handles).
|
||||
// returns true only on success
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// MatrixXd W;
|
||||
// igl::biharmonic_coordinates(V,F,S,W);
|
||||
// const size_t dim = T.cols()-1;
|
||||
// MatrixXd H(W.cols(),dim);
|
||||
// {
|
||||
// int c = 0;
|
||||
// for(int h = 0;h<S.size();h++)
|
||||
// {
|
||||
// if(S[h].size()==1)
|
||||
// {
|
||||
// H.row(c++) = V.block(S[h][0],0,1,dim);
|
||||
// }else
|
||||
// {
|
||||
// H.block(c,0,dim+1,dim).setIdentity();
|
||||
// c+=dim+1;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// assert( (V-(W*H)).array().maxCoeff() < 1e-7 );
|
||||
/// Compute "discrete biharmonic generalized barycentric coordinates" as
|
||||
/// described in "Linear Subspace Design for Real-Time Shape Deformation"
|
||||
/// [Wang et al. 2015]. Not to be confused with "Bounded Biharmonic Weights
|
||||
/// for Real-Time Deformation" [Jacobson et al. 2011] or "Biharmonic
|
||||
/// Coordinates" (2D complex barycentric coordinates) [Weber et al. 2012].
|
||||
/// These weights minimize a discrete version of the squared Laplacian energy
|
||||
/// subject to positional interpolation constraints at selected vertices
|
||||
/// (point handles) and transformation interpolation constraints at regions
|
||||
/// (region handles).
|
||||
///
|
||||
/// @tparam SType should be a simple index type e.g. `int`,`size_t`
|
||||
/// @param[in] V #V by dim list of mesh vertex positions
|
||||
/// @param[in] T #T by dim+1 list of / triangle indices into V if dim=2
|
||||
/// \ tetrahedron indices into V if dim=3
|
||||
/// @param[in] S #point-handles+#region-handles list of lists of selected vertices for
|
||||
/// each handle. Point handles should have singleton lists and region
|
||||
/// handles should have lists of size at least dim+1 (and these points
|
||||
/// should be in general position).
|
||||
/// @param[out] W #V by #points-handles+(#region-handles * dim+1) matrix of weights so
|
||||
/// that columns correspond to each handles generalized barycentric
|
||||
/// coordinates (for point-handles) or animation space weights (for region
|
||||
/// handles).
|
||||
/// @return true only on success
|
||||
///
|
||||
/// #### Example:
|
||||
///
|
||||
/// \code{cpp}
|
||||
/// MatrixXd W;
|
||||
/// igl::biharmonic_coordinates(V,F,S,W);
|
||||
/// const size_t dim = T.cols()-1;
|
||||
/// MatrixXd H(W.cols(),dim);
|
||||
/// {
|
||||
/// int c = 0;
|
||||
/// for(int h = 0;h<S.size();h++)
|
||||
/// {
|
||||
/// if(S[h].size()==1)
|
||||
/// {
|
||||
/// H.row(c++) = V.block(S[h][0],0,1,dim);
|
||||
/// }else
|
||||
/// {
|
||||
/// H.block(c,0,dim+1,dim).setIdentity();
|
||||
/// c+=dim+1;
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// assert( (V-(W*H)).array().maxCoeff() < 1e-7 );
|
||||
/// \endcode
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedT,
|
||||
@@ -70,7 +69,8 @@ namespace igl
|
||||
const Eigen::MatrixBase<DerivedT> & T,
|
||||
const std::vector<std::vector<SType> > & S,
|
||||
Eigen::PlainObjectBase<DerivedW> & W);
|
||||
// k 2-->biharmonic, 3-->triharmonic
|
||||
/// \overload
|
||||
/// @param[in] k power of Laplacian (experimental)
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedT,
|
||||
|
||||
@@ -12,26 +12,24 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// Compute a planar mapping of a triangulated polygon (V,F) subjected to
|
||||
// boundary conditions (b,bc). The mapping should be bijective in the sense
|
||||
// that no triangles' areas become negative (this assumes they started
|
||||
// positive). This mapping is computed by "composing" harmonic mappings
|
||||
// between incremental morphs of the boundary conditions. This is a bit like
|
||||
// a discrete version of "Bijective Composite Mean Value Mappings" [Schneider
|
||||
// et al. 2013] but with a discrete harmonic map (cf. harmonic coordinates)
|
||||
// instead of mean value coordinates. This is inspired by "Embedding a
|
||||
// triangular graph within a given boundary" [Xu et al. 2011].
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by 2 list of triangle mesh vertex positions
|
||||
// F #F by 3 list of triangle indices into V
|
||||
// b #b list of boundary indices into V
|
||||
// bc #b by 2 list of boundary conditions corresponding to b
|
||||
// Outputs:
|
||||
// U #V by 2 list of output mesh vertex locations
|
||||
// Returns true if and only if U contains a successful bijectie mapping
|
||||
//
|
||||
//
|
||||
/// Compute a injective planar mapping of a triangulated polygon (V,F) subjected to
|
||||
/// boundary conditions (b,bc). The mapping should be bijective in the sense
|
||||
/// that no triangles' areas become negative (this assumes they started
|
||||
/// positive). This mapping is computed by "composing" harmonic mappings
|
||||
/// between incremental morphs of the boundary conditions. This is a bit like
|
||||
/// a discrete version of "Bijective Composite Mean Value Mappings" [Schneider
|
||||
/// et al. 2013] but with a discrete harmonic map (cf. harmonic coordinates)
|
||||
/// instead of mean value coordinates. This is inspired by "Embedding a
|
||||
/// triangular graph within a given boundary" [Xu et al. 2011].
|
||||
///
|
||||
/// @param[in] V #V by 2 list of triangle mesh vertex positions
|
||||
/// @param[in] F #F by 3 list of triangle indices into V
|
||||
/// @param[in] b #b list of boundary indices into V
|
||||
/// @param[in] bc #b by 2 list of boundary conditions corresponding to b
|
||||
/// @param[out] U #V by 2 list of output mesh vertex locations
|
||||
/// @return true if and only if U contains a successful bijectie mapping
|
||||
///
|
||||
///
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
@@ -44,17 +42,15 @@ namespace igl
|
||||
const Eigen::MatrixBase<Derivedb> & b,
|
||||
const Eigen::MatrixBase<Derivedbc> & bc,
|
||||
Eigen::PlainObjectBase<DerivedU> & U);
|
||||
//
|
||||
// Inputs:
|
||||
// min_steps minimum number of steps to take from V(b,:) to bc
|
||||
// max_steps minimum number of steps to take from V(b,:) to bc (if
|
||||
// max_steps == min_steps then no further number of steps will be tried)
|
||||
// num_inner_iters number of iterations of harmonic solves to run after
|
||||
// for each morph step (to try to push flips back in)
|
||||
// test_for_flips whether to check if flips occurred (and trigger more
|
||||
// steps). if test_for_flips = false then this function always returns
|
||||
// true
|
||||
//
|
||||
/// \overload
|
||||
/// @param[in] min_steps minimum number of steps to take from V(b,:) to bc
|
||||
/// @param[in] max_steps minimum number of steps to take from V(b,:) to bc (if
|
||||
/// max_steps == min_steps then no further number of steps will be tried)
|
||||
/// @param[in] num_inner_iters number of iterations of harmonic solves to run after
|
||||
/// for each morph step (to try to push flips back in)
|
||||
/// @param[in] test_for_flips whether to check if flips occurred (and trigger more
|
||||
/// steps). if test_for_flips = false then this function always returns
|
||||
/// true
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
|
||||
+10
-9
@@ -14,19 +14,20 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// Given a list of matrices place them along the diagonal as blocks of the
|
||||
// output matrix. Like matlab's blkdiag.
|
||||
//
|
||||
// Inputs:
|
||||
// L list of matrices {A,B, ...}
|
||||
// Outputs:
|
||||
// Y A.rows()+B.rows()+... by A.cols()+B.cols()+... block diagonal
|
||||
//
|
||||
// See also: cat, repdiag
|
||||
/// Given a list of matrices place them along the diagonal as blocks of the
|
||||
/// output matrix. Like matlab's blkdiag.
|
||||
///
|
||||
/// @param[in] L list of matrices {A,B, ...}
|
||||
/// @param[out] Y A.rows()+B.rows()+... by A.cols()+B.cols()+... block diagonal
|
||||
///
|
||||
/// \see
|
||||
/// cat,
|
||||
/// repdiag
|
||||
template <typename Scalar>
|
||||
IGL_INLINE void blkdiag(
|
||||
const std::vector<Eigen::SparseMatrix<Scalar>> & L,
|
||||
Eigen::SparseMatrix<Scalar> & Y);
|
||||
/// \overload
|
||||
template <typename DerivedY>
|
||||
IGL_INLINE void blkdiag(
|
||||
const std::vector<DerivedY> & L,
|
||||
|
||||
+14
-16
@@ -11,22 +11,20 @@
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
// "Fast Poisson Disk Sampling in Arbitrary Dimensions" [Bridson 2007]
|
||||
//
|
||||
// For very dense samplings this is faster than (up to 2x) cyCodeBase's
|
||||
// implementation of "Sample Elimination for Generating Poisson Disk Sample
|
||||
// Sets" [Yuksel 2015]. YMMV
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by dim list of mesh vertex positions
|
||||
// F #F by 3 list of mesh triangle indices into rows of V
|
||||
// r Poisson disk radius (evaluated according to Euclidean distance on V)
|
||||
// Outputs:
|
||||
// B #P by 3 list of barycentric coordinates, ith row are coordinates of
|
||||
// ith sampled point in face FI(i)
|
||||
// FI #P list of indices into F
|
||||
// P #P by dim list of sample positions.
|
||||
// See also: random_points_on_mesh
|
||||
/// "Fast Poisson Disk Sampling in Arbitrary Dimensions" [Bridson 2007].
|
||||
///
|
||||
/// For very dense samplings this is faster than (up to 2x) cyCodeBase's
|
||||
/// implementation of "Sample Elimination for Generating Poisson Disk Sample
|
||||
/// Sets" [Yuksel 2015]. YMMV
|
||||
///
|
||||
/// @param[in] V #V by dim list of mesh vertex positions
|
||||
/// @param[in] F #F by 3 list of mesh triangle indices into rows of V
|
||||
/// @param[in] r Poisson disk radius (evaluated according to Euclidean distance on V)
|
||||
/// @param[out] B #P by 3 list of barycentric coordinates, ith row are coordinates of
|
||||
/// ith sampled point in face FI(i)
|
||||
/// @param[out] FI #P list of indices into F
|
||||
/// @param[out] P #P by dim list of sample positions.
|
||||
/// \see random_points_on_mesh
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
|
||||
@@ -11,13 +11,10 @@
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
// BONE_PARENTS Recover "parent" bones from directed graph representation.
|
||||
//
|
||||
// Inputs:
|
||||
// BE #BE by 2 list of directed bone edges
|
||||
// Outputs:
|
||||
// P #BE by 1 list of parent indices into BE, -1 means root.
|
||||
//
|
||||
/// Recover "parent" bones from directed graph representation.
|
||||
///
|
||||
/// @param[in] BE #BE by 2 list of directed bone edges
|
||||
/// @param[out] P #BE by 1 list of parent indices into BE, -1 means root.
|
||||
template <typename DerivedBE, typename DerivedP>
|
||||
IGL_INLINE void bone_parents(
|
||||
const Eigen::MatrixBase<DerivedBE>& BE,
|
||||
|
||||
@@ -12,31 +12,30 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
|
||||
// Compute boundary conditions for automatic weights computation. This
|
||||
// function expects that the given mesh (V,Ele) has sufficient samples
|
||||
// (vertices) exactly at point handle locations and exactly along bone and
|
||||
// cage edges.
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by dim list of domain vertices
|
||||
// Ele #Ele by simplex-size list of simplex indices
|
||||
// C #C by dim list of handle positions
|
||||
// P #P by 1 list of point handle indices into C
|
||||
// BE #BE by 2 list of bone edge indices into C
|
||||
// CE #CE by 2 list of cage edge indices into *P*
|
||||
// Outputs:
|
||||
// b #b list of boundary indices (indices into V of vertices which have
|
||||
// known, fixed values)
|
||||
// bc #b by #weights list of known/fixed values for boundary vertices
|
||||
// (notice the #b != #weights in general because #b will include all the
|
||||
// intermediary samples along each bone, etc.. The ordering of the
|
||||
// weights corresponds to [P;BE]
|
||||
// Returns false if boundary conditions are suspicious:
|
||||
// P and BE are empty
|
||||
// bc is empty
|
||||
// some column of bc doesn't have a 0 (assuming bc has >1 columns)
|
||||
// some column of bc doesn't have a 1 (assuming bc has >1 columns)
|
||||
/// Compute boundary conditions for automatic weights computation. This
|
||||
/// function expects that the given mesh (V,Ele) has sufficient samples
|
||||
/// (vertices) exactly at point handle locations and exactly along bone and
|
||||
/// cage edges.
|
||||
///
|
||||
/// @param[in] V #V by dim list of domain vertices
|
||||
/// @param[in] Ele #Ele by simplex-size list of simplex indices
|
||||
/// @param[in] C #C by dim list of handle positions
|
||||
/// @param[in] P #P by 1 list of point handle indices into C
|
||||
/// @param[in] BE #BE by 2 list of bone edge indices into C
|
||||
/// @param[in] CE #CE by 2 list of cage edge indices into *P*
|
||||
/// @param[out] b #b list of boundary indices (indices into V of vertices which have
|
||||
/// known, fixed values)
|
||||
/// @param[out] bc #b by #weights list of known/fixed values for boundary vertices
|
||||
/// (notice the #b != #weights in general because #b will include all the
|
||||
/// intermediary samples along each bone, etc.. The ordering of the
|
||||
/// weights corresponds to [P;BE]
|
||||
/// @return false if boundary conditions are suspicious:
|
||||
/// P and BE are empty
|
||||
/// bc is empty
|
||||
/// some column of bc doesn't have a 0 (assuming bc has >1 columns)
|
||||
/// some column of bc doesn't have a 1 (assuming bc has >1 columns)
|
||||
///
|
||||
/// \note 3D cages are not yet supported.
|
||||
IGL_INLINE bool boundary_conditions(
|
||||
const Eigen::MatrixXd & V,
|
||||
const Eigen::MatrixXi & Ele,
|
||||
|
||||
@@ -15,17 +15,14 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// BOUNDARY_FACETS Determine boundary faces (edges) of tetrahedra (triangles)
|
||||
// stored in T (analogous to qptoolbox's `outline` and `boundary_faces`).
|
||||
//
|
||||
// Input:
|
||||
// T tetrahedron (triangle) index list, m by 4 (3), where m is the number of tetrahedra
|
||||
// Output:
|
||||
// F list of boundary faces, n by 3 (2), where n is the number of boundary faces
|
||||
// J list of indices into T, n by 1
|
||||
// K list of indices revealing across from which vertex is this facet
|
||||
//
|
||||
//
|
||||
/// Determine boundary faces (edges) of tetrahedra (triangles) stored in T
|
||||
/// (analogous to qptoolbox's `outline` and `boundary_faces`).
|
||||
///
|
||||
/// @param[in] T tetrahedron (triangle) index list, m by 4 (3), where m is the number of tetrahedra
|
||||
/// @param[out] F list of boundary faces, n by 3 (2), where n is the number of boundary faces
|
||||
/// @param[out] J list of indices into T, n by 1
|
||||
/// @param[out] K list of indices revealing across from which vertex is this facet
|
||||
///
|
||||
template <
|
||||
typename DerivedT,
|
||||
typename DerivedF,
|
||||
@@ -36,14 +33,26 @@ namespace igl
|
||||
Eigen::PlainObjectBase<DerivedF>& F,
|
||||
Eigen::PlainObjectBase<DerivedJ>& J,
|
||||
Eigen::PlainObjectBase<DerivedK>& K);
|
||||
/// Determine boundary faces (edges) of tetrahedra (triangles) stored in T.
|
||||
///
|
||||
/// @param[in] T tetrahedron (triangle) index list, m by 4 (3), where m is the number of tetrahedra
|
||||
/// @param[out] F list of boundary faces, n by 3 (2), where n is the number of boundary faces
|
||||
template <typename DerivedT, typename DerivedF>
|
||||
IGL_INLINE void boundary_facets(
|
||||
const Eigen::MatrixBase<DerivedT>& T,
|
||||
Eigen::PlainObjectBase<DerivedF>& F);
|
||||
// Same as above but returns F
|
||||
/// Determine boundary faces (edges) of tetrahedra (triangles) stored in T.
|
||||
///
|
||||
/// @param[in] T tetrahedron (triangle) index list, m by 4 (3), where m is the number of tetrahedra
|
||||
/// @return list of boundary faces, n by 3 (2), where n is the number of boundary faces
|
||||
template <typename DerivedT, typename Ret>
|
||||
Ret boundary_facets(
|
||||
const Eigen::MatrixBase<DerivedT>& T);
|
||||
/// Determine boundary faces (edges) of tetrahedra (triangles) stored in T;
|
||||
/// inputs and outputs lists.
|
||||
///
|
||||
/// @param[in] T tetrahedron (triangle) index list, m by 4 (3), where m is the number of tetrahedra
|
||||
/// @param[out] F list of boundary faces, n by 3 (2), where n is the number of boundary faces
|
||||
template <typename IntegerT, typename IntegerF>
|
||||
IGL_INLINE void boundary_facets(
|
||||
const std::vector<std::vector<IntegerT> > & T,
|
||||
|
||||
+20
-30
@@ -14,46 +14,36 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// Compute list of ordered boundary loops for a manifold mesh.
|
||||
//
|
||||
// Templates:
|
||||
// Index index type
|
||||
// Inputs:
|
||||
// F #V by dim list of mesh faces
|
||||
// Outputs:
|
||||
// L list of loops where L[i] = ordered list of boundary vertices in loop i
|
||||
//
|
||||
/// Compute list of ordered boundary loops for a manifold mesh.
|
||||
///
|
||||
/// @tparam Index index type
|
||||
/// @param[in] F #F by dim list of mesh faces
|
||||
/// @param[out] L list of loops where L[i] = ordered list of boundary vertices in loop i
|
||||
///
|
||||
template <typename DerivedF, typename Index>
|
||||
IGL_INLINE void boundary_loop(
|
||||
const Eigen::MatrixBase<DerivedF>& F,
|
||||
std::vector<std::vector<Index> >& L);
|
||||
|
||||
|
||||
// Compute ordered boundary loops for a manifold mesh and return the
|
||||
// longest loop in terms of vertices.
|
||||
//
|
||||
// Templates:
|
||||
// Index index type
|
||||
// Inputs:
|
||||
// F #V by dim list of mesh faces
|
||||
// Outputs:
|
||||
// L ordered list of boundary vertices of longest boundary loop
|
||||
//
|
||||
/// Compute ordered boundary loops for a manifold mesh and return the
|
||||
/// longest loop in terms of vertices.
|
||||
///
|
||||
/// @tparam Index index type
|
||||
/// @param[in] F #F by dim list of mesh faces
|
||||
/// @param[out] L ordered list of boundary vertices of longest boundary loop
|
||||
///
|
||||
template <typename DerivedF, typename Index>
|
||||
IGL_INLINE void boundary_loop(
|
||||
const Eigen::MatrixBase<DerivedF>& F,
|
||||
std::vector<Index>& L);
|
||||
|
||||
// Compute ordered boundary loops for a manifold mesh and return the
|
||||
// longest loop in terms of vertices.
|
||||
//
|
||||
// Templates:
|
||||
// Index index type
|
||||
// Inputs:
|
||||
// F #V by dim list of mesh faces
|
||||
// Outputs:
|
||||
// L ordered list of boundary vertices of longest boundary loop
|
||||
//
|
||||
/// Compute ordered boundary loops for a manifold mesh and return the
|
||||
/// longest loop in terms of vertices.
|
||||
///
|
||||
/// @tparam Index index type
|
||||
/// @param[in] F #F by dim list of mesh faces
|
||||
/// @param[out] L ordered list of boundary vertices of longest boundary loop
|
||||
///
|
||||
template <typename DerivedF, typename DerivedL>
|
||||
IGL_INLINE void boundary_loop(
|
||||
const Eigen::MatrixBase<DerivedF>& F,
|
||||
|
||||
@@ -11,18 +11,19 @@
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
// Build a triangle mesh of the bounding box of a given list of vertices
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by dim list of rest domain positions
|
||||
// Outputs:
|
||||
// BV 2^dim by dim list of bounding box corners positions
|
||||
// BF #BF by dim list of simplex facets
|
||||
/// Build a triangle mesh of the bounding box of a given list of vertices
|
||||
///
|
||||
/// @param[in] V #V by dim list of rest domain positions
|
||||
/// @param[out] BV 2^dim by dim list of bounding box corners positions
|
||||
/// @param[out] BF #BF by dim list of simplex facets
|
||||
template <typename DerivedV, typename DerivedBV, typename DerivedBF>
|
||||
IGL_INLINE void bounding_box(
|
||||
const Eigen::MatrixBase<DerivedV>& V,
|
||||
Eigen::PlainObjectBase<DerivedBV>& BV,
|
||||
Eigen::PlainObjectBase<DerivedBF>& BF);
|
||||
/// \overload \brief With padding.
|
||||
///
|
||||
/// @param[in] pad padding offset
|
||||
template <typename DerivedV, typename DerivedBV, typename DerivedBF>
|
||||
IGL_INLINE void bounding_box(
|
||||
const Eigen::MatrixBase<DerivedV>& V,
|
||||
|
||||
@@ -11,12 +11,11 @@
|
||||
#include <Eigen/Dense>
|
||||
namespace igl
|
||||
{
|
||||
// Compute the length of the diagonal of a given meshes axis-aligned bounding
|
||||
// box
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by 3 list of vertex/point positions
|
||||
// Returns length of bounding box diagonal
|
||||
/// Compute the length of the diagonal of a given meshes axis-aligned bounding
|
||||
/// box.
|
||||
///
|
||||
/// @param[in] V #V by 3 list of vertex/point positions
|
||||
/// @return length of bounding box diagonal
|
||||
IGL_INLINE double bounding_box_diagonal( const Eigen::MatrixXd & V);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,14 +8,19 @@
|
||||
#ifndef IGL_CANONICAL_QUATERNIONS_H
|
||||
#define IGL_CANONICAL_QUATERNIONS_H
|
||||
#include "igl_inline.h"
|
||||
// Define some canonical quaternions for floats and doubles
|
||||
// A Quaternion, q, is defined here as an arrays of four scalars (x,y,z,w),
|
||||
// such that q = x*i + y*j + z*k + w
|
||||
/// @file canonical_quaternions
|
||||
///
|
||||
/// Define some canonical quaternions for floats and doubles
|
||||
/// A Quaternion, q, is defined here as an arrays of four scalars (x,y,z,w),
|
||||
/// such that q = x*i + y*j + z*k + w.
|
||||
///
|
||||
/// \see snap_to_canonical_view_quat
|
||||
namespace igl
|
||||
{
|
||||
// Float versions
|
||||
// This will get undef'd below
|
||||
#define SQRT_2_OVER_2 0.707106781f
|
||||
// Identity
|
||||
// Identity quaternion
|
||||
const float IDENTITY_QUAT_F[4] = {0,0,0,1};
|
||||
// The following match the Matlab canonical views
|
||||
// X point right, Y pointing up and Z point out
|
||||
|
||||
+42
-39
@@ -16,61 +16,64 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// If you're using Dense matrices you might be better off using the << operator
|
||||
|
||||
// This is an attempt to act like matlab's cat function.
|
||||
|
||||
// Perform concatenation of a two matrices along a single dimension
|
||||
// If dim == 1, then C = [A;B]. If dim == 2 then C = [A B]
|
||||
//
|
||||
// Template:
|
||||
// Scalar scalar data type for sparse matrices like double or int
|
||||
// Mat matrix type for all matrices (e.g. MatrixXd, SparseMatrix)
|
||||
// MatC matrix type for output matrix (e.g. MatrixXd) needs to support
|
||||
// resize
|
||||
// Inputs:
|
||||
// A first input matrix
|
||||
// B second input matrix
|
||||
// dim dimension along which to concatenate, 1 or 2
|
||||
// Outputs:
|
||||
// C output matrix
|
||||
//
|
||||
/// Perform concatenation of a two _sparse_ matrices along a single dimension
|
||||
/// If dim == 1, then C = [A;B]; If dim == 2 then C = [A B].
|
||||
/// This is an attempt to act like matlab's cat function.
|
||||
///
|
||||
/// @tparam Scalar scalar data type for sparse matrices like double or int
|
||||
/// @tparam Mat matrix type for all matrices (e.g. MatrixXd, SparseMatrix)
|
||||
/// @tparam MatC matrix type for output matrix (e.g. MatrixXd) needs to support
|
||||
/// resize
|
||||
/// @param[in] dim dimension along which to concatenate, 1 or 2
|
||||
/// @param[in] A first input matrix
|
||||
/// @param[in] B second input matrix
|
||||
/// @param[out] C output matrix
|
||||
///
|
||||
template <typename Scalar>
|
||||
IGL_INLINE void cat(
|
||||
const int dim,
|
||||
const Eigen::SparseMatrix<Scalar> & A,
|
||||
const Eigen::SparseMatrix<Scalar> & B,
|
||||
Eigen::SparseMatrix<Scalar> & C);
|
||||
|
||||
/// Perform concatenation of a two _dense_ matrices along a single dimension
|
||||
/// If dim == 1, then C = [A;B]; If dim == 2 then C = [A B].
|
||||
///
|
||||
/// @param[in] dim dimension along which to concatenate, 1 or 2
|
||||
/// @param[in] A first input matrix
|
||||
/// @param[in] B second input matrix
|
||||
/// @param[out] C output matrix
|
||||
///
|
||||
/// \note If you're using Dense matrices you might be better off using the << operator
|
||||
template <typename Derived, class MatC>
|
||||
IGL_INLINE void cat(
|
||||
const int dim,
|
||||
const Eigen::MatrixBase<Derived> & A,
|
||||
const Eigen::MatrixBase<Derived> & B,
|
||||
MatC & C);
|
||||
// Wrapper that returns C
|
||||
/// Perform concatenation of a two _dense_ matrices along a single dimension
|
||||
/// If dim == 1, then C = [A;B]; If dim == 2 then C = [A B].
|
||||
///
|
||||
/// @param[in] dim dimension along which to concatenate, 1 or 2
|
||||
/// @param[in] A first input matrix
|
||||
/// @param[in] B second input matrix
|
||||
/// @return C output matrix
|
||||
///
|
||||
/// \note If you're using Dense matrices you might be better off using the << operator
|
||||
template <class Mat>
|
||||
IGL_INLINE Mat cat(const int dim, const Mat & A, const Mat & B);
|
||||
|
||||
// Note: Maybe we can autogenerate a bunch of overloads D = cat(int,A,B,C),
|
||||
// E = cat(int,A,B,C,D), etc.
|
||||
|
||||
// Concatenate a "matrix" of blocks
|
||||
// C = [A0;A1;A2;...;An] where Ai = [A[i][0] A[i][1] ... A[i][m]];
|
||||
//
|
||||
// Inputs:
|
||||
// A a matrix (vector of row vectors)
|
||||
// Output:
|
||||
// C
|
||||
/// Concatenate a "matrix" of sub-blocks
|
||||
/// C = [A0;A1;A2;...;An] where Ai = [A[i][0] A[i][1] ... A[i][m]];
|
||||
///
|
||||
/// @param[in] A a list of list of matrices (sizes must be compatibile)
|
||||
/// @param[out] C output matrix
|
||||
template <class Mat>
|
||||
IGL_INLINE void cat(const std::vector<std::vector< Mat > > & A, Mat & C);
|
||||
|
||||
// Concatenate a std::vector of matrices along the specified dimension
|
||||
//
|
||||
// Inputs:
|
||||
// dim dimension along which to concatenate, 1 or 2
|
||||
// A std::vector of eigen matrices. Must have identical # cols if dim == 1 or rows if dim == 2
|
||||
// Outputs:
|
||||
// C output matrix
|
||||
/// Concatenate a std::vector of matrices along the specified dimension
|
||||
///
|
||||
/// @param[in] dim dimension along which to concatenate, 1 or 2
|
||||
/// @param[in] A std::vector of eigen matrices. Must have identical # cols if dim == 1 or rows if dim == 2
|
||||
/// @param[out] C output matrix
|
||||
template <typename T, typename DerivedC>
|
||||
IGL_INLINE void cat(const int dim, const std::vector<T> & A, Eigen::PlainObjectBase<DerivedC> & C);
|
||||
}
|
||||
|
||||
+4
-6
@@ -11,12 +11,10 @@
|
||||
#include <Eigen/Dense>
|
||||
namespace igl
|
||||
{
|
||||
// Ceil a given matrix to nearest integers
|
||||
//
|
||||
// Inputs:
|
||||
// X m by n matrix of scalars
|
||||
// Outputs:
|
||||
// Y m by n matrix of ceiled integers
|
||||
/// Ceil a given matrix to nearest integers
|
||||
///
|
||||
/// @param[in] X m by n matrix of scalars
|
||||
/// @param[out] Y m by n matrix of ceiled integers
|
||||
template < typename DerivedX, typename DerivedY>
|
||||
IGL_INLINE void ceil(
|
||||
const Eigen::PlainObjectBase<DerivedX>& X,
|
||||
|
||||
@@ -11,15 +11,13 @@
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
// CENTROID Computes the centroid of a closed mesh using a surface integral.
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by dim list of rest domain positions
|
||||
// F #F by 3 list of triangle indices into V
|
||||
// Outputs:
|
||||
// c dim vector of centroid coordinates
|
||||
// vol total volume of solid.
|
||||
//
|
||||
/// Computes the centroid and enclosed volume of a closed mesh using a surface integral.
|
||||
///
|
||||
/// @param[in] V #V by dim list of rest domain positions
|
||||
/// @param[in] F #F by 3 list of triangle indices into V
|
||||
/// @param[out] c dim vector of centroid coordinates
|
||||
/// @param[out] vol total volume of solid.
|
||||
///
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
@@ -30,6 +28,7 @@ namespace igl
|
||||
const Eigen::MatrixBase<DerivedF>& F,
|
||||
Eigen::PlainObjectBase<Derivedc>& c,
|
||||
Derivedvol & vol);
|
||||
/// \overload
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
|
||||
+46
-21
@@ -13,29 +13,42 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// Return list of faces around the end point of an edge. Assumes
|
||||
// data-structures are built from an edge-manifold **closed** mesh.
|
||||
//
|
||||
// Inputs:
|
||||
// e index into E of edge to circulate
|
||||
// ccw whether to _continue_ in ccw direction of edge (circulate around
|
||||
// E(e,1))
|
||||
// EMAP #F*3 list of indices into E, mapping each directed edge to unique
|
||||
// unique edge in E
|
||||
// EF #E by 2 list of edge flaps, EF(e,0)=f means e=(i-->j) is the edge of
|
||||
// F(f,:) opposite the vth corner, where EI(e,0)=v. Similarly EF(e,1) "
|
||||
// e=(j->i)
|
||||
// EI #E by 2 list of edge flap corners (see above).
|
||||
// Returns list of faces touched by circulation (in cyclically order).
|
||||
//
|
||||
// See also: edge_flaps
|
||||
/// Return list of faces around the end point of an edge. Assumes
|
||||
/// data-structures are built from an edge-manifold **closed** mesh.
|
||||
///
|
||||
/// @param[in] e index into E of edge to circulate
|
||||
/// @param[in] ccw whether to _continue_ in ccw direction of edge (circulate around
|
||||
/// E(e,1))
|
||||
/// @param[in] EMAP #F*3 list of indices into E, mapping each directed edge to unique
|
||||
/// unique edge in E
|
||||
/// @param[in] EF #E by 2 list of edge flaps, EF(e,0)=f means e=(i-->j) is the edge of
|
||||
/// F(f,:) opposite the vth corner, where EI(e,0)=v. Similarly EF(e,1) "
|
||||
/// e=(j->i)
|
||||
/// @param[in] EI #E by 2 list of edge flap corners (see above).
|
||||
/// @return list of faces touched by circulation (in cyclically order).
|
||||
///
|
||||
/// \see edge_flaps
|
||||
IGL_INLINE std::vector<int> circulation(
|
||||
const int e,
|
||||
const bool ccw,
|
||||
const Eigen::VectorXi & EMAP,
|
||||
const Eigen::MatrixXi & EF,
|
||||
const Eigen::MatrixXi & EI);
|
||||
// Wrapper with VectorXi output.
|
||||
/// Return list of faces around the end point of an edge. Assumes
|
||||
/// data-structures are built from an edge-manifold **closed** mesh.
|
||||
///
|
||||
/// @param[in] e index into E of edge to circulate
|
||||
/// @param[in] ccw whether to _continue_ in ccw direction of edge (circulate around
|
||||
/// E(e,1))
|
||||
/// @param[in] EMAP #F*3 list of indices into E, mapping each directed edge to unique
|
||||
/// unique edge in E
|
||||
/// @param[in] EF #E by 2 list of edge flaps, EF(e,0)=f means e=(i-->j) is the edge of
|
||||
/// F(f,:) opposite the vth corner, where EI(e,0)=v. Similarly EF(e,1) "
|
||||
/// e=(j->i)
|
||||
/// @param[in] EI #E by 2 list of edge flap corners (see above).
|
||||
/// @param[out] #vN list of of faces touched by circulation (in cyclically order).
|
||||
///
|
||||
/// \see edge_flaps
|
||||
IGL_INLINE void circulation(
|
||||
const int e,
|
||||
const bool ccw,
|
||||
@@ -43,10 +56,22 @@ namespace igl
|
||||
const Eigen::MatrixXi & EF,
|
||||
const Eigen::MatrixXi & EI,
|
||||
Eigen::VectorXi & vN);
|
||||
// Outputs:
|
||||
//// Ne 2*#Nf list of indices into E of "next" rim-spoke-rim-spoke-...
|
||||
// Nv #Nv list of "next" vertex indices
|
||||
// Nf #Nf list of face indices
|
||||
/// Return list of faces around the end point of an edge. Assumes
|
||||
/// data-structures are built from an edge-manifold **closed** mesh.
|
||||
///
|
||||
/// @param[in] e index into E of edge to circulate
|
||||
/// @param[in] ccw whether to _continue_ in ccw direction of edge (circulate around
|
||||
/// E(e,1))
|
||||
/// @param[in] EMAP #F*3 list of indices into E, mapping each directed edge to unique
|
||||
/// unique edge in E
|
||||
/// @param[in] EF #E by 2 list of edge flaps, EF(e,0)=f means e=(i-->j) is the edge of
|
||||
/// F(f,:) opposite the vth corner, where EI(e,0)=v. Similarly EF(e,1) "
|
||||
/// e=(j->i)
|
||||
/// @param[in] EI #E by 2 list of edge flap corners (see above).
|
||||
/// @param[out] Nv #Nv list of "next" vertex indices
|
||||
/// @param[out] Nf #Nf list of face indices
|
||||
///
|
||||
/// \see edge_flaps
|
||||
IGL_INLINE void circulation(
|
||||
const int e,
|
||||
const bool ccw,
|
||||
|
||||
@@ -11,14 +11,12 @@
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
// Compute the circumradius of each triangle in a mesh (V,F)
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by dim list of mesh vertex positions
|
||||
// F #F by 3 list of triangle indices into V
|
||||
// Outputs:
|
||||
// R #F list of circumradius
|
||||
//
|
||||
/// Compute the circumradius of each triangle in a mesh (V,F)
|
||||
///
|
||||
/// @param[in] V #V by dim list of mesh vertex positions
|
||||
/// @param[in] F #F by 3 list of triangle indices into V
|
||||
/// @param[out] R #F list of circumradius
|
||||
///
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
|
||||
+101
-80
@@ -15,35 +15,39 @@
|
||||
#include <set>
|
||||
namespace igl
|
||||
{
|
||||
// Assumes (V,F) is a closed manifold mesh (except for previously collapsed
|
||||
// faces which should be set to:
|
||||
// [IGL_COLLAPSE_EDGE_NULL IGL_COLLAPSE_EDGE_NULL IGL_COLLAPSE_EDGE_NULL].
|
||||
// Collapses exactly two faces and exactly 3 edges from E (e and one side of
|
||||
// each face gets collapsed to the other). This is implemented in a way that
|
||||
// it can be repeatedly called until satisfaction and then the garbage in F
|
||||
// can be collected by removing NULL faces.
|
||||
//
|
||||
// Inputs:
|
||||
// e index into E of edge to try to collapse. E(e,:) = [s d] or [d s] so
|
||||
// that s<d, then d is collapsed to s.
|
||||
/// p dim list of vertex position where to place merged vertex
|
||||
// Inputs/Outputs:
|
||||
// V #V by dim list of vertex positions, lesser index of E(e,:) will be set
|
||||
// to midpoint of edge.
|
||||
// F #F by 3 list of face indices into V.
|
||||
// E #E by 2 list of edge indices into V.
|
||||
// EMAP #F*3 list of indices into E, mapping each directed edge to unique
|
||||
// unique edge in E
|
||||
// EF #E by 2 list of edge flaps, EF(e,0)=f means e=(i-->j) is the edge of
|
||||
// F(f,:) opposite the vth corner, where EI(e,0)=v. Similarly EF(e,1) "
|
||||
// e=(j->i)
|
||||
// EI #E by 2 list of edge flap corners (see above).
|
||||
// e1 index into E of edge collpased on left
|
||||
// e2 index into E of edge collpased on right
|
||||
// f1 index into F of face collpased on left
|
||||
// f2 index into F of face collpased on right
|
||||
// Returns true if edge was collapsed
|
||||
#ifndef IGL_COLLAPSE_EDGE_NULL
|
||||
/// Special value for indicating a null vertex index as the result of a
|
||||
/// collapsed edge.
|
||||
#define IGL_COLLAPSE_EDGE_NULL 0
|
||||
#endif
|
||||
/// Attempt to collapse a given edge of a mesh. Assumes (V,F) is a closed
|
||||
/// manifold mesh (except for previously collapsed faces which should be set
|
||||
/// to: [IGL_COLLAPSE_EDGE_NULL IGL_COLLAPSE_EDGE_NULL
|
||||
/// IGL_COLLAPSE_EDGE_NULL]. Collapses exactly two faces and exactly 3 edges
|
||||
/// from E (e and one side of each face gets collapsed to the other). This is
|
||||
/// implemented in a way that it can be repeatedly called until satisfaction
|
||||
/// and then the garbage in F can be collected by removing NULL faces.
|
||||
///
|
||||
/// @param[in] e index into E of edge to try to collapse. E(e,:) = [s d] or [d s] so
|
||||
/// that s<d, then d is collapsed to s.
|
||||
/// @param[in] p dim list of vertex position where to place merged vertex
|
||||
/// [mesh inputs]
|
||||
/// @param[in,out] V #V by dim list of vertex positions, lesser index of E(e,:) will be set
|
||||
/// to midpoint of edge.
|
||||
/// @param[in,out] F #F by 3 list of face indices into V.
|
||||
/// @param[in,out] E #E by 2 list of edge indices into V.
|
||||
/// @param[in,out] EMAP #F*3 list of indices into E, mapping each directed edge to unique
|
||||
/// unique edge in E
|
||||
/// @param[in,out] EF #E by 2 list of edge flaps, EF(e,0)=f means e=(i-->j) is the edge of
|
||||
/// F(f,:) opposite the vth corner, where EI(e,0)=v. Similarly EF(e,1) "
|
||||
/// e=(j->i)
|
||||
/// @param[in,out] EI #E by 2 list of edge flap corners (see above).
|
||||
/// [mesh inputs]
|
||||
/// @param[out] e1 index into E of edge collpased on left
|
||||
/// @param[out] e2 index into E of edge collpased on right
|
||||
/// @param[out] f1 index into F of face collpased on left
|
||||
/// @param[out] f2 index into F of face collpased on right
|
||||
/// @return true if edge was collapsed
|
||||
IGL_INLINE bool collapse_edge(
|
||||
const int e,
|
||||
const Eigen::RowVectorXd & p,
|
||||
@@ -57,7 +61,12 @@ namespace igl
|
||||
int & e2,
|
||||
int & f1,
|
||||
int & f2);
|
||||
// Inputs:
|
||||
/// \overload
|
||||
///
|
||||
/// @param[in] Nsv #Nsv vertex circulation around s (see circulation)
|
||||
/// @param[in] Nsf #Nsf face circulation around s
|
||||
/// @param[in] Ndv #Ndv vertex circulation around d
|
||||
/// @param[in] Ndf #Ndf face circulation around d
|
||||
IGL_INLINE bool collapse_edge(
|
||||
const int e,
|
||||
const Eigen::RowVectorXd & p,
|
||||
@@ -75,6 +84,7 @@ namespace igl
|
||||
int & e2,
|
||||
int & f1,
|
||||
int & f2);
|
||||
/// \overload
|
||||
IGL_INLINE bool collapse_edge(
|
||||
const int e,
|
||||
const Eigen::RowVectorXd & p,
|
||||
@@ -84,57 +94,42 @@ namespace igl
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI);
|
||||
// Collapse least-cost edge from a priority queue and update queue
|
||||
//
|
||||
// Inputs/Outputs:
|
||||
// cost_and_placement function computing cost of collapsing an edge and 3d
|
||||
// position where it should be placed:
|
||||
// cost_and_placement(V,F,E,EMAP,EF,EI,cost,placement);
|
||||
// **If the edges is collapsed** then this function will be called on all
|
||||
// edges of all faces previously incident on the endpoints of the
|
||||
// collapsed edge.
|
||||
// Q queue containing pairs of costs and edge indices and insertion "time"
|
||||
// EQ #E list of "time" of last time pushed into Q
|
||||
// C #E by dim list of stored placements
|
||||
IGL_INLINE bool collapse_edge(
|
||||
const decimate_cost_and_placement_callback & cost_and_placement,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
igl::min_heap< std::tuple<double,int,int> > & Q,
|
||||
Eigen::VectorXi & EQ,
|
||||
Eigen::MatrixXd & C);
|
||||
// Inputs:
|
||||
// pre_collapse callback called with index of edge whose collapse is about
|
||||
// to be attempted. This function should return whether to **proceed**
|
||||
// with the collapse: returning true means "yes, try to collapse",
|
||||
// returning false means "No, consider this edge 'uncollapsable', behave
|
||||
// as if collapse_edge(e) returned false.
|
||||
// post_collapse callback called with index of edge whose collapse was
|
||||
// just attempted and a flag revealing whether this was successful.
|
||||
IGL_INLINE bool collapse_edge(
|
||||
const decimate_cost_and_placement_callback & cost_and_placement,
|
||||
const decimate_pre_collapse_callback & pre_collapse,
|
||||
const decimate_post_collapse_callback & post_collapse,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
igl::min_heap< std::tuple<double,int,int> > & Q,
|
||||
Eigen::VectorXi & EQ,
|
||||
Eigen::MatrixXd & C);
|
||||
// Outputs:
|
||||
// e index into E of attempted collapsed edge. Set to -1 if Q is empty or
|
||||
// contains only infinite cost edges.
|
||||
// e1 index into E of edge collpased on left.
|
||||
// e2 index into E of edge collpased on right.
|
||||
// f1 index into F of face collpased on left.
|
||||
// f2 index into F of face collpased on right.
|
||||
/// Collapse least-cost edge from a priority queue and update queue
|
||||
///
|
||||
/// See decimate.h for more details.
|
||||
///
|
||||
/// @param[in] cost_and_placement function computing cost of collapsing an edge and 3d
|
||||
/// position where it should be placed:
|
||||
/// cost_and_placement(V,F,E,EMAP,EF,EI,cost,placement);
|
||||
/// **If the edges is collapsed** then this function will be called on all
|
||||
/// edges of all faces previously incident on the endpoints of the
|
||||
/// collapsed edge.
|
||||
/// @param[in] pre_collapse callback called with index of edge whose collapse is about
|
||||
/// to be attempted. This function should return whether to **proceed**
|
||||
/// with the collapse: returning true means "yes, try to collapse",
|
||||
/// returning false means "No, consider this edge 'uncollapsable', behave
|
||||
/// as if collapse_edge(e) returned false.
|
||||
/// @param[in] post_collapse callback called with index of edge whose collapse was
|
||||
/// just attempted and a flag revealing whether this was successful.
|
||||
/// @param[in,out] V #V by dim list of vertex positions, lesser index of E(e,:) will be set
|
||||
/// to midpoint of edge.
|
||||
/// @param[in,out] F #F by 3 list of face indices into V.
|
||||
/// @param[in,out] E #E by 2 list of edge indices into V.
|
||||
/// @param[in,out] EMAP #F*3 list of indices into E, mapping each directed edge to unique
|
||||
/// unique edge in E
|
||||
/// @param[in,out] EF #E by 2 list of edge flaps, EF(e,0)=f means e=(i-->j) is the edge of
|
||||
/// F(f,:) opposite the vth corner, where EI(e,0)=v. Similarly EF(e,1)
|
||||
/// e=(j->i)
|
||||
/// @param[in,out] EI #E by 2 list of edge flap corners (see above).
|
||||
/// @param[in] Q queue containing pairs of costs and edge indices and insertion "time"
|
||||
/// @param[in] EQ #E list of "time" of last time pushed into Q
|
||||
/// @param[in] C #E by dim list of stored placements
|
||||
/// @param[out] e index into E of attempted collapsed edge. Set to -1 if Q is empty or
|
||||
/// contains only infinite cost edges.
|
||||
/// @param[out] e1 index into E of edge collpased on left.
|
||||
/// @param[out] e2 index into E of edge collpased on right.
|
||||
/// @param[out] f1 index into F of face collpased on left.
|
||||
/// @param[out] f2 index into F of face collpased on right.
|
||||
IGL_INLINE bool collapse_edge(
|
||||
const decimate_cost_and_placement_callback & cost_and_placement,
|
||||
const decimate_pre_collapse_callback & pre_collapse,
|
||||
@@ -153,6 +148,32 @@ namespace igl
|
||||
int & e2,
|
||||
int & f1,
|
||||
int & f2);
|
||||
/// \overload
|
||||
IGL_INLINE bool collapse_edge(
|
||||
const decimate_cost_and_placement_callback & cost_and_placement,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
igl::min_heap< std::tuple<double,int,int> > & Q,
|
||||
Eigen::VectorXi & EQ,
|
||||
Eigen::MatrixXd & C);
|
||||
/// \overload
|
||||
IGL_INLINE bool collapse_edge(
|
||||
const decimate_cost_and_placement_callback & cost_and_placement,
|
||||
const decimate_pre_collapse_callback & pre_collapse,
|
||||
const decimate_post_collapse_callback & post_collapse,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
igl::min_heap< std::tuple<double,int,int> > & Q,
|
||||
Eigen::VectorXi & EQ,
|
||||
Eigen::MatrixXd & C);
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
|
||||
@@ -10,22 +10,20 @@
|
||||
#include <Eigen/Dense>
|
||||
namespace igl
|
||||
{
|
||||
// Given a triangle mesh (V,F) compute a new mesh (VV,FF) which contains the
|
||||
// original faces and vertices of (V,F) except any small triangles have been
|
||||
// removed via collapse.
|
||||
//
|
||||
// We are *not* following the rules in "Mesh Optimization" [Hoppe et al]
|
||||
// Section 4.2. But for our purposes we don't care about this criteria.
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by 3 list of vertex positions
|
||||
// F #F by 3 list of triangle indices into V
|
||||
// eps epsilon for smallest allowed area treated as fraction of squared bounding box
|
||||
// diagonal
|
||||
// Outputs:
|
||||
// FF #FF by 3 list of triangle indices into V
|
||||
//
|
||||
//
|
||||
/// Given a triangle mesh (V,F) compute a new mesh (VV,FF) which contains the
|
||||
/// original faces and vertices of (V,F) except any small triangles have been
|
||||
/// removed via collapse.
|
||||
///
|
||||
/// We are *not* following the rules in "Mesh Optimization" [Hoppe et al]
|
||||
/// Section 4.2. But for our purposes we don't care about this criteria.
|
||||
///
|
||||
/// @param[in] V #V by 3 list of vertex positions
|
||||
/// @param[in] F #F by 3 list of triangle indices into V
|
||||
/// @param[in] eps epsilon for smallest allowed area treated as fraction of squared bounding box
|
||||
/// diagonal
|
||||
/// @param[out] FF #FF by 3 list of triangle indices into V
|
||||
///
|
||||
///
|
||||
void collapse_small_triangles(
|
||||
const Eigen::MatrixXd & V,
|
||||
const Eigen::MatrixXi & F,
|
||||
|
||||
+62
-29
@@ -11,47 +11,80 @@
|
||||
#include <Eigen/Dense>
|
||||
namespace igl
|
||||
{
|
||||
// Note:
|
||||
// This should be potentially replaced with eigen's LinSpaced() function
|
||||
//
|
||||
// If step = 1, it's about 5 times faster to use:
|
||||
// X = Eigen::VectorXi::LinSpaced(n,0,n-1);
|
||||
// than
|
||||
// X = igl::colon<int>(0,n-1);
|
||||
//
|
||||
|
||||
// Colon operator like matlab's colon operator. Enumerats values between low
|
||||
// and hi with step step.
|
||||
// Templates:
|
||||
// L should be a eigen matrix primitive type like int or double
|
||||
// S should be a eigen matrix primitive type like int or double
|
||||
// H should be a eigen matrix primitive type like int or double
|
||||
// T should be a eigen matrix primitive type like int or double
|
||||
// Inputs:
|
||||
// low starting value if step is valid then this is *always* the first
|
||||
// element of I
|
||||
// step step difference between sequential elements returned in I,
|
||||
// remember this will be cast to template T at compile time. If low<hi
|
||||
// then step must be positive. If low>hi then step must be negative.
|
||||
// Otherwise I will be set to empty.
|
||||
// hi ending value, if (hi-low)%step is zero then this will be the last
|
||||
// element in I. If step is positive there will be no elements greater
|
||||
// than hi, vice versa if hi<low
|
||||
// Output:
|
||||
// I list of values from low to hi with step size step
|
||||
/// Colon operator like matlab's colon operator. Enumerates values between low
|
||||
/// and hi with step step.
|
||||
///
|
||||
/// @tparam L should be a eigen matrix primitive type like int or double
|
||||
/// @tparam S should be a eigen matrix primitive type like int or double
|
||||
/// @tparam H should be a eigen matrix primitive type like int or double
|
||||
/// @tparam T should be a eigen matrix primitive type like int or double
|
||||
/// @param[in] low starting value if step is valid then this is *always* the first
|
||||
/// element of I
|
||||
/// @param[in] step step difference between sequential elements returned in I,
|
||||
/// remember this will be cast to template T at compile time. If low<hi
|
||||
/// then step must be positive. If low>hi then step must be negative.
|
||||
/// Otherwise I will be set to empty.
|
||||
/// @param[in] hi ending value, if (hi-low)%step is zero then this will be the last
|
||||
/// element in I. If step is positive there will be no elements greater
|
||||
/// than hi, vice versa if hi<low
|
||||
/// @param[out] I list of values from low to hi with step size step
|
||||
///
|
||||
/// \note
|
||||
/// This should be potentially replaced with eigen's LinSpaced() function
|
||||
///
|
||||
/// If step = 1, it's about 5 times faster to use:
|
||||
/// X = Eigen::VectorXi::LinSpaced(n,0,n-1);
|
||||
/// than
|
||||
/// X = igl::colon<int>(0,n-1);
|
||||
///
|
||||
template <typename L,typename S,typename H,typename T>
|
||||
IGL_INLINE void colon(
|
||||
const L low,
|
||||
const S step,
|
||||
const H hi,
|
||||
Eigen::Matrix<T,Eigen::Dynamic,1> & I);
|
||||
// Same as above but step == (T)1
|
||||
/// Colon operator like matlab's colon operator. Enumerates values between low
|
||||
/// and hi with unit step.
|
||||
///
|
||||
/// @tparam L should be a eigen matrix primitive type like int or double
|
||||
/// @tparam H should be a eigen matrix primitive type like int or double
|
||||
/// @tparam T should be a eigen matrix primitive type like int or double
|
||||
/// @param[in] low starting value if step is valid then this is *always* the first
|
||||
/// element of I
|
||||
/// @param[in] step step difference between sequential elements returned in I,
|
||||
/// remember this will be cast to template T at compile time. If low<hi
|
||||
/// then step must be positive. If low>hi then step must be negative.
|
||||
/// Otherwise I will be set to empty.
|
||||
/// @param[in] hi ending value, if (hi-low)%step is zero then this will be the last
|
||||
/// element in I. If step is positive there will be no elements greater
|
||||
/// than hi, vice versa if hi<low
|
||||
/// @param[out] I list of values from low to hi with step size step
|
||||
template <typename L,typename H,typename T>
|
||||
IGL_INLINE void colon(
|
||||
const L low,
|
||||
const H hi,
|
||||
Eigen::Matrix<T,Eigen::Dynamic,1> & I);
|
||||
// Return output rather than set in reference
|
||||
/// @private
|
||||
///
|
||||
/// Hiding this from doxygen because it's messing up the indentation.
|
||||
///
|
||||
/// Colon operator like matlab's colon operator. Enumerates values between low
|
||||
/// and hi with unit step.
|
||||
///
|
||||
/// @tparam T should be a eigen matrix primitive type like int or double
|
||||
/// @tparam L should be a eigen matrix primitive type like int or double
|
||||
/// @tparam H should be a eigen matrix primitive type like int or double
|
||||
/// @param[in] low starting value if step is valid then this is *always* the first
|
||||
/// element of I
|
||||
/// @param[in] step step difference between sequential elements returned in I,
|
||||
/// remember this will be cast to template T at compile time. If low<hi
|
||||
/// then step must be positive. If low>hi then step must be negative.
|
||||
/// Otherwise I will be set to empty.
|
||||
/// @param[in] hi ending value, if (hi-low)%step is zero then this will be the last
|
||||
/// element in I. If step is positive there will be no elements greater
|
||||
/// than hi, vice versa if hi<low
|
||||
/// @return list of values from low to hi with step size step
|
||||
template <typename T,typename L,typename H>
|
||||
IGL_INLINE Eigen::Matrix<T,Eigen::Dynamic,1> colon(
|
||||
const L low,
|
||||
|
||||
+38
-23
@@ -14,6 +14,7 @@
|
||||
|
||||
namespace igl {
|
||||
|
||||
// Common colormap types.
|
||||
enum ColorMapType
|
||||
{
|
||||
COLOR_MAP_TYPE_INFERNO = 0,
|
||||
@@ -25,42 +26,56 @@ namespace igl {
|
||||
COLOR_MAP_TYPE_TURBO = 6,
|
||||
NUM_COLOR_MAP_TYPES = 7
|
||||
};
|
||||
// Comput [r,g,b] values of the selected colormap for
|
||||
// a given factor f between 0 and 1
|
||||
//
|
||||
// Inputs:
|
||||
// c colormap enum
|
||||
// f factor determining color value as if 0 was min and 1 was max
|
||||
// Outputs:
|
||||
// rgb red, green, blue value
|
||||
/// Compute [r,g,b] values of the selected colormap for
|
||||
/// a given factor f between 0 and 1
|
||||
///
|
||||
/// @param[in] c colormap enum
|
||||
/// @param[in] f factor determining color value as if 0 was min and 1 was max
|
||||
/// @param[out] rgb red, green, blue value
|
||||
template <typename T>
|
||||
IGL_INLINE void colormap(const ColorMapType cm, const T f, T * rgb);
|
||||
// Outputs:
|
||||
// r red value
|
||||
// g green value
|
||||
// b blue value
|
||||
/// Compute [r,g,b] values of the selected colormap for
|
||||
/// a given factor f between 0 and 1
|
||||
///
|
||||
/// @param[in] c colormap enum
|
||||
/// @param[in] f factor determining color value as if 0 was min and 1 was max
|
||||
/// @param[out] r red value
|
||||
/// @param[out] g green value
|
||||
/// @param[out] b blue value
|
||||
template <typename T>
|
||||
IGL_INLINE void colormap(const ColorMapType cm, const T f, T & r, T & g, T & b);
|
||||
// Inputs:
|
||||
// palette 256 by 3 array of color values
|
||||
/// Compute [r,g,b] values of the colormap palette for
|
||||
/// a given factor f between 0 and 1
|
||||
///
|
||||
/// @param[in] palette 256 by 3 array of color values
|
||||
/// @param[in] x_in factor determining color value as if 0 was min and 1 was max
|
||||
/// @param[out] r red value
|
||||
/// @param[out] g green value
|
||||
/// @param[out] b blue value
|
||||
template <typename T>
|
||||
IGL_INLINE void colormap(
|
||||
const double palette[256][3], const T x_in, T & r, T & g, T & b);
|
||||
// Inputs:
|
||||
// cm selected colormap palette to interpolate from
|
||||
// Z #Z list of factors
|
||||
// normalize whether to normalize Z to be tightly between [0,1]
|
||||
// Outputs:
|
||||
// C #C by 3 list of rgb colors
|
||||
/// Compute [r,g,b] values of the colormap palette for
|
||||
/// a given factors between 0 and 1
|
||||
///
|
||||
/// @param[in] cm selected colormap palette to interpolate from
|
||||
/// @param[in] Z #Z list of factors
|
||||
/// @param[in] normalize whether to normalize Z to be tightly between [0,1]
|
||||
/// @param[out] C #C by 3 list of rgb colors
|
||||
template <typename DerivedZ, typename DerivedC>
|
||||
IGL_INLINE void colormap(
|
||||
const ColorMapType cm,
|
||||
const Eigen::MatrixBase<DerivedZ> & Z,
|
||||
const bool normalize,
|
||||
Eigen::PlainObjectBase<DerivedC> & C);
|
||||
// Inputs:
|
||||
// min_z value at "0"
|
||||
// max_z value at "1"
|
||||
/// Compute [r,g,b] values of the colormap palette for
|
||||
/// a given factors between `min_Z` and `max_Z`
|
||||
///
|
||||
/// @param[in] cm selected colormap palette to interpolate from
|
||||
/// @param[in] Z #Z list of factors
|
||||
/// @param[in] min_z value at "0"
|
||||
/// @param[in] max_z value at "1"
|
||||
/// @param[out] C #C by 3 list of rgb colors
|
||||
template <typename DerivedZ, typename DerivedC>
|
||||
IGL_INLINE void colormap(
|
||||
const ColorMapType cm,
|
||||
|
||||
@@ -14,13 +14,11 @@
|
||||
#include <vector>
|
||||
namespace igl
|
||||
{
|
||||
// "Columnize" a list of quaternions (q1x,q1y,q1z,q1w,q2x,q2y,q2z,q2w,...)
|
||||
//
|
||||
// Inputs:
|
||||
// Q n*4-long list of coefficients
|
||||
// Outputs:
|
||||
// vQ n-long list of quaternions
|
||||
// Returns false if n%4!=0
|
||||
/// de-"Columnize" a list of quaternions (q1x,q1y,q1z,q1w,q2x,q2y,q2z,q2w,...)
|
||||
///
|
||||
/// @param[in] Q n*4-long list of coefficients
|
||||
/// @param[out] vQ n-long list of quaternions
|
||||
/// @return false if n%4!=0
|
||||
IGL_INLINE bool column_to_quats(
|
||||
const Eigen::VectorXd & Q,
|
||||
std::vector<
|
||||
|
||||
+13
-16
@@ -12,22 +12,19 @@
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
// "Columnize" a stack of block matrices. If A = [A1,A2,A3,...,Ak] with each A*
|
||||
// an m by n block then this produces the column vector whose entries are
|
||||
// B(j*m*k+i*k+b) = A(i,b*n+j);
|
||||
// or if A = [A1;A2;...;Ak] then
|
||||
// B(j*m*k+i*k+b) = A(i+b*m,j);
|
||||
//
|
||||
// Templates:
|
||||
// T should be a eigen matrix primitive type like int or double
|
||||
// Inputs:
|
||||
// A m*k by n (dim: 1) or m by n*k (dim: 2) eigen Matrix of type T values
|
||||
// k number of blocks
|
||||
// dim dimension in which blocks are stacked
|
||||
// Output
|
||||
// B m*n*k eigen vector of type T values,
|
||||
//
|
||||
// See also: transpose_blocks
|
||||
/// "Columnize" a stack of block matrices. If A = [A1,A2,A3,...,Ak] with each A*
|
||||
/// an m by n block then this produces the column vector whose entries are
|
||||
/// B(j*m*k+i*k+b) = A(i,b*n+j);
|
||||
/// or if A = [A1;A2;...;Ak] then
|
||||
/// B(j*m*k+i*k+b) = A(i+b*m,j);
|
||||
///
|
||||
/// @tparam T should be a eigen matrix primitive type like int or double
|
||||
/// @param[in] A m*k by n (dim: 1) or m by n*k (dim: 2) eigen Matrix of type T values
|
||||
/// @param[in] k number of blocks
|
||||
/// @param[in] dim dimension in which blocks are stacked
|
||||
/// @param[out] B m*n*k eigen vector of type T values,
|
||||
///
|
||||
/// \see transpose_blocks
|
||||
template <typename DerivedA, typename DerivedB>
|
||||
IGL_INLINE void columnize(
|
||||
const Eigen::PlainObjectBase<DerivedA> & A,
|
||||
|
||||
@@ -12,20 +12,16 @@
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
// Computes principal matchings of the vectors of a cross field across face edges,
|
||||
// and generates a combed cross field defined on the mesh faces
|
||||
|
||||
// Inputs:
|
||||
// V #V by 3 eigen Matrix of mesh vertex 3D positions
|
||||
// F #F by 4 eigen Matrix of face (quad) indices
|
||||
// PD1in #F by 3 eigen Matrix of the first per face cross field vector
|
||||
// PD2in #F by 3 eigen Matrix of the second per face cross field vector
|
||||
// Output:
|
||||
// PD1out #F by 3 eigen Matrix of the first combed cross field vector
|
||||
// PD2out #F by 3 eigen Matrix of the second combed cross field vector
|
||||
//
|
||||
|
||||
|
||||
/// Computes principal matchings of the vectors of a cross field across face edges,
|
||||
/// and generates a combed cross field defined on the mesh faces
|
||||
///
|
||||
/// @param[in] V #V by 3 eigen Matrix of mesh vertex 3D positions
|
||||
/// @param[in] F #F by 4 eigen Matrix of face (quad) indices
|
||||
/// @param[in] PD1in #F by 3 eigen Matrix of the first per face cross field vector
|
||||
/// @param[in] PD2in #F by 3 eigen Matrix of the second per face cross field vector
|
||||
/// @param[out] PD1out #F by 3 eigen Matrix of the first combed cross field vector
|
||||
/// @param[out] PD2out #F by 3 eigen Matrix of the second combed cross field vector
|
||||
///
|
||||
template <typename DerivedV, typename DerivedF>
|
||||
IGL_INLINE void comb_cross_field(const Eigen::MatrixBase<DerivedV> &V,
|
||||
const Eigen::MatrixBase<DerivedF> &F,
|
||||
|
||||
@@ -12,24 +12,20 @@
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
// Computes principal matchings of the vectors of a frame field across face edges,
|
||||
// and generates a combed frame field defined on the mesh faces. This makes use of a
|
||||
// combed cross field generated by combing the field created by the bisectors of the
|
||||
// frame field.
|
||||
|
||||
// Inputs:
|
||||
// V #V by 3 eigen Matrix of mesh vertex 3D positions
|
||||
// F #F by 4 eigen Matrix of face (quad) indices
|
||||
// PD1 #F by 3 eigen Matrix of the first per face cross field vector
|
||||
// PD2 #F by 3 eigen Matrix of the second per face cross field vector
|
||||
// BIS1_combed #F by 3 eigen Matrix of the first combed bisector field vector
|
||||
// BIS2_combed #F by 3 eigen Matrix of the second combed bisector field vector
|
||||
// Output:
|
||||
// PD1_combed #F by 3 eigen Matrix of the first combed cross field vector
|
||||
// PD2_combed #F by 3 eigen Matrix of the second combed cross field vector
|
||||
//
|
||||
|
||||
|
||||
/// Computes principal matchings of the vectors of a frame field across face edges,
|
||||
/// and generates a combed frame field defined on the mesh faces. This makes use of a
|
||||
/// combed cross field generated by combing the field created by the bisectors of the
|
||||
/// frame field.
|
||||
///
|
||||
/// @param[in] V #V by 3 eigen Matrix of mesh vertex 3D positions
|
||||
/// @param[in] F #F by 4 eigen Matrix of face (quad) indices
|
||||
/// @param[in] PD1 #F by 3 eigen Matrix of the first per face cross field vector
|
||||
/// @param[in] PD2 #F by 3 eigen Matrix of the second per face cross field vector
|
||||
/// @param[in] BIS1_combed #F by 3 eigen Matrix of the first combed bisector field vector
|
||||
/// @param[in] BIS2_combed #F by 3 eigen Matrix of the second combed bisector field vector
|
||||
/// @param[out] PD1_combed #F by 3 eigen Matrix of the first combed cross field vector
|
||||
/// @param[out] PD2_combed #F by 3 eigen Matrix of the second combed cross field vector
|
||||
///
|
||||
template <typename DerivedV, typename DerivedF, typename DerivedP>
|
||||
IGL_INLINE void comb_frame_field(const Eigen::MatrixBase<DerivedV> &V,
|
||||
const Eigen::MatrixBase<DerivedF> &F,
|
||||
|
||||
@@ -12,17 +12,13 @@
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
// Computes principal matchings of the vectors of a cross field across face edges,
|
||||
// and generates a combed cross field defined on the mesh faces
|
||||
|
||||
// Inputs:
|
||||
// V #V by 3 eigen Matrix of mesh vertex 3D positions
|
||||
// F #F by 4 eigen Matrix of face (quad) indices
|
||||
// PD1in #F by 3 eigen Matrix of the first per face cross field vector
|
||||
// Output:
|
||||
// PD1out #F by 3 eigen Matrix of the first combed cross field vector
|
||||
|
||||
|
||||
/// Computes principal matchings of the vectors of a cross field across face edges,
|
||||
/// and generates a combed cross field defined on the mesh faces
|
||||
///
|
||||
/// @param[in] V #V by 3 eigen Matrix of mesh vertex 3D positions
|
||||
/// @param[in] F #F by 4 eigen Matrix of face (quad) indices
|
||||
/// @param[in] PD1in #F by 3 eigen Matrix of the first per face cross field vector
|
||||
/// @param[out] PD1out #F by 3 eigen Matrix of the first combed cross field vector
|
||||
template <typename DerivedV, typename DerivedF>
|
||||
IGL_INLINE void comb_line_field(const Eigen::MatrixBase<DerivedV> &V,
|
||||
const Eigen::MatrixBase<DerivedF> &F,
|
||||
|
||||
+20
-19
@@ -14,25 +14,25 @@
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// Concatenate k meshes into a single >=k connected component mesh with a
|
||||
// single vertex list and face list. Similar to Maya's Combine operation.
|
||||
//
|
||||
// Inputs:
|
||||
// VV k-long list of lists of mesh vertex positions
|
||||
// FF k-long list of lists of mesh face indices so that FF[i] indexes
|
||||
// VV[i]
|
||||
// Outputs:
|
||||
// V VV[0].rows()+...+VV[k-1].rows() by VV[0].cols() list of mesh
|
||||
// vertex positions
|
||||
// F FF[0].rows()+...+FF[k-1].rows() by FF[0].cols() list of mesh faces
|
||||
// indices into V
|
||||
// Vsizes k list so that Vsizes(i) is the #vertices in the ith input
|
||||
// Fsizes k list so that Fsizes(i) is the #faces in the ith input
|
||||
// Example:
|
||||
// // Suppose you have mesh A (VA,FA) and mesh B (VB,FB)
|
||||
// igl::combine<Eigen::MatrixXd,Eigen::MatrixXi>({VA,VB},{FA,FB},V,F);
|
||||
//
|
||||
//
|
||||
/// Concatenate k meshes into a single >=k connected component mesh with a
|
||||
/// single vertex list and face list. Similar to Maya's Combine operation.
|
||||
///
|
||||
/// @param[in] VV k-long list of lists of mesh vertex positions
|
||||
/// @param[in] FF k-long list of lists of mesh face indices so that FF[i] indexes
|
||||
/// VV[i]
|
||||
/// @param[out] V VV[0].rows()+...+VV[k-1].rows() by VV[0].cols() list of mesh
|
||||
/// vertex positions
|
||||
/// @param[out] F FF[0].rows()+...+FF[k-1].rows() by FF[0].cols() list of mesh faces
|
||||
/// indices into V
|
||||
/// @param[out] Vsizes k list so that Vsizes(i) is the #vertices in the ith input
|
||||
/// @param[out] Fsizes k list so that Fsizes(i) is the #faces in the ith input
|
||||
///
|
||||
/// #### Example
|
||||
/// \code{cpp}
|
||||
/// // Suppose you have mesh A (VA,FA) and mesh B (VB,FB)
|
||||
/// igl::combine<Eigen::MatrixXd,Eigen::MatrixXi>({VA,VB},{FA,FB},V,F);
|
||||
/// \endcode
|
||||
///
|
||||
template <
|
||||
typename DerivedVV,
|
||||
typename DerivedFF,
|
||||
@@ -47,6 +47,7 @@ namespace igl
|
||||
Eigen::PlainObjectBase<DerivedF> & F,
|
||||
Eigen::PlainObjectBase<DerivedVsizes> & Vsizes,
|
||||
Eigen::PlainObjectBase<DerivedFsizes> & Fsizes);
|
||||
/// \overload
|
||||
template <
|
||||
typename DerivedVV,
|
||||
typename DerivedFF,
|
||||
|
||||
@@ -12,38 +12,36 @@
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
// Compute bisectors of a frame field defined on mesh faces
|
||||
// Inputs:
|
||||
// V #V by 3 eigen Matrix of mesh vertex 3D positions
|
||||
// F #F by 3 eigen Matrix of face (triangle) indices
|
||||
// B1 #F by 3 eigen Matrix of face (triangle) base vector 1
|
||||
// B2 #F by 3 eigen Matrix of face (triangle) base vector 2
|
||||
// PD1 #F by 3 eigen Matrix of the first per face frame field vector
|
||||
// PD2 #F by 3 eigen Matrix of the second per face frame field vector
|
||||
// Output:
|
||||
// BIS1 #F by 3 eigen Matrix of the first per face frame field bisector
|
||||
// BIS2 #F by 3 eigen Matrix of the second per face frame field bisector
|
||||
//
|
||||
/// Compute bisectors of a frame field defined on mesh faces
|
||||
///
|
||||
/// @param[in] V #V by 3 eigen Matrix of mesh vertex 3D positions
|
||||
/// @param[in] F #F by 3 eigen Matrix of face (triangle) indices
|
||||
/// @param[in] B1 #F by 3 eigen Matrix of face (triangle) base vector 1
|
||||
/// @param[in] B2 #F by 3 eigen Matrix of face (triangle) base vector 2
|
||||
/// @param[in] PD1 #F by 3 eigen Matrix of the first per face frame field vector
|
||||
/// @param[in] PD2 #F by 3 eigen Matrix of the second per face frame field vector
|
||||
/// @param[out] BIS1 #F by 3 eigen Matrix of the first per face frame field bisector
|
||||
/// @param[out] BIS2 #F by 3 eigen Matrix of the second per face frame field bisector
|
||||
///
|
||||
template <typename DerivedV, typename DerivedF>
|
||||
IGL_INLINE void compute_frame_field_bisectors(
|
||||
const Eigen::MatrixBase<DerivedV>& V,
|
||||
const Eigen::MatrixBase<DerivedF>& F,
|
||||
const Eigen::MatrixBase<DerivedV>& B1,
|
||||
const Eigen::MatrixBase<DerivedV>& B2,
|
||||
const Eigen::MatrixBase<DerivedV>& PD1,
|
||||
const Eigen::MatrixBase<DerivedV>& PD2,
|
||||
Eigen::PlainObjectBase<DerivedV>& BIS1,
|
||||
Eigen::PlainObjectBase<DerivedV>& BIS2);
|
||||
|
||||
// Wrapper without given basis vectors.
|
||||
const Eigen::MatrixBase<DerivedV>& V,
|
||||
const Eigen::MatrixBase<DerivedF>& F,
|
||||
const Eigen::MatrixBase<DerivedV>& B1,
|
||||
const Eigen::MatrixBase<DerivedV>& B2,
|
||||
const Eigen::MatrixBase<DerivedV>& PD1,
|
||||
const Eigen::MatrixBase<DerivedV>& PD2,
|
||||
Eigen::PlainObjectBase<DerivedV>& BIS1,
|
||||
Eigen::PlainObjectBase<DerivedV>& BIS2);
|
||||
/// \overload
|
||||
template <typename DerivedV, typename DerivedF>
|
||||
IGL_INLINE void compute_frame_field_bisectors(
|
||||
const Eigen::MatrixBase<DerivedV>& V,
|
||||
const Eigen::MatrixBase<DerivedF>& F,
|
||||
const Eigen::MatrixBase<DerivedV>& PD1,
|
||||
const Eigen::MatrixBase<DerivedV>& PD2,
|
||||
Eigen::PlainObjectBase<DerivedV>& BIS1,
|
||||
Eigen::PlainObjectBase<DerivedV>& BIS2);
|
||||
const Eigen::MatrixBase<DerivedV>& V,
|
||||
const Eigen::MatrixBase<DerivedF>& F,
|
||||
const Eigen::MatrixBase<DerivedV>& PD1,
|
||||
const Eigen::MatrixBase<DerivedV>& PD2,
|
||||
Eigen::PlainObjectBase<DerivedV>& BIS1,
|
||||
Eigen::PlainObjectBase<DerivedV>& BIS2);
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
|
||||
@@ -11,34 +11,38 @@
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
// Connect all boundary edges to a fictitious point at infinity.
|
||||
//
|
||||
// Inputs:
|
||||
// F #F by 3 list of face indices into some V
|
||||
// Outputs:
|
||||
// FO #F+#O by 3 list of face indices into [V;inf inf inf], original F are
|
||||
// guaranteed to come first. If (V,F) was a manifold mesh, now it is
|
||||
// closed with a possibly non-manifold vertex at infinity (but it will be
|
||||
// edge-manifold).
|
||||
/// Connect all boundary edges to a fictitious point at infinity.
|
||||
///
|
||||
/// @param[in] F #F by 3 list of face indices into some V
|
||||
/// @param[out] FO #F+#O by 3 list of face indices into [V;inf inf inf], original F are
|
||||
/// guaranteed to come first. If (V,F) was a manifold mesh, now it is
|
||||
/// closed with a possibly non-manifold vertex at infinity (but it will be
|
||||
/// edge-manifold).
|
||||
template <typename DerivedF, typename DerivedFO>
|
||||
IGL_INLINE void connect_boundary_to_infinity(
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
Eigen::PlainObjectBase<DerivedFO> & FO);
|
||||
// Inputs:
|
||||
// inf_index index of point at infinity (usually V.rows() or F.maxCoeff())
|
||||
/// Connect all boundary edges to a fictitious point at infinity.
|
||||
///
|
||||
/// @param[in] F #F by 3 list of face indices into some V
|
||||
/// @param[in] inf_index index of point at infinity (usually V.rows() or F.maxCoeff())
|
||||
/// @param[out] FO #F+#O by 3 list of face indices into [V;inf inf inf], original F are
|
||||
/// guaranteed to come first. If (V,F) was a manifold mesh, now it is
|
||||
/// closed with a possibly non-manifold vertex at infinity (but it will be
|
||||
/// edge-manifold).
|
||||
template <typename DerivedF, typename DerivedFO>
|
||||
IGL_INLINE void connect_boundary_to_infinity(
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
const typename DerivedF::Scalar inf_index,
|
||||
Eigen::PlainObjectBase<DerivedFO> & FO);
|
||||
// Inputs:
|
||||
// V #V by 3 list of vertex positions
|
||||
// F #F by 3 list of face indices into some V
|
||||
// Outputs:
|
||||
// VO #V+1 by 3 list of vertex positions, original V are guaranteed to
|
||||
// come first. Last point is inf, inf, inf
|
||||
// FO #F+#O by 3 list of face indices into VO
|
||||
//
|
||||
/// Connect all boundary edges to a fictitious point at infinity.
|
||||
///
|
||||
/// @param[in] V #V by 3 list of vertex positions
|
||||
/// @param[in] F #F by 3 list of face indices into some V
|
||||
/// @param[out] VO #V+1 by 3 list of vertex positions, original V are guaranteed to
|
||||
/// come first. Last point is inf, inf, inf
|
||||
/// @param[out] FO #F+#O by 3 list of face indices into VO
|
||||
///
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
|
||||
@@ -12,16 +12,14 @@
|
||||
#include <Eigen/Sparse>
|
||||
namespace igl
|
||||
{
|
||||
// Determine the connected components of a graph described by the input
|
||||
// adjacency matrix (similar to MATLAB's graphconncomp or gptoolbox's
|
||||
// conncomp, but A is transposed for unsymmetric graphs).
|
||||
//
|
||||
// Inputs:
|
||||
// A #A by #A adjacency matrix (treated as describing an directed graph)
|
||||
// Outputs:
|
||||
// C #A list of component indices into [0,#K-1]
|
||||
// K #K list of sizes of each component
|
||||
// Returns number of connected components
|
||||
/// Determine the connected components of a graph described by the input
|
||||
/// adjacency matrix (similar to MATLAB's graphconncomp or gptoolbox's
|
||||
/// conncomp, but A is transposed for unsymmetric graphs).
|
||||
///
|
||||
/// @param[in] A #A by #A adjacency matrix (treated as describing an directed graph)
|
||||
/// @param[out] C #A list of component indices into [0,#K-1]
|
||||
/// @param[out] K #K list of sizes of each component
|
||||
/// @return number of connected components
|
||||
template < typename Atype, typename DerivedC, typename DerivedK>
|
||||
IGL_INLINE int connected_components(
|
||||
const Eigen::SparseMatrix<Atype> & A,
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace igl
|
||||
{
|
||||
namespace cgal
|
||||
{
|
||||
/// Binary winding number operations
|
||||
template <igl::MeshBooleanType Op>
|
||||
class BinaryWindingNumberOperations {
|
||||
public:
|
||||
@@ -36,7 +37,7 @@ namespace igl
|
||||
}
|
||||
};
|
||||
|
||||
// A ∪ B ∪ ... ∪ Z
|
||||
/// A ∪ B ∪ ... ∪ Z
|
||||
template <>
|
||||
class BinaryWindingNumberOperations<MESH_BOOLEAN_TYPE_UNION> {
|
||||
public:
|
||||
@@ -52,7 +53,7 @@ namespace igl
|
||||
}
|
||||
};
|
||||
|
||||
// A ∩ B ∩ ... ∩ Z
|
||||
/// A ∩ B ∩ ... ∩ Z
|
||||
template <>
|
||||
class BinaryWindingNumberOperations<MESH_BOOLEAN_TYPE_INTERSECT> {
|
||||
public:
|
||||
@@ -68,7 +69,7 @@ namespace igl
|
||||
}
|
||||
};
|
||||
|
||||
// A \ B \ ... \ Z = A \ (B ∪ ... ∪ Z)
|
||||
/// A \ B \ ... \ Z = A \ (B ∪ ... ∪ Z)
|
||||
template <>
|
||||
class BinaryWindingNumberOperations<MESH_BOOLEAN_TYPE_MINUS> {
|
||||
public:
|
||||
@@ -89,7 +90,7 @@ namespace igl
|
||||
}
|
||||
};
|
||||
|
||||
// A ∆ B ∆ ... ∆ Z (equivalent to set inside odd number of objects)
|
||||
/// A ∆ B ∆ ... ∆ Z (equivalent to set inside odd number of objects)
|
||||
template <>
|
||||
class BinaryWindingNumberOperations<MESH_BOOLEAN_TYPE_XOR> {
|
||||
public:
|
||||
@@ -107,6 +108,7 @@ namespace igl
|
||||
}
|
||||
};
|
||||
|
||||
/// Resolve all intersections without removing non-coplanar faces
|
||||
template <>
|
||||
class BinaryWindingNumberOperations<MESH_BOOLEAN_TYPE_RESOLVE> {
|
||||
public:
|
||||
@@ -123,11 +125,15 @@ namespace igl
|
||||
typedef BinaryWindingNumberOperations<MESH_BOOLEAN_TYPE_XOR> BinaryXor;
|
||||
typedef BinaryWindingNumberOperations<MESH_BOOLEAN_TYPE_RESOLVE> BinaryResolve;
|
||||
|
||||
/// Types of Keep policies
|
||||
enum KeeperType {
|
||||
/// Keep only inside
|
||||
KEEP_INSIDE,
|
||||
/// Keep everything
|
||||
KEEP_ALL
|
||||
};
|
||||
|
||||
/// Filter winding numbers according to keep policy
|
||||
template<KeeperType T>
|
||||
class WindingNumberFilter {
|
||||
public:
|
||||
@@ -138,6 +144,7 @@ namespace igl
|
||||
}
|
||||
};
|
||||
|
||||
/// Keep inside policy
|
||||
template<>
|
||||
class WindingNumberFilter<KEEP_INSIDE> {
|
||||
public:
|
||||
@@ -149,6 +156,7 @@ namespace igl
|
||||
}
|
||||
};
|
||||
|
||||
/// Keep all policy
|
||||
template<>
|
||||
class WindingNumberFilter<KEEP_ALL> {
|
||||
public:
|
||||
@@ -158,8 +166,8 @@ namespace igl
|
||||
}
|
||||
};
|
||||
|
||||
typedef WindingNumberFilter<KEEP_INSIDE> KeepInside;
|
||||
typedef WindingNumberFilter<KEEP_ALL> KeepAll;
|
||||
using KeepInside = WindingNumberFilter<KEEP_INSIDE>;
|
||||
using KeepAll = WindingNumberFilter<KEEP_ALL>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,9 @@ namespace igl
|
||||
{
|
||||
namespace cgal
|
||||
{
|
||||
// Class for defining and computing a constructive solid geometry result
|
||||
// out of a tree of boolean operations on "solid" triangle meshes.
|
||||
//
|
||||
//template <typename DerivedF>
|
||||
/// Class for defining and computing a constructive solid geometry result
|
||||
/// out of a tree of boolean operations on "solid" triangle meshes.
|
||||
///
|
||||
class CSGTree
|
||||
{
|
||||
public:
|
||||
@@ -33,12 +32,14 @@ namespace igl
|
||||
typedef Eigen::Matrix<ExactScalar,Eigen::Dynamic,3> MatrixX3E;
|
||||
typedef Eigen::VectorXi VectorJ;
|
||||
private:
|
||||
// Resulting mesh
|
||||
/// Resulting mesh vertex positions
|
||||
MatrixX3E m_V;
|
||||
/// Resulting mesh face indices into V
|
||||
POBF m_F;
|
||||
/// Birth index of each face in resulting mesh. Birth index is the index
|
||||
VectorJ m_J;
|
||||
// Number of birth faces in A + those in B. I.e. sum of original "leaf"
|
||||
// faces involved in result.
|
||||
/// Number of birth faces in A + those in B. I.e. sum of original "leaf"
|
||||
/// faces involved in result.
|
||||
size_t m_number_of_birth_faces;
|
||||
public:
|
||||
CSGTree()
|
||||
@@ -82,12 +83,11 @@ namespace igl
|
||||
{
|
||||
swap(*this,other);
|
||||
}
|
||||
// Construct and compute a boolean operation on existing CSGTree nodes.
|
||||
//
|
||||
// Inputs:
|
||||
// A Solid result of previous CSG operation (or identity, see below)
|
||||
// B Solid result of previous CSG operation (or identity, see below)
|
||||
// type type of mesh boolean to compute
|
||||
/// Construct and compute a boolean operation on existing CSGTree nodes.
|
||||
///
|
||||
/// @param[in] A Solid result of previous CSG operation (or identity, see below)
|
||||
/// @param[in] B Solid result of previous CSG operation (or identity, see below)
|
||||
/// @param[in] type type of mesh boolean to compute
|
||||
CSGTree(
|
||||
const CSGTree & A,
|
||||
const CSGTree & B,
|
||||
@@ -111,7 +111,7 @@ namespace igl
|
||||
m_number_of_birth_faces =
|
||||
A.number_of_birth_faces() + B.number_of_birth_faces();
|
||||
}
|
||||
// Overload using string for type
|
||||
/// \overload
|
||||
CSGTree(
|
||||
const CSGTree & A,
|
||||
const CSGTree & B,
|
||||
@@ -120,12 +120,11 @@ namespace igl
|
||||
{
|
||||
// do nothing (all done in constructor).
|
||||
}
|
||||
// "Leaf" node with identity operation on assumed "solid" mesh (V,F)
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by 3 list of mesh vertices (in any precision, will be
|
||||
// converted to exact)
|
||||
// F #F by 3 list of mesh face indices into V
|
||||
/// "Leaf" node with identity operation on assumed "solid" mesh (V,F)
|
||||
///
|
||||
/// @param[in] V #V by 3 list of mesh vertices (in any precision, will be
|
||||
/// converted to exact)
|
||||
/// @param[in] F #F by 3 list of mesh face indices into V
|
||||
template <typename DerivedV>
|
||||
CSGTree(const Eigen::PlainObjectBase<DerivedV> & V, const POBF & F)//:
|
||||
// Possible Eigen bug:
|
||||
|
||||
@@ -14,21 +14,20 @@ namespace igl
|
||||
{
|
||||
namespace cgal
|
||||
{
|
||||
// Optional Parameters
|
||||
// DetectOnly Only compute IF, leave VV and FF alone
|
||||
//
|
||||
// detect_only avoid constructing intersections results when possible
|
||||
// first_only return after detecting the first intersection (if
|
||||
// first_only==true, then detect_only should also be true)
|
||||
// stitch_all whether to stitch all resulting constructed elements into a
|
||||
// (non-manifold) mesh
|
||||
// slow_and_more_precise_rounding whether to use slow and more precise
|
||||
// rounding (see assign_scalar)
|
||||
/// Parameters for SelfIntersectMesh, remesh_self_intersections and
|
||||
/// remesh_intersections, and intersect_other
|
||||
///
|
||||
struct RemeshSelfIntersectionsParam
|
||||
{
|
||||
/// avoid constructing intersections results when possible
|
||||
bool detect_only;
|
||||
/// return after detecting the first intersection (if first_only==true,
|
||||
/// then detect_only should also be true)
|
||||
bool first_only;
|
||||
/// whether to stitch all resulting constructed elements into a
|
||||
/// (non-manifold) mesh
|
||||
bool stitch_all;
|
||||
/// whether to use slow and more precise rounding (see assign_scalar)
|
||||
bool slow_and_more_precise_rounding;
|
||||
inline RemeshSelfIntersectionsParam(
|
||||
bool _detect_only=false,
|
||||
|
||||
@@ -34,11 +34,12 @@ namespace igl
|
||||
{
|
||||
namespace cgal
|
||||
{
|
||||
// Kernel is a CGAL kernel like:
|
||||
// CGAL::Exact_predicates_inexact_constructions_kernel
|
||||
// or
|
||||
// CGAL::Exact_predicates_exact_constructions_kernel
|
||||
|
||||
/// Class for computing the self-intersections of a mesh
|
||||
///
|
||||
/// @tparam Kernel is a CGAL kernel like:
|
||||
/// CGAL::Exact_predicates_inexact_constructions_kernel
|
||||
/// or
|
||||
/// CGAL::Exact_predicates_exact_constructions_kernel
|
||||
template <
|
||||
typename Kernel,
|
||||
typename DerivedV,
|
||||
@@ -109,10 +110,20 @@ namespace igl
|
||||
public:
|
||||
RemeshSelfIntersectionsParam params;
|
||||
public:
|
||||
// Constructs (VV,FF) a new mesh with self-intersections of (V,F)
|
||||
// subdivided
|
||||
//
|
||||
// See also: remesh_self_intersections.h
|
||||
/// Constructs (VV,FF) a new mesh with self-intersections of (V,F)
|
||||
/// subdivided
|
||||
///
|
||||
/// @param[in] V #V by 3 list of vertex positions
|
||||
/// @param[in] F #F by 3 list of triangle indices into V
|
||||
/// @param[in] params parameters
|
||||
/// @param[out] VV #VV by 3 list of vertex positions
|
||||
/// @param[out] FF #FF by 3 list of triangle indices into VV
|
||||
/// @param[out] IF #IF by 2 list of edge indices into VV
|
||||
/// @param[out] J #F list of indices into FF of birth parents
|
||||
/// @param[out] IM #VV list of indices into V of birth parents
|
||||
///
|
||||
///
|
||||
/// \see remesh_self_intersections.h
|
||||
inline SelfIntersectMesh(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
@@ -123,47 +134,43 @@ namespace igl
|
||||
Eigen::PlainObjectBase<DerivedJ> & J,
|
||||
Eigen::PlainObjectBase<DerivedIM> & IM);
|
||||
private:
|
||||
// Helper function to mark a face as offensive
|
||||
//
|
||||
// Inputs:
|
||||
// f index of face in F
|
||||
/// Helper function to mark a face as offensive
|
||||
///
|
||||
/// @param[in] f index of face in F
|
||||
inline void mark_offensive(const Index f);
|
||||
// Helper function to count intersections between faces
|
||||
//
|
||||
// Input:
|
||||
// fa index of face A in F
|
||||
// fb index of face B in F
|
||||
/// Helper function to count intersections between faces
|
||||
///
|
||||
/// @param[in] fa index of face A in F
|
||||
/// @param[in] fb index of face B in F
|
||||
inline void count_intersection( const Index fa, const Index fb);
|
||||
// Helper function for box_intersect. Intersect two triangles A and B,
|
||||
// append the intersection object (point,segment,triangle) to a running
|
||||
// list for A and B
|
||||
//
|
||||
// Inputs:
|
||||
// A triangle in 3D
|
||||
// B triangle in 3D
|
||||
// fa index of A in F (and key into offending)
|
||||
// fb index of B in F (and key into offending)
|
||||
// Returns true only if A intersects B
|
||||
//
|
||||
/// Helper function for box_intersect. Intersect two triangles A and B,
|
||||
/// append the intersection object (point,segment,triangle) to a running
|
||||
/// list for A and B
|
||||
///
|
||||
/// @param[in] A triangle in 3D
|
||||
/// @param[in] B triangle in 3D
|
||||
/// @param[in] fa index of A in F (and key into offending)
|
||||
/// @param[in] fb index of B in F (and key into offending)
|
||||
/// @return true only if A intersects B
|
||||
///
|
||||
inline bool intersect(
|
||||
const Triangle_3 & A,
|
||||
const Triangle_3 & B,
|
||||
const Index fa,
|
||||
const Index fb);
|
||||
// Helper function for box_intersect. In the case where A and B have
|
||||
// already been identified to share a vertex, then we only want to
|
||||
// add possible segment intersections. Assumes truly duplicate
|
||||
// triangles are not given as input
|
||||
//
|
||||
// Inputs:
|
||||
// A triangle in 3D
|
||||
// B triangle in 3D
|
||||
// fa index of A in F (and key into offending)
|
||||
// fb index of B in F (and key into offending)
|
||||
// va index of shared vertex in A (and key into offending)
|
||||
// vb index of shared vertex in B (and key into offending)
|
||||
// Returns true if intersection (besides shared point)
|
||||
//
|
||||
/// Helper function for box_intersect. In the case where A and B have
|
||||
/// already been identified to share a vertex, then we only want to
|
||||
/// add possible segment intersections. Assumes truly duplicate
|
||||
/// triangles are not given as input
|
||||
///
|
||||
/// @param[in] A triangle in 3D
|
||||
/// @param[in] B triangle in 3D
|
||||
/// @param[in] fa index of A in F (and key into offending)
|
||||
/// @param[in] fb index of B in F (and key into offending)
|
||||
/// @param[in] va index of shared vertex in A (and key into offending)
|
||||
/// @param[in] vb index of shared vertex in B (and key into offending)
|
||||
/// @return true if intersection (besides shared point)
|
||||
///
|
||||
inline bool single_shared_vertex(
|
||||
const Triangle_3 & A,
|
||||
const Triangle_3 & B,
|
||||
@@ -171,17 +178,31 @@ namespace igl
|
||||
const Index fb,
|
||||
const Index va,
|
||||
const Index vb);
|
||||
// Helper handling one direction
|
||||
//// Helper handling one direction
|
||||
///
|
||||
/// @param[in] A triangle in 3D
|
||||
/// @param[in] B triangle in 3D
|
||||
/// @param[in] fa index of A in F (and key into offending)
|
||||
/// @param[in] fb index of B in F (and key into offending)
|
||||
/// @param[in] va index of shared vertex in A (and key into offending)
|
||||
/// @return true if intersection (besides shared point)
|
||||
inline bool single_shared_vertex(
|
||||
const Triangle_3 & A,
|
||||
const Triangle_3 & B,
|
||||
const Index fa,
|
||||
const Index fb,
|
||||
const Index va);
|
||||
// Helper function for box_intersect. In the case where A and B have
|
||||
// already been identified to share two vertices, then we only want
|
||||
// to add a possible coplanar (Triangle) intersection. Assumes truly
|
||||
// degenerate facets are not givin as input.
|
||||
/// Helper function for box_intersect. In the case where A and B have
|
||||
/// already been identified to share two vertices, then we only want
|
||||
/// to add a possible coplanar (Triangle) intersection. Assumes truly
|
||||
/// degenerate facets are not givin as input.
|
||||
///
|
||||
/// @param[in] A triangle in 3D
|
||||
/// @param[in] B triangle in 3D
|
||||
/// @param[in] fa index of A in F (and key into offending)
|
||||
/// @param[in] fb index of B in F (and key into offending)
|
||||
/// @param[in] shared list of pairs of indices of shared vertices
|
||||
/// @return true if intersection (besides shared point)
|
||||
inline bool double_shared_vertex(
|
||||
const Triangle_3 & A,
|
||||
const Triangle_3 & B,
|
||||
@@ -190,18 +211,23 @@ namespace igl
|
||||
const std::vector<std::pair<Index,Index> > shared);
|
||||
|
||||
public:
|
||||
// Callback function called during box self intersections test. Means
|
||||
// boxes a and b intersect. This method then checks if the triangles
|
||||
// in each box intersect and if so, then processes the intersections
|
||||
//
|
||||
// Inputs:
|
||||
// a box containing a triangle
|
||||
// b box containing a triangle
|
||||
/// Callback function called during box self intersections test. Means
|
||||
/// boxes a and b intersect. This method then checks if the triangles
|
||||
/// in each box intersect and if so, then processes the intersections
|
||||
///
|
||||
/// @param[in] a box containing a triangle
|
||||
/// @param[in] b box containing a triangle
|
||||
inline void box_intersect(const Box& a, const Box& b);
|
||||
/// Process all of the intersecting boxes
|
||||
inline void process_intersecting_boxes();
|
||||
public:
|
||||
// Getters:
|
||||
//const IndexList& get_lIF() const{ return lIF;}
|
||||
/// Static function that captures a SelfIntersectMesh instance to pass
|
||||
/// to cgal.
|
||||
/// @param[in] SIM pointer to SelfIntersectMesh instance
|
||||
/// @param[in] a box containing a triangle
|
||||
/// @param[in] b box containing a triangle
|
||||
static inline void box_intersect_static(
|
||||
SelfIntersectMesh * SIM,
|
||||
const Box &a,
|
||||
|
||||
@@ -17,20 +17,24 @@ namespace igl
|
||||
{
|
||||
namespace cgal
|
||||
{
|
||||
// Inputs:
|
||||
// C matrix of scalars
|
||||
// slow_and_more_precise see assign_scalar
|
||||
// Outputs:
|
||||
// D matrix same size as C
|
||||
/// Vector version of assign_scalar
|
||||
///
|
||||
/// @param[in] C matrix of scalars
|
||||
/// @param[in] slow_and_more_precise see assign_scalar
|
||||
/// @param[out] D matrix same size as C
|
||||
///
|
||||
/// \see assign_scalar
|
||||
template <typename DerivedC, typename DerivedD>
|
||||
IGL_INLINE void assign(
|
||||
const Eigen::MatrixBase<DerivedC> & C,
|
||||
const bool slow_and_more_precise,
|
||||
Eigen::PlainObjectBase<DerivedD> & D);
|
||||
/// \overload
|
||||
template <typename DerivedC, typename DerivedD>
|
||||
IGL_INLINE void assign(
|
||||
const Eigen::MatrixBase<DerivedC> & C,
|
||||
Eigen::PlainObjectBase<DerivedD> & D);
|
||||
/// \overload
|
||||
template <typename ReturnScalar, typename DerivedC>
|
||||
IGL_INLINE
|
||||
Eigen::Matrix<
|
||||
|
||||
@@ -21,76 +21,84 @@ namespace igl
|
||||
{
|
||||
namespace cgal
|
||||
{
|
||||
// Conduct the casting copy:
|
||||
// lhs = rhs
|
||||
// using `slow_and_more_precise` rounding if more desired.
|
||||
//
|
||||
// Inputs:
|
||||
// rhs right-hand side scalar
|
||||
// slow_and_more_precise when appropriate use more elaborate rounding
|
||||
// guaranteed to find a closest lhs value in an absolute value sense.
|
||||
// Think of `slow_and_more_precise=true` as "round to closest number"
|
||||
// and `slow_and_more_precise=false` as "round down/up". CGAL's number
|
||||
// types are bit mysterious about how exactly rounding is conducted.
|
||||
// For example, the rationals created during remesh_intersections on
|
||||
// floating point input appear to be tightly rounded up or down so the
|
||||
// difference with the `slow_and_more_precise=true` will be exactly
|
||||
// zero 50% of the time and "one floating point unit" (at whatever
|
||||
// scale) the other 50% of the time.
|
||||
// Outputs:
|
||||
// lhs left-hand side scalar
|
||||
/// Conduct the casting copy:
|
||||
/// lhs = rhs
|
||||
/// using `slow_and_more_precise` rounding if more desired.
|
||||
///
|
||||
/// @tparam RHS right-hand side scalar type
|
||||
/// @tparam LHS left-hand side scalar type
|
||||
/// @param[in] rhs right-hand side scalar
|
||||
/// @param[in] slow_and_more_precise when appropriate use more elaborate rounding
|
||||
/// guaranteed to find a closest lhs value in an absolute value sense.
|
||||
/// Think of `slow_and_more_precise=true` as "round to closest number"
|
||||
/// and `slow_and_more_precise=false` as "round down/up". CGAL's number
|
||||
/// types are bit mysterious about how exactly rounding is conducted.
|
||||
/// For example, the rationals created during remesh_intersections on
|
||||
/// floating point input appear to be tightly rounded up or down so the
|
||||
/// difference with the `slow_and_more_precise=true` will be exactly
|
||||
/// zero 50% of the time and "one floating point unit" (at whatever
|
||||
/// scale) the other 50% of the time.
|
||||
/// @param[out] lhs left-hand side scalar
|
||||
template <typename RHS, typename LHS>
|
||||
IGL_INLINE void assign_scalar(
|
||||
const RHS & rhs,
|
||||
const bool & slow_and_more_precise,
|
||||
LHS & lhs);
|
||||
// For legacy reasons, all of these overload uses
|
||||
// `slow_and_more_precise=true`. This is subject to change if we determine
|
||||
// it is sufficiently overkill. In that case, we'd create a new
|
||||
// non-overloaded function.
|
||||
//
|
||||
// Inputs:
|
||||
// cgal cgal scalar
|
||||
// Outputs:
|
||||
// d output scalar
|
||||
/// \overload
|
||||
/// \brief For legacy reasons, all of these overload uses
|
||||
/// `slow_and_more_precise=true`. This is subject to change if we determine
|
||||
/// it is sufficiently overkill. In that case, we'd create a new
|
||||
/// non-overloaded function.
|
||||
IGL_INLINE void assign_scalar(
|
||||
const CGAL::Epeck::FT & cgal,
|
||||
CGAL::Epeck::FT & d);
|
||||
/// \overload
|
||||
IGL_INLINE void assign_scalar(
|
||||
const CGAL::Epeck::FT & cgal,
|
||||
double & d);
|
||||
/// \overload
|
||||
IGL_INLINE void assign_scalar(
|
||||
/// \overload
|
||||
const CGAL::Epeck::FT & cgal,
|
||||
float& d);
|
||||
IGL_INLINE void assign_scalar(
|
||||
/// \overload
|
||||
const double & c,
|
||||
double & d);
|
||||
/// \overload
|
||||
IGL_INLINE void assign_scalar(
|
||||
const float& c,
|
||||
float & d);
|
||||
/// \overload
|
||||
IGL_INLINE void assign_scalar(
|
||||
const float& c,
|
||||
double& d);
|
||||
/// \overload
|
||||
IGL_INLINE void assign_scalar(
|
||||
const CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT & cgal,
|
||||
CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT & d);
|
||||
/// \overload
|
||||
IGL_INLINE void assign_scalar(
|
||||
const CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT & cgal,
|
||||
double & d);
|
||||
/// \overload
|
||||
IGL_INLINE void assign_scalar(
|
||||
const CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT & cgal,
|
||||
float& d);
|
||||
#ifndef WIN32
|
||||
/// \overload
|
||||
IGL_INLINE void assign_scalar(
|
||||
const CGAL::Simple_cartesian<mpq_class>::FT & cgal,
|
||||
CGAL::Simple_cartesian<mpq_class>::FT & d);
|
||||
/// \overload
|
||||
IGL_INLINE void assign_scalar(
|
||||
const CGAL::Simple_cartesian<mpq_class>::FT & cgal,
|
||||
double & d);
|
||||
/// \overload
|
||||
IGL_INLINE void assign_scalar(
|
||||
const CGAL::Simple_cartesian<mpq_class>::FT & cgal,
|
||||
float& d);
|
||||
#endif // WIN32
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,20 +20,16 @@ namespace igl
|
||||
{
|
||||
namespace cgal
|
||||
{
|
||||
// Inputs:
|
||||
// per_patch_cells #P by 2 list of cell labels on each side of each
|
||||
// patch. Cell labels are assumed to be continuous
|
||||
// from 0 to #C.
|
||||
// num_cells number of cells.
|
||||
//
|
||||
// Outputs:
|
||||
// adjacency_list #C array of list of adjcent cell information. If
|
||||
// cell i and cell j are adjacent via patch x, where i
|
||||
// is on the positive side of x, and j is on the
|
||||
// negative side. Then,
|
||||
// adjacency_list[i] will contain the entry {j, false, x}
|
||||
// and
|
||||
// adjacency_list[j] will contain the entry {i, true, x}
|
||||
/// Determine adjacency of cells
|
||||
///
|
||||
/// @param[in] per_patch_cells #P by 2 list of cell labels on each side
|
||||
/// of each patch. Cell labels are assumed to be continuous from 0 to #C.
|
||||
/// @param[in] num_cells number of cells.
|
||||
/// @param[out] adjacency_list #C array of list of adjcent cell
|
||||
/// information. If cell i and cell j are adjacent via patch x, where i
|
||||
/// is on the positive side of x, and j is on the negative side. Then,
|
||||
/// adjacency_list[i] will contain the entry {j, false, x} and
|
||||
/// adjacency_list[j] will contain the entry {i, true, x}
|
||||
template < typename DerivedC >
|
||||
IGL_INLINE void cell_adjacency(
|
||||
const Eigen::PlainObjectBase<DerivedC>& per_patch_cells,
|
||||
|
||||
@@ -25,26 +25,26 @@ namespace igl
|
||||
{
|
||||
namespace cgal
|
||||
{
|
||||
// Determine the closest facet for each of the input points.
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by 3 array of vertices.
|
||||
// F #F by 3 array of faces.
|
||||
// I #I list of triangle indices to consider.
|
||||
// P #P by 3 array of query points.
|
||||
// EMAP #F*3 list of indices into uE.
|
||||
// uEC #uE+1 list of cumsums of directed edges sharing each unique edge
|
||||
// uEE #E list of indices into E (see `igl::unique_edge_map`)
|
||||
// VF #V list of lists of incident faces (adjacency list)
|
||||
// VFi #V list of lists of index of incidence within incident faces
|
||||
// listed in VF
|
||||
// tree AABB containing triangles of (V,F(I,:))
|
||||
// triangles #I list of cgal triangles
|
||||
// in_I #F list of whether in submesh
|
||||
// Outputs:
|
||||
// R #P list of closest facet indices.
|
||||
// S #P list of bools indicating on which side of the closest facet
|
||||
// each query point lies.
|
||||
/// Determine the closest facet for each of the input points.
|
||||
///
|
||||
/// @param[in] V #V by 3 array of vertices.
|
||||
/// @param[in] F #F by 3 array of faces.
|
||||
/// @param[in] I #I list of triangle indices to consider.
|
||||
/// @param[in] P #P by 3 array of query points.
|
||||
/// @param[in] EMAP #F*3 list of indices into uE.
|
||||
/// @param[in] uEC #uE+1 list of cumsums of directed edges sharing each unique edge
|
||||
/// @param[in] uEE #E list of indices into E (see `igl::unique_edge_map`)
|
||||
/// @param[in] VF #V list of lists of incident faces (adjacency list)
|
||||
/// @param[in] VFi #V list of lists of index of incidence within incident faces listed in VF
|
||||
/// @param[in] tree AABB containing triangles of (V,F(I,:))
|
||||
/// @param[in] triangles #I list of cgal triangles
|
||||
/// @param[in] in_I #F list of whether in submesh
|
||||
/// @param[out] R #P list of closest facet indices.
|
||||
/// @param[out] S #P list of bools indicating on which side of the closest facet
|
||||
/// each query point lies.
|
||||
///
|
||||
/// \note The use of `size_t` here is a bad idea. These should just be int
|
||||
/// to avoid nonsense with windows.
|
||||
template<
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
@@ -76,6 +76,7 @@ namespace igl
|
||||
const std::vector<bool> & in_I,
|
||||
Eigen::PlainObjectBase<DerivedR>& R,
|
||||
Eigen::PlainObjectBase<DerivedS>& S);
|
||||
/// \overload
|
||||
template<
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
@@ -96,6 +97,7 @@ namespace igl
|
||||
const Eigen::PlainObjectBase<DeriveduEE>& uEE,
|
||||
Eigen::PlainObjectBase<DerivedR>& R,
|
||||
Eigen::PlainObjectBase<DerivedS>& S);
|
||||
/// \overload
|
||||
template<
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
@@ -114,6 +116,7 @@ namespace igl
|
||||
const Eigen::PlainObjectBase<DeriveduEE>& uEE,
|
||||
Eigen::PlainObjectBase<DerivedR>& R,
|
||||
Eigen::PlainObjectBase<DerivedS>& S);
|
||||
/// \overload
|
||||
template<
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
|
||||
@@ -18,18 +18,16 @@ namespace igl
|
||||
{
|
||||
namespace cgal
|
||||
{
|
||||
// Templates:
|
||||
// Tr CGAL triangulation type, e.g.
|
||||
// CGAL::Surface_mesh_default_triangulation_3
|
||||
// Inputs
|
||||
// c2t3 2-complex (surface) living in a 3d triangulation (e.g. result of
|
||||
// CGAL::make_surface_mesh)
|
||||
// Outputs:
|
||||
// V #V by 3 list of vertex positions
|
||||
// F #F by 3 list of triangle indices
|
||||
// Returns true iff conversion was successful, failure can ok if CGAL code
|
||||
// can't figure out ordering.
|
||||
//
|
||||
/// Convert a CGAL::Complex_2_in_triangulation_3 to a mesh (V,F)
|
||||
///
|
||||
/// @tparam Tr CGAL triangulation type, e.g. CGAL::Surface_mesh_default_triangulation_3
|
||||
/// @param[in] c2t3 2-complex (surface) living in a 3d triangulation
|
||||
/// (e.g. result of CGAL::make_surface_mesh)
|
||||
/// @param[out] V #V by 3 list of vertex positions
|
||||
/// @param[out] F #F by 3 list of triangle indices
|
||||
/// @return true iff conversion was successful, failure can ok if CGAL code
|
||||
/// can't figure out ordering.
|
||||
///
|
||||
template <typename Tr, typename DerivedV, typename DerivedF>
|
||||
IGL_INLINE bool complex_to_mesh(
|
||||
const CGAL::Complex_2_in_triangulation_3<Tr> & c2t3,
|
||||
|
||||
@@ -15,56 +15,37 @@
|
||||
namespace igl {
|
||||
namespace copyleft
|
||||
{
|
||||
namespace cgal {
|
||||
|
||||
// Determine if connected facet component (V1, F1, I1) is inside of
|
||||
// connected facet component (V2, F2, I2).
|
||||
//
|
||||
// Precondition:
|
||||
// Both components must represent closed, self-intersection free,
|
||||
// non-degenerated surfaces that are the boundary of 3D volumes. In
|
||||
// addition, (V1, F1, I1) must not intersect with (V2, F2, I2).
|
||||
//
|
||||
// Inputs:
|
||||
// V1 #V1 by 3 list of vertex position of mesh 1
|
||||
// F1 #F1 by 3 list of triangles indices into V1
|
||||
// I1 #I1 list of indices into F1, indicate the facets of component
|
||||
// V2 #V2 by 3 list of vertex position of mesh 2
|
||||
// F2 #F2 by 3 list of triangles indices into V2
|
||||
// I2 #I2 list of indices into F2, indicate the facets of component
|
||||
//
|
||||
// Outputs:
|
||||
// return true iff (V1, F1, I1) is entirely inside of (V2, F2, I2).
|
||||
template<typename DerivedV, typename DerivedF, typename DerivedI>
|
||||
IGL_INLINE bool component_inside_component(
|
||||
const Eigen::PlainObjectBase<DerivedV>& V1,
|
||||
const Eigen::PlainObjectBase<DerivedF>& F1,
|
||||
const Eigen::PlainObjectBase<DerivedI>& I1,
|
||||
const Eigen::PlainObjectBase<DerivedV>& V2,
|
||||
const Eigen::PlainObjectBase<DerivedF>& F2,
|
||||
const Eigen::PlainObjectBase<DerivedI>& I2);
|
||||
|
||||
// Determine if mesh (V1, F1) is inside of mesh (V2, F2).
|
||||
//
|
||||
// Precondition:
|
||||
// Both meshes must be closed, self-intersection free, non-degenerated
|
||||
// surfaces that are the boundary of 3D volumes. They should not
|
||||
// intersect each other.
|
||||
//
|
||||
// Inputs:
|
||||
// V1 #V1 by 3 list of vertex position of mesh 1
|
||||
// F1 #F1 by 3 list of triangles indices into V1
|
||||
// V2 #V2 by 3 list of vertex position of mesh 2
|
||||
// F2 #F2 by 3 list of triangles indices into V2
|
||||
//
|
||||
// Outputs:
|
||||
// return true iff (V1, F1) is entirely inside of (V2, F2).
|
||||
template<typename DerivedV, typename DerivedF>
|
||||
IGL_INLINE bool component_inside_component(
|
||||
const Eigen::PlainObjectBase<DerivedV>& V1,
|
||||
const Eigen::PlainObjectBase<DerivedF>& F1,
|
||||
const Eigen::PlainObjectBase<DerivedV>& V2,
|
||||
const Eigen::PlainObjectBase<DerivedF>& F2);
|
||||
namespace cgal
|
||||
{
|
||||
/// Determine if connected facet component (V1, F1, I1) is inside of
|
||||
/// connected facet component (V2, F2, I2).
|
||||
///
|
||||
/// \pre Both components must represent closed, self-intersection free,
|
||||
/// non-degenerated surfaces that are the boundary of 3D volumes. In
|
||||
/// addition, (V1, F1, I1) must not intersect with (V2, F2, I2).
|
||||
///
|
||||
/// @param[in] V1 #V1 by 3 list of vertex position of mesh 1
|
||||
/// @param[in] F1 #F1 by 3 list of triangles indices into V1
|
||||
/// @param[in] I1 #I1 list of indices into F1, indicate the facets of component
|
||||
/// @param[in] V2 #V2 by 3 list of vertex position of mesh 2
|
||||
/// @param[in] F2 #F2 by 3 list of triangles indices into V2
|
||||
/// @param[in] I2 #I2 list of indices into F2, indicate the facets of component
|
||||
/// @return true iff (V1, F1, I1) is entirely inside of (V2, F2, I2).
|
||||
template<typename DerivedV, typename DerivedF, typename DerivedI>
|
||||
IGL_INLINE bool component_inside_component(
|
||||
const Eigen::PlainObjectBase<DerivedV>& V1,
|
||||
const Eigen::PlainObjectBase<DerivedF>& F1,
|
||||
const Eigen::PlainObjectBase<DerivedI>& I1,
|
||||
const Eigen::PlainObjectBase<DerivedV>& V2,
|
||||
const Eigen::PlainObjectBase<DerivedF>& F2,
|
||||
const Eigen::PlainObjectBase<DerivedI>& I2);
|
||||
/// \overload
|
||||
template<typename DerivedV, typename DerivedF>
|
||||
IGL_INLINE bool component_inside_component(
|
||||
const Eigen::PlainObjectBase<DerivedV>& V1,
|
||||
const Eigen::PlainObjectBase<DerivedF>& F1,
|
||||
const Eigen::PlainObjectBase<DerivedV>& V2,
|
||||
const Eigen::PlainObjectBase<DerivedF>& F2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,13 +16,11 @@ namespace igl
|
||||
{
|
||||
namespace cgal
|
||||
{
|
||||
// Given a set of points (V), compute the convex hull as a triangle mesh (W,G)
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by 3 list of input points
|
||||
// Outputs:
|
||||
// W #W by 3 list of convex hull points
|
||||
// G #G by 3 list of triangle indices into W
|
||||
/// Given a set of points (V), compute the convex hull as a triangle mesh (W,G)
|
||||
///
|
||||
/// @param[in] V #V by 3 list of input points
|
||||
/// @param[out] W #W by 3 list of convex hull points
|
||||
/// @param[out] G #G by 3 list of triangle indices into W
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedW,
|
||||
@@ -31,14 +29,7 @@ namespace igl
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
Eigen::PlainObjectBase<DerivedW> & W,
|
||||
Eigen::PlainObjectBase<DerivedG> & G);
|
||||
// Given a set of points (V), compute the convex hull as a triangle mesh (F)
|
||||
// over input vertex set (V)
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by 3 list of input points
|
||||
// Outputs:
|
||||
// F #F by 3 list of triangle indices into V
|
||||
//
|
||||
/// \overload
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF>
|
||||
|
||||
@@ -8,11 +8,10 @@ namespace igl
|
||||
{
|
||||
namespace cgal
|
||||
{
|
||||
// Test whether all points are on same plane.
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by 3 list of 3D vertex positions
|
||||
// Returns true if all points lie on the same plane
|
||||
/// Test whether all points are on same plane.
|
||||
///
|
||||
/// @param[in] V #V by 3 list of 3D vertex positions
|
||||
/// @return true if all points lie on the same plane
|
||||
template <typename DerivedV>
|
||||
IGL_INLINE bool coplanar(
|
||||
const Eigen::MatrixBase<DerivedV> & V);
|
||||
|
||||
@@ -18,15 +18,11 @@ namespace igl
|
||||
{
|
||||
namespace cgal
|
||||
{
|
||||
|
||||
// Given a set of points in 2D, return a Delaunay triangulation of these
|
||||
// points.
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by 2 list of vertex positions
|
||||
//
|
||||
// Outputs:
|
||||
// F #F by 3 of faces in Delaunay triangulation.
|
||||
/// Given a set of points in 2D, return a Delaunay triangulation of these
|
||||
/// points.
|
||||
///
|
||||
/// @param[in] V #V by 2 list of vertex positions
|
||||
/// @param[out] F #F by 3 of faces in Delaunay triangulation.
|
||||
template<
|
||||
typename DerivedV,
|
||||
typename DerivedF
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user