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:
Alec Jacobson
2023-08-16 13:14:06 -04:00
committed by GitHub
parent b1bd5b1216
commit 2cc372f70d
609 changed files with 16549 additions and 11998 deletions
File diff suppressed because it is too large Load Diff
+2728
View File
File diff suppressed because it is too large Load Diff
+21
View File
@@ -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
View File
@@ -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,
+12 -15
View File
@@ -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
View File
@@ -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
View File
@@ -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
+7 -4
View File
@@ -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
View File
@@ -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>();
+1 -1
View File
@@ -10,7 +10,7 @@
namespace igl
{
/// File encoding types for writing files.
enum class FileEncoding {
Binary,
Ascii
+1
View File
@@ -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)
+48 -44
View File
@@ -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
View File
@@ -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;
};
}
+7 -9
View File
@@ -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
View File
@@ -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(
+2 -3
View File
@@ -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,
+7
View File
@@ -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
};
};
+5 -3
View File
@@ -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
+6 -3
View File
@@ -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();
+5 -4
View File
@@ -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
View File
@@ -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;
+2
View File
@@ -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
}
+9 -1
View File
@@ -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
View File
@@ -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
+5 -3
View File
@@ -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,
};
};
+15 -2
View File
@@ -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
View File
@@ -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;
+1
View File
@@ -10,6 +10,7 @@
namespace igl
{
/// @private
// Simple Viewport class for an opengl context. Handles reshaping and mouse.
struct Viewport
{
+10 -1
View File
@@ -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);
+4 -3
View File
@@ -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
};
}
+3 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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),
+24 -18
View File
@@ -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,
+34 -33
View File
@@ -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
View File
@@ -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,
+10 -15
View File
@@ -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,
+32 -16
View File
@@ -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,
+6 -7
View File
@@ -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
View File
@@ -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,
+8 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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),
+65 -30
View File
@@ -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
View File
@@ -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,
+9 -10
View File
@@ -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(
+5 -7
View File
@@ -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,
+6 -9
View File
@@ -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,
+10 -12
View File
@@ -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,
+9 -8
View File
@@ -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,
+6 -8
View File
@@ -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,
+17 -21
View File
@@ -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,
+7 -9
View File
@@ -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,
+8 -6
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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,
+6 -11
View File
@@ -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,
+49 -49
View File
@@ -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
View File
@@ -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
View File
@@ -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,
+4 -7
View File
@@ -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,
+24 -25
View File
@@ -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,
+21 -12
View File
@@ -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
View File
@@ -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,
+8 -7
View File
@@ -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,
+5 -6
View File
@@ -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);
}
+9 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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,
+8 -9
View File
@@ -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
View File
@@ -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,
+6 -8
View File
@@ -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
View File
@@ -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
+14 -16
View File
@@ -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
View File
@@ -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
View File
@@ -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,
+5 -7
View File
@@ -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
View File
@@ -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,
+10 -14
View File
@@ -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,
+14 -18
View File
@@ -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,
+7 -11
View File
@@ -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
View File
@@ -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,
+26 -28
View File
@@ -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
+23 -19
View File
@@ -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,
+8 -10
View File
@@ -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>;
}
}
}
+19 -20
View File
@@ -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,
+81 -55
View File
@@ -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,
+9 -5
View File
@@ -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<
+36 -28
View File
@@ -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
}
}
}
+10 -14
View File
@@ -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,
+23 -20
View File
@@ -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,
+10 -12
View File
@@ -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);
}
}
}
+6 -15
View File
@@ -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>
+4 -5
View File
@@ -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