Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
igl Namespace Reference

Namespaces

namespace  anttweakbar
 
namespace  copyleft
 
namespace  embree
 
namespace  flip_avoiding
 
namespace  geodesic
 
namespace  lim
 
namespace  matlab
 
namespace  mosek
 
namespace  opengl
 
namespace  opengl2
 
namespace  ply
 
namespace  png
 
namespace  serialization
 
namespace  slim
 
namespace  triangle
 
namespace  xml
 

Classes

class  AABB
 
struct  active_set_params
 
struct  ARAPData
 
struct  ArapDOFData
 
struct  AtA_cached_data
 
class  BBWData
 
class  Camera
 
class  Comb
 
class  CombLine
 
class  Frame_field_deformer
 
class  HalfEdgeIterator
 
struct  Hit
 
struct  IndexDimLessThan
 
struct  IndexedPointer
 
struct  IndexedPointerBase
 
struct  IndexEquals
 
struct  IndexLessThan
 
struct  IndexRowEquals
 
struct  IndexRowLessThan
 
struct  IndexVectorLessThan
 
class  MeshCutter
 
class  MeshCutterMini
 
struct  min_quad_with_fixed_data
 
class  MissMatchCalculator
 
class  MissMatchCalculatorLine
 
class  PlanarizerShapeUp
 
class  Serializable
 
struct  SerializableBase
 
struct  ShapeupData
 
struct  SLIMData
 
class  SortableRow
 
class  Timer
 
struct  Viewport
 
class  WindingNumberAABB
 
class  WindingNumberTree
 

Typedefs

typedef std::function< bool(const Eigen::PlainObjectBase< Eigen::MatrixXd > &, const Eigen::PlainObjectBase< Eigen::VectorXi > &, const Eigen::PlainObjectBase< Eigen::MatrixXi > &, Eigen::PlainObjectBase< Eigen::MatrixXd > &)> shapeup_projection_function
 

Enumerations

enum  ARAPEnergyType {
  ARAP_ENERGY_TYPE_SPOKES = 0 , ARAP_ENERGY_TYPE_SPOKES_AND_RIMS = 1 , ARAP_ENERGY_TYPE_ELEMENTS = 2 , ARAP_ENERGY_TYPE_DEFAULT = 3 ,
  NUM_ARAP_ENERGY_TYPES = 4
}
 
enum  ColorMapType {
  COLOR_MAP_TYPE_INFERNO = 0 , COLOR_MAP_TYPE_JET = 1 , COLOR_MAP_TYPE_MAGMA = 2 , COLOR_MAP_TYPE_PARULA = 3 ,
  COLOR_MAP_TYPE_PLASMA = 4 , COLOR_MAP_TYPE_VIRIDIS = 5 , NUM_COLOR_MAP_TYPES = 6
}
 
enum  EigsType { EIGS_TYPE_SM = 0 , EIGS_TYPE_LM = 1 , NUM_EIGS_TYPES = 2 }
 
enum  MassMatrixType {
  MASSMATRIX_TYPE_BARYCENTRIC = 0 , MASSMATRIX_TYPE_VORONOI = 1 , MASSMATRIX_TYPE_FULL = 2 , MASSMATRIX_TYPE_DEFAULT = 3 ,
  NUM_MASSMATRIX_TYPE = 4
}
 
enum  MeshBooleanType {
  MESH_BOOLEAN_TYPE_UNION = 0 , MESH_BOOLEAN_TYPE_INTERSECT = 1 , MESH_BOOLEAN_TYPE_MINUS = 2 , MESH_BOOLEAN_TYPE_XOR = 3 ,
  MESH_BOOLEAN_TYPE_RESOLVE = 4 , NUM_MESH_BOOLEAN_TYPES = 5
}
 
enum  NormalType { PER_VERTEX_NORMALS , PER_FACE_NORMALS , PER_CORNER_NORMALS }
 
enum  PerEdgeNormalsWeightingType { PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM = 0 , PER_EDGE_NORMALS_WEIGHTING_TYPE_AREA = 1 , PER_EDGE_NORMALS_WEIGHTING_TYPE_DEFAULT = 2 , NUM_PER_EDGE_NORMALS_WEIGHTING_TYPE = 3 }
 
enum  PerVertexNormalsWeightingType {
  PER_VERTEX_NORMALS_WEIGHTING_TYPE_UNIFORM = 0 , PER_VERTEX_NORMALS_WEIGHTING_TYPE_AREA = 1 , PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE = 2 , PER_VERTEX_NORMALS_WEIGHTING_TYPE_DEFAULT = 3 ,
  NUM_PER_VERTEX_NORMALS_WEIGHTING_TYPE = 4
}
 
enum  SignedDistanceType {
  SIGNED_DISTANCE_TYPE_PSEUDONORMAL = 0 , SIGNED_DISTANCE_TYPE_WINDING_NUMBER = 1 , SIGNED_DISTANCE_TYPE_DEFAULT = 2 , SIGNED_DISTANCE_TYPE_UNSIGNED = 3 ,
  NUM_SIGNED_DISTANCE_TYPE = 4
}
 
enum  SolverStatus { SOLVER_STATUS_CONVERGED = 0 , SOLVER_STATUS_MAX_ITER = 1 , SOLVER_STATUS_ERROR = 2 , NUM_SOLVER_STATUSES = 3 }
 
enum  WindingNumberMethod { EXACT_WINDING_NUMBER_METHOD = 0 , APPROX_SIMPLE_WINDING_NUMBER_METHOD = 1 , APPROX_CACHE_WINDING_NUMBER_METHOD = 2 , NUM_WINDING_NUMBER_METHODS = 3 }
 

Functions

template<typename AT , typename DerivedB , typename Derivedknown , typename DerivedY , typename AeqT , typename DerivedBeq , typename AieqT , typename DerivedBieq , typename Derivedlx , typename Derivedux , typename DerivedZ >
IGL_INLINE igl::SolverStatus active_set (const Eigen::SparseMatrix< AT > &A, const Eigen::PlainObjectBase< DerivedB > &B, const Eigen::PlainObjectBase< Derivedknown > &known, const Eigen::PlainObjectBase< DerivedY > &Y, const Eigen::SparseMatrix< AeqT > &Aeq, const Eigen::PlainObjectBase< DerivedBeq > &Beq, const Eigen::SparseMatrix< AieqT > &Aieq, const Eigen::PlainObjectBase< DerivedBieq > &Bieq, const Eigen::PlainObjectBase< Derivedlx > &lx, const Eigen::PlainObjectBase< Derivedux > &ux, const igl::active_set_params &params, Eigen::PlainObjectBase< DerivedZ > &Z)
 
template<typename Index , typename IndexVector >
IGL_INLINE void adjacency_list (const Eigen::PlainObjectBase< Index > &F, std::vector< std::vector< IndexVector > > &A, bool sorted=false)
 
template<typename Index >
IGL_INLINE void adjacency_list (const std::vector< std::vector< Index > > &F, std::vector< std::vector< Index > > &A)
 
template<typename DerivedF , typename T >
IGL_INLINE void adjacency_matrix (const Eigen::MatrixBase< DerivedF > &F, Eigen::SparseMatrix< T > &A)
 
template<typename AType , typename DerivedB >
IGL_INLINE void all (const Eigen::SparseMatrix< AType > &A, const int dim, Eigen::PlainObjectBase< DerivedB > &B)
 
template<typename DerivedF , typename DerivedE >
IGL_INLINE void all_edges (const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedE > &E)
 
template<typename Mat >
IGL_INLINE void all_pairs_distances (const Mat &V, const Mat &U, const bool squared, Mat &D)
 
template<typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void ambient_occlusion (const std::function< bool(const Eigen::Vector3f &, const Eigen::Vector3f &) > &shoot_ray, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedN > &N, const int num_samples, Eigen::PlainObjectBase< DerivedS > &S)
 
template<typename DerivedV , int DIM, typename DerivedF , typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void ambient_occlusion (const igl::AABB< DerivedV, DIM > &aabb, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedN > &N, const int num_samples, Eigen::PlainObjectBase< DerivedS > &S)
 
template<typename DerivedV , typename DerivedF , typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void ambient_occlusion (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedN > &N, const int num_samples, Eigen::PlainObjectBase< DerivedS > &S)
 
IGL_INLINE double angular_distance (const Eigen::Quaterniond &A, const Eigen::Quaterniond &B)
 
template<typename AType , typename DerivedB >
IGL_INLINE void any (const Eigen::SparseMatrix< AType > &A, const int dim, Eigen::PlainObjectBase< DerivedB > &B)
 
template<typename Mat >
IGL_INLINE bool any_of (const Mat &S)
 
template<typename DerivedV , typename DerivedF , typename Derivedb >
IGL_INLINE bool arap_precomputation (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const int dim, const Eigen::PlainObjectBase< Derivedb > &b, ARAPData &data)
 
template<typename Derivedbc , typename DerivedU >
IGL_INLINE bool arap_solve (const Eigen::PlainObjectBase< Derivedbc > &bc, ARAPData &data, Eigen::PlainObjectBase< DerivedU > &U)
 
template<typename SSCALAR >
static SSCALAR maxBlokErr (const Eigen::Matrix3f &blok)
 
template<typename MatrixXS >
static MatrixXS::Scalar condense_CSM (const std::vector< MatrixXS > &CSM_M_SSCALAR, int numBones, int dim, MatrixXS &CSM)
 
template<typename MatL , typename MatLsep >
static void splitColumns (const MatL &L, int numBones, int dim, int dimp1, MatLsep &Lsep)
 
template<typename MatrixXS >
static void mergeColumns (const MatrixXS &Lsep, int numBones, int dim, int dimp1, MatrixXS &L)
 
template<typename MatrixXS >
static MatrixXS::Scalar condense_Solve1 (MatrixXS &Solve1, int numBones, int numGroups, int dim, MatrixXS &CSolve1)
 
template<typename LbsMatrixType , typename SSCALAR >
IGL_INLINE bool arap_dof_precomputation (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const LbsMatrixType &M, const Eigen::Matrix< int, Eigen::Dynamic, 1 > &G, ArapDOFData< LbsMatrixType, SSCALAR > &data)
 
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)
 
template<typename LbsMatrixType , typename SSCALAR >
IGL_INLINE bool arap_dof_update (const ArapDOFData< LbsMatrixType, SSCALAR > &data, const Eigen::Matrix< double, Eigen::Dynamic, 1 > &B_eq, const Eigen::MatrixXd &L0, const int max_iters, const double tol, Eigen::MatrixXd &L)
 
template<typename MatV , typename MatF , typename Scalar >
IGL_INLINE void arap_linear_block (const MatV &V, const MatF &F, const int d, const igl::ARAPEnergyType energy, Eigen::SparseMatrix< Scalar > &Kd)
 
template<typename MatV , typename MatF , typename Scalar >
IGL_INLINE void arap_linear_block_spokes (const MatV &V, const MatF &F, const int d, Eigen::SparseMatrix< Scalar > &Kd)
 
template<typename MatV , typename MatF , typename Scalar >
IGL_INLINE void arap_linear_block_spokes_and_rims (const MatV &V, const MatF &F, const int d, Eigen::SparseMatrix< Scalar > &Kd)
 
template<typename MatV , typename MatF , typename Scalar >
IGL_INLINE void arap_linear_block_elements (const MatV &V, const MatF &F, const int d, Eigen::SparseMatrix< Scalar > &Kd)
 
IGL_INLINE void arap_rhs (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const int dim, const igl::ARAPEnergyType energy, Eigen::SparseMatrix< double > &K)
 
template<typename Scalar >
IGL_INLINE void AtA_cached_precompute (const Eigen::SparseMatrix< Scalar > &A, AtA_cached_data &data, Eigen::SparseMatrix< Scalar > &AtA)
 
template<typename Scalar >
IGL_INLINE void AtA_cached (const Eigen::SparseMatrix< Scalar > &A, const AtA_cached_data &data, Eigen::SparseMatrix< Scalar > &AtA)
 
template<typename T , typename I >
IGL_INLINE void average_onto_faces (const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &V, const Eigen::Matrix< I, Eigen::Dynamic, Eigen::Dynamic > &F, const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &S, Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &SF)
 
template<typename DerivedV , typename DerivedF , typename DerivedS >
IGL_INLINE void average_onto_vertices (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedS > &S, Eigen::MatrixBase< DerivedS > &SV)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE double avg_edge_length (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F)
 
template<typename Q_type >
IGL_INLINE void axis_angle_to_quat (const Q_type *axis, const Q_type angle, Q_type *out)
 
template<typename DerivedV , typename DerivedF , typename DerivedBC >
IGL_INLINE void barycenter (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedBC > &BC)
 
template<typename DerivedP , typename DerivedA , typename DerivedB , typename DerivedC , typename DerivedD , typename DerivedL >
IGL_INLINE void barycentric_coordinates (const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &B, const Eigen::MatrixBase< DerivedC > &C, const Eigen::MatrixBase< DerivedD > &D, Eigen::PlainObjectBase< DerivedL > &L)
 
template<typename DerivedP , typename DerivedA , typename DerivedB , typename DerivedC , typename DerivedL >
IGL_INLINE void barycentric_coordinates (const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &B, const Eigen::MatrixBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedL > &L)
 
template<typename Scalar , typename Index >
IGL_INLINE Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamicbarycentric_to_global (const Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > &V, const Eigen::Matrix< Index, Eigen::Dynamic, Eigen::Dynamic > &F, const Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > &bc)
 
IGL_INLINE std::string basename (const std::string &path)
 
template<typename DerivedV , typename DerivedEle , typename Derivedb , typename Derivedbc , typename DerivedW >
IGL_INLINE bool bbw (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedEle > &Ele, const Eigen::PlainObjectBase< Derivedb > &b, const Eigen::PlainObjectBase< Derivedbc > &bc, BBWData &data, Eigen::PlainObjectBase< DerivedW > &W)
 
template<typename AType , typename DerivedD , typename DerivedP >
IGL_INLINE void bfs (const AType &A, const size_t s, Eigen::PlainObjectBase< DerivedD > &D, Eigen::PlainObjectBase< DerivedP > &P)
 
template<typename AType , typename DType , typename PType >
IGL_INLINE void bfs (const std::vector< std::vector< AType > > &A, const size_t s, std::vector< DType > &D, std::vector< PType > &P)
 
template<typename AType , typename DType , typename PType >
IGL_INLINE void bfs (const Eigen::SparseMatrix< AType > &A, const size_t s, std::vector< DType > &D, std::vector< PType > &P)
 
template<typename DerivedF , typename DerivedFF , typename DerivedC >
IGL_INLINE void bfs_orient (const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedFF > &FF, Eigen::PlainObjectBase< DerivedC > &C)
 
template<typename DerivedV , typename DerivedT , typename SType , typename DerivedW >
IGL_INLINE bool biharmonic_coordinates (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedT > &T, const std::vector< std::vector< SType > > &S, Eigen::PlainObjectBase< DerivedW > &W)
 
template<typename DerivedV , typename DerivedT , typename SType , typename DerivedW >
IGL_INLINE bool biharmonic_coordinates (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedT > &T, const std::vector< std::vector< SType > > &S, const int k, Eigen::PlainObjectBase< DerivedW > &W)
 
template<typename DerivedV , typename DerivedF , typename Derivedb , typename Derivedbc , typename DerivedU >
IGL_INLINE bool bijective_composite_harmonic_mapping (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< Derivedb > &b, const Eigen::MatrixBase< Derivedbc > &bc, Eigen::PlainObjectBase< DerivedU > &U)
 
template<typename DerivedV , typename DerivedF , typename Derivedb , typename Derivedbc , typename DerivedU >
IGL_INLINE bool bijective_composite_harmonic_mapping (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< Derivedb > &b, const Eigen::MatrixBase< Derivedbc > &bc, const int min_steps, const int max_steps, const int num_inner_iters, const bool test_for_flips, Eigen::PlainObjectBase< DerivedU > &U)
 
template<typename DerivedBE , typename DerivedP >
IGL_INLINE void bone_parents (const Eigen::PlainObjectBase< DerivedBE > &BE, Eigen::PlainObjectBase< DerivedP > &P)
 
IGL_INLINE bool boundary_conditions (const Eigen::MatrixXd &V, const Eigen::MatrixXi &Ele, const Eigen::MatrixXd &C, const Eigen::VectorXi &P, const Eigen::MatrixXi &BE, const Eigen::MatrixXi &CE, Eigen::VectorXi &b, Eigen::MatrixXd &bc)
 
template<typename IntegerT , typename IntegerF >
IGL_INLINE void boundary_facets (const std::vector< std::vector< IntegerT > > &T, std::vector< std::vector< IntegerF > > &F)
 
template<typename DerivedT , typename DerivedF >
IGL_INLINE void boundary_facets (const Eigen::PlainObjectBase< DerivedT > &T, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename DerivedT , typename Ret >
Ret boundary_facets (const Eigen::PlainObjectBase< DerivedT > &T)
 
template<typename DerivedF , typename Index >
IGL_INLINE void boundary_loop (const Eigen::PlainObjectBase< DerivedF > &F, std::vector< std::vector< Index > > &L)
 
template<typename DerivedF , typename Index >
IGL_INLINE void boundary_loop (const Eigen::PlainObjectBase< DerivedF > &F, std::vector< Index > &L)
 
template<typename DerivedF , typename DerivedL >
IGL_INLINE void boundary_loop (const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedL > &L)
 
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)
 
template<typename DerivedV , typename DerivedBV , typename DerivedBF >
IGL_INLINE void bounding_box (const Eigen::MatrixBase< DerivedV > &V, const typename DerivedV::Scalar pad, Eigen::PlainObjectBase< DerivedBV > &BV, Eigen::PlainObjectBase< DerivedBF > &BF)
 
IGL_INLINE double bounding_box_diagonal (const Eigen::MatrixXd &V)
 
template<typename Q_type >
IGL_INLINE Q_type CANONICAL_VIEW_QUAT (int i, int j)
 
template<>
IGL_INLINE float CANONICAL_VIEW_QUAT< float > (int i, int j)
 
template<>
IGL_INLINE double CANONICAL_VIEW_QUAT< double > (int i, int j)
 
template<typename Scalar >
IGL_INLINE void cat (const int dim, const Eigen::SparseMatrix< Scalar > &A, const Eigen::SparseMatrix< Scalar > &B, Eigen::SparseMatrix< Scalar > &C)
 
template<typename Derived , class MatC >
IGL_INLINE void cat (const int dim, const Eigen::MatrixBase< Derived > &A, const Eigen::MatrixBase< Derived > &B, MatC &C)
 
template<class Mat >
IGL_INLINE Mat cat (const int dim, const Mat &A, const Mat &B)
 
template<class Mat >
IGL_INLINE void cat (const std::vector< std::vector< Mat > > &A, Mat &C)
 
template<typename DerivedX , typename DerivedY >
IGL_INLINE void ceil (const Eigen::PlainObjectBase< DerivedX > &X, Eigen::PlainObjectBase< DerivedY > &Y)
 
template<typename DerivedV , typename DerivedF , typename Derivedc , typename Derivedvol >
IGL_INLINE void centroid (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< Derivedc > &c, Derivedvol &vol)
 
template<typename DerivedV , typename DerivedF , typename Derivedc >
IGL_INLINE void centroid (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< Derivedc > &c)
 
IGL_INLINE std::vector< int > circulation (const int e, const bool ccw, const Eigen::MatrixXi &F, const Eigen::MatrixXi &E, const Eigen::VectorXi &EMAP, const Eigen::MatrixXi &EF, const Eigen::MatrixXi &EI)
 
IGL_INLINE void circulation (const int e, const bool ccw, const Eigen::MatrixXi &F, const Eigen::MatrixXi &E, const Eigen::VectorXi &EMAP, const Eigen::MatrixXi &EF, const Eigen::MatrixXi &EI, Eigen::VectorXi &vN)
 
template<typename DerivedV , typename DerivedF , typename DerivedR >
IGL_INLINE void circumradius (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedR > &R)
 
IGL_INLINE bool collapse_edge (const int e, const Eigen::RowVectorXd &p, Eigen::MatrixXd &V, Eigen::MatrixXi &F, Eigen::MatrixXi &E, Eigen::VectorXi &EMAP, Eigen::MatrixXi &EF, Eigen::MatrixXi &EI, int &e1, int &e2, int &f1, int &f2)
 
IGL_INLINE bool collapse_edge (const int e, const Eigen::RowVectorXd &p, Eigen::MatrixXd &V, Eigen::MatrixXi &F, Eigen::MatrixXi &E, Eigen::VectorXi &EMAP, Eigen::MatrixXi &EF, Eigen::MatrixXi &EI)
 
IGL_INLINE bool collapse_edge (const std::function< void(const int, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> &cost_and_placement, Eigen::MatrixXd &V, Eigen::MatrixXi &F, Eigen::MatrixXi &E, Eigen::VectorXi &EMAP, Eigen::MatrixXi &EF, Eigen::MatrixXi &EI, std::set< std::pair< double, int > > &Q, std::vector< std::set< std::pair< double, int > >::iterator > &Qit, Eigen::MatrixXd &C)
 
IGL_INLINE bool collapse_edge (const std::function< void(const int, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> &cost_and_placement, const std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int)> &pre_collapse, const std::function< void(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int, const bool)> &post_collapse, Eigen::MatrixXd &V, Eigen::MatrixXi &F, Eigen::MatrixXi &E, Eigen::VectorXi &EMAP, Eigen::MatrixXi &EF, Eigen::MatrixXi &EI, std::set< std::pair< double, int > > &Q, std::vector< std::set< std::pair< double, int > >::iterator > &Qit, Eigen::MatrixXd &C)
 
IGL_INLINE bool collapse_edge (const std::function< void(const int, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> &cost_and_placement, const std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int)> &pre_collapse, const std::function< void(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int, const bool)> &post_collapse, Eigen::MatrixXd &V, Eigen::MatrixXi &F, Eigen::MatrixXi &E, Eigen::VectorXi &EMAP, Eigen::MatrixXi &EF, Eigen::MatrixXi &EI, std::set< std::pair< double, int > > &Q, std::vector< std::set< std::pair< double, int > >::iterator > &Qit, Eigen::MatrixXd &C, int &e, int &e1, int &e2, int &f1, int &f2)
 
void collapse_small_triangles (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const double eps, Eigen::MatrixXi &FF)
 
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)
 
template<typename L , typename H , typename T >
IGL_INLINE void colon (const L low, const H hi, Eigen::Matrix< T, Eigen::Dynamic, 1 > &I)
 
template<typename T , typename L , typename H >
IGL_INLINE Eigen::Matrix< T, Eigen::Dynamic, 1 > colon (const L low, const H hi)
 
template<typename T >
IGL_INLINE void colormap (const ColorMapType cm, const T f, T *rgb)
 
template<typename T >
IGL_INLINE void colormap (const ColorMapType cm, const T f, T &r, T &g, T &b)
 
template<typename T >
IGL_INLINE void colormap (const double palette[256][3], const T x_in, T &r, T &g, T &b)
 
template<typename DerivedZ , typename DerivedC >
IGL_INLINE void colormap (const ColorMapType cm, const Eigen::MatrixBase< DerivedZ > &Z, const bool normalize, Eigen::PlainObjectBase< DerivedC > &C)
 
template<typename DerivedZ , typename DerivedC >
IGL_INLINE void colormap (const ColorMapType cm, const Eigen::MatrixBase< DerivedZ > &Z, const double min_Z, const double max_Z, Eigen::PlainObjectBase< DerivedC > &C)
 
IGL_INLINE bool column_to_quats (const Eigen::VectorXd &Q, std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > &vQ)
 
template<typename DerivedA , typename DerivedB >
IGL_INLINE void columnize (const Eigen::PlainObjectBase< DerivedA > &A, const int k, const int dim, Eigen::PlainObjectBase< DerivedB > &B)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE void comb_cross_field (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedV > &PD1in, const Eigen::PlainObjectBase< DerivedV > &PD2in, Eigen::PlainObjectBase< DerivedV > &PD1out, Eigen::PlainObjectBase< DerivedV > &PD2out)
 
template<typename DerivedV , typename DerivedF , typename DerivedP >
IGL_INLINE void comb_frame_field (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedP > &PD1, const Eigen::PlainObjectBase< DerivedP > &PD2, const Eigen::PlainObjectBase< DerivedP > &BIS1_combed, const Eigen::PlainObjectBase< DerivedP > &BIS2_combed, Eigen::PlainObjectBase< DerivedP > &PD1_combed, Eigen::PlainObjectBase< DerivedP > &PD2_combed)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE void comb_line_field (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedV > &PD1in, Eigen::PlainObjectBase< DerivedV > &PD1out)
 
template<typename DerivedVV , typename DerivedFF , typename DerivedV , typename DerivedF , typename DerivedVsizes , typename DerivedFsizes >
IGL_INLINE void combine (const std::vector< DerivedVV > &VV, const std::vector< DerivedFF > &FF, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedVsizes > &Vsizes, Eigen::PlainObjectBase< DerivedFsizes > &Fsizes)
 
template<typename DerivedVV , typename DerivedFF , typename DerivedV , typename DerivedF >
IGL_INLINE void combine (const std::vector< DerivedVV > &VV, const std::vector< DerivedFF > &FF, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename AScalar , typename DerivedC , typename Derivedcounts >
IGL_INLINE void components (const Eigen::SparseMatrix< AScalar > &A, Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< Derivedcounts > &counts)
 
template<typename AScalar , typename DerivedC >
IGL_INLINE void components (const Eigen::SparseMatrix< AScalar > &A, Eigen::PlainObjectBase< DerivedC > &C)
 
template<typename DerivedF , typename DerivedC >
IGL_INLINE void components (const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedC > &C)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE void compute_frame_field_bisectors (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedV > &B1, const Eigen::PlainObjectBase< DerivedV > &B2, const Eigen::PlainObjectBase< DerivedV > &PD1, const Eigen::PlainObjectBase< DerivedV > &PD2, Eigen::PlainObjectBase< DerivedV > &BIS1, Eigen::PlainObjectBase< DerivedV > &BIS2)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE void compute_frame_field_bisectors (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedV > &PD1, const Eigen::PlainObjectBase< DerivedV > &PD2, Eigen::PlainObjectBase< DerivedV > &BIS1, Eigen::PlainObjectBase< DerivedV > &BIS2)
 
template<typename DerivedF , typename DerivedFO >
IGL_INLINE void connect_boundary_to_infinity (const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedFO > &FO)
 
template<typename DerivedF , typename DerivedFO >
IGL_INLINE void connect_boundary_to_infinity (const Eigen::PlainObjectBase< DerivedF > &F, const typename DerivedF::Scalar inf_index, Eigen::PlainObjectBase< DerivedFO > &FO)
 
template<typename DerivedV , typename DerivedF , typename DerivedVO , typename DerivedFO >
IGL_INLINE void connect_boundary_to_infinity (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedVO > &VO, Eigen::PlainObjectBase< DerivedFO > &FO)
 
template<typename DerivedP , typename DerivedN , typename DerivedQ , typename BetaType , typename DerivedWN >
IGL_INLINE void fast_winding_number (const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedN > &N, const Eigen::MatrixBase< DerivedQ > &Q, const int expansion_order, const BetaType beta, Eigen::PlainObjectBase< DerivedWN > &WN)
 
template<typename DerivedP , typename DerivedN , typename DerivedQ , typename DerivedWN >
IGL_INLINE void fast_winding_number (const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedN > &N, const Eigen::MatrixBase< DerivedQ > &Q, Eigen::PlainObjectBase< DerivedWN > &WN)
 
template<typename DerivedV , typename DerivedF , typename Scalar >
IGL_INLINE void cotmatrix (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::SparseMatrix< Scalar > &L)
 
template<typename DerivedV , typename DerivedF , typename DerivedC >
IGL_INLINE void cotmatrix_entries (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedC > &C)
 
template<typename XType , typename SType >
IGL_INLINE void count (const Eigen::SparseMatrix< XType > &X, const int dim, Eigen::SparseVector< SType > &S)
 
template<typename XType , typename DerivedS >
IGL_INLINE void count (const Eigen::SparseMatrix< XType > &X, const int dim, Eigen::PlainObjectBase< DerivedS > &S)
 
IGL_INLINE void covariance_scatter_matrix (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const ARAPEnergyType energy, Eigen::SparseMatrix< double > &CSM)
 
IGL_INLINE void cross (const double *a, const double *b, double *out)
 
template<typename DerivedA , typename DerivedB , typename DerivedC >
IGL_INLINE void cross (const Eigen::PlainObjectBase< DerivedA > &A, const Eigen::PlainObjectBase< DerivedB > &B, Eigen::PlainObjectBase< DerivedC > &C)
 
template<typename DerivedV , typename DerivedF , typename DerivedM >
IGL_INLINE void cross_field_missmatch (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedV > &PD1, const Eigen::PlainObjectBase< DerivedV > &PD2, const bool isCombed, Eigen::PlainObjectBase< DerivedM > &missmatch)
 
template<typename DerivedV , typename DerivedF , typename LT , typename DerivedE , typename DerivedEMAP >
void crouzeix_raviart_cotmatrix (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::SparseMatrix< LT > &L, Eigen::PlainObjectBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedEMAP > &EMAP)
 
template<typename DerivedV , typename DerivedF , typename DerivedE , typename DerivedEMAP , typename LT >
void crouzeix_raviart_cotmatrix (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedE > &E, const Eigen::MatrixBase< DerivedEMAP > &EMAP, Eigen::SparseMatrix< LT > &L)
 
template<typename MT , typename DerivedV , typename DerivedF , typename DerivedE , typename DerivedEMAP >
void crouzeix_raviart_massmatrix (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::SparseMatrix< MT > &M, Eigen::PlainObjectBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedEMAP > &EMAP)
 
template<typename MT , typename DerivedV , typename DerivedF , typename DerivedE , typename DerivedEMAP >
void crouzeix_raviart_massmatrix (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedE > &E, const Eigen::MatrixBase< DerivedEMAP > &EMAP, Eigen::SparseMatrix< MT > &M)
 
template<typename DerivedX , typename DerivedY >
IGL_INLINE void cumsum (const Eigen::MatrixBase< DerivedX > &X, const int dim, Eigen::PlainObjectBase< DerivedY > &Y)
 
template<typename DerivedV , typename DerivedF , typename VFType , typename DerivedTT , typename DerivedC >
IGL_INLINE void cut_mesh (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const std::vector< std::vector< VFType > > &VF, const std::vector< std::vector< VFType > > &VFi, const Eigen::PlainObjectBase< DerivedTT > &TT, const Eigen::PlainObjectBase< DerivedTT > &TTi, const std::vector< bool > &V_border, const Eigen::PlainObjectBase< DerivedC > &cuts, Eigen::PlainObjectBase< DerivedV > &Vcut, Eigen::PlainObjectBase< DerivedF > &Fcut)
 
template<typename DerivedV , typename DerivedF , typename DerivedC >
IGL_INLINE void cut_mesh (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedC > &cuts, Eigen::PlainObjectBase< DerivedV > &Vcut, Eigen::PlainObjectBase< DerivedF > &Fcut)
 
template<typename DerivedV , typename DerivedF , typename DerivedM , typename DerivedO >
IGL_INLINE void cut_mesh_from_singularities (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedM > &MMatch, Eigen::PlainObjectBase< DerivedO > &seams)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE void cylinder (const int axis_devisions, const int height_devisions, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F)
 
IGL_INLINE bool dated_copy (const std::string &src_path, const std::string &dir)
 
IGL_INLINE bool dated_copy (const std::string &src_path)
 
IGL_INLINE bool decimate (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const size_t max_m, Eigen::MatrixXd &U, Eigen::MatrixXi &G, Eigen::VectorXi &J, Eigen::VectorXi &I)
 
IGL_INLINE bool decimate (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const size_t max_m, Eigen::MatrixXd &U, Eigen::MatrixXi &G, Eigen::VectorXi &J)
 
IGL_INLINE bool decimate (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const std::function< void(const int, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> &cost_and_placement, const std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int)> &stopping_condition, Eigen::MatrixXd &U, Eigen::MatrixXi &G, Eigen::VectorXi &J, Eigen::VectorXi &I)
 
IGL_INLINE bool decimate (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const std::function< void(const int, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> &cost_and_placement, const std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int)> &stopping_condition, const std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int)> &pre_collapse, const std::function< void(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int, const bool)> &post_collapse, Eigen::MatrixXd &U, Eigen::MatrixXi &G, Eigen::VectorXi &J, Eigen::VectorXi &I)
 
IGL_INLINE bool decimate (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const std::function< void(const int, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> &cost_and_placement, const std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int)> &stopping_condition, const std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int)> &pre_collapse, const std::function< void(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int, const bool)> &post_collapse, const Eigen::MatrixXi &E, const Eigen::VectorXi &EMAP, const Eigen::MatrixXi &EF, const Eigen::MatrixXi &EI, Eigen::MatrixXd &U, Eigen::MatrixXi &G, Eigen::VectorXi &J, Eigen::VectorXi &I)
 
IGL_INLINE void deform_skeleton (const Eigen::MatrixXd &C, const Eigen::MatrixXi &BE, const std::vector< Eigen::Affine3d, Eigen::aligned_allocator< Eigen::Affine3d > > &vA, Eigen::MatrixXd &CT, Eigen::MatrixXi &BET)
 
IGL_INLINE void deform_skeleton (const Eigen::MatrixXd &C, const Eigen::MatrixXi &BE, const Eigen::MatrixXd &T, Eigen::MatrixXd &CT, Eigen::MatrixXi &BET)
 
template<typename DerivedV , typename Orient2D , typename InCircle , typename DerivedF >
IGL_INLINE void delaunay_triangulation (const Eigen::PlainObjectBase< DerivedV > &V, Orient2D orient2D, InCircle incircle, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename AType , typename DerivedD , typename DerivedP , typename DerivedC >
IGL_INLINE void dfs (const std::vector< std::vector< AType > > &A, const size_t s, Eigen::PlainObjectBase< DerivedD > &D, Eigen::PlainObjectBase< DerivedP > &P, Eigen::PlainObjectBase< DerivedC > &C)
 
template<typename AType , typename DType , typename PType , typename CType >
IGL_INLINE void dfs (const std::vector< std::vector< AType > > &A, const size_t s, std::vector< DType > &D, std::vector< PType > &P, std::vector< CType > &C)
 
template<typename T >
IGL_INLINE void diag (const Eigen::SparseMatrix< T > &X, Eigen::SparseVector< T > &V)
 
template<typename T , typename DerivedV >
IGL_INLINE void diag (const Eigen::SparseMatrix< T > &X, Eigen::MatrixBase< DerivedV > &V)
 
template<typename T >
IGL_INLINE void diag (const Eigen::SparseVector< T > &V, Eigen::SparseMatrix< T > &X)
 
template<typename T , typename DerivedV >
IGL_INLINE void diag (const Eigen::MatrixBase< DerivedV > &V, Eigen::SparseMatrix< T > &X)
 
template<typename DerivedV , typename DerivedT , typename Derivedtheta , typename Derivedcos_theta >
IGL_INLINE void dihedral_angles (Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedT > &T, Eigen::PlainObjectBase< Derivedtheta > &theta, Eigen::PlainObjectBase< Derivedcos_theta > &cos_theta)
 
template<typename DerivedL , typename DerivedA , typename Derivedtheta , typename Derivedcos_theta >
IGL_INLINE void dihedral_angles_intrinsic (Eigen::PlainObjectBase< DerivedL > &L, Eigen::PlainObjectBase< DerivedA > &A, Eigen::PlainObjectBase< Derivedtheta > &theta, Eigen::PlainObjectBase< Derivedcos_theta > &cos_theta)
 
template<typename IndexType , typename DerivedD , typename DerivedP >
IGL_INLINE int dijkstra_compute_paths (const IndexType &source, const std::set< IndexType > &targets, const std::vector< std::vector< IndexType > > &VV, Eigen::PlainObjectBase< DerivedD > &min_distance, Eigen::PlainObjectBase< DerivedP > &previous)
 
template<typename IndexType , typename DerivedP >
IGL_INLINE void dijkstra_get_shortest_path_to (const IndexType &vertex, const Eigen::PlainObjectBase< DerivedP > &previous, std::vector< IndexType > &path)
 
template<typename DerivedC , typename DerivedE >
IGL_INLINE void directed_edge_orientations (const Eigen::PlainObjectBase< DerivedC > &C, const Eigen::PlainObjectBase< DerivedE > &E, std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > &Q)
 
template<typename DerivedE , typename DerivedP >
IGL_INLINE void directed_edge_parents (const Eigen::PlainObjectBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedP > &P)
 
IGL_INLINE std::string dirname (const std::string &path)
 
IGL_INLINE double dot (const double *a, const double *b)
 
template<typename DerivedV >
IGL_INLINE DerivedV dot_row (const Eigen::PlainObjectBase< DerivedV > &A, const Eigen::PlainObjectBase< DerivedV > &B)
 
template<typename DerivedV , typename DerivedF , typename DeriveddblA >
IGL_INLINE void doublearea (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DeriveddblA > &dblA)
 
template<typename DerivedA , typename DerivedB , typename DerivedC , typename DerivedD >
IGL_INLINE void doublearea (const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &B, const Eigen::MatrixBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedD > &D)
 
template<typename DerivedA , typename DerivedB , typename DerivedC >
IGL_INLINE DerivedA::Scalar doublearea_single (const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &B, const Eigen::MatrixBase< DerivedC > &C)
 
template<typename Derivedl , typename DeriveddblA >
IGL_INLINE void doublearea (const Eigen::MatrixBase< Derivedl > &l, const typename Derivedl::Scalar nan_replacement, Eigen::PlainObjectBase< DeriveddblA > &dblA)
 
template<typename Derivedl , typename DeriveddblA >
IGL_INLINE void doublearea (const Eigen::MatrixBase< Derivedl > &l, Eigen::PlainObjectBase< DeriveddblA > &dblA)
 
template<typename DerivedV , typename DerivedF , typename DeriveddblA >
IGL_INLINE void doublearea_quad (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DeriveddblA > &dblA)
 
template<typename DerivedV , typename DerivedW , typename Q , typename QAlloc , typename T , typename DerivedU >
IGL_INLINE void dqs (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedW > &W, const std::vector< Q, QAlloc > &vQ, const std::vector< T > &vT, Eigen::PlainObjectBase< DerivedU > &U)
 
template<typename DerivedF , typename Derivedear , typename Derivedear_opp >
IGL_INLINE void ears (const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< Derivedear > &ear, Eigen::PlainObjectBase< Derivedear_opp > &ear_opp)
 
IGL_INLINE bool edge_collapse_is_valid (const int e, const Eigen::MatrixXi &F, const Eigen::MatrixXi &E, const Eigen::VectorXi &EMAP, const Eigen::MatrixXi &EF, const Eigen::MatrixXi &EI)
 
IGL_INLINE void edge_flaps (const Eigen::MatrixXi &F, const Eigen::MatrixXi &E, const Eigen::VectorXi &EMAP, Eigen::MatrixXi &EF, Eigen::MatrixXi &EI)
 
IGL_INLINE void edge_flaps (const Eigen::MatrixXi &F, Eigen::MatrixXi &E, Eigen::VectorXi &EMAP, Eigen::MatrixXi &EF, Eigen::MatrixXi &EI)
 
template<typename DerivedV , typename DerivedF , typename DerivedL >
IGL_INLINE void edge_lengths (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedL > &L)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE void edge_topology (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::MatrixXi &EV, Eigen::MatrixXi &FE, Eigen::MatrixXi &EF)
 
template<typename DerivedF , typename DerivedE >
IGL_INLINE void edges (const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedE > &E)
 
template<typename DerivedE , typename DerivedI , typename DerivedJ , typename DerivedK >
IGL_INLINE void edges_to_path (const Eigen::MatrixBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::PlainObjectBase< DerivedK > &K)
 
template<typename Atype , typename Btype , typename DerivedU , typename DerivedS >
IGL_INLINE bool eigs (const Eigen::SparseMatrix< Atype > &A, const Eigen::SparseMatrix< Btype > &B, const size_t k, const EigsType type, Eigen::PlainObjectBase< DerivedU > &sU, Eigen::PlainObjectBase< DerivedS > &sS)
 
template<typename S_type >
IGL_INLINE S_type EPS ()
 
template<typename S_type >
IGL_INLINE S_type EPS_SQ ()
 
template<>
IGL_INLINE float EPS< float > ()
 
template<>
IGL_INLINE double EPS< double > ()
 
template<>
IGL_INLINE float EPS_SQ< float > ()
 
template<>
IGL_INLINE double EPS_SQ< double > ()
 
template<typename DerivedF >
IGL_INLINE int euler_characteristic (const Eigen::MatrixBase< DerivedF > &F)
 
template<typename Scalar , typename Index >
IGL_INLINE int euler_characteristic (const Eigen::PlainObjectBase< Scalar > &V, const Eigen::PlainObjectBase< Index > &F)
 
template<typename DerivedV , typename DerivedF , typename DerivedVS , typename DerivedFS , typename DerivedVT , typename DerivedFT , typename DerivedD >
IGL_INLINE void exact_geodesic (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedVS > &VS, const Eigen::MatrixBase< DerivedFS > &FS, const Eigen::MatrixBase< DerivedVT > &VT, const Eigen::MatrixBase< DerivedFT > &FT, Eigen::PlainObjectBase< DerivedD > &D)
 
template<typename Printable >
IGL_INLINE bool example_fun (const Printable &input)
 
IGL_INLINE void exterior_edges (const Eigen::MatrixXi &F, Eigen::MatrixXi &E)
 
IGL_INLINE Eigen::MatrixXi exterior_edges (const Eigen::MatrixXi &F)
 
template<typename DerivedF , typename DerivedEMAP , typename uE2EType , typename DerivedP >
IGL_INLINE size_t extract_manifold_patches (const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedEMAP > &EMAP, const std::vector< std::vector< uE2EType > > &uE2E, Eigen::PlainObjectBase< DerivedP > &P)
 
template<typename DerivedF , typename DerivedP >
IGL_INLINE size_t extract_manifold_patches (const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedP > &P)
 
template<typename DerivedF , typename DerivedEMAP , typename uE2EType >
IGL_INLINE void extract_non_manifold_edge_curves (const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedEMAP > &EMAP, const std::vector< std::vector< uE2EType > > &uE2E, std::vector< std::vector< size_t > > &curves)
 
template<typename DerivedV , typename DerivedT , typename DerivedA >
IGL_INLINE void face_areas (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedT > &T, Eigen::PlainObjectBase< DerivedA > &A)
 
template<typename DerivedL , typename DerivedA >
IGL_INLINE void face_areas (const Eigen::MatrixBase< DerivedL > &L, Eigen::PlainObjectBase< DerivedA > &A)
 
template<typename DerivedL , typename DerivedA >
IGL_INLINE void face_areas (const Eigen::MatrixBase< DerivedL > &L, const typename DerivedL::Scalar doublearea_nan_replacement, Eigen::PlainObjectBase< DerivedA > &A)
 
template<typename IntegerF , typename IntegerC >
IGL_INLINE void face_occurrences (const std::vector< std::vector< IntegerF > > &F, std::vector< IntegerC > &C)
 
template<typename MatV , typename MatF , typename VecI >
IGL_INLINE void faces_first (const MatV &V, const MatF &F, MatV &RV, MatF &RF, VecI &IM)
 
template<typename MatV , typename MatF , typename VecI >
IGL_INLINE void faces_first (MatV &V, MatF &F, VecI &IM)
 
template<typename DerivedF , typename DerivedC >
IGL_INLINE void facet_components (const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedC > &C)
 
template<typename TTIndex , typename DerivedC , typename Derivedcounts >
IGL_INLINE void facet_components (const std::vector< std::vector< std::vector< TTIndex > > > &TT, Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< Derivedcounts > &counts)
 
template<typename Scalar , typename Index >
IGL_INLINE void false_barycentric_subdivision (const Eigen::PlainObjectBase< Scalar > &V, const Eigen::PlainObjectBase< Index > &F, Eigen::PlainObjectBase< Scalar > &VD, Eigen::PlainObjectBase< Index > &FD)
 
template<typename DerivedP , typename DerivedA , typename DerivedN , typename Index , typename DerivedCH , typename DerivedCM , typename DerivedR , typename DerivedEC >
IGL_INLINE void fast_winding_number (const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedN > &N, const Eigen::MatrixBase< DerivedA > &A, const std::vector< std::vector< Index > > &point_indices, const Eigen::MatrixBase< DerivedCH > &CH, const int expansion_order, Eigen::PlainObjectBase< DerivedCM > &CM, Eigen::PlainObjectBase< DerivedR > &R, Eigen::PlainObjectBase< DerivedEC > &EC)
 
template<typename DerivedP , typename DerivedA , typename DerivedN , typename Index , typename DerivedCH , typename DerivedCM , typename DerivedR , typename DerivedEC , typename DerivedQ , typename BetaType , typename DerivedWN >
IGL_INLINE void fast_winding_number (const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedN > &N, const Eigen::MatrixBase< DerivedA > &A, const std::vector< std::vector< Index > > &point_indices, const Eigen::MatrixBase< DerivedCH > &CH, const Eigen::MatrixBase< DerivedCM > &CM, const Eigen::MatrixBase< DerivedR > &R, const Eigen::MatrixBase< DerivedEC > &EC, const Eigen::MatrixBase< DerivedQ > &Q, const BetaType beta, Eigen::PlainObjectBase< DerivedWN > &WN)
 
template<typename DerivedP , typename DerivedA , typename DerivedN , typename DerivedQ , typename BetaType , typename DerivedWN >
IGL_INLINE void fast_winding_number (const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedN > &N, const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedQ > &Q, const int expansion_order, const BetaType beta, Eigen::PlainObjectBase< DerivedWN > &WN)
 
template<typename DerivedP , typename DerivedA , typename DerivedN , typename DerivedQ , typename DerivedWN >
IGL_INLINE void fast_winding_number (const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedN > &N, const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedQ > &Q, Eigen::PlainObjectBase< DerivedWN > &WN)
 
IGL_INLINE bool file_contents_as_string (const std::string file_name, std::string &content)
 
IGL_INLINE std::string file_contents_as_string (const std::string file_name)
 
IGL_INLINE std::string file_dialog_open ()
 
IGL_INLINE std::string file_dialog_save ()
 
IGL_INLINE bool file_exists (const std::string filename)
 
template<typename T , typename DerivedI , typename DerivedJ , typename DerivedV >
IGL_INLINE void find (const Eigen::SparseMatrix< T > &X, Eigen::DenseBase< DerivedI > &I, Eigen::DenseBase< DerivedJ > &J, Eigen::DenseBase< DerivedV > &V)
 
template<typename DerivedX , typename DerivedI , typename DerivedJ , typename DerivedV >
IGL_INLINE void find (const Eigen::DenseBase< DerivedX > &X, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::PlainObjectBase< DerivedV > &V)
 
template<typename DerivedX , typename DerivedI >
IGL_INLINE void find (const Eigen::DenseBase< DerivedX > &X, Eigen::PlainObjectBase< DerivedI > &I)
 
template<typename T >
IGL_INLINE void find (const Eigen::SparseVector< T > &X, Eigen::Matrix< int, Eigen::Dynamic, 1 > &I, Eigen::Matrix< T, Eigen::Dynamic, 1 > &V)
 
template<typename DerivedV , typename DerivedF , typename DerivedM , typename DerivedO >
IGL_INLINE void find_cross_field_singularities (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedM > &Handle_MMatch, Eigen::PlainObjectBase< DerivedO > &isSingularity, Eigen::PlainObjectBase< DerivedO > &singularityIndex)
 
template<typename DerivedV , typename DerivedF , typename DerivedO >
IGL_INLINE void find_cross_field_singularities (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedV > &PD1, const Eigen::PlainObjectBase< DerivedV > &PD2, Eigen::PlainObjectBase< DerivedO > &isSingularity, Eigen::PlainObjectBase< DerivedO > &singularityIndex, bool isCombed=false)
 
template<typename AType , typename DerivedI >
IGL_INLINE void find_zero (const Eigen::SparseMatrix< AType > &A, const int dim, Eigen::PlainObjectBase< DerivedI > &I)
 
IGL_INLINE void fit_plane (const Eigen::MatrixXd &V, Eigen::RowVector3d &N, Eigen::RowVector3d &C)
 
template<typename DerivedS , typename DerivedD >
IGL_INLINE void fit_rotations (const Eigen::PlainObjectBase< DerivedS > &S, const bool single_precision, Eigen::PlainObjectBase< DerivedD > &R)
 
template<typename DerivedS , typename DerivedD >
IGL_INLINE void fit_rotations_planar (const Eigen::PlainObjectBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedD > &R)
 
IGL_INLINE double flip_avoiding_line_search (const Eigen::MatrixXi F, Eigen::MatrixXd &cur_v, Eigen::MatrixXd &dst_v, std::function< double(Eigen::MatrixXd &)> energy, double cur_energy=-1)
 
template<typename DerivedF , typename DerivedE , typename DeriveduE , typename DerivedEMAP , typename uE2EType >
IGL_INLINE void flip_edge (Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedE > &E, Eigen::PlainObjectBase< DeriveduE > &uE, Eigen::PlainObjectBase< DerivedEMAP > &EMAP, std::vector< std::vector< uE2EType > > &uE2E, const size_t uei)
 
template<typename DerivedV , typename DerivedF , typename DerivedX >
IGL_INLINE void flipped_triangles (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedX > &X)
 
template<typename Scalar , typename Index >
IGL_INLINE Eigen::VectorXi flipped_triangles (const Eigen::PlainObjectBase< Scalar > &V, const Eigen::PlainObjectBase< Index > &F)
 
template<typename Derivedres , typename DerivedS >
IGL_INLINE void flood_fill (const Eigen::MatrixBase< Derivedres > &res, Eigen::PlainObjectBase< DerivedS > &S)
 
template<typename DerivedX , typename DerivedY >
IGL_INLINE void floor (const Eigen::PlainObjectBase< DerivedX > &X, Eigen::PlainObjectBase< DerivedY > &Y)
 
template<typename AType , typename Func >
void for_each (const Eigen::SparseMatrix< AType > &A, const Func &func)
 
template<typename DerivedA , typename Func >
void for_each (const Eigen::DenseBase< DerivedA > &A, const Func &func)
 
IGL_INLINE void forward_kinematics (const Eigen::MatrixXd &C, const Eigen::MatrixXi &BE, const Eigen::VectorXi &P, const std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > &dQ, const std::vector< Eigen::Vector3d > &dT, std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > &vQ, std::vector< Eigen::Vector3d > &vT)
 
IGL_INLINE void forward_kinematics (const Eigen::MatrixXd &C, const Eigen::MatrixXi &BE, const Eigen::VectorXi &P, const std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > &dQ, std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > &vQ, std::vector< Eigen::Vector3d > &vT)
 
IGL_INLINE void forward_kinematics (const Eigen::MatrixXd &C, const Eigen::MatrixXi &BE, const Eigen::VectorXi &P, const std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > &dQ, const std::vector< Eigen::Vector3d > &dT, Eigen::MatrixXd &T)
 
IGL_INLINE void forward_kinematics (const Eigen::MatrixXd &C, const Eigen::MatrixXi &BE, const Eigen::VectorXi &P, const std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > &dQ, Eigen::MatrixXd &T)
 
IGL_INLINE void frame_field_deformer (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const Eigen::MatrixXd &FF1, const Eigen::MatrixXd &FF2, Eigen::MatrixXd &V_d, Eigen::MatrixXd &FF1_d, Eigen::MatrixXd &FF2_d, const int iterations=50, const double lambda=0.1, const bool perturb_initial_guess=true)
 
IGL_INLINE void frame_to_cross_field (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const Eigen::MatrixXd &FF1, const Eigen::MatrixXd &FF2, Eigen::MatrixXd &X)
 
template<typename DerivedP >
IGL_INLINE void frustum (const typename DerivedP::Scalar left, const typename DerivedP::Scalar right, const typename DerivedP::Scalar bottom, const typename DerivedP::Scalar top, const typename DerivedP::Scalar nearVal, const typename DerivedP::Scalar farVal, Eigen::PlainObjectBase< DerivedP > &P)
 
template<typename DerivedV , typename DerivedF , typename DerivedK >
IGL_INLINE void gaussian_curvature (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedK > &K)
 
IGL_INLINE double get_seconds ()
 
IGL_INLINE double get_seconds_hires ()
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE void grad (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::SparseMatrix< typename DerivedV::Scalar > &G, bool uniform=false)
 
template<typename Derivedres , typename DerivedGV >
IGL_INLINE void grid (const Eigen::MatrixBase< Derivedres > &res, Eigen::PlainObjectBase< DerivedGV > &GV)
 
template<typename Scalar , typename DerivedX , typename DerivedLB , typename DerivedUB , typename DerivedI >
IGL_INLINE Scalar grid_search (const std::function< Scalar(DerivedX &) > f, const Eigen::MatrixBase< DerivedLB > &LB, const Eigen::MatrixBase< DerivedUB > &UB, const Eigen::MatrixBase< DerivedI > &I, DerivedX &X)
 
template<typename T >
IGL_INLINE void group_sum_matrix (const Eigen::Matrix< int, Eigen::Dynamic, 1 > &G, const int k, Eigen::SparseMatrix< T > &A)
 
template<typename T >
IGL_INLINE void group_sum_matrix (const Eigen::Matrix< int, Eigen::Dynamic, 1 > &G, Eigen::SparseMatrix< T > &A)
 
IGL_INLINE void guess_extension (FILE *fp, std::string &guess)
 
IGL_INLINE std::string guess_extension (FILE *fp)
 
template<typename DerivedV , typename DerivedF , typename Derivedb , typename Derivedbc , typename DerivedW >
IGL_INLINE bool harmonic (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< Derivedb > &b, const Eigen::MatrixBase< Derivedbc > &bc, const int k, Eigen::PlainObjectBase< DerivedW > &W)
 
template<typename DerivedF , typename Derivedb , typename Derivedbc , typename DerivedW >
IGL_INLINE bool harmonic (const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< Derivedb > &b, const Eigen::MatrixBase< Derivedbc > &bc, const int k, Eigen::PlainObjectBase< DerivedW > &W)
 
template<typename DerivedL , typename DerivedM , typename Derivedb , typename Derivedbc , typename DerivedW >
IGL_INLINE bool harmonic (const Eigen::SparseMatrix< DerivedL > &L, const Eigen::SparseMatrix< DerivedM > &M, const Eigen::MatrixBase< Derivedb > &b, const Eigen::MatrixBase< Derivedbc > &bc, const int k, Eigen::PlainObjectBase< DerivedW > &W)
 
template<typename DerivedL , typename DerivedM , typename DerivedQ >
IGL_INLINE void harmonic (const Eigen::SparseMatrix< DerivedL > &L, const Eigen::SparseMatrix< DerivedM > &M, const int k, Eigen::SparseMatrix< DerivedQ > &Q)
 
template<typename DerivedV , typename DerivedF , typename DerivedQ >
IGL_INLINE void harmonic (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const int k, Eigen::SparseMatrix< DerivedQ > &Q)
 
template<typename Scalar , typename Index >
IGL_INLINE void harwell_boeing (const Eigen::SparseMatrix< Scalar > &A, int &num_rows, std::vector< Scalar > &V, std::vector< Index > &R, std::vector< Index > &C)
 
template<typename DerivedVA , typename DerivedFA , typename DerivedVB , typename DerivedFB , typename Scalar >
IGL_INLINE void hausdorff (const Eigen::PlainObjectBase< DerivedVA > &VA, const Eigen::PlainObjectBase< DerivedFA > &FA, const Eigen::PlainObjectBase< DerivedVB > &VB, const Eigen::PlainObjectBase< DerivedFB > &FB, Scalar &d)
 
template<typename DerivedV , typename Scalar >
IGL_INLINE void hausdorff (const Eigen::MatrixBase< DerivedV > &V, const std::function< Scalar(const Scalar &, const Scalar &, const Scalar &)> &dist_to_B, Scalar &l, Scalar &u)
 
template<typename DerivedV , typename DerivedF , typename Scalar >
IGL_INLINE void hessian (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::SparseMatrix< Scalar > &H)
 
template<typename DerivedV , typename DerivedF , typename Scalar >
IGL_INLINE void hessian_energy (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::SparseMatrix< Scalar > &Q)
 
template<typename DerivedX , typename DerivedE , typename DerivedN , typename DerivedB >
IGL_INLINE void histc (const Eigen::MatrixBase< DerivedX > &X, const Eigen::MatrixBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedN > &N, Eigen::PlainObjectBase< DerivedB > &B)
 
template<typename DerivedX , typename DerivedE , typename DerivedB >
IGL_INLINE void histc (const Eigen::MatrixBase< DerivedX > &X, const Eigen::MatrixBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedB > &B)
 
template<typename DerivedE >
IGL_INLINE void histc (const typename DerivedE::Scalar &x, const Eigen::MatrixBase< DerivedE > &E, typename DerivedE::Index &b)
 
template<typename T >
IGL_INLINE void hsv_to_rgb (const T *hsv, T *rgb)
 
template<typename T >
IGL_INLINE void hsv_to_rgb (const T &h, const T &s, const T &v, T &r, T &g, T &b)
 
template<typename DerivedH , typename DerivedR >
void hsv_to_rgb (const Eigen::PlainObjectBase< DerivedH > &H, Eigen::PlainObjectBase< DerivedR > &R)
 
template<typename DerivedV , typename DerivedQ , int DIM>
IGL_INLINE void in_element (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::MatrixXi &Ele, const Eigen::PlainObjectBase< DerivedQ > &Q, const AABB< DerivedV, DIM > &aabb, Eigen::VectorXi &I)
 
template<typename DerivedV , typename DerivedQ , int DIM, typename Scalar >
IGL_INLINE void in_element (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::MatrixXi &Ele, const Eigen::PlainObjectBase< DerivedQ > &Q, const AABB< DerivedV, DIM > &aabb, Eigen::SparseMatrix< Scalar > &I)
 
IGL_INLINE void infinite_cost_stopping_condition (const std::function< void(const int, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> &cost_and_placement, std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int)> &stopping_condition)
 
IGL_INLINE std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int)> infinite_cost_stopping_condition (const std::function< void(const int, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> &cost_and_placement)
 
template<typename DerivedV , typename DerivedF , typename DerivedR >
IGL_INLINE void inradius (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedR > &R)
 
template<typename DerivedV , typename DerivedF , typename DerivedK >
IGL_INLINE void internal_angles (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedK > &K)
 
template<typename DerivedL , typename DerivedK >
IGL_INLINE void internal_angles_using_squared_edge_lengths (const Eigen::MatrixBase< DerivedL > &L_sq, Eigen::PlainObjectBase< DerivedK > &K)
 
template<typename DerivedL , typename DerivedK >
IGL_INLINE void internal_angles_using_edge_lengths (const Eigen::MatrixBase< DerivedL > &L, Eigen::PlainObjectBase< DerivedK > &K)
 
template<class M >
IGL_INLINE void intersect (const M &A, const M &B, M &C)
 
template<class M >
IGL_INLINEintersect (const M &A, const M &B)
 
template<typename T >
IGL_INLINE void invert_diag (const Eigen::SparseMatrix< T > &X, Eigen::SparseMatrix< T > &Y)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE std::vector< bool > is_border_vertex (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename DerivedF , typename DerivedE , typename DerivedB >
void is_boundary_edge (const Eigen::PlainObjectBase< DerivedE > &E, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedB > &B)
 
template<typename DerivedF , typename DerivedE , typename DerivedB , typename DerivedEMAP >
void is_boundary_edge (const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedB > &B, Eigen::PlainObjectBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedEMAP > &EMAP)
 
IGL_INLINE bool is_dir (const char *filename)
 
template<typename DerivedF , typename DerivedBF , typename DerivedE , typename DerivedEMAP , typename DerivedBE >
IGL_INLINE bool is_edge_manifold (const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedBF > &BF, Eigen::PlainObjectBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedEMAP > &EMAP, Eigen::PlainObjectBase< DerivedBE > &BE)
 
template<typename DerivedF >
IGL_INLINE bool is_edge_manifold (const Eigen::MatrixBase< DerivedF > &F)
 
IGL_INLINE bool is_file (const char *filename)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE std::vector< bool > is_irregular_vertex (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F)
 
IGL_INLINE bool is_planar (const Eigen::MatrixXd &V)
 
IGL_INLINE bool is_readable (const char *filename)
 
template<typename T >
IGL_INLINE bool is_sparse (const Eigen::SparseMatrix< T > &A)
 
template<typename DerivedA >
IGL_INLINE bool is_sparse (const Eigen::PlainObjectBase< DerivedA > &A)
 
IGL_INLINE bool is_stl (FILE *stl_file, bool &is_ascii)
 
IGL_INLINE bool is_stl (FILE *stl_file)
 
template<typename AT >
IGL_INLINE bool is_symmetric (const Eigen::SparseMatrix< AT > &A)
 
template<typename AT , typename epsilonT >
IGL_INLINE bool is_symmetric (const Eigen::SparseMatrix< AT > &A, const epsilonT epsilon)
 
template<typename DerivedA >
IGL_INLINE bool is_symmetric (const Eigen::PlainObjectBase< DerivedA > &A)
 
template<typename DerivedF , typename DerivedB >
IGL_INLINE bool is_vertex_manifold (const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedB > &B)
 
IGL_INLINE bool is_writable (const char *filename)
 
template<typename Scalar >
IGL_INLINE bool isdiag (const Eigen::SparseMatrix< Scalar > &A)
 
template<typename DerivedA , typename DerivedB , typename DerivedIA , typename DerivedLOCB >
IGL_INLINE void ismember (const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &B, Eigen::PlainObjectBase< DerivedIA > &IA, Eigen::PlainObjectBase< DerivedLOCB > &LOCB)
 
template<typename DerivedA , typename DerivedB , typename DerivedIA , typename DerivedLOCB >
IGL_INLINE void ismember_rows (const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &B, Eigen::PlainObjectBase< DerivedIA > &IA, Eigen::PlainObjectBase< DerivedLOCB > &LOCB)
 
template<typename DerivedV , typename DerivedF , typename DerivedZ , typename DerivedIsoV , typename DerivedIsoE >
IGL_INLINE void isolines (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedZ > &z, const int n, Eigen::PlainObjectBase< DerivedIsoV > &isoV, Eigen::PlainObjectBase< DerivedIsoE > &isoE)
 
template<typename T >
IGL_INLINE void jet (const T f, T *rgb)
 
template<typename T >
IGL_INLINE void jet (const T f, T &r, T &g, T &b)
 
template<typename DerivedZ , typename DerivedC >
IGL_INLINE void jet (const Eigen::MatrixBase< DerivedZ > &Z, const bool normalize, Eigen::PlainObjectBase< DerivedC > &C)
 
template<typename DerivedZ , typename DerivedC >
IGL_INLINE void jet (const Eigen::MatrixBase< DerivedZ > &Z, const double min_Z, const double max_Z, Eigen::PlainObjectBase< DerivedC > &C)
 
template<typename DerivedP , typename KType , typename IndexType , typename DerivedCH , typename DerivedCN , typename DerivedW , typename DerivedI >
IGL_INLINE void knn (const Eigen::MatrixBase< DerivedP > &P, const KType &k, const std::vector< std::vector< IndexType > > &point_indices, const Eigen::MatrixBase< DerivedCH > &CH, const Eigen::MatrixBase< DerivedCN > &CN, const Eigen::MatrixBase< DerivedW > &W, Eigen::PlainObjectBase< DerivedI > &I)
 
template<typename DerivedV , typename DerivedT , typename DerivedF >
IGL_INLINE int launch_medit (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedT > &T, const Eigen::PlainObjectBase< DerivedF > &F, const bool wait)
 
IGL_INLINE void lbs_matrix (const Eigen::MatrixXd &V, const Eigen::MatrixXd &W, Eigen::MatrixXd &M)
 
IGL_INLINE void lbs_matrix_column (const Eigen::MatrixXd &V, const Eigen::MatrixXd &W, Eigen::SparseMatrix< double > &M)
 
IGL_INLINE void lbs_matrix_column (const Eigen::MatrixXd &V, const Eigen::MatrixXd &W, Eigen::MatrixXd &M)
 
IGL_INLINE void lbs_matrix_column (const Eigen::MatrixXd &V, const Eigen::MatrixXd &W, const Eigen::MatrixXi &WI, Eigen::SparseMatrix< double > &M)
 
IGL_INLINE void lbs_matrix_column (const Eigen::MatrixXd &V, const Eigen::MatrixXd &W, const Eigen::MatrixXi &WI, Eigen::MatrixXd &M)
 
template<typename DerivedP , typename Orient2D , typename DerivedF >
IGL_INLINE void lexicographic_triangulation (const Eigen::PlainObjectBase< DerivedP > &P, Orient2D orient2D, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename MatF , typename VecL >
IGL_INLINE void limit_faces (const MatF &F, const VecL &L, const bool exclusive, MatF &LF)
 
template<typename DerivedV , typename DerivedF , typename DerivedO >
IGL_INLINE void line_field_missmatch (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedV > &PD1, const bool isCombed, Eigen::PlainObjectBase< DerivedO > &missmatch)
 
IGL_INLINE double line_search (Eigen::MatrixXd &x, const Eigen::MatrixXd &d, double i_step_size, std::function< double(Eigen::MatrixXd &)> energy, double cur_energy=-1)
 
IGL_INLINE bool line_segment_in_rectangle (const Eigen::Vector2d &s, const Eigen::Vector2d &d, const Eigen::Vector2d &A, const Eigen::Vector2d &B)
 
IGL_INLINE bool linprog (const Eigen::VectorXd &c, const Eigen::MatrixXd &A, const Eigen::VectorXd &b, const int k, Eigen::VectorXd &f)
 
IGL_INLINE bool linprog (const Eigen::VectorXd &f, const Eigen::MatrixXd &A, const Eigen::VectorXd &b, const Eigen::MatrixXd &B, const Eigen::VectorXd &c, Eigen::VectorXd &x)
 
template<typename Derived >
Derived LinSpaced (typename Derived::Index size, const typename Derived::Scalar &low, const typename Derived::Scalar &high)
 
template<typename T , typename Derived >
IGL_INLINE bool list_to_matrix (const std::vector< std::vector< T > > &V, Eigen::PlainObjectBase< Derived > &M)
 
template<typename T , typename Derived >
IGL_INLINE bool list_to_matrix (const std::vector< std::vector< T > > &V, const int n, const T &padding, Eigen::PlainObjectBase< Derived > &M)
 
template<typename T , typename Derived >
IGL_INLINE bool list_to_matrix (const std::vector< T > &V, Eigen::PlainObjectBase< Derived > &M)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE void local_basis (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedV > &B1, Eigen::PlainObjectBase< DerivedV > &B2, Eigen::PlainObjectBase< DerivedV > &B3)
 
template<typename Derivedeye , typename Derivedcenter , typename Derivedup , typename DerivedR >
IGL_INLINE void look_at (const Eigen::PlainObjectBase< Derivedeye > &eye, const Eigen::PlainObjectBase< Derivedcenter > &center, const Eigen::PlainObjectBase< Derivedup > &up, Eigen::PlainObjectBase< DerivedR > &R)
 
template<typename DerivedF , typename SType , typename DerivedNF >
IGL_INLINE void loop (const int n_verts, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::SparseMatrix< SType > &S, Eigen::PlainObjectBase< DerivedNF > &NF)
 
template<typename DerivedV , typename DerivedF , typename DerivedNV , typename DerivedNF >
IGL_INLINE void loop (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedNV > &NV, Eigen::PlainObjectBase< DerivedNF > &NF, const int number_of_subdivs=1)
 
IGL_INLINE bool lscm (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const Eigen::VectorXi &b, const Eigen::MatrixXd &bc, Eigen::MatrixXd &V_uv)
 
IGL_INLINE void map_vertices_to_circle (const Eigen::MatrixXd &V, const Eigen::VectorXi &bnd, Eigen::MatrixXd &UV)
 
template<typename DerivedV , typename DerivedF , typename Scalar >
IGL_INLINE void massmatrix (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const MassMatrixType type, Eigen::SparseMatrix< Scalar > &M)
 
template<typename DerivedX , typename DerivedY , typename DerivedI >
IGL_INLINE void mat_max (const Eigen::DenseBase< DerivedX > &X, const int dim, Eigen::PlainObjectBase< DerivedY > &Y, Eigen::PlainObjectBase< DerivedI > &I)
 
template<typename DerivedX , typename DerivedY , typename DerivedI >
IGL_INLINE void mat_min (const Eigen::DenseBase< DerivedX > &X, const int dim, Eigen::PlainObjectBase< DerivedY > &Y, Eigen::PlainObjectBase< DerivedI > &I)
 
template<typename Q_type >
IGL_INLINE void mat4_to_quat (const Q_type *m, Q_type *q)
 
template<typename Q_type >
IGL_INLINE void mat3_to_quat (const Q_type *m, Q_type *q)
 
const Eigen::Vector4f MAYA_GREEN (128./255., 242./255., 0./255., 1.)
 
const Eigen::Vector4f MAYA_YELLOW (255./255., 247./255., 50./255., 1.)
 
const Eigen::Vector4f MAYA_RED (234./255., 63./255., 52./255., 1.)
 
const Eigen::Vector4f MAYA_BLUE (0./255., 73./255., 252./255., 1.)
 
const Eigen::Vector4f MAYA_PURPLE (180./255., 73./255., 200./255., 1.)
 
const Eigen::Vector4f MAYA_VIOLET (31./255., 15./255., 66./255., 1.)
 
const Eigen::Vector4f MAYA_GREY (0.5, 0.5, 0.5, 1.0)
 
const Eigen::Vector4f MAYA_CYAN (131./255., 219./255., 252./255., 1.)
 
const Eigen::Vector4f MAYA_SEA_GREEN (70./255., 252./255., 167./255., 1.)
 
template<typename DerivedM >
IGL_INLINE const Eigen::WithFormat< DerivedM > matlab_format (const Eigen::DenseBase< DerivedM > &M, const std::string name="")
 
template<typename DerivedS >
IGL_INLINE const std::string matlab_format (const Eigen::SparseMatrix< DerivedS > &S, const std::string name="")
 
IGL_INLINE const std::string matlab_format (const double v, const std::string name="")
 
IGL_INLINE const std::string matlab_format (const float v, const std::string name="")
 
IGL_INLINE Eigen::IOFormat matlab_format ()
 
template<typename DerivedM >
IGL_INLINE void matrix_to_list (const Eigen::DenseBase< DerivedM > &M, std::vector< std::vector< typename DerivedM::Scalar > > &V)
 
template<typename DerivedM >
IGL_INLINE void matrix_to_list (const Eigen::DenseBase< DerivedM > &M, std::vector< typename DerivedM::Scalar > &V)
 
template<typename DerivedM >
IGL_INLINE std::vector< typename DerivedM::Scalar > matrix_to_list (const Eigen::DenseBase< DerivedM > &M)
 
template<typename AType , typename DerivedB , typename DerivedI >
IGL_INLINE void max (const Eigen::SparseMatrix< AType > &A, const int dim, Eigen::PlainObjectBase< DerivedB > &B, Eigen::PlainObjectBase< DerivedI > &I)
 
IGL_INLINE void max_faces_stopping_condition (int &m, const int orig_m, const int max_m, std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int)> &stopping_condition)
 
IGL_INLINE std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int)> max_faces_stopping_condition (int &m, const int orign_m, const int max_m)
 
template<typename T >
IGL_INLINE int max_size (const std::vector< T > &V)
 
template<typename DerivedV , typename mType >
IGL_INLINE bool median (const Eigen::MatrixBase< DerivedV > &V, mType &m)
 
template<typename AType , typename DerivedB , typename DerivedI >
IGL_INLINE void min (const Eigen::SparseMatrix< AType > &A, const int dim, Eigen::PlainObjectBase< DerivedB > &B, Eigen::PlainObjectBase< DerivedI > &I)
 
template<typename T >
IGL_INLINE void min_quad_dense_precompute (const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &A, const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &Aeq, const bool use_lu_decomposition, Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &S)
 
template<typename T , typename Derivedknown >
IGL_INLINE bool min_quad_with_fixed_precompute (const Eigen::SparseMatrix< T > &A, const Eigen::MatrixBase< Derivedknown > &known, const Eigen::SparseMatrix< T > &Aeq, const bool pd, min_quad_with_fixed_data< T > &data)
 
template<typename T , typename DerivedB , typename DerivedY , typename DerivedBeq , typename DerivedZ , typename Derivedsol >
IGL_INLINE bool min_quad_with_fixed_solve (const min_quad_with_fixed_data< T > &data, const Eigen::MatrixBase< DerivedB > &B, const Eigen::MatrixBase< DerivedY > &Y, const Eigen::MatrixBase< DerivedBeq > &Beq, Eigen::PlainObjectBase< DerivedZ > &Z, Eigen::PlainObjectBase< Derivedsol > &sol)
 
template<typename T , typename DerivedB , typename DerivedY , typename DerivedBeq , typename DerivedZ >
IGL_INLINE bool min_quad_with_fixed_solve (const min_quad_with_fixed_data< T > &data, const Eigen::MatrixBase< DerivedB > &B, const Eigen::MatrixBase< DerivedY > &Y, const Eigen::MatrixBase< DerivedBeq > &Beq, Eigen::PlainObjectBase< DerivedZ > &Z)
 
template<typename T , typename Derivedknown , typename DerivedB , typename DerivedY , typename DerivedBeq , typename DerivedZ >
IGL_INLINE bool min_quad_with_fixed (const Eigen::SparseMatrix< T > &A, const Eigen::MatrixBase< DerivedB > &B, const Eigen::MatrixBase< Derivedknown > &known, const Eigen::MatrixBase< DerivedY > &Y, const Eigen::SparseMatrix< T > &Aeq, const Eigen::MatrixBase< DerivedBeq > &Beq, const bool pd, Eigen::PlainObjectBase< DerivedZ > &Z)
 
template<typename T >
IGL_INLINE int min_size (const std::vector< T > &V)
 
template<typename DerivedA , typename DerivedB >
IGL_INLINE void mod (const Eigen::PlainObjectBase< DerivedA > &A, const int base, Eigen::PlainObjectBase< DerivedB > &B)
 
template<typename DerivedA >
IGL_INLINE DerivedA mod (const Eigen::PlainObjectBase< DerivedA > &A, const int base)
 
template<typename T >
IGL_INLINE void mode (const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &X, const int d, Eigen::Matrix< T, Eigen::Dynamic, 1 > &M)
 
IGL_INLINE void mvc (const Eigen::MatrixXd &V, const Eigen::MatrixXd &C, Eigen::MatrixXd &W)
 
IGL_INLINE double nchoosek (const int n, const int k)
 
template<typename DerivedV , typename DerivedU >
IGL_INLINE void nchoosek (const Eigen::MatrixBase< DerivedV > &V, const int k, Eigen::PlainObjectBase< DerivedU > &U)
 
IGL_INLINE bool next_filename (const std::string &prefix, const int zeros, const std::string &suffix, std::string &next)
 
template<typename DerivedV , typename DerivedEle , typename Scalar >
IGL_INLINE void normal_derivative (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedEle > &Ele, Eigen::SparseMatrix< Scalar > &DD)
 
template<typename Q_type >
IGL_INLINE bool normalize_quat (const Q_type *q, Q_type *out)
 
template<typename DerivedV >
IGL_INLINE void normalize_row_lengths (const Eigen::PlainObjectBase< DerivedV > &A, Eigen::PlainObjectBase< DerivedV > &B)
 
template<typename DerivedA , typename DerivedB >
IGL_INLINE void normalize_row_sums (const Eigen::MatrixBase< DerivedA > &A, Eigen::MatrixBase< DerivedB > &B)
 
template<typename DerivedA , typename DerivedN >
IGL_INLINE void null (const Eigen::PlainObjectBase< DerivedA > &A, Eigen::PlainObjectBase< DerivedN > &N)
 
template<typename DerivedP , typename IndexType , typename DerivedCH , typename DerivedCN , typename DerivedW >
IGL_INLINE void octree (const Eigen::MatrixBase< DerivedP > &P, std::vector< std::vector< IndexType > > &point_indices, Eigen::PlainObjectBase< DerivedCH > &CH, Eigen::PlainObjectBase< DerivedCN > &CN, Eigen::PlainObjectBase< DerivedW > &W)
 
template<typename IntegerT >
IGL_INLINE void on_boundary (const std::vector< std::vector< IntegerT > > &T, std::vector< bool > &I, std::vector< std::vector< bool > > &C)
 
template<typename DerivedT , typename DerivedI , typename DerivedC >
IGL_INLINE void on_boundary (const Eigen::MatrixBase< DerivedT > &T, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedC > &C)
 
template<typename DerivedV , typename DerivedF , typename DerivedC , typename DerivedFF , typename DerivedI >
IGL_INLINE void orient_outward (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedFF > &FF, Eigen::PlainObjectBase< DerivedI > &I)
 
template<typename DerivedF , typename DerivedC , typename AScalar >
IGL_INLINE void orientable_patches (const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedC > &C, Eigen::SparseMatrix< AScalar > &A)
 
template<typename DerivedF , typename DerivedC >
IGL_INLINE void orientable_patches (const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedC > &C)
 
template<typename DerivedF , typename DerivedE >
IGL_INLINE void oriented_facets (const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedE > &E)
 
IGL_INLINE void orth (const Eigen::MatrixXd &A, Eigen::MatrixXd &Q)
 
template<typename DerivedP >
IGL_INLINE void ortho (const typename DerivedP::Scalar left, const typename DerivedP::Scalar right, const typename DerivedP::Scalar bottom, const typename DerivedP::Scalar top, const typename DerivedP::Scalar nearVal, const typename DerivedP::Scalar farVal, Eigen::PlainObjectBase< DerivedP > &P)
 
template<typename DerivedV , typename DerivedF , typename DerivedI , typename IndexType , typename DerivedA >
IGL_INLINE void outer_vertex (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedI > &I, IndexType &v_index, Eigen::PlainObjectBase< DerivedA > &A)
 
template<typename DerivedV , typename DerivedF , typename DerivedI , typename IndexType , typename DerivedA >
IGL_INLINE void outer_edge (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedI > &I, IndexType &v1, IndexType &v2, Eigen::PlainObjectBase< DerivedA > &A)
 
template<typename DerivedV , typename DerivedF , typename DerivedN , typename DerivedI , typename IndexType >
IGL_INLINE void outer_facet (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedN > &N, const Eigen::PlainObjectBase< DerivedI > &I, IndexType &f, bool &flipped)
 
template<typename Index , typename FunctionType >
bool parallel_for (const Index loop_size, const FunctionType &func, const size_t min_parallel=0)
 
template<typename Index , typename PrepFunctionType , typename FunctionType , typename AccumFunctionType >
bool parallel_for (const Index loop_size, const PrepFunctionType &prep_func, const FunctionType &func, const AccumFunctionType &accum_func, const size_t min_parallel=0)
 
template<typename DerivedV , typename DerivedF , typename DerivedK >
IGL_INLINE void parallel_transport_angles (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedV > &FN, const Eigen::MatrixXi &E2F, const Eigen::MatrixXi &F2E, Eigen::PlainObjectBase< DerivedK > &K)
 
IGL_INLINE void partition (const Eigen::MatrixXd &W, const int k, Eigen::Matrix< int, Eigen::Dynamic, 1 > &G, Eigen::Matrix< int, Eigen::Dynamic, 1 > &S, Eigen::Matrix< double, Eigen::Dynamic, 1 > &D)
 
template<typename T >
IGL_INLINE void parula (const T f, T *rgb)
 
template<typename T >
IGL_INLINE void parula (const T f, T &r, T &g, T &b)
 
template<typename DerivedZ , typename DerivedC >
IGL_INLINE void parula (const Eigen::MatrixBase< DerivedZ > &Z, const bool normalize, Eigen::PlainObjectBase< DerivedC > &C)
 
template<typename DerivedZ , typename DerivedC >
IGL_INLINE void parula (const Eigen::MatrixBase< DerivedZ > &Z, const double min_Z, const double max_Z, Eigen::PlainObjectBase< DerivedC > &C)
 
IGL_INLINE std::string path_to_executable ()
 
IGL_INLINE void pathinfo (const std::string &path, std::string &dirname, std::string &basename, std::string &extension, std::string &filename)
 
template<typename DerivedV , typename DerivedF , typename DerivedCN >
IGL_INLINE void per_corner_normals (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const double corner_threshold, Eigen::PlainObjectBase< DerivedCN > &CN)
 
template<typename DerivedV , typename DerivedF , typename DerivedFN , typename DerivedCN >
IGL_INLINE void per_corner_normals (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedFN > &FN, const double corner_threshold, Eigen::PlainObjectBase< DerivedCN > &CN)
 
template<typename DerivedV , typename DerivedF , typename DerivedFN , typename IndexType , typename DerivedCN >
IGL_INLINE void per_corner_normals (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedFN > &FN, const std::vector< std::vector< IndexType > > &VF, const double corner_threshold, Eigen::PlainObjectBase< DerivedCN > &CN)
 
template<typename DerivedV , typename DerivedF , typename DerivedFN , typename DerivedN , typename DerivedE , typename DerivedEMAP >
IGL_INLINE void per_edge_normals (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const PerEdgeNormalsWeightingType weight, const Eigen::MatrixBase< DerivedFN > &FN, Eigen::PlainObjectBase< DerivedN > &N, Eigen::PlainObjectBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedEMAP > &EMAP)
 
template<typename DerivedV , typename DerivedF , typename DerivedN , typename DerivedE , typename DerivedEMAP >
IGL_INLINE void per_edge_normals (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const PerEdgeNormalsWeightingType weight, Eigen::PlainObjectBase< DerivedN > &N, Eigen::PlainObjectBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedEMAP > &EMAP)
 
template<typename DerivedV , typename DerivedF , typename DerivedN , typename DerivedE , typename DerivedEMAP >
IGL_INLINE void per_edge_normals (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedN > &N, Eigen::PlainObjectBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedEMAP > &EMAP)
 
template<typename DerivedV , typename DerivedF , typename DerivedZ , typename DerivedN >
IGL_INLINE void per_face_normals (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedZ > &Z, Eigen::PlainObjectBase< DerivedN > &N)
 
template<typename DerivedV , typename DerivedF , typename DerivedN >
IGL_INLINE void per_face_normals (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedN > &N)
 
template<typename DerivedV , typename DerivedF , typename DerivedN >
IGL_INLINE void per_face_normals_stable (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedN > &N)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE void per_vertex_attribute_smoothing (const Eigen::PlainObjectBase< DerivedV > &Ain, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedV > &Aout)
 
template<typename DerivedV , typename DerivedF , typename DerivedN >
IGL_INLINE void per_vertex_normals (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const igl::PerVertexNormalsWeightingType weighting, Eigen::PlainObjectBase< DerivedN > &N)
 
template<typename DerivedV , typename DerivedF , typename DerivedN >
IGL_INLINE void per_vertex_normals (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedN > &N)
 
template<typename DerivedV , typename DerivedF , typename DerivedFN , typename DerivedN >
IGL_INLINE void per_vertex_normals (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const PerVertexNormalsWeightingType weighting, const Eigen::MatrixBase< DerivedFN > &FN, Eigen::PlainObjectBase< DerivedN > &N)
 
template<typename DerivedV , typename DerivedF , typename DerivedFN , typename DerivedN >
IGL_INLINE void per_vertex_normals (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedFN > &FN, Eigen::PlainObjectBase< DerivedN > &N)
 
IGL_INLINE void per_vertex_point_to_plane_quadrics (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const Eigen::MatrixXi &EMAP, const Eigen::MatrixXi &EF, const Eigen::MatrixXi &EI, std::vector< std::tuple< Eigen::MatrixXd, Eigen::RowVectorXd, double > > &quadrics)
 
template<typename DerivedF , typename DeriveduE , typename uE2EType >
IGL_INLINE bool piecewise_constant_winding_number (const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DeriveduE > &uE, const std::vector< std::vector< uE2EType > > &uE2E)
 
template<typename DerivedF >
IGL_INLINE bool piecewise_constant_winding_number (const Eigen::MatrixBase< DerivedF > &F)
 
template<typename DerivedA , typename DerivedX >
void pinv (const Eigen::MatrixBase< DerivedA > &A, typename DerivedA::Scalar tol, Eigen::PlainObjectBase< DerivedX > &X)
 
template<typename DerivedA , typename DerivedX >
void pinv (const Eigen::MatrixBase< DerivedA > &A, Eigen::PlainObjectBase< DerivedX > &X)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE void planarize_quad_mesh (const Eigen::PlainObjectBase< DerivedV > &Vin, const Eigen::PlainObjectBase< DerivedF > &F, const int maxIter, const double &threshold, Eigen::PlainObjectBase< DerivedV > &Vout)
 
IGL_INLINE bool point_in_circle (const double qx, const double qy, const double cx, const double cy, const double r)
 
bool IGL_INLINE point_in_poly (const std::vector< std::vector< unsigned int > > &poly, const unsigned int xt, const unsigned int yt)
 
template<typename DerivedP , typename DerivedV , typename DerivedsqrD , typename DerivedI , typename DerivedC >
IGL_INLINE void point_mesh_squared_distance (const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::MatrixXi &Ele, Eigen::PlainObjectBase< DerivedsqrD > &sqrD, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedC > &C)
 
template<>
IGL_INLINE void point_simplex_squared_distance< 2 > (Eigen::MatrixBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > const &, Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 0, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< int, -1, 3, 0, -1, 3 > > const &, Eigen::Matrix< int, -1, 3, 0, -1, 3 >::Index, float &, Eigen::MatrixBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > &)
 
template<>
IGL_INLINE void point_simplex_squared_distance< 2 > (Eigen::MatrixBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > const &, Eigen::MatrixBase< Eigen::Matrix< double, -1, 3, 0, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< int, -1, 3, 0, -1, 3 > > const &, Eigen::Matrix< int, -1, 3, 0, -1, 3 >::Index, double &, Eigen::MatrixBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > &)
 
template<>
IGL_INLINE void point_simplex_squared_distance< 2 > (Eigen::MatrixBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > const &, Eigen::MatrixBase< Eigen::Matrix< double, -1, 3, 1, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< int, -1, 3, 1, -1, 3 > > const &, Eigen::Matrix< int, -1, 3, 1, -1, 3 >::Index, double &, Eigen::MatrixBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > &)
 
template<int DIM, typename Derivedp , typename DerivedV , typename DerivedEle , typename Derivedsqr_d , typename Derivedc >
IGL_INLINE void point_simplex_squared_distance (const Eigen::MatrixBase< Derivedp > &p, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedEle > &Ele, const typename DerivedEle::Index i, Derivedsqr_d &sqr_d, Eigen::MatrixBase< Derivedc > &c)
 
template<int DIM, typename Derivedp , typename DerivedV , typename DerivedEle , typename Derivedsqr_d , typename Derivedc , typename Derivedb >
IGL_INLINE void point_simplex_squared_distance (const Eigen::MatrixBase< Derivedp > &p, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedEle > &Ele, const typename DerivedEle::Index i, Derivedsqr_d &sqr_d, Eigen::MatrixBase< Derivedc > &c, Eigen::PlainObjectBase< Derivedb > &b)
 
template<typename DerivedA , typename DerivedR , typename DerivedT , typename DerivedU , typename DerivedS , typename DerivedV >
IGL_INLINE void polar_dec (const Eigen::PlainObjectBase< DerivedA > &A, Eigen::PlainObjectBase< DerivedR > &R, Eigen::PlainObjectBase< DerivedT > &T, Eigen::PlainObjectBase< DerivedU > &U, Eigen::PlainObjectBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedV > &V)
 
template<typename DerivedA , typename DerivedR , typename DerivedT >
IGL_INLINE void polar_dec (const Eigen::PlainObjectBase< DerivedA > &A, Eigen::PlainObjectBase< DerivedR > &R, Eigen::PlainObjectBase< DerivedT > &T)
 
template<typename DerivedA , typename DerivedR , typename DerivedT , typename DerivedU , typename DerivedS , typename DerivedV >
IGL_INLINE void polar_svd (const Eigen::PlainObjectBase< DerivedA > &A, Eigen::PlainObjectBase< DerivedR > &R, Eigen::PlainObjectBase< DerivedT > &T, Eigen::PlainObjectBase< DerivedU > &U, Eigen::PlainObjectBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedV > &V)
 
template<typename DerivedA , typename DerivedR , typename DerivedT >
IGL_INLINE void polar_svd (const Eigen::PlainObjectBase< DerivedA > &A, Eigen::PlainObjectBase< DerivedR > &R, Eigen::PlainObjectBase< DerivedT > &T)
 
template<typename Mat >
IGL_INLINE void polar_svd3x3 (const Mat &A, Mat &R)
 
template<typename Index , typename DerivedF >
IGL_INLINE void polygon_mesh_to_triangle_mesh (const std::vector< std::vector< Index > > &vF, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename DerivedP , typename DerivedF >
IGL_INLINE void polygon_mesh_to_triangle_mesh (const Eigen::PlainObjectBase< DerivedP > &P, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename DerivedV , typename DerivedF , typename DerivedPD1 , typename DerivedPD2 , typename DerivedPV1 , typename DerivedPV2 >
IGL_INLINE void principal_curvature (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedPD1 > &PD1, Eigen::PlainObjectBase< DerivedPD2 > &PD2, Eigen::PlainObjectBase< DerivedPV1 > &PV1, Eigen::PlainObjectBase< DerivedPV2 > &PV2, unsigned radius=5, bool useKring=true)
 
template<typename T >
IGL_INLINE void print_ijv (const Eigen::SparseMatrix< T > &X, const int offset=0)
 
template<typename T >
IGL_INLINE void print_vector (std::vector< T > &v)
 
template<typename T >
IGL_INLINE void print_vector (std::vector< std::vector< T > > &v)
 
template<typename T >
IGL_INLINE void print_vector (std::vector< std::vector< std::vector< T > > > &v)
 
template<typename DerivedX , typename DerivedY , typename Scalar , typename DerivedR , typename DerivedT >
IGL_INLINE void procrustes (const Eigen::PlainObjectBase< DerivedX > &X, const Eigen::PlainObjectBase< DerivedY > &Y, bool includeScaling, bool includeReflections, Scalar &scale, Eigen::PlainObjectBase< DerivedR > &R, Eigen::PlainObjectBase< DerivedT > &t)
 
template<typename DerivedX , typename DerivedY , typename Scalar , int DIM, int TType>
IGL_INLINE void procrustes (const Eigen::PlainObjectBase< DerivedX > &X, const Eigen::PlainObjectBase< DerivedY > &Y, bool includeScaling, bool includeReflections, Eigen::Transform< Scalar, DIM, TType > &T)
 
template<typename DerivedX , typename DerivedY , typename DerivedR , typename DerivedT >
IGL_INLINE void procrustes (const Eigen::PlainObjectBase< DerivedX > &X, const Eigen::PlainObjectBase< DerivedY > &Y, bool includeScaling, bool includeReflections, Eigen::PlainObjectBase< DerivedR > &S, Eigen::PlainObjectBase< DerivedT > &t)
 
template<typename DerivedX , typename DerivedY , typename DerivedR , typename DerivedT >
IGL_INLINE void procrustes (const Eigen::PlainObjectBase< DerivedX > &X, const Eigen::PlainObjectBase< DerivedY > &Y, Eigen::PlainObjectBase< DerivedR > &R, Eigen::PlainObjectBase< DerivedT > &t)
 
template<typename DerivedX , typename DerivedY , typename Scalar , typename DerivedT >
IGL_INLINE void procrustes (const Eigen::PlainObjectBase< DerivedX > &X, const Eigen::PlainObjectBase< DerivedY > &Y, Eigen::Rotation2D< Scalar > &R, Eigen::PlainObjectBase< DerivedT > &t)
 
template<typename Scalar >
IGL_INLINE Eigen::Matrix< Scalar, 3, 1 > project (const Eigen::Matrix< Scalar, 3, 1 > &obj, const Eigen::Matrix< Scalar, 4, 4 > &model, const Eigen::Matrix< Scalar, 4, 4 > &proj, const Eigen::Matrix< Scalar, 4, 1 > &viewport)
 
template<typename DerivedV , typename DerivedM , typename DerivedN , typename DerivedO , typename DerivedP >
IGL_INLINE void project (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::MatrixBase< DerivedM > &model, const Eigen::MatrixBase< DerivedN > &proj, const Eigen::MatrixBase< DerivedO > &viewport, Eigen::PlainObjectBase< DerivedP > &P)
 
template<typename DerivedV , typename DerivedF , typename DerivedU , typename DerivedUF , typename Scalar >
IGL_INLINE void project_isometrically_to_plane (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedU > &U, Eigen::PlainObjectBase< DerivedUF > &UF, Eigen::SparseMatrix< Scalar > &I)
 
template<typename DerivedP , typename DerivedS , typename DerivedD , typename Derivedt , typename DerivedsqrD >
IGL_INLINE void project_to_line (const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedS > &S, const Eigen::MatrixBase< DerivedD > &D, Eigen::PlainObjectBase< Derivedt > &t, Eigen::PlainObjectBase< DerivedsqrD > &sqrD)
 
template<typename Scalar >
IGL_INLINE void project_to_line (const Scalar px, const Scalar py, const Scalar pz, const Scalar sx, const Scalar sy, const Scalar sz, const Scalar dx, const Scalar dy, const Scalar dz, Scalar &projpx, Scalar &projpy, Scalar &projpz, Scalar &t, Scalar &sqrd)
 
template<typename Scalar >
IGL_INLINE void project_to_line (const Scalar px, const Scalar py, const Scalar pz, const Scalar sx, const Scalar sy, const Scalar sz, const Scalar dx, const Scalar dy, const Scalar dz, Scalar &t, Scalar &sqrd)
 
template<typename DerivedP , typename DerivedS , typename DerivedD , typename Derivedt , typename DerivedsqrD >
IGL_INLINE void project_to_line_segment (const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedS > &S, const Eigen::MatrixBase< DerivedD > &D, Eigen::PlainObjectBase< Derivedt > &t, Eigen::PlainObjectBase< DerivedsqrD > &sqrD)
 
template<>
IGL_INLINE void pseudonormal_test (Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 1, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< int, -1, 3, 1, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 0, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 0, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > const &, int, Eigen::PlainObjectBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > &, float &, Eigen::PlainObjectBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > &)
 
template<>
IGL_INLINE void pseudonormal_test (Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 1, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< int, -1, 2, 0, -1, 2 > > const &, Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 0, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 0, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > const &, int, Eigen::PlainObjectBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > &, float &, Eigen::PlainObjectBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > &)
 
template<>
IGL_INLINE void pseudonormal_test (Eigen::MatrixBase< Eigen::Matrix< double, -1, 3, 1, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< int, -1, 3, 1, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< double, -1, 3, 0, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< double, -1, 3, 0, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > const &, int, Eigen::PlainObjectBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > &, double &, Eigen::PlainObjectBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > &)
 
template<>
IGL_INLINE void pseudonormal_test (Eigen::MatrixBase< Eigen::Matrix< double, -1, 3, 1, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< int, -1, 2, 0, -1, 2 > > const &, Eigen::MatrixBase< Eigen::Matrix< double, -1, 3, 0, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< double, -1, 3, 0, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > const &, int, Eigen::PlainObjectBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > &, double &, Eigen::PlainObjectBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > &)
 
template<>
IGL_INLINE void pseudonormal_test (Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 0, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< int, -1, 2, 0, -1, 2 > > const &, Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 0, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 0, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > const &, int, Eigen::PlainObjectBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > &, float &, Eigen::PlainObjectBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > &)
 
template<typename DerivedV , typename DerivedF , typename DerivedFN , typename DerivedVN , typename DerivedEN , typename DerivedEMAP , typename Derivedq , typename Derivedc , typename Scalar , typename Derivedn >
IGL_INLINE void pseudonormal_test (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedFN > &FN, const Eigen::MatrixBase< DerivedVN > &VN, const Eigen::MatrixBase< DerivedEN > &EN, const Eigen::MatrixBase< DerivedEMAP > &EMAP, const Eigen::MatrixBase< Derivedq > &q, const int f, Eigen::PlainObjectBase< Derivedc > &c, Scalar &s, Eigen::PlainObjectBase< Derivedn > &n)
 
template<typename DerivedV , typename DerivedF , typename DerivedEN , typename DerivedVN , typename Derivedq , typename Derivedc , typename Scalar , typename Derivedn >
IGL_INLINE void pseudonormal_test (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &E, const Eigen::MatrixBase< DerivedEN > &EN, const Eigen::MatrixBase< DerivedVN > &VN, const Eigen::MatrixBase< Derivedq > &q, const int e, Eigen::PlainObjectBase< Derivedc > &c, Scalar &s, Eigen::PlainObjectBase< Derivedn > &n)
 
template<typename Scalar , typename DerivedX , typename DerivedLB , typename DerivedUB >
IGL_INLINE Scalar pso (const std::function< Scalar(DerivedX &) > f, const Eigen::MatrixBase< DerivedLB > &LB, const Eigen::MatrixBase< DerivedUB > &UB, const int max_iters, const int population, DerivedX &X)
 
template<typename Scalar , typename DerivedX , typename DerivedLB , typename DerivedUB , typename DerivedP >
IGL_INLINE Scalar pso (const std::function< Scalar(DerivedX &) > f, const Eigen::MatrixBase< DerivedLB > &LB, const Eigen::MatrixBase< DerivedUB > &UB, const Eigen::DenseBase< DerivedP > &P, const int max_iters, const int population, DerivedX &X)
 
IGL_INLINE bool qslim (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const size_t max_m, Eigen::MatrixXd &U, Eigen::MatrixXi &G, Eigen::VectorXi &J, Eigen::VectorXi &I)
 
IGL_INLINE void qslim_optimal_collapse_edge_callbacks (Eigen::MatrixXi &E, std::vector< std::tuple< Eigen::MatrixXd, Eigen::RowVectorXd, double > > &quadrics, int &v1, int &v2, std::function< void(const int e, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> &cost_and_placement, std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int)> &pre_collapse, std::function< void(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int, const bool)> &post_collapse)
 
template<typename DerivedV , typename DerivedF , typename DerivedP >
IGL_INLINE void quad_planarity (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedP > &P)
 
IGL_INLINE std::tuple< Eigen::MatrixXd, Eigen::RowVectorXd, double > operator+ (const std::tuple< Eigen::MatrixXd, Eigen::RowVectorXd, double > &a, const std::tuple< Eigen::MatrixXd, Eigen::RowVectorXd, double > &b)
 
template<typename Q_type >
IGL_INLINE void quat_conjugate (const Q_type *q1, Q_type *out)
 
template<typename Q_type >
IGL_INLINE void quat_mult (const Q_type *q1, const Q_type *q2, Q_type *out)
 
template<typename Q_type >
IGL_INLINE void quat_to_axis_angle (const Q_type *q, Q_type *axis, Q_type &angle)
 
template<typename Q_type >
IGL_INLINE void quat_to_axis_angle_deg (const Q_type *q, Q_type *axis, Q_type &angle)
 
template<typename Q_type >
IGL_INLINE void quat_to_mat (const Q_type *quat, Q_type *mat)
 
IGL_INLINE void quats_to_column (const std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > vQ, Eigen::VectorXd &Q)
 
IGL_INLINE Eigen::VectorXd quats_to_column (const std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > vQ)
 
template<typename DerivedP , typename DerivedS , typename DerivedJ >
IGL_INLINE void ramer_douglas_peucker (const Eigen::MatrixBase< DerivedP > &P, const typename DerivedP::Scalar tol, Eigen::PlainObjectBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<typename DerivedP , typename DerivedS , typename DerivedJ , typename DerivedQ >
IGL_INLINE void ramer_douglas_peucker (const Eigen::MatrixBase< DerivedP > &P, const typename DerivedP::Scalar tol, Eigen::PlainObjectBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::PlainObjectBase< DerivedQ > &Q)
 
IGL_INLINE Eigen::Vector3d random_dir ()
 
IGL_INLINE Eigen::MatrixXd random_dir_stratified (const int n)
 
template<typename DerivedV , typename DerivedF , typename DerivedB , typename DerivedFI >
IGL_INLINE void random_points_on_mesh (const int n, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedB > &B, Eigen::PlainObjectBase< DerivedFI > &FI)
 
template<typename DerivedV , typename DerivedF , typename ScalarB , typename DerivedFI >
IGL_INLINE void random_points_on_mesh (const int n, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::SparseMatrix< ScalarB > &B, Eigen::PlainObjectBase< DerivedFI > &FI)
 
template<typename Scalar >
IGL_INLINE Eigen::Quaternion< Scalar > random_quaternion ()
 
template<typename Scalar , typename DerivedX , typename DerivedLB , typename DerivedUB >
IGL_INLINE Scalar random_search (const std::function< Scalar(DerivedX &) > f, const Eigen::MatrixBase< DerivedLB > &LB, const Eigen::MatrixBase< DerivedUB > &UB, const int iters, DerivedX &X)
 
template<typename DerivedI >
IGL_INLINE void randperm (const int n, Eigen::PlainObjectBase< DerivedI > &I)
 
template<typename Derivedsource , typename Deriveddir , typename Scalar >
IGL_INLINE bool ray_box_intersect (const Eigen::MatrixBase< Derivedsource > &source, const Eigen::MatrixBase< Deriveddir > &dir, const Eigen::AlignedBox< Scalar, 3 > &box, const Scalar &t0, const Scalar &t1, Scalar &tmin, Scalar &tmax)
 
template<typename Derivedsource , typename Deriveddir , typename DerivedV , typename DerivedF >
IGL_INLINE bool ray_mesh_intersect (const Eigen::MatrixBase< Derivedsource > &source, const Eigen::MatrixBase< Deriveddir > &dir, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, std::vector< igl::Hit > &hits)
 
template<typename Derivedsource , typename Deriveddir , typename DerivedV , typename DerivedF >
IGL_INLINE bool ray_mesh_intersect (const Eigen::MatrixBase< Derivedsource > &source, const Eigen::MatrixBase< Deriveddir > &dir, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, igl::Hit &hit)
 
template<typename Derivedo , typename Derivedd , typename Derivedc , typename r_type , typename t_type >
IGL_INLINE int ray_sphere_intersect (const Eigen::PlainObjectBase< Derivedo > &o, const Eigen::PlainObjectBase< Derivedd > &d, const Eigen::PlainObjectBase< Derivedc > &c, r_type r, t_type &t0, t_type &t1)
 
template<typename Scalar , typename Index >
IGL_INLINE bool read_triangle_mesh (const std::string str, std::vector< std::vector< Scalar > > &V, std::vector< std::vector< Index > > &F)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE bool read_triangle_mesh (const std::string str, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE bool read_triangle_mesh (const std::string str, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F, std::string &dir, std::string &base, std::string &ext, std::string &name)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE bool read_triangle_mesh (const std::string &ext, FILE *fp, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename DerivedWI , typename DerivedP , typename DerivedO >
IGL_INLINE bool readBF (const std::string &filename, Eigen::PlainObjectBase< DerivedWI > &WI, Eigen::PlainObjectBase< DerivedP > &P, Eigen::PlainObjectBase< DerivedO > &O)
 
template<typename DerivedWI , typename DerivedbfP , typename DerivedO , typename DerivedC , typename DerivedBE , typename DerivedP >
IGL_INLINE bool readBF (const std::string &filename, Eigen::PlainObjectBase< DerivedWI > &WI, Eigen::PlainObjectBase< DerivedbfP > &bfP, Eigen::PlainObjectBase< DerivedO > &O, Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedBE > &BE, Eigen::PlainObjectBase< DerivedP > &P)
 
template<typename Scalar >
IGL_INLINE bool readCSV (const std::string str, Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > &M)
 
template<typename DerivedW >
IGL_INLINE bool readDMAT (const std::string file_name, Eigen::PlainObjectBase< DerivedW > &W)
 
template<typename Scalar >
IGL_INLINE bool readDMAT (const std::string file_name, std::vector< std::vector< Scalar > > &W)
 
template<typename Scalar , typename Index >
IGL_INLINE bool readMESH (const std::string mesh_file_name, std::vector< std::vector< Scalar > > &V, std::vector< std::vector< Index > > &T, std::vector< std::vector< Index > > &F)
 
template<typename Scalar , typename Index >
IGL_INLINE bool readMESH (FILE *mesh_file, std::vector< std::vector< Scalar > > &V, std::vector< std::vector< Index > > &T, std::vector< std::vector< Index > > &F)
 
template<typename DerivedV , typename DerivedF , typename DerivedT >
IGL_INLINE bool readMESH (const std::string mesh_file_name, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedT > &T, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename DerivedV , typename DerivedF , typename DerivedT >
IGL_INLINE bool readMESH (FILE *mesh_file, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedT > &T, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename DerivedV , typename DerivedT >
IGL_INLINE bool readMSH (const std::string &filename, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedT > &T)
 
template<typename Scalar , typename Index >
IGL_INLINE bool readNODE (const std::string node_file_name, std::vector< std::vector< Scalar > > &V, std::vector< std::vector< Index > > &I)
 
template<typename DerivedV , typename DerivedI >
IGL_INLINE bool readNODE (const std::string node_file_name, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedI > &I)
 
template<typename Scalar , typename Index >
IGL_INLINE bool readOBJ (const std::string obj_file_name, std::vector< std::vector< Scalar > > &V, std::vector< std::vector< Scalar > > &TC, std::vector< std::vector< Scalar > > &N, std::vector< std::vector< Index > > &F, std::vector< std::vector< Index > > &FTC, std::vector< std::vector< Index > > &FN)
 
template<typename Scalar , typename Index >
IGL_INLINE bool readOBJ (FILE *obj_file, std::vector< std::vector< Scalar > > &V, std::vector< std::vector< Scalar > > &TC, std::vector< std::vector< Scalar > > &N, std::vector< std::vector< Index > > &F, std::vector< std::vector< Index > > &FTC, std::vector< std::vector< Index > > &FN)
 
template<typename Scalar , typename Index >
IGL_INLINE bool readOBJ (const std::string obj_file_name, std::vector< std::vector< Scalar > > &V, std::vector< std::vector< Index > > &F)
 
template<typename DerivedV , typename DerivedTC , typename DerivedCN , typename DerivedF , typename DerivedFTC , typename DerivedFN >
IGL_INLINE bool readOBJ (const std::string str, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedTC > &TC, Eigen::PlainObjectBase< DerivedCN > &CN, Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedFTC > &FTC, Eigen::PlainObjectBase< DerivedFN > &FN)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE bool readOBJ (const std::string str, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename Scalar , typename Index >
IGL_INLINE bool readOFF (const std::string off_file_name, std::vector< std::vector< Scalar > > &V, std::vector< std::vector< Index > > &F, std::vector< std::vector< Scalar > > &N, std::vector< std::vector< Scalar > > &C)
 
template<typename Scalar , typename Index >
IGL_INLINE bool readOFF (FILE *off_file, std::vector< std::vector< Scalar > > &V, std::vector< std::vector< Index > > &F, std::vector< std::vector< Scalar > > &N, std::vector< std::vector< Scalar > > &C)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE bool readOFF (const std::string str, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE bool readOFF (const std::string str, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedV > &N)
 
template<typename Vtype , typename Ftype , typename Ntype , typename UVtype >
IGL_INLINE bool readPLY (const std::string filename, std::vector< std::vector< Vtype > > &V, std::vector< std::vector< Ftype > > &F, std::vector< std::vector< Ntype > > &N, std::vector< std::vector< UVtype > > &UV)
 
template<typename Vtype , typename Ftype , typename Ntype , typename UVtype >
IGL_INLINE bool readPLY (FILE *ply_file, std::vector< std::vector< Vtype > > &V, std::vector< std::vector< Ftype > > &F, std::vector< std::vector< Ntype > > &N, std::vector< std::vector< UVtype > > &UV)
 
template<typename DerivedV , typename DerivedF , typename DerivedN , typename DerivedUV >
IGL_INLINE bool readPLY (const std::string filename, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedN > &N, Eigen::PlainObjectBase< DerivedUV > &UV)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE bool readPLY (const std::string filename, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename DerivedV , typename DerivedF , typename DerivedN >
IGL_INLINE bool readSTL (const std::string &filename, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedN > &N)
 
template<typename TypeV , typename TypeF , typename TypeN >
IGL_INLINE bool readSTL (FILE *stl_file, std::vector< std::vector< TypeV > > &V, std::vector< std::vector< TypeF > > &F, std::vector< std::vector< TypeN > > &N)
 
template<typename TypeV , typename TypeF , typename TypeN >
IGL_INLINE bool readSTL (const std::string &filename, std::vector< std::vector< TypeV > > &V, std::vector< std::vector< TypeF > > &F, std::vector< std::vector< TypeN > > &N)
 
IGL_INLINE bool readTGF (const std::string tgf_filename, std::vector< std::vector< double > > &C, std::vector< std::vector< int > > &E, std::vector< int > &P, std::vector< std::vector< int > > &BE, std::vector< std::vector< int > > &CE, std::vector< std::vector< int > > &PE)
 
IGL_INLINE bool readTGF (const std::string tgf_filename, Eigen::MatrixXd &C, Eigen::MatrixXi &E, Eigen::VectorXi &P, Eigen::MatrixXi &BE, Eigen::MatrixXi &CE, Eigen::MatrixXi &PE)
 
IGL_INLINE bool readTGF (const std::string tgf_filename, Eigen::MatrixXd &C, Eigen::MatrixXi &E)
 
template<typename Scalar , typename Index >
IGL_INLINE bool readWRL (const std::string wrl_file_name, std::vector< std::vector< Scalar > > &V, std::vector< std::vector< Index > > &F)
 
template<typename Scalar , typename Index >
IGL_INLINE bool readWRL (FILE *wrl_file, std::vector< std::vector< Scalar > > &V, std::vector< std::vector< Index > > &F)
 
template<typename AType , typename Func , typename DerivedB >
void redux (const Eigen::SparseMatrix< AType > &A, const int dim, const Func &func, Eigen::PlainObjectBase< DerivedB > &B)
 
template<typename DerivedV , typename DerivedF , typename DerivedS , typename DerivedU , typename DerivedG , typename DerivedJ , typename BCtype , typename DerivedSU , typename DerivedL >
IGL_INLINE void remesh_along_isoline (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedS > &S, const typename DerivedS::Scalar val, Eigen::PlainObjectBase< DerivedU > &U, Eigen::PlainObjectBase< DerivedG > &G, Eigen::PlainObjectBase< DerivedSU > &SU, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::SparseMatrix< BCtype > &BC, Eigen::PlainObjectBase< DerivedL > &L)
 
template<typename DerivedF , typename DerivedS , typename DerivedG , typename DerivedJ , typename BCtype , typename DerivedSU , typename DerivedL >
IGL_INLINE void remesh_along_isoline (const int n, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedS > &S, const typename DerivedS::Scalar val, Eigen::PlainObjectBase< DerivedG > &G, Eigen::PlainObjectBase< DerivedSU > &SU, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::SparseMatrix< BCtype > &BC, Eigen::PlainObjectBase< DerivedL > &L)
 
template<typename DerivedV , typename DerivedSV , typename DerivedSVI , typename DerivedSVJ >
IGL_INLINE void remove_duplicate_vertices (const Eigen::MatrixBase< DerivedV > &V, const double epsilon, Eigen::PlainObjectBase< DerivedSV > &SV, Eigen::PlainObjectBase< DerivedSVI > &SVI, Eigen::PlainObjectBase< DerivedSVJ > &SVJ)
 
template<typename DerivedV , typename DerivedF , typename DerivedSV , typename DerivedSVI , typename DerivedSVJ , typename DerivedSF >
IGL_INLINE void remove_duplicate_vertices (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const double epsilon, Eigen::PlainObjectBase< DerivedSV > &SV, Eigen::PlainObjectBase< DerivedSVI > &SVI, Eigen::PlainObjectBase< DerivedSVJ > &SVJ, Eigen::PlainObjectBase< DerivedSF > &SF)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE void remove_duplicates (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedV > &NV, Eigen::PlainObjectBase< DerivedF > &NF, Eigen::Matrix< typename DerivedF::Scalar, Eigen::Dynamic, 1 > &I, const double epsilon=2.2204e-15)
 
template<typename DerivedV , typename DerivedF , typename DerivedNV , typename DerivedNF , typename DerivedI >
IGL_INLINE void remove_unreferenced (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedNV > &NV, Eigen::PlainObjectBase< DerivedNF > &NF, Eigen::PlainObjectBase< DerivedI > &I)
 
template<typename DerivedV , typename DerivedF , typename DerivedNV , typename DerivedNF , typename DerivedI , typename DerivedJ >
IGL_INLINE void remove_unreferenced (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedNV > &NV, Eigen::PlainObjectBase< DerivedNF > &NF, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<typename DerivedF , typename DerivedI , typename DerivedJ >
IGL_INLINE void remove_unreferenced (const size_t n, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<class T >
IGL_INLINE void reorder (const std::vector< T > &unordered, std::vector< size_t > const &index_map, std::vector< T > &ordered)
 
template<typename T >
IGL_INLINE void repdiag (const Eigen::SparseMatrix< T > &A, const int d, Eigen::SparseMatrix< T > &B)
 
template<typename T >
IGL_INLINE void repdiag (const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &A, const int d, Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &B)
 
template<class Mat >
IGL_INLINE Mat repdiag (const Mat &A, const int d)
 
template<typename DerivedA , typename DerivedB >
IGL_INLINE void repmat (const Eigen::MatrixBase< DerivedA > &A, const int r, const int c, Eigen::PlainObjectBase< DerivedB > &B)
 
template<typename T >
IGL_INLINE void repmat (const Eigen::SparseMatrix< T > &A, const int r, const int c, Eigen::SparseMatrix< T > &B)
 
template<typename DerivedF1 , typename DerivedF2 , typename DerivedJ >
IGL_INLINE void resolve_duplicated_faces (const Eigen::PlainObjectBase< DerivedF1 > &F1, Eigen::PlainObjectBase< DerivedF2 > &F2, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<typename R , typename H >
IGL_INLINE void rgb_to_hsv (const R *rgb, H *hsv)
 
template<typename DerivedR , typename DerivedH >
IGL_INLINE void rgb_to_hsv (const Eigen::PlainObjectBase< DerivedR > &R, Eigen::PlainObjectBase< DerivedH > &H)
 
template<typename Q_type >
IGL_INLINE void rotate_by_quat (const Q_type *v, const Q_type *q, Q_type *out)
 
IGL_INLINE Eigen::MatrixXd rotate_vectors (const Eigen::MatrixXd &V, const Eigen::VectorXd &A, const Eigen::MatrixXd &B1, const Eigen::MatrixXd &B2)
 
template<typename Scalar >
IGL_INLINE Eigen::Matrix< Scalar, 3, 3 > rotation_matrix_from_directions (const Eigen::Matrix< Scalar, 3, 1 > v0, const Eigen::Matrix< Scalar, 3, 1 > v1)
 
template<typename DerivedX >
DerivedX round (const DerivedX r)
 
template<typename DerivedX , typename DerivedY >
IGL_INLINE void round (const Eigen::PlainObjectBase< DerivedX > &X, Eigen::PlainObjectBase< DerivedY > &Y)
 
template<class Row , class Mat >
IGL_INLINE bool rows_to_matrix (const std::vector< Row > &V, Mat &M)
 
IGL_INLINE void sample_edges (const Eigen::MatrixXd &V, const Eigen::MatrixXi &E, const int k, Eigen::MatrixXd &S)
 
template<typename DerivedV , typename DerivedTC , typename DerivedF , typename DerivedFTC , typename Derivedseams , typename Derivedboundaries , typename Derivedfoldovers >
IGL_INLINE void seam_edges (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedTC > &TC, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedFTC > &FTC, Eigen::PlainObjectBase< Derivedseams > &seams, Eigen::PlainObjectBase< Derivedboundaries > &boundaries, Eigen::PlainObjectBase< Derivedfoldovers > &foldovers)
 
template<typename DerivedSource , typename DerivedDir >
IGL_INLINE bool segments_intersect (const Eigen::PlainObjectBase< DerivedSource > &p, const Eigen::PlainObjectBase< DerivedDir > &r, const Eigen::PlainObjectBase< DerivedSource > &q, const Eigen::PlainObjectBase< DerivedDir > &s, double &t, double &u, double eps=1e-6)
 
template<typename T >
bool serialize (const T &obj, const std::string &filename)
 
template<typename T >
bool serialize (const T &obj, const std::string &objectName, const std::string &filename, bool overwrite=false)
 
template<typename T >
bool serialize (const T &obj, const std::string &objectName, std::vector< char > &buffer)
 
template<typename T >
bool deserialize (T &obj, const std::string &filename)
 
template<typename T >
bool deserialize (T &obj, const std::string &objectName, const std::string &filename)
 
template<typename T >
bool deserialize (T &obj, const std::string &objectName, const std::vector< char > &buffer)
 
template<typename T >
bool serializer (bool serialize, T &obj, const std::string &filename)
 
template<typename T >
bool serializer (bool serialize, T &obj, const std::string &objectName, const std::string &filename, bool overwrite=false)
 
template<typename T >
bool serializer (bool serialize, T &obj, const std::string &objectName, std::vector< char > &buffer)
 
template<typename DerivedA , typename DerivedB , typename DerivedC , typename DerivedIA >
IGL_INLINE void setdiff (const Eigen::DenseBase< DerivedA > &A, const Eigen::DenseBase< DerivedB > &B, Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedIA > &IA)
 
template<typename DerivedA , typename DerivedB , typename DerivedC , typename DerivedIA , typename DerivedIB >
IGL_INLINE void setunion (const Eigen::DenseBase< DerivedA > &A, const Eigen::DenseBase< DerivedB > &B, Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedIA > &IA, Eigen::PlainObjectBase< DerivedIB > &IB)
 
template<typename DerivedA , typename DerivedB , typename DerivedC , typename DerivedIA , typename DerivedIB >
IGL_INLINE void setxor (const Eigen::DenseBase< DerivedA > &A, const Eigen::DenseBase< DerivedB > &B, Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedIA > &IA, Eigen::PlainObjectBase< DerivedIB > &IB)
 
template<typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void shape_diameter_function (const std::function< double(const Eigen::Vector3f &, const Eigen::Vector3f &) > &shoot_ray, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedN > &N, const int num_samples, Eigen::PlainObjectBase< DerivedS > &S)
 
template<typename DerivedV , int DIM, typename DerivedF , typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void shape_diameter_function (const igl::AABB< DerivedV, DIM > &aabb, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedN > &N, const int num_samples, Eigen::PlainObjectBase< DerivedS > &S)
 
template<typename DerivedV , typename DerivedF , typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void shape_diameter_function (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedN > &N, const int num_samples, Eigen::PlainObjectBase< DerivedS > &S)
 
template<typename DerivedV , typename DerivedF , typename DerivedS >
IGL_INLINE void shape_diameter_function (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const bool per_face, const int num_samples, Eigen::PlainObjectBase< DerivedS > &S)
 
IGL_INLINE bool shapeup_identity_projection (const Eigen::PlainObjectBase< Eigen::MatrixXd > &P, const Eigen::PlainObjectBase< Eigen::VectorXi > &SC, const Eigen::PlainObjectBase< Eigen::MatrixXi > &S, Eigen::PlainObjectBase< Eigen::MatrixXd > &projP)
 
IGL_INLINE bool shapeup_regular_face_projection (const Eigen::PlainObjectBase< Eigen::MatrixXd > &P, const Eigen::PlainObjectBase< Eigen::VectorXi > &SC, const Eigen::PlainObjectBase< Eigen::MatrixXi > &S, Eigen::PlainObjectBase< Eigen::MatrixXd > &projP)
 
template<typename DerivedP , typename DerivedSC , typename DerivedS , typename Derivedw >
IGL_INLINE bool shapeup_precomputation (const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedSC > &SC, const Eigen::PlainObjectBase< DerivedS > &S, const Eigen::PlainObjectBase< DerivedS > &E, const Eigen::PlainObjectBase< DerivedSC > &b, const Eigen::PlainObjectBase< Derivedw > &wShape, const Eigen::PlainObjectBase< Derivedw > &wSmooth, ShapeupData &sudata)
 
template<typename DerivedP , typename DerivedSC , typename DerivedS >
IGL_INLINE bool shapeup_solve (const Eigen::PlainObjectBase< DerivedP > &bc, const std::function< bool(const Eigen::PlainObjectBase< DerivedP > &, const Eigen::PlainObjectBase< DerivedSC > &, const Eigen::PlainObjectBase< DerivedS > &, Eigen::PlainObjectBase< DerivedP > &)> &local_projection, const Eigen::PlainObjectBase< DerivedP > &P0, const ShapeupData &sudata, const bool quietIterations, Eigen::PlainObjectBase< DerivedP > &P)
 
IGL_INLINE void shortest_edge_and_midpoint (const int e, const Eigen::MatrixXd &V, const Eigen::MatrixXi &, const Eigen::MatrixXi &E, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &cost, Eigen::RowVectorXd &p)
 
template<typename DerivedA , typename DerivedB , typename DerivedP >
IGL_INLINE DerivedA::Scalar signed_angle (const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &B, const Eigen::MatrixBase< DerivedP > &P)
 
template<typename DerivedP , typename DerivedV , typename DerivedF , typename DerivedS , typename DerivedI , typename DerivedC , typename DerivedN >
IGL_INLINE void signed_distance (const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const SignedDistanceType sign_type, const typename DerivedV::Scalar lower_bound, const typename DerivedV::Scalar upper_bound, Eigen::PlainObjectBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedN > &N)
 
template<typename DerivedP , typename DerivedV , typename DerivedF , typename DerivedS , typename DerivedI , typename DerivedC , typename DerivedN >
IGL_INLINE void signed_distance (const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const SignedDistanceType sign_type, Eigen::PlainObjectBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedN > &N)
 
template<typename DerivedV , typename DerivedF , typename DerivedFN , typename DerivedVN , typename DerivedEN , typename DerivedEMAP , typename Derivedq >
IGL_INLINE DerivedV::Scalar signed_distance_pseudonormal (const AABB< DerivedV, 3 > &tree, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedFN > &FN, const Eigen::MatrixBase< DerivedVN > &VN, const Eigen::MatrixBase< DerivedEN > &EN, const Eigen::MatrixBase< DerivedEMAP > &EMAP, const Eigen::MatrixBase< Derivedq > &q)
 
template<typename DerivedP , typename DerivedV , typename DerivedF , typename DerivedFN , typename DerivedVN , typename DerivedEN , typename DerivedEMAP , typename DerivedS , typename DerivedI , typename DerivedC , typename DerivedN >
IGL_INLINE void signed_distance_pseudonormal (const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const AABB< DerivedV, 3 > &tree, const Eigen::MatrixBase< DerivedFN > &FN, const Eigen::MatrixBase< DerivedVN > &VN, const Eigen::MatrixBase< DerivedEN > &EN, const Eigen::MatrixBase< DerivedEMAP > &EMAP, Eigen::PlainObjectBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedN > &N)
 
template<typename DerivedV , typename DerivedF , typename DerivedFN , typename DerivedVN , typename DerivedEN , typename DerivedEMAP , typename Derivedq , typename Scalar , typename Derivedc , typename Derivedn >
IGL_INLINE void signed_distance_pseudonormal (const AABB< DerivedV, 3 > &tree, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedFN > &FN, const Eigen::MatrixBase< DerivedVN > &VN, const Eigen::MatrixBase< DerivedEN > &EN, const Eigen::MatrixBase< DerivedEMAP > &EMAP, const Eigen::MatrixBase< Derivedq > &q, Scalar &s, Scalar &sqrd, int &i, Eigen::PlainObjectBase< Derivedc > &c, Eigen::PlainObjectBase< Derivedn > &n)
 
template<typename DerivedV , typename DerivedE , typename DerivedEN , typename DerivedVN , typename Derivedq , typename Scalar , typename Derivedc , typename Derivedn >
IGL_INLINE void signed_distance_pseudonormal (const AABB< DerivedV, 2 > &tree, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedE > &E, const Eigen::MatrixBase< DerivedEN > &EN, const Eigen::MatrixBase< DerivedVN > &VN, const Eigen::MatrixBase< Derivedq > &q, Scalar &s, Scalar &sqrd, int &i, Eigen::PlainObjectBase< Derivedc > &c, Eigen::PlainObjectBase< Derivedn > &n)
 
template<typename DerivedV , typename DerivedF , typename Derivedq >
IGL_INLINE DerivedV::Scalar signed_distance_winding_number (const AABB< DerivedV, 3 > &tree, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const igl::WindingNumberAABB< Derivedq, DerivedV, DerivedF > &hier, const Eigen::MatrixBase< Derivedq > &q)
 
template<typename DerivedV , typename DerivedF , typename Derivedq , typename Scalar , typename Derivedc >
IGL_INLINE void signed_distance_winding_number (const AABB< DerivedV, 3 > &tree, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const igl::WindingNumberAABB< Derivedq, DerivedV, DerivedF > &hier, const Eigen::MatrixBase< Derivedq > &q, Scalar &s, Scalar &sqrd, int &i, Eigen::PlainObjectBase< Derivedc > &c)
 
template<typename DerivedV , typename DerivedF , typename Derivedq , typename Scalar , typename Derivedc >
IGL_INLINE void signed_distance_winding_number (const AABB< DerivedV, 2 > &tree, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< Derivedq > &q, Scalar &s, Scalar &sqrd, int &i, Eigen::PlainObjectBase< Derivedc > &c)
 
IGL_INLINE void simplify_polyhedron (const Eigen::MatrixXd &OV, const Eigen::MatrixXi &OF, Eigen::MatrixXd &V, Eigen::MatrixXi &F, Eigen::VectorXi &J)
 
template<typename TX , typename TY >
IGL_INLINE void slice (const Eigen::SparseMatrix< TX > &X, const Eigen::Matrix< int, Eigen::Dynamic, 1 > &R, const Eigen::Matrix< int, Eigen::Dynamic, 1 > &C, Eigen::SparseMatrix< TY > &Y)
 
template<typename MatX , typename DerivedR , typename MatY >
IGL_INLINE void slice (const MatX &X, const Eigen::DenseBase< DerivedR > &R, const int dim, MatY &Y)
 
template<typename DerivedX , typename DerivedR , typename DerivedC , typename DerivedY >
IGL_INLINE void slice (const Eigen::DenseBase< DerivedX > &X, const Eigen::DenseBase< DerivedR > &R, const Eigen::DenseBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedY > &Y)
 
template<typename DerivedX , typename DerivedY >
IGL_INLINE void slice (const Eigen::DenseBase< DerivedX > &X, const Eigen::Matrix< int, Eigen::Dynamic, 1 > &R, Eigen::PlainObjectBase< DerivedY > &Y)
 
template<typename DerivedX >
IGL_INLINE DerivedX slice (const Eigen::DenseBase< DerivedX > &X, const Eigen::Matrix< int, Eigen::Dynamic, 1 > &R)
 
template<typename DerivedX >
IGL_INLINE DerivedX slice (const Eigen::DenseBase< DerivedX > &X, const Eigen::Matrix< int, Eigen::Dynamic, 1 > &R, const int dim)
 
template<typename TX , typename TY , typename DerivedI >
IGL_INLINE void slice_cached_precompute (const Eigen::SparseMatrix< TX > &X, const Eigen::Matrix< int, Eigen::Dynamic, 1 > &R, const Eigen::Matrix< int, Eigen::Dynamic, 1 > &C, Eigen::MatrixBase< DerivedI > &data, Eigen::SparseMatrix< TY > &Y)
 
template<typename TX , typename TY , typename DerivedI >
IGL_INLINE void slice_cached (const Eigen::SparseMatrix< TX > &X, const Eigen::MatrixBase< DerivedI > &data, Eigen::SparseMatrix< TY > &Y)
 
template<typename T >
IGL_INLINE void slice_into (const Eigen::SparseMatrix< T > &X, const Eigen::Matrix< int, Eigen::Dynamic, 1 > &R, const Eigen::Matrix< int, Eigen::Dynamic, 1 > &C, Eigen::SparseMatrix< T > &Y)
 
template<typename DerivedX , typename DerivedY >
IGL_INLINE void slice_into (const Eigen::DenseBase< DerivedX > &X, const Eigen::Matrix< int, Eigen::Dynamic, 1 > &R, const Eigen::Matrix< int, Eigen::Dynamic, 1 > &C, Eigen::PlainObjectBase< DerivedY > &Y)
 
template<typename MatX , typename MatY >
IGL_INLINE void slice_into (const MatX &X, const Eigen::Matrix< int, Eigen::Dynamic, 1 > &R, const int dim, MatY &Y)
 
template<typename DerivedX , typename DerivedY >
IGL_INLINE void slice_into (const Eigen::DenseBase< DerivedX > &X, const Eigen::Matrix< int, Eigen::Dynamic, 1 > &R, Eigen::PlainObjectBase< DerivedY > &Y)
 
template<typename DerivedX , typename DerivedY >
IGL_INLINE void slice_mask (const Eigen::DenseBase< DerivedX > &X, const Eigen::Array< bool, Eigen::Dynamic, 1 > &R, const Eigen::Array< bool, Eigen::Dynamic, 1 > &C, Eigen::PlainObjectBase< DerivedY > &Y)
 
template<typename DerivedX , typename DerivedY >
IGL_INLINE void slice_mask (const Eigen::DenseBase< DerivedX > &X, const Eigen::Array< bool, Eigen::Dynamic, 1 > &R, const int dim, Eigen::PlainObjectBase< DerivedY > &Y)
 
template<typename DerivedX >
IGL_INLINE DerivedX slice_mask (const Eigen::DenseBase< DerivedX > &X, const Eigen::Array< bool, Eigen::Dynamic, 1 > &R, const Eigen::Array< bool, Eigen::Dynamic, 1 > &C)
 
template<typename DerivedX >
IGL_INLINE DerivedX slice_mask (const Eigen::DenseBase< DerivedX > &X, const Eigen::Array< bool, Eigen::Dynamic, 1 > &R, const int dim)
 
template<typename XType , typename YType >
IGL_INLINE void slice_mask (const Eigen::SparseMatrix< XType > &X, const Eigen::Array< bool, Eigen::Dynamic, 1 > &R, const int dim, Eigen::SparseMatrix< YType > &Y)
 
template<typename XType , typename YType >
IGL_INLINE void slice_mask (const Eigen::SparseMatrix< XType > &X, const Eigen::Array< bool, Eigen::Dynamic, 1 > &R, const Eigen::Array< bool, Eigen::Dynamic, 1 > &C, Eigen::SparseMatrix< YType > &Y)
 
template<typename DerivedV , typename DerivedT , typename DerivedS , typename DerivedSV , typename DerivedSF , typename DerivedJ , typename BCType >
IGL_INLINE void slice_tets (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedT > &T, const Eigen::MatrixBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedSV > &SV, Eigen::PlainObjectBase< DerivedSF > &SF, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::SparseMatrix< BCType > &BC)
 
template<typename DerivedV , typename DerivedT , typename DerivedS , typename DerivedSV , typename DerivedSF , typename DerivedJ >
IGL_INLINE void slice_tets (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedT > &T, const Eigen::MatrixBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedSV > &SV, Eigen::PlainObjectBase< DerivedSF > &SF, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<typename DerivedV , typename DerivedT , typename DerivedS , typename DerivedSV , typename DerivedSF , typename DerivedJ , typename DerivedsE , typename Derivedlambda >
IGL_INLINE void slice_tets (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedT > &T, const Eigen::MatrixBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedSV > &SV, Eigen::PlainObjectBase< DerivedSF > &SF, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::PlainObjectBase< DerivedsE > &sE, Eigen::PlainObjectBase< Derivedlambda > &lambda)
 
IGL_INLINE void slim_precompute (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const Eigen::MatrixXd &V_init, SLIMData &data, SLIMData::SLIM_ENERGY slim_energy, Eigen::VectorXi &b, Eigen::MatrixXd &bc, double soft_p)
 Slim Implementation.
 
IGL_INLINE Eigen::MatrixXd slim_solve (SLIMData &data, int iter_num)
 
template<typename DerivedC , typename DerivedV , typename DerivedI , typename DerivedminD , typename DerivedVI >
IGL_INLINE void snap_points (const Eigen::PlainObjectBase< DerivedC > &C, const Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedminD > &minD, Eigen::PlainObjectBase< DerivedVI > &VI)
 
template<typename DerivedC , typename DerivedV , typename DerivedI , typename DerivedminD >
IGL_INLINE void snap_points (const Eigen::PlainObjectBase< DerivedC > &C, const Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedminD > &minD)
 
template<typename DerivedC , typename DerivedV , typename DerivedI >
IGL_INLINE void snap_points (const Eigen::PlainObjectBase< DerivedC > &C, const Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedI > &I)
 
template<typename Q_type >
IGL_INLINE bool snap_to_canonical_view_quat (const Q_type *q, const Q_type threshold, Q_type *s)
 
template<typename Scalarq , typename Scalars >
IGL_INLINE bool snap_to_canonical_view_quat (const Eigen::Quaternion< Scalarq > &q, const double threshold, Eigen::Quaternion< Scalars > &s)
 
template<typename Qtype >
IGL_INLINE void snap_to_fixed_up (const Eigen::Quaternion< Qtype > &q, Eigen::Quaternion< Qtype > &s)
 
template<typename DerivedA , typename DerivedB , typename DerivedC , typename DerivedP >
IGL_INLINE DerivedA::Scalar solid_angle (const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &B, const Eigen::MatrixBase< DerivedC > &C, const Eigen::MatrixBase< DerivedP > &P)
 
template<typename DerivedX , typename DerivedY , typename DerivedIX >
IGL_INLINE void sort (const Eigen::DenseBase< DerivedX > &X, const int dim, const bool ascending, Eigen::PlainObjectBase< DerivedY > &Y, Eigen::PlainObjectBase< DerivedIX > &IX)
 
template<typename DerivedX , typename DerivedY , typename DerivedIX >
IGL_INLINE void sort_new (const Eigen::DenseBase< DerivedX > &X, const int dim, const bool ascending, Eigen::PlainObjectBase< DerivedY > &Y, Eigen::PlainObjectBase< DerivedIX > &IX)
 
template<typename DerivedX , typename DerivedY , typename DerivedIX >
IGL_INLINE void sort2 (const Eigen::DenseBase< DerivedX > &X, const int dim, const bool ascending, Eigen::PlainObjectBase< DerivedY > &Y, Eigen::PlainObjectBase< DerivedIX > &IX)
 
template<typename DerivedX , typename DerivedY , typename DerivedIX >
IGL_INLINE void sort3 (const Eigen::DenseBase< DerivedX > &X, const int dim, const bool ascending, Eigen::PlainObjectBase< DerivedY > &Y, Eigen::PlainObjectBase< DerivedIX > &IX)
 
template<class T >
IGL_INLINE void sort (const std::vector< T > &unsorted, const bool ascending, std::vector< T > &sorted, std::vector< size_t > &index_map)
 
template<typename DerivedM , typename DerivedR >
IGL_INLINE void sort_angles (const Eigen::PlainObjectBase< DerivedM > &M, Eigen::PlainObjectBase< DerivedR > &R)
 
template<typename DerivedV , typename DerivedF , typename DerivedMV , typename DerivedP , typename DerivedFF , typename DerivedI >
IGL_INLINE void sort_triangles (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedMV > &MV, const Eigen::PlainObjectBase< DerivedP > &P, Eigen::PlainObjectBase< DerivedFF > &FF, Eigen::PlainObjectBase< DerivedI > &I)
 
template<typename DerivedS , typename DerivedI >
IGL_INLINE void sort_vectors_ccw (const Eigen::PlainObjectBase< DerivedS > &P, const Eigen::PlainObjectBase< DerivedS > &N, Eigen::PlainObjectBase< DerivedI > &order, Eigen::PlainObjectBase< DerivedS > &sorted, Eigen::PlainObjectBase< DerivedI > &inv_order)
 
template<typename DerivedS , typename DerivedI >
IGL_INLINE void sort_vectors_ccw (const Eigen::PlainObjectBase< DerivedS > &P, const Eigen::PlainObjectBase< DerivedS > &N, Eigen::PlainObjectBase< DerivedI > &order, Eigen::PlainObjectBase< DerivedS > &sorted)
 
template<typename DerivedS , typename DerivedI >
IGL_INLINE void sort_vectors_ccw (const Eigen::PlainObjectBase< DerivedS > &P, const Eigen::PlainObjectBase< DerivedS > &N, Eigen::PlainObjectBase< DerivedI > &order, Eigen::PlainObjectBase< DerivedI > &inv_order)
 
template<typename DerivedS , typename DerivedI >
IGL_INLINE void sort_vectors_ccw (const Eigen::PlainObjectBase< DerivedS > &P, const Eigen::PlainObjectBase< DerivedS > &N, Eigen::PlainObjectBase< DerivedI > &order)
 
template<typename DerivedX , typename DerivedI >
IGL_INLINE void sortrows (const Eigen::DenseBase< DerivedX > &X, const bool ascending, Eigen::PlainObjectBase< DerivedX > &Y, Eigen::PlainObjectBase< DerivedI > &I)
 
template<class IndexVector , class ValueVector , typename T >
IGL_INLINE void sparse (const IndexVector &I, const IndexVector &J, const ValueVector &V, Eigen::SparseMatrix< T > &X)
 
template<class IndexVectorI , class IndexVectorJ , class ValueVector , typename T >
IGL_INLINE void sparse (const IndexVectorI &I, const IndexVectorJ &J, const ValueVector &V, const size_t m, const size_t n, Eigen::SparseMatrix< T > &X)
 
template<typename DerivedD , typename T >
IGL_INLINE void sparse (const Eigen::PlainObjectBase< DerivedD > &D, Eigen::SparseMatrix< T > &X)
 
template<typename DerivedD >
IGL_INLINE Eigen::SparseMatrix< typename DerivedD::Scalar > sparse (const Eigen::PlainObjectBase< DerivedD > &D)
 
template<typename DerivedI , typename Scalar >
IGL_INLINE void sparse_cached_precompute (const Eigen::MatrixBase< DerivedI > &I, const Eigen::MatrixBase< DerivedI > &J, Eigen::VectorXi &data, Eigen::SparseMatrix< Scalar > &X)
 
template<typename Scalar >
IGL_INLINE void sparse_cached_precompute (const std::vector< Eigen::Triplet< Scalar > > &triplets, Eigen::VectorXi &data, Eigen::SparseMatrix< Scalar > &X)
 
template<typename Scalar >
IGL_INLINE void sparse_cached (const std::vector< Eigen::Triplet< Scalar > > &triplets, const Eigen::VectorXi &data, Eigen::SparseMatrix< Scalar > &X)
 
template<typename DerivedV , typename Scalar >
IGL_INLINE void sparse_cached (const Eigen::MatrixBase< DerivedV > &V, const Eigen::VectorXi &data, Eigen::SparseMatrix< Scalar > &X)
 
template<typename T >
IGL_INLINE void speye (const int n, const int m, Eigen::SparseMatrix< T > &I)
 
template<typename T >
IGL_INLINE void speye (const int n, Eigen::SparseMatrix< T > &I)
 
template<typename DerivedV , typename DerivedF , typename DerivedL >
IGL_INLINE void squared_edge_lengths (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedL > &L)
 
IGL_INLINE bool stdin_to_temp (FILE **temp_file)
 
template<typename DerivedV , typename DerivedF , typename DerivedVT , typename DerivedFT , typename Scalar , typename DerivedUE , typename DerivedUT , typename DerivedOT >
IGL_INLINE void straighten_seams (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedVT > &VT, const Eigen::MatrixBase< DerivedFT > &FT, const Scalar tol, Eigen::PlainObjectBase< DerivedUE > &UE, Eigen::PlainObjectBase< DerivedUT > &UT, Eigen::PlainObjectBase< DerivedOT > &OT)
 
template<typename T >
IGL_INLINE void sum (const Eigen::SparseMatrix< T > &X, const int dim, Eigen::SparseVector< T > &S)
 
template<typename AType , typename DerivedB >
IGL_INLINE void sum (const Eigen::SparseMatrix< AType > &A, const int dim, Eigen::PlainObjectBase< DerivedB > &B)
 
template<typename T >
IGL_INLINE void svd3x3 (const Eigen::Matrix< T, 3, 3 > &A, Eigen::Matrix< T, 3, 3 > &U, Eigen::Matrix< T, 3, 1 > &S, Eigen::Matrix< T, 3, 3 > &V)
 
template<typename T >
IGL_INLINE void svd3x3_avx (const Eigen::Matrix< T, 3 *8, 3 > &A, Eigen::Matrix< T, 3 *8, 3 > &U, Eigen::Matrix< T, 3 *8, 1 > &S, Eigen::Matrix< T, 3 *8, 3 > &V)
 
template<typename T >
IGL_INLINE void svd3x3_sse (const Eigen::Matrix< T, 3 *4, 3 > &A, Eigen::Matrix< T, 3 *4, 3 > &U, Eigen::Matrix< T, 3 *4, 1 > &S, Eigen::Matrix< T, 3 *4, 3 > &V)
 
IGL_INLINE void swept_volume_bounding_box (const size_t &n, const std::function< Eigen::RowVector3d(const size_t vi, const double t)> &V, const size_t &steps, Eigen::AlignedBox3d &box)
 
IGL_INLINE void swept_volume_signed_distance (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const std::function< Eigen::Affine3d(const double t)> &transform, const size_t &steps, const Eigen::MatrixXd &GV, const Eigen::RowVector3i &res, const double h, const double isolevel, const Eigen::VectorXd &S0, Eigen::VectorXd &S)
 
IGL_INLINE void swept_volume_signed_distance (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const std::function< Eigen::Affine3d(const double t)> &transform, const size_t &steps, const Eigen::MatrixXd &GV, const Eigen::RowVector3i &res, const double h, const double isolevel, Eigen::VectorXd &S)
 
template<typename Q_type >
IGL_INLINE void trackball (const double w, const double h, const Q_type speed_factor, const double down_mouse_x, const double down_mouse_y, const double mouse_x, const double mouse_y, Q_type *quat)
 
template<typename Q_type >
IGL_INLINE void trackball (const double w, const double h, const Q_type speed_factor, const Q_type *down_quat, const double down_mouse_x, const double down_mouse_y, const double mouse_x, const double mouse_y, Q_type *quat)
 
template<typename Scalardown_quat , typename Scalarquat >
IGL_INLINE void trackball (const double w, const double h, const double speed_factor, const Eigen::Quaternion< Scalardown_quat > &down_quat, const double down_mouse_x, const double down_mouse_y, const double mouse_x, const double mouse_y, Eigen::Quaternion< Scalarquat > &quat)
 
template<typename T >
IGL_INLINE void transpose_blocks (const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &A, const size_t k, const size_t dim, Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &B)
 
IGL_INLINE void triangle_fan (const Eigen::MatrixXi &E, Eigen::MatrixXi &cap)
 
IGL_INLINE Eigen::MatrixXi triangle_fan (const Eigen::MatrixXi &E)
 
template<typename DerivedF , typename DerivedTT , typename DerivedTTi >
IGL_INLINE void triangle_triangle_adjacency (const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedTT > &TT, Eigen::PlainObjectBase< DerivedTTi > &TTi)
 
template<typename DerivedF , typename DerivedTT >
IGL_INLINE void triangle_triangle_adjacency (const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedTT > &TT)
 
template<typename DerivedF , typename TTT_type >
IGL_INLINE void triangle_triangle_adjacency_preprocess (const Eigen::MatrixBase< DerivedF > &F, std::vector< std::vector< TTT_type > > &TTT)
 
template<typename DerivedF , typename TTT_type , typename DerivedTT >
IGL_INLINE void triangle_triangle_adjacency_extractTT (const Eigen::MatrixBase< DerivedF > &F, std::vector< std::vector< TTT_type > > &TTT, Eigen::PlainObjectBase< DerivedTT > &TT)
 
template<typename DerivedF , typename TTT_type , typename DerivedTTi >
IGL_INLINE void triangle_triangle_adjacency_extractTTi (const Eigen::MatrixBase< DerivedF > &F, std::vector< std::vector< TTT_type > > &TTT, Eigen::PlainObjectBase< DerivedTTi > &TTi)
 
template<typename DerivedF , typename TTIndex , typename TTiIndex >
IGL_INLINE void triangle_triangle_adjacency (const Eigen::MatrixBase< DerivedF > &F, std::vector< std::vector< std::vector< TTIndex > > > &TT, std::vector< std::vector< std::vector< TTiIndex > > > &TTi)
 
template<typename DerivedF , typename TTIndex >
IGL_INLINE void triangle_triangle_adjacency (const Eigen::MatrixBase< DerivedF > &F, std::vector< std::vector< std::vector< TTIndex > > > &TT)
 
template<typename DerivedF , typename TTIndex , typename TTiIndex >
IGL_INLINE void triangle_triangle_adjacency (const Eigen::MatrixBase< DerivedF > &F, const bool construct_TTi, std::vector< std::vector< std::vector< TTIndex > > > &TT, std::vector< std::vector< std::vector< TTiIndex > > > &TTi)
 
template<typename DerivedE , typename DerivedEMAP , typename uE2EType , typename TTIndex , typename TTiIndex >
IGL_INLINE void triangle_triangle_adjacency (const Eigen::MatrixBase< DerivedE > &E, const Eigen::MatrixBase< DerivedEMAP > &EMAP, const std::vector< std::vector< uE2EType > > &uE2E, const bool construct_TTi, std::vector< std::vector< std::vector< TTIndex > > > &TT, std::vector< std::vector< std::vector< TTiIndex > > > &TTi)
 
template<typename DerivedS , typename DerivedF >
IGL_INLINE void triangles_from_strip (const Eigen::MatrixBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename Scalardown_quat , typename Scalarquat >
IGL_INLINE void two_axis_valuator_fixed_up (const int w, const int h, const double speed, const Eigen::Quaternion< Scalardown_quat > &down_quat, const int down_x, const int down_y, const int mouse_x, const int mouse_y, Eigen::Quaternion< Scalarquat > &quat)
 
IGL_INLINE void uniformly_sample_two_manifold (const Eigen::MatrixXd &W, const Eigen::MatrixXi &F, const int k, const double push, Eigen::MatrixXd &WS)
 
IGL_INLINE void uniformly_sample_two_manifold_at_vertices (const Eigen::MatrixXd &OW, const int k, const double push, Eigen::VectorXi &S)
 
template<typename T >
IGL_INLINE void unique (const std::vector< T > &A, std::vector< T > &C, std::vector< size_t > &IA, std::vector< size_t > &IC)
 
template<typename T >
IGL_INLINE void unique (const std::vector< T > &A, std::vector< T > &C)
 
template<typename DerivedA , typename DerivedC , typename DerivedIA , typename DerivedIC >
IGL_INLINE void unique (const Eigen::DenseBase< DerivedA > &A, Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedIA > &IA, Eigen::PlainObjectBase< DerivedIC > &IC)
 
template<typename DerivedA , typename DerivedC >
IGL_INLINE void unique (const Eigen::DenseBase< DerivedA > &A, Eigen::PlainObjectBase< DerivedC > &C)
 
template<typename DerivedF , typename DerivedE , typename DeriveduE , typename DerivedEMAP , typename uE2EType >
IGL_INLINE void unique_edge_map (const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedE > &E, Eigen::PlainObjectBase< DeriveduE > &uE, Eigen::PlainObjectBase< DerivedEMAP > &EMAP, std::vector< std::vector< uE2EType > > &uE2E)
 
template<typename DerivedA , typename DerivedC , typename DerivedIA , typename DerivedIC >
IGL_INLINE void unique_rows (const Eigen::DenseBase< DerivedA > &A, Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedIA > &IA, Eigen::PlainObjectBase< DerivedIC > &IC)
 
template<typename DerivedF , typename DerivedFF , typename DerivedIA , typename DerivedIC >
IGL_INLINE void unique_simplices (const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedFF > &FF, Eigen::PlainObjectBase< DerivedIA > &IA, Eigen::PlainObjectBase< DerivedIC > &IC)
 
template<typename DerivedF , typename DerivedFF >
IGL_INLINE void unique_simplices (const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedFF > &FF)
 
template<typename Derivedwin , typename Derivedmodel , typename Derivedproj , typename Derivedviewport , typename Derivedscene >
IGL_INLINE void unproject (const Eigen::MatrixBase< Derivedwin > &win, const Eigen::MatrixBase< Derivedmodel > &model, const Eigen::MatrixBase< Derivedproj > &proj, const Eigen::MatrixBase< Derivedviewport > &viewport, Eigen::PlainObjectBase< Derivedscene > &scene)
 
template<typename Scalar >
IGL_INLINE Eigen::Matrix< Scalar, 3, 1 > unproject (const Eigen::Matrix< Scalar, 3, 1 > &win, const Eigen::Matrix< Scalar, 4, 4 > &model, const Eigen::Matrix< Scalar, 4, 4 > &proj, const Eigen::Matrix< Scalar, 4, 1 > &viewport)
 
template<typename DerivedV , typename DerivedF , typename Derivedobj >
IGL_INLINE int unproject_in_mesh (const Eigen::Vector2f &pos, const Eigen::Matrix4f &model, const Eigen::Matrix4f &proj, const Eigen::Vector4f &viewport, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< Derivedobj > &obj, std::vector< igl::Hit > &hits)
 
template<typename Derivedobj >
IGL_INLINE int unproject_in_mesh (const Eigen::Vector2f &pos, const Eigen::Matrix4f &model, const Eigen::Matrix4f &proj, const Eigen::Vector4f &viewport, const std::function< void(const Eigen::Vector3f &, const Eigen::Vector3f &, std::vector< igl::Hit > &) > &shoot_ray, Eigen::PlainObjectBase< Derivedobj > &obj, std::vector< igl::Hit > &hits)
 
template<typename DerivedV , typename DerivedF , typename Derivedobj >
IGL_INLINE int unproject_in_mesh (const Eigen::Vector2f &pos, const Eigen::Matrix4f &model, const Eigen::Matrix4f &proj, const Eigen::Vector4f &viewport, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< Derivedobj > &obj)
 
template<typename DerivedV , typename DerivedF , typename Derivedbc >
IGL_INLINE bool unproject_onto_mesh (const Eigen::Vector2f &pos, const Eigen::Matrix4f &model, const Eigen::Matrix4f &proj, const Eigen::Vector4f &viewport, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, int &fid, Eigen::PlainObjectBase< Derivedbc > &bc)
 
template<typename Derivedbc >
IGL_INLINE bool unproject_onto_mesh (const Eigen::Vector2f &pos, const Eigen::Matrix4f &model, const Eigen::Matrix4f &proj, const Eigen::Vector4f &viewport, const std::function< bool(const Eigen::Vector3f &, const Eigen::Vector3f &, igl::Hit &) > &shoot_ray, int &fid, Eigen::PlainObjectBase< Derivedbc > &bc)
 
template<typename Derivedpos , typename Derivedmodel , typename Derivedproj , typename Derivedviewport , typename Deriveds , typename Deriveddir >
IGL_INLINE void unproject_ray (const Eigen::PlainObjectBase< Derivedpos > &pos, const Eigen::PlainObjectBase< Derivedmodel > &model, const Eigen::PlainObjectBase< Derivedproj > &proj, const Eigen::PlainObjectBase< Derivedviewport > &viewport, Eigen::PlainObjectBase< Deriveds > &s, Eigen::PlainObjectBase< Deriveddir > &dir)
 dir direction of ray (d - s) where d is pos unprojected with z=1
 
template<typename DerivedA , typename DerivedU , typename DerivedG , typename DerivedJ >
IGL_INLINE void unzip_corners (const std::vector< std::reference_wrapper< DerivedA > > &A, Eigen::PlainObjectBase< DerivedU > &U, Eigen::PlainObjectBase< DerivedG > &G, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<typename DerivedF , typename SType , typename DerivedNF >
IGL_INLINE void upsample (const int n_verts, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::SparseMatrix< SType > &S, Eigen::PlainObjectBase< DerivedNF > &NF)
 
template<typename DerivedV , typename DerivedF , typename DerivedNV , typename DerivedNF >
IGL_INLINE void upsample (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedNV > &NV, Eigen::PlainObjectBase< DerivedNF > &NF, const int number_of_subdivs=1)
 
template<typename MatV , typename MatF >
IGL_INLINE void upsample (MatV &V, MatF &F, const int number_of_subdivs=1)
 
template<typename DerivedF , typename Scalar >
IGL_INLINE void vector_area_matrix (const Eigen::PlainObjectBase< DerivedF > &F, Eigen::SparseMatrix< Scalar > &A)
 
int verbose (const char *msg,...)
 
template<typename DerivedF , typename VFType , typename VFiType >
IGL_INLINE void vertex_triangle_adjacency (const typename DerivedF::Scalar n, const Eigen::MatrixBase< DerivedF > &F, std::vector< std::vector< VFType > > &VF, std::vector< std::vector< VFiType > > &VFi)
 
template<typename DerivedV , typename DerivedF , typename IndexType >
IGL_INLINE void vertex_triangle_adjacency (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, std::vector< std::vector< IndexType > > &VF, std::vector< std::vector< IndexType > > &VFi)
 
template<typename DerivedF , typename DerivedVF , typename DerivedNI >
IGL_INLINE void vertex_triangle_adjacency (const Eigen::MatrixBase< DerivedF > &F, const int n, Eigen::PlainObjectBase< DerivedVF > &VF, Eigen::PlainObjectBase< DerivedNI > &NI)
 
template<typename DerivedV , typename DerivedT , typename Derivedvol >
IGL_INLINE void volume (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedT > &T, Eigen::PlainObjectBase< Derivedvol > &vol)
 
template<typename DerivedA , typename DerivedB , typename DerivedC , typename DerivedD , typename Derivedvol >
IGL_INLINE void volume (const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &B, const Eigen::MatrixBase< DerivedC > &C, const Eigen::MatrixBase< DerivedD > &D, Eigen::PlainObjectBase< Derivedvol > &vol)
 
template<typename VecA , typename VecB , typename VecC , typename VecD >
IGL_INLINE VecA::Scalar volume_single (const VecA &a, const VecB &b, const VecC &c, const VecD &d)
 
template<typename DerivedL , typename Derivedvol >
IGL_INLINE void volume (const Eigen::MatrixBase< DerivedL > &L, Eigen::PlainObjectBase< Derivedvol > &vol)
 
template<typename Scalar , typename DerivedGV , typename Derivedside >
IGL_INLINE void voxel_grid (const Eigen::AlignedBox< Scalar, 3 > &box, const int s, const int pad_count, Eigen::PlainObjectBase< DerivedGV > &GV, Eigen::PlainObjectBase< Derivedside > &side)
 
template<typename DerivedV , typename DerivedF , typename DerivedO , typename DerivedW >
IGL_INLINE void winding_number (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedO > &O, Eigen::PlainObjectBase< DerivedW > &W)
 
template<typename DerivedV , typename DerivedF , typename Derivedp >
IGL_INLINE DerivedV::Scalar winding_number (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< Derivedp > &p)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE bool write_triangle_mesh (const std::string str, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const bool force_ascii=true)
 
template<typename DerivedWI , typename DerivedP , typename DerivedO >
IGL_INLINE bool writeBF (const std::string &filename, const Eigen::PlainObjectBase< DerivedWI > &WI, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedO > &O)
 
template<typename DerivedW >
IGL_INLINE bool writeDMAT (const std::string file_name, const Eigen::MatrixBase< DerivedW > &W, const bool ascii=true)
 
template<typename Scalar >
IGL_INLINE bool writeDMAT (const std::string file_name, const std::vector< std::vector< Scalar > > &W, const bool ascii=true)
 
template<typename Scalar >
IGL_INLINE bool writeDMAT (const std::string file_name, const std::vector< Scalar > &W, const bool ascii=true)
 
template<typename Scalar , typename Index >
IGL_INLINE bool writeMESH (const std::string mesh_file_name, const std::vector< std::vector< Scalar > > &V, const std::vector< std::vector< Index > > &T, const std::vector< std::vector< Index > > &F)
 
template<typename DerivedV , typename DerivedT , typename DerivedF >
IGL_INLINE bool writeMESH (const std::string str, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedT > &T, const Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename DerivedV , typename DerivedF , typename DerivedCN , typename DerivedFN , typename DerivedTC , typename DerivedFTC >
IGL_INLINE bool writeOBJ (const std::string str, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedCN > &CN, const Eigen::MatrixBase< DerivedFN > &FN, const Eigen::MatrixBase< DerivedTC > &TC, const Eigen::MatrixBase< DerivedFTC > &FTC)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE bool writeOBJ (const std::string str, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F)
 
template<typename DerivedV , typename DerivedF , typename DerivedC >
IGL_INLINE bool writeOFF (const std::string str, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedC > &C)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE bool writeOFF (const std::string str, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename DerivedV , typename DerivedF , typename DerivedN , typename DerivedUV >
IGL_INLINE bool writePLY (const std::string &filename, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedN > &N, const Eigen::MatrixBase< DerivedUV > &UV, const bool ascii=true)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE bool writePLY (const std::string &filename, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const bool ascii=true)
 
template<typename DerivedV , typename DerivedF , typename DerivedN >
IGL_INLINE bool writeSTL (const std::string &filename, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedN > &N, const bool ascii=true)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE bool writeSTL (const std::string &filename, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const bool ascii=true)
 
IGL_INLINE bool writeTGF (const std::string tgf_filename, const std::vector< std::vector< double > > &C, const std::vector< std::vector< int > > &E)
 
IGL_INLINE bool writeTGF (const std::string tgf_filename, const Eigen::MatrixXd &C, const Eigen::MatrixXi &E)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE bool writeWRL (const std::string &str, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename DerivedV , typename DerivedF , typename DerivedC >
IGL_INLINE bool writeWRL (const std::string &str, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedC > &C)
 

Variables

const float IDENTITY_QUAT_F [4] = {0,0,0,1}
 
const float XY_PLANE_QUAT_F [4] = {0,0,0,1}
 
const float XZ_PLANE_QUAT_F [4] = {-SQRT_2_OVER_2,0,0,SQRT_2_OVER_2}
 
const float YZ_PLANE_QUAT_F [4] = {-0.5,-0.5,-0.5,0.5}
 
const float CANONICAL_VIEW_QUAT_F [][4]
 
const double IDENTITY_QUAT_D [4] = {0,0,0,1}
 
const double XY_PLANE_QUAT_D [4] = {0,0,0,1}
 
const double XZ_PLANE_QUAT_D [4] = {-SQRT_2_OVER_2,0,0,SQRT_2_OVER_2}
 
const double YZ_PLANE_QUAT_D [4] = {-0.5,-0.5,-0.5,0.5}
 
const double CANONICAL_VIEW_QUAT_D [][4]
 
static double inferno_cm [256][3]
 
static double magma_cm [256][3]
 
static double plasma_cm [256][3]
 
static double viridis_cm [256][3]
 
static double parula_cm [256][3]
 
const double DOUBLE_EPS = 1.0e-14
 
const double DOUBLE_EPS_SQ = 1.0e-28
 
const float FLOAT_EPS = 1.0e-7f
 
const float FLOAT_EPS_SQ = 1.0e-14f
 
const float GOLD_AMBIENT [4] = { 51.0/255.0, 43.0/255.0,33.3/255.0,1.0f }
 
const float GOLD_DIFFUSE [4] = { 255.0/255.0,228.0/255.0,58.0/255.0,1.0f }
 
const float GOLD_SPECULAR [4] = { 255.0/255.0,235.0/255.0,80.0/255.0,1.0f }
 
const float SILVER_AMBIENT [4] = { 0.2f, 0.2f, 0.2f, 1.0f }
 
const float SILVER_DIFFUSE [4] = { 1.0f, 1.0f, 1.0f, 1.0f }
 
const float SILVER_SPECULAR [4] = { 1.0f, 1.0f, 1.0f, 1.0f }
 
const float CYAN_AMBIENT [4] = { 59.0/255.0, 68.0/255.0,255.0/255.0,1.0f }
 
const float CYAN_DIFFUSE [4] = { 94.0/255.0,185.0/255.0,238.0/255.0,1.0f }
 
const float CYAN_SPECULAR [4] = { 163.0/255.0,221.0/255.0,255.0/255.0,1.0f }
 
const float DENIS_PURPLE_DIFFUSE [4] = { 80.0/255.0,64.0/255.0,255.0/255.0,1.0f }
 
const float LADISLAV_ORANGE_DIFFUSE [4] = {1.0f, 125.0f / 255.0f, 19.0f / 255.0f, 0.0f}
 
const float FAST_GREEN_DIFFUSE [4] = { 113.0f/255.0f, 239.0f/255.0f, 46.0f/255.0f, 1.0f}
 
const float FAST_RED_DIFFUSE [4] = { 255.0f/255.0f, 65.0f/255.0f, 46.0f/255.0f, 1.0f}
 
const float FAST_BLUE_DIFFUSE [4] = { 106.0f/255.0f, 106.0f/255.0f, 255.0f/255.0f, 1.0f}
 
const float FAST_GRAY_DIFFUSE [4] = { 150.0f/255.0f, 150.0f/255.0f, 150.0f/255.0f, 1.0f}
 
const float WHITE [4] = { 255.0/255.0,255.0/255.0,255.0/255.0,1.0f }
 
const float BLACK [4] = { 0.0/255.0,0.0/255.0,0.0/255.0,1.0f }
 
const float WHITE_AMBIENT [4] = { 255.0/255.0,255.0/255.0,255.0/255.0,1.0f }
 
const float WHITE_DIFFUSE [4] = { 255.0/255.0,255.0/255.0,255.0/255.0,1.0f }
 
const float WHITE_SPECULAR [4] = { 255.0/255.0,255.0/255.0,255.0/255.0,1.0f }
 
const float BBW_POINT_COLOR [4] = {239./255.,213./255.,46./255.,255.0/255.0}
 
const float BBW_LINE_COLOR [4] = {106./255.,106./255.,255./255.,255./255.}
 
const float MIDNIGHT_BLUE_DIFFUSE [4] = { 21.0f/255.0f, 27.0f/255.0f, 84.0f/255.0f, 1.0f}
 
const float EASTER_RED_DIFFUSE [4] = {0.603922,0.494118f,0.603922f,1.0f}
 
const float WN_OPEN_BOUNDARY_COLOR [4] = {154./255.,0./255.,0./255.,1.0f}
 
const float WN_NON_MANIFOLD_EDGE_COLOR [4] = {201./255., 51./255.,255./255.,1.0f}
 
const char CHAR_ONE = 1
 
const int INT_ONE = 1
 
const unsigned int UNSIGNED_INT_ONE = 1
 
const double DOUBLE_ONE = 1
 
const float FLOAT_ONE = 1
 
const double PI = 3.1415926535897932384626433832795
 
const char CHAR_ZERO = 0
 
const int INT_ZERO = 0
 
const unsigned int UNSIGNED_INT_ZERO = 0
 
const double DOUBLE_ZERO = 0
 
const float FLOAT_ZERO = 0
 

Class Documentation

◆ igl::AtA_cached_data

struct igl::AtA_cached_data
+ Collaboration diagram for igl::AtA_cached_data:
Class Members
vector< int > I_col
vector< int > I_outer
vector< int > I_row
vector< int > I_w
VectorXd W

◆ igl::Hit

struct igl::Hit
Class Members
int gid
int id
float t
float u
float v

Typedef Documentation

◆ shapeup_projection_function

typedef std::function<bool(const Eigen::PlainObjectBase<Eigen::MatrixXd>&, const Eigen::PlainObjectBase<Eigen::VectorXi>&, const Eigen::PlainObjectBase<Eigen::MatrixXi>&, Eigen::PlainObjectBase<Eigen::MatrixXd>&)> igl::shapeup_projection_function

Enumeration Type Documentation

◆ ARAPEnergyType

Enumerator
ARAP_ENERGY_TYPE_SPOKES 
ARAP_ENERGY_TYPE_SPOKES_AND_RIMS 
ARAP_ENERGY_TYPE_ELEMENTS 
ARAP_ENERGY_TYPE_DEFAULT 
NUM_ARAP_ENERGY_TYPES 
28 {
34 };
@ ARAP_ENERGY_TYPE_DEFAULT
Definition ARAPEnergyType.h:32
@ ARAP_ENERGY_TYPE_SPOKES_AND_RIMS
Definition ARAPEnergyType.h:30
@ ARAP_ENERGY_TYPE_SPOKES
Definition ARAPEnergyType.h:29
@ NUM_ARAP_ENERGY_TYPES
Definition ARAPEnergyType.h:33
@ ARAP_ENERGY_TYPE_ELEMENTS
Definition ARAPEnergyType.h:31

◆ ColorMapType

Enumerator
COLOR_MAP_TYPE_INFERNO 
COLOR_MAP_TYPE_JET 
COLOR_MAP_TYPE_MAGMA 
COLOR_MAP_TYPE_PARULA 
COLOR_MAP_TYPE_PLASMA 
COLOR_MAP_TYPE_VIRIDIS 
NUM_COLOR_MAP_TYPES 
18 {
26 };
@ COLOR_MAP_TYPE_PLASMA
Definition colormap.h:23
@ COLOR_MAP_TYPE_MAGMA
Definition colormap.h:21
@ COLOR_MAP_TYPE_PARULA
Definition colormap.h:22
@ COLOR_MAP_TYPE_INFERNO
Definition colormap.h:19
@ NUM_COLOR_MAP_TYPES
Definition colormap.h:25
@ COLOR_MAP_TYPE_JET
Definition colormap.h:20
@ COLOR_MAP_TYPE_VIRIDIS
Definition colormap.h:24

◆ EigsType

Enumerator
EIGS_TYPE_SM 
EIGS_TYPE_LM 
NUM_EIGS_TYPES 
39 {
40 EIGS_TYPE_SM = 0,
41 EIGS_TYPE_LM = 1,
43 };
@ EIGS_TYPE_SM
Definition eigs.h:40
@ NUM_EIGS_TYPES
Definition eigs.h:42
@ EIGS_TYPE_LM
Definition eigs.h:41

◆ MassMatrixType

Enumerator
MASSMATRIX_TYPE_BARYCENTRIC 
MASSMATRIX_TYPE_VORONOI 
MASSMATRIX_TYPE_FULL 
MASSMATRIX_TYPE_DEFAULT 
NUM_MASSMATRIX_TYPE 
20 {
26 };
@ NUM_MASSMATRIX_TYPE
Definition massmatrix.h:25
@ MASSMATRIX_TYPE_DEFAULT
Definition massmatrix.h:24
@ MASSMATRIX_TYPE_VORONOI
Definition massmatrix.h:22
@ MASSMATRIX_TYPE_FULL
Definition massmatrix.h:23
@ MASSMATRIX_TYPE_BARYCENTRIC
Definition massmatrix.h:21

◆ MeshBooleanType

Enumerator
MESH_BOOLEAN_TYPE_UNION 
MESH_BOOLEAN_TYPE_INTERSECT 
MESH_BOOLEAN_TYPE_MINUS 
MESH_BOOLEAN_TYPE_XOR 
MESH_BOOLEAN_TYPE_RESOLVE 
NUM_MESH_BOOLEAN_TYPES 
13 {
20 };
@ MESH_BOOLEAN_TYPE_MINUS
Definition MeshBooleanType.h:16
@ MESH_BOOLEAN_TYPE_XOR
Definition MeshBooleanType.h:17
@ MESH_BOOLEAN_TYPE_INTERSECT
Definition MeshBooleanType.h:15
@ MESH_BOOLEAN_TYPE_UNION
Definition MeshBooleanType.h:14
@ MESH_BOOLEAN_TYPE_RESOLVE
Definition MeshBooleanType.h:18
@ NUM_MESH_BOOLEAN_TYPES
Definition MeshBooleanType.h:19

◆ NormalType

Enumerator
PER_VERTEX_NORMALS 
PER_FACE_NORMALS 
PER_CORNER_NORMALS 
18 {
22 };
@ PER_FACE_NORMALS
Definition NormalType.h:20
@ PER_CORNER_NORMALS
Definition NormalType.h:21
@ PER_VERTEX_NORMALS
Definition NormalType.h:19

◆ PerEdgeNormalsWeightingType

Enumerator
PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM 
PER_EDGE_NORMALS_WEIGHTING_TYPE_AREA 
PER_EDGE_NORMALS_WEIGHTING_TYPE_DEFAULT 
NUM_PER_EDGE_NORMALS_WEIGHTING_TYPE 
15 {
16 // Incident face normals have uniform influence on edge normal
18 // Incident face normals are averaged weighted by area
20 // Area weights
23 };
@ NUM_PER_EDGE_NORMALS_WEIGHTING_TYPE
Definition per_edge_normals.h:22
@ PER_EDGE_NORMALS_WEIGHTING_TYPE_AREA
Definition per_edge_normals.h:19
@ PER_EDGE_NORMALS_WEIGHTING_TYPE_DEFAULT
Definition per_edge_normals.h:21
@ PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM
Definition per_edge_normals.h:17

◆ PerVertexNormalsWeightingType

Enumerator
PER_VERTEX_NORMALS_WEIGHTING_TYPE_UNIFORM 
PER_VERTEX_NORMALS_WEIGHTING_TYPE_AREA 
PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE 
PER_VERTEX_NORMALS_WEIGHTING_TYPE_DEFAULT 
NUM_PER_VERTEX_NORMALS_WEIGHTING_TYPE 
17 {
18 // Incident face normals have uniform influence on vertex normal
20 // Incident face normals are averaged weighted by area
22 // Incident face normals are averaged weighted by incident angle of vertex
24 // Area weights
27 };
@ PER_VERTEX_NORMALS_WEIGHTING_TYPE_UNIFORM
Definition per_vertex_normals.h:19
@ PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE
Definition per_vertex_normals.h:23
@ PER_VERTEX_NORMALS_WEIGHTING_TYPE_AREA
Definition per_vertex_normals.h:21
@ PER_VERTEX_NORMALS_WEIGHTING_TYPE_DEFAULT
Definition per_vertex_normals.h:25
@ NUM_PER_VERTEX_NORMALS_WEIGHTING_TYPE
Definition per_vertex_normals.h:26

◆ SignedDistanceType

Enumerator
SIGNED_DISTANCE_TYPE_PSEUDONORMAL 
SIGNED_DISTANCE_TYPE_WINDING_NUMBER 
SIGNED_DISTANCE_TYPE_DEFAULT 
SIGNED_DISTANCE_TYPE_UNSIGNED 
NUM_SIGNED_DISTANCE_TYPE 
19 {
20 // Use fast pseudo-normal test [Bærentzen & Aanæs 2005]
26 };
@ SIGNED_DISTANCE_TYPE_WINDING_NUMBER
Definition signed_distance.h:22
@ SIGNED_DISTANCE_TYPE_UNSIGNED
Definition signed_distance.h:24
@ SIGNED_DISTANCE_TYPE_DEFAULT
Definition signed_distance.h:23
@ NUM_SIGNED_DISTANCE_TYPE
Definition signed_distance.h:25
@ SIGNED_DISTANCE_TYPE_PSEUDONORMAL
Definition signed_distance.h:21

◆ SolverStatus

Enumerator
SOLVER_STATUS_CONVERGED 
SOLVER_STATUS_MAX_ITER 
SOLVER_STATUS_ERROR 
NUM_SOLVER_STATUSES 
13 {
14 // Good
16 // OK
18 // Bad
21 };
@ SOLVER_STATUS_MAX_ITER
Definition SolverStatus.h:17
@ NUM_SOLVER_STATUSES
Definition SolverStatus.h:20
@ SOLVER_STATUS_ERROR
Definition SolverStatus.h:19
@ SOLVER_STATUS_CONVERGED
Definition SolverStatus.h:15

◆ WindingNumberMethod

Enumerator
EXACT_WINDING_NUMBER_METHOD 
APPROX_SIMPLE_WINDING_NUMBER_METHOD 
APPROX_CACHE_WINDING_NUMBER_METHOD 
NUM_WINDING_NUMBER_METHODS 
16 {
21 };
@ APPROX_SIMPLE_WINDING_NUMBER_METHOD
Definition WindingNumberMethod.h:18
@ NUM_WINDING_NUMBER_METHODS
Definition WindingNumberMethod.h:20
@ APPROX_CACHE_WINDING_NUMBER_METHOD
Definition WindingNumberMethod.h:19
@ EXACT_WINDING_NUMBER_METHOD
Definition WindingNumberMethod.h:17

Function Documentation

◆ active_set()

template<typename AT , typename DerivedB , typename Derivedknown , typename DerivedY , typename AeqT , typename DerivedBeq , typename AieqT , typename DerivedBieq , typename Derivedlx , typename Derivedux , typename DerivedZ >
IGL_INLINE igl::SolverStatus igl::active_set ( const Eigen::SparseMatrix< AT > &  A,
const Eigen::PlainObjectBase< DerivedB > &  B,
const Eigen::PlainObjectBase< Derivedknown > &  known,
const Eigen::PlainObjectBase< DerivedY > &  Y,
const Eigen::SparseMatrix< AeqT > &  Aeq,
const Eigen::PlainObjectBase< DerivedBeq > &  Beq,
const Eigen::SparseMatrix< AieqT > &  Aieq,
const Eigen::PlainObjectBase< DerivedBieq > &  Bieq,
const Eigen::PlainObjectBase< Derivedlx > &  lx,
const Eigen::PlainObjectBase< Derivedux > &  ux,
const igl::active_set_params params,
Eigen::PlainObjectBase< DerivedZ > &  Z 
)
46{
47//#define ACTIVE_SET_CPP_DEBUG
48#if defined(ACTIVE_SET_CPP_DEBUG) && !defined(_MSC_VER)
49# warning "ACTIVE_SET_CPP_DEBUG"
50#endif
51 using namespace Eigen;
52 using namespace std;
54 const int n = A.rows();
55 assert(n == A.cols() && "A must be square");
56 // Discard const qualifiers
57 //if(B.size() == 0)
58 //{
59 // B = DerivedB::Zero(n,1);
60 //}
61 assert(n == B.rows() && "B.rows() must match A.rows()");
62 assert(B.cols() == 1 && "B must be a column vector");
63 assert(Y.cols() == 1 && "Y must be a column vector");
64 assert((Aeq.size() == 0 && Beq.size() == 0) || Aeq.cols() == n);
65 assert((Aeq.size() == 0 && Beq.size() == 0) || Aeq.rows() == Beq.rows());
66 assert((Aeq.size() == 0 && Beq.size() == 0) || Beq.cols() == 1);
67 assert((Aieq.size() == 0 && Bieq.size() == 0) || Aieq.cols() == n);
68 assert((Aieq.size() == 0 && Bieq.size() == 0) || Aieq.rows() == Bieq.rows());
69 assert((Aieq.size() == 0 && Bieq.size() == 0) || Bieq.cols() == 1);
72 if(p_lx.size() == 0)
73 {
74 lx = Derivedlx::Constant(
75 n,1,-numeric_limits<typename Derivedlx::Scalar>::max());
76 }else
77 {
78 lx = p_lx;
79 }
80 if(p_ux.size() == 0)
81 {
82 ux = Derivedux::Constant(
83 n,1,numeric_limits<typename Derivedux::Scalar>::max());
84 }else
85 {
86 ux = p_ux;
87 }
88 assert(lx.rows() == n && "lx must have n rows");
89 assert(ux.rows() == n && "ux must have n rows");
90 assert(ux.cols() == 1 && "lx must be a column vector");
91 assert(lx.cols() == 1 && "ux must be a column vector");
92 assert((ux.array()-lx.array()).minCoeff() > 0 && "ux(i) must be > lx(i)");
93 if(Z.size() != 0)
94 {
95 // Initial guess should have correct size
96 assert(Z.rows() == n && "Z must have n rows");
97 assert(Z.cols() == 1 && "Z must be a column vector");
98 }
99 assert(known.cols() == 1 && "known must be a column vector");
100 // Number of knowns
101 const int nk = known.size();
102
103 // Initialize active sets
104 typedef int BOOL;
105#define TRUE 1
106#define FALSE 0
110
111 // Keep track of previous Z for comparison
112 DerivedZ old_Z;
113 old_Z = DerivedZ::Constant(
114 n,1,numeric_limits<typename DerivedZ::Scalar>::max());
115
116 int iter = 0;
117 while(true)
118 {
119#ifdef ACTIVE_SET_CPP_DEBUG
120 cout<<"Iteration: "<<iter<<":"<<endl;
121 cout<<" pre"<<endl;
122#endif
123 // FIND BREACHES OF CONSTRAINTS
124 int new_as_lx = 0;
125 int new_as_ux = 0;
126 int new_as_ieq = 0;
127 if(Z.size() > 0)
128 {
129 for(int z = 0;z < n;z++)
130 {
131 if(Z(z) < lx(z))
132 {
133 new_as_lx += (as_lx(z)?0:1);
134 //new_as_lx++;
135 as_lx(z) = TRUE;
136 }
137 if(Z(z) > ux(z))
138 {
139 new_as_ux += (as_ux(z)?0:1);
140 //new_as_ux++;
141 as_ux(z) = TRUE;
142 }
143 }
144 if(Aieq.rows() > 0)
145 {
146 DerivedZ AieqZ;
147 AieqZ = Aieq*Z;
148 for(int a = 0;a<Aieq.rows();a++)
149 {
150 if(AieqZ(a) > Bieq(a))
151 {
152 new_as_ieq += (as_ieq(a)?0:1);
153 as_ieq(a) = TRUE;
154 }
155 }
156 }
157#ifdef ACTIVE_SET_CPP_DEBUG
158 cout<<" new_as_lx: "<<new_as_lx<<endl;
159 cout<<" new_as_ux: "<<new_as_ux<<endl;
160#endif
161 const double diff = (Z-old_Z).squaredNorm();
162#ifdef ACTIVE_SET_CPP_DEBUG
163 cout<<"diff: "<<diff<<endl;
164#endif
165 if(diff < params.solution_diff_threshold)
166 {
168 break;
169 }
170 old_Z = Z;
171 }
172
173 const int as_lx_count = std::count(as_lx.data(),as_lx.data()+n,TRUE);
174 const int as_ux_count = std::count(as_ux.data(),as_ux.data()+n,TRUE);
175 const int as_ieq_count =
176 std::count(as_ieq.data(),as_ieq.data()+as_ieq.size(),TRUE);
177#ifndef NDEBUG
178 {
179 int count = 0;
180 for(int a = 0;a<as_ieq.size();a++)
181 {
182 if(as_ieq(a))
183 {
184 assert(as_ieq(a) == TRUE);
185 count++;
186 }
187 }
188 assert(as_ieq_count == count);
189 }
190#endif
191
192 // PREPARE FIXED VALUES
193 Derivedknown known_i;
194 known_i.resize(nk + as_lx_count + as_ux_count,1);
195 DerivedY Y_i;
196 Y_i.resize(nk + as_lx_count + as_ux_count,1);
197 {
198 known_i.block(0,0,known.rows(),known.cols()) = known;
199 Y_i.block(0,0,Y.rows(),Y.cols()) = Y;
200 int k = nk;
201 // Then all lx
202 for(int z = 0;z < n;z++)
203 {
204 if(as_lx(z))
205 {
206 known_i(k) = z;
207 Y_i(k) = lx(z);
208 k++;
209 }
210 }
211 // Finally all ux
212 for(int z = 0;z < n;z++)
213 {
214 if(as_ux(z))
215 {
216 known_i(k) = z;
217 Y_i(k) = ux(z);
218 k++;
219 }
220 }
221 assert(k==Y_i.size());
222 assert(k==known_i.size());
223 }
224 //cout<<matlab_format((known_i.array()+1).eval(),"known_i")<<endl;
225 // PREPARE EQUALITY CONSTRAINTS
226 VectorXi as_ieq_list(as_ieq_count,1);
227 // Gather active constraints and resp. rhss
228 DerivedBeq Beq_i;
229 Beq_i.resize(Beq.rows()+as_ieq_count,1);
230 Beq_i.head(Beq.rows()) = Beq;
231 {
232 int k =0;
233 for(int a=0;a<as_ieq.size();a++)
234 {
235 if(as_ieq(a))
236 {
237 assert(k<as_ieq_list.size());
238 as_ieq_list(k)=a;
239 Beq_i(Beq.rows()+k,0) = Bieq(k,0);
240 k++;
241 }
242 }
243 assert(k == as_ieq_count);
244 }
245 // extract active constraint rows
246 SparseMatrix<AeqT> Aeq_i,Aieq_i;
247 slice(Aieq,as_ieq_list,1,Aieq_i);
248 // Append to equality constraints
249 cat(1,Aeq,Aieq_i,Aeq_i);
250
251
252 min_quad_with_fixed_data<AT> data;
253#ifndef NDEBUG
254 {
255 // NO DUPES!
257 for(int k = 0;k<known_i.size();k++)
258 {
259 assert(!fixed[known_i(k)]);
260 fixed[known_i(k)] = TRUE;
261 }
262 }
263#endif
264
265 DerivedZ sol;
266 if(known_i.size() == A.rows())
267 {
268 // Everything's fixed?
269#ifdef ACTIVE_SET_CPP_DEBUG
270 cout<<" everything's fixed."<<endl;
271#endif
272 Z.resize(A.rows(),Y_i.cols());
273 slice_into(Y_i,known_i,1,Z);
274 sol.resize(0,Y_i.cols());
275 assert(Aeq_i.rows() == 0 && "All fixed but linearly constrained");
276 }else
277 {
278#ifdef ACTIVE_SET_CPP_DEBUG
279 cout<<" min_quad_with_fixed_precompute"<<endl;
280#endif
281 if(!min_quad_with_fixed_precompute(A,known_i,Aeq_i,params.Auu_pd,data))
282 {
283 cerr<<"Error: min_quad_with_fixed precomputation failed."<<endl;
284 if(iter > 0 && Aeq_i.rows() > Aeq.rows())
285 {
286 cerr<<" *Are you sure rows of [Aeq;Aieq] are linearly independent?*"<<
287 endl;
288 }
290 break;
291 }
292#ifdef ACTIVE_SET_CPP_DEBUG
293 cout<<" min_quad_with_fixed_solve"<<endl;
294#endif
295 if(!min_quad_with_fixed_solve(data,B,Y_i,Beq_i,Z,sol))
296 {
297 cerr<<"Error: min_quad_with_fixed solve failed."<<endl;
299 break;
300 }
301 //cout<<matlab_format((Aeq*Z-Beq).eval(),"cr")<<endl;
302 //cout<<matlab_format(Z,"Z")<<endl;
303#ifdef ACTIVE_SET_CPP_DEBUG
304 cout<<" post"<<endl;
305#endif
306 // Computing Lagrange multipliers needs to be adjusted slightly if A is not symmetric
307 assert(data.Auu_sym);
308 }
309
310 // Compute Lagrange multiplier values for known_i
312 // Slow
313 slice(A,known_i,1,Ak);
314 DerivedB Bk;
315 slice(B,known_i,Bk);
316 MatrixXd Lambda_known_i = -(0.5*Ak*Z + 0.5*Bk);
317 // reverse the lambda values for lx
318 Lambda_known_i.block(nk,0,as_lx_count,1) =
319 (-1*Lambda_known_i.block(nk,0,as_lx_count,1)).eval();
320
321 // Extract Lagrange multipliers for Aieq_i (always at back of sol)
322 VectorXd Lambda_Aieq_i(Aieq_i.rows(),1);
323 for(int l = 0;l<Aieq_i.rows();l++)
324 {
325 Lambda_Aieq_i(Aieq_i.rows()-1-l) = sol(sol.rows()-1-l);
326 }
327
328 // Remove from active set
329 for(int l = 0;l<as_lx_count;l++)
330 {
331 if(Lambda_known_i(nk + l) < params.inactive_threshold)
332 {
333 as_lx(known_i(nk + l)) = FALSE;
334 }
335 }
336 for(int u = 0;u<as_ux_count;u++)
337 {
338 if(Lambda_known_i(nk + as_lx_count + u) <
339 params.inactive_threshold)
340 {
341 as_ux(known_i(nk + as_lx_count + u)) = FALSE;
342 }
343 }
344 for(int a = 0;a<as_ieq_count;a++)
345 {
346 if(Lambda_Aieq_i(a) < params.inactive_threshold)
347 {
348 as_ieq(as_ieq_list(a)) = FALSE;
349 }
350 }
351
352 iter++;
353 //cout<<iter<<endl;
354 if(params.max_iter>0 && iter>=params.max_iter)
355 {
357 break;
358 }
359
360 }
361
362 return ret;
363}
#define TRUE
#define FALSE
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:180
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index cols() const
Definition PlainObjectBase.h:153
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar * data() const
Definition PlainObjectBase.h:255
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index rows() const
Definition PlainObjectBase.h:151
Index size() const
Definition SparseMatrixBase.h:176
A versatible sparse matrix representation.
Definition SparseMatrix.h:98
Index rows() const
Definition SparseMatrix.h:136
Index cols() const
Definition SparseMatrix.h:138
Definition LDLT.h:16
@ Y
Definition libslic3r.h:99
@ Z
Definition libslic3r.h:100
Slic3r::Polygons diff(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:672
constexpr auto data(C &c) -> decltype(c.data())
Definition span.hpp:195
@ fixed
Definition fast_float.h:46
IGL_INLINE void count(const Eigen::SparseMatrix< XType > &X, const int dim, Eigen::SparseVector< SType > &S)
Definition count.cpp:12
IGL_INLINE void slice_into(const Eigen::SparseMatrix< T > &X, const Eigen::Matrix< int, Eigen::Dynamic, 1 > &R, const Eigen::Matrix< int, Eigen::Dynamic, 1 > &C, Eigen::SparseMatrix< T > &Y)
Definition slice_into.cpp:16
IGL_INLINE bool min_quad_with_fixed_solve(const min_quad_with_fixed_data< T > &data, const Eigen::MatrixBase< DerivedB > &B, const Eigen::MatrixBase< DerivedY > &Y, const Eigen::MatrixBase< DerivedBeq > &Beq, Eigen::PlainObjectBase< DerivedZ > &Z, Eigen::PlainObjectBase< Derivedsol > &sol)
Definition min_quad_with_fixed.cpp:389
SolverStatus
Definition SolverStatus.h:13
IGL_INLINE bool min_quad_with_fixed_precompute(const Eigen::SparseMatrix< T > &A, const Eigen::MatrixBase< Derivedknown > &known, const Eigen::SparseMatrix< T > &Aeq, const bool pd, min_quad_with_fixed_data< T > &data)
Definition min_quad_with_fixed.cpp:28
IGL_INLINE void slice(const Eigen::SparseMatrix< TX > &X, const Eigen::Matrix< int, Eigen::Dynamic, 1 > &R, const Eigen::Matrix< int, Eigen::Dynamic, 1 > &C, Eigen::SparseMatrix< TY > &Y)
Definition slice.cpp:15
IGL_INLINE void cat(const int dim, const Eigen::SparseMatrix< Scalar > &A, const Eigen::SparseMatrix< Scalar > &B, Eigen::SparseMatrix< Scalar > &C)
Definition cat.cpp:21
STL namespace.
bool Auu_pd
Definition active_set.h:93
double solution_diff_threshold
Definition active_set.h:97
int max_iter
Definition active_set.h:94
double inactive_threshold
Definition active_set.h:95

References igl::active_set_params::Auu_pd, cat(), Eigen::PlainObjectBase< Derived >::cols(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), count(), Eigen::PlainObjectBase< Derived >::data(), FALSE, igl::active_set_params::inactive_threshold, igl::active_set_params::max_iter, min_quad_with_fixed_precompute(), min_quad_with_fixed_solve(), Eigen::PlainObjectBase< Derived >::rows(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows(), Eigen::SparseMatrixBase< Derived >::size(), slice(), slice_into(), igl::active_set_params::solution_diff_threshold, SOLVER_STATUS_CONVERGED, SOLVER_STATUS_ERROR, SOLVER_STATUS_MAX_ITER, and TRUE.

Referenced by bbw().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ adjacency_list() [1/2]

template<typename Index , typename IndexVector >
IGL_INLINE void igl::adjacency_list ( const Eigen::PlainObjectBase< Index > &  F,
std::vector< std::vector< IndexVector > > &  A,
bool  sorted = false 
)
18{
19 A.clear();
20 A.resize(F.maxCoeff()+1);
21
22 // Loop over faces
23 for(int i = 0;i<F.rows();i++)
24 {
25 // Loop over this face
26 for(int j = 0;j<F.cols();j++)
27 {
28 // Get indices of edge: s --> d
29 int s = F(i,j);
30 int d = F(i,(j+1)%F.cols());
31 A.at(s).push_back(d);
32 A.at(d).push_back(s);
33 }
34 }
35
36 // Remove duplicates
37 for(int i=0; i<(int)A.size();++i)
38 {
39 std::sort(A[i].begin(), A[i].end());
40 A[i].erase(std::unique(A[i].begin(), A[i].end()), A[i].end());
41 }
42
43 // If needed, sort every VV
44 if (sorted)
45 {
46 // Loop over faces
47
48 // for every vertex v store a set of ordered edges not incident to v that belongs to triangle incident on v.
49 std::vector<std::vector<std::vector<int> > > SR;
50 SR.resize(A.size());
51
52 for(int i = 0;i<F.rows();i++)
53 {
54 // Loop over this face
55 for(int j = 0;j<F.cols();j++)
56 {
57 // Get indices of edge: s --> d
58 int s = F(i,j);
59 int d = F(i,(j+1)%F.cols());
60 // Get index of opposing vertex v
61 int v = F(i,(j+2)%F.cols());
62
63 std::vector<int> e(2);
64 e[0] = d;
65 e[1] = v;
66 SR[s].push_back(e);
67 }
68 }
69
70 for(int v=0; v<(int)SR.size();++v)
71 {
72 std::vector<IndexVector>& vv = A.at(v);
73 std::vector<std::vector<int> >& sr = SR[v];
74
75 std::vector<std::vector<int> > pn = sr;
76
77 // Compute previous/next for every element in sr
78 for(int i=0;i<(int)sr.size();++i)
79 {
80 int a = sr[i][0];
81 int b = sr[i][1];
82
83 // search for previous
84 int p = -1;
85 for(int j=0;j<(int)sr.size();++j)
86 if(sr[j][1] == a)
87 p = j;
88 pn[i][0] = p;
89
90 // search for next
91 int n = -1;
92 for(int j=0;j<(int)sr.size();++j)
93 if(sr[j][0] == b)
94 n = j;
95 pn[i][1] = n;
96
97 }
98
99 // assume manifoldness (look for beginning of a single chain)
100 int c = 0;
101 for(int j=0; j<=(int)sr.size();++j)
102 if (pn[c][0] != -1)
103 c = pn[c][0];
104
105 if (pn[c][0] == -1) // border case
106 {
107 // finally produce the new vv relation
108 for(int j=0; j<(int)sr.size();++j)
109 {
110 vv[j] = sr[c][0];
111 if (pn[c][1] != -1)
112 c = pn[c][1];
113 }
114 vv.back() = sr[c][1];
115 }
116 else
117 {
118 // finally produce the new vv relation
119 for(int j=0; j<(int)sr.size();++j)
120 {
121 vv[j] = sr[c][0];
122
123 c = pn[c][1];
124 }
125 }
126 }
127 }
128}
@ F
Definition libslic3r.h:102
S::iterator begin(S &sh, const PathTag &)
Definition geometry_traits.hpp:614
S::iterator end(S &sh, const PathTag &)
Definition geometry_traits.hpp:620

Referenced by igl::copyleft::cgal::cell_adjacency(), edges_to_path(), CurvatureCalculator::init(), and loop().

+ Here is the caller graph for this function:

◆ adjacency_list() [2/2]

template<typename Index >
IGL_INLINE void igl::adjacency_list ( const std::vector< std::vector< Index > > &  F,
std::vector< std::vector< Index > > &  A 
)
134{
135 A.clear();
136 A.resize(F.maxCoeff()+1);
137
138 // Loop over faces
139 for(int i = 0;i<F.size();i++)
140 {
141 // Loop over this face
142 for(int j = 0;j<F[i].size();j++)
143 {
144 // Get indices of edge: s --> d
145 int s = F(i,j);
146 int d = F(i,(j+1)%F[i].size());
147 A.at(s).push_back(d);
148 A.at(d).push_back(s);
149 }
150 }
151
152 // Remove duplicates
153 for(int i=0; i<(int)A.size();++i)
154 {
155 std::sort(A[i].begin(), A[i].end());
156 A[i].erase(std::unique(A[i].begin(), A[i].end()), A[i].end());
157 }
158
159}

◆ adjacency_matrix()

template<typename DerivedF , typename T >
IGL_INLINE void igl::adjacency_matrix ( const Eigen::MatrixBase< DerivedF > &  F,
Eigen::SparseMatrix< T > &  A 
)
18{
19 using namespace std;
20 using namespace Eigen;
21 typedef typename DerivedF::Scalar Index;
22
23 typedef Triplet<T> IJV;
24 vector<IJV > ijv;
25 ijv.reserve(F.size()*2);
26 // Loop over **simplex** (i.e., **not quad**)
27 for(int i = 0;i<F.rows();i++)
28 {
29 // Loop over this **simplex**
30 for(int j = 0;j<F.cols();j++)
31 for(int k = j+1;k<F.cols();k++)
32 {
33 // Get indices of edge: s --> d
34 Index s = F(i,j);
35 Index d = F(i,k);
36 ijv.push_back(IJV(s,d,1));
37 ijv.push_back(IJV(d,s,1));
38 }
39 }
40
41 const Index n = F.maxCoeff()+1;
42 A.resize(n,n);
43 switch(F.cols())
44 {
45 case 3:
46 A.reserve(6*(F.maxCoeff()+1));
47 break;
48 case 4:
49 A.reserve(26*(F.maxCoeff()+1));
50 break;
51 }
52 A.setFromTriplets(ijv.begin(),ijv.end());
53
54 // Force all non-zeros to be one
55
56 // Iterate over outside
57 for(int k=0; k<A.outerSize(); ++k)
58 {
59 // Iterate over inside
60 for(typename Eigen::SparseMatrix<T>::InnerIterator it (A,k); it; ++it)
61 {
62 assert(it.value() != 0);
63 A.coeffRef(it.row(),it.col()) = 1;
64 }
65 }
66}
Definition SparseCompressedBase.h:137
void reserve(Index reserveSize)
Definition SparseMatrix.h:262
Index outerSize() const
Definition SparseMatrix.h:143
void setFromTriplets(const InputIterators &begin, const InputIterators &end)
Definition SparseMatrix.h:993
Scalar & coeffRef(Index row, Index col)
Definition SparseMatrix.h:206
void resize(Index rows, Index cols)
Definition SparseMatrix.h:621
A small structure to hold a non zero as a triplet (i,j,value).
Definition SparseUtil.h:155
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:33

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::coeffRef(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::outerSize(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::reserve(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::resize(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets().

Referenced by components(), edges(), harmonic(), and straighten_seams().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ all()

template<typename AType , typename DerivedB >
IGL_INLINE void igl::all ( const Eigen::SparseMatrix< AType > &  A,
const int  dim,
Eigen::PlainObjectBase< DerivedB > &  B 
)
17{
18 typedef typename DerivedB::Scalar Scalar;
19 igl::redux(A,dim,[](Scalar a, Scalar b){ return a && b!=0;},B);
20}
void redux(const Eigen::SparseMatrix< AType > &A, const int dim, const Func &func, Eigen::PlainObjectBase< DerivedB > &B)
Definition redux.h:41

References redux().

Referenced by is_edge_manifold(), is_vertex_manifold(), limit_faces(), igl::copyleft::cgal::minkowski_sum(), and octree().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ all_edges()

template<typename DerivedF , typename DerivedE >
IGL_INLINE void igl::all_edges ( const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedE > &  E 
)
15{
16 return oriented_facets(F,E);
17}
IGL_INLINE void oriented_facets(const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedE > &E)
Definition oriented_facets.cpp:11

References oriented_facets().

+ Here is the call graph for this function:

◆ all_pairs_distances()

template<typename Mat >
IGL_INLINE void igl::all_pairs_distances ( const Mat &  V,
const Mat &  U,
const bool  squared,
Mat &  D 
)
17{
18 // dimension should be the same
19 assert(V.cols() == U.cols());
20 // resize output
21 D.resize(V.rows(),U.rows());
22 for(int i = 0;i<V.rows();i++)
23 {
24 for(int j=0;j<U.rows();j++)
25 {
26 D(i,j) = (V.row(i)-U.row(j)).squaredNorm();
27 if(!squared)
28 {
29 D(i,j) = sqrt(D(i,j));
30 }
31 }
32 }
33}
EIGEN_DEVICE_FUNC const SqrtReturnType sqrt() const
Definition ArrayCwiseUnaryOps.h:152

References sqrt().

Referenced by uniformly_sample_two_manifold_at_vertices().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ambient_occlusion() [1/3]

template<typename DerivedV , typename DerivedF , typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void igl::ambient_occlusion ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedP > &  P,
const Eigen::PlainObjectBase< DerivedN > &  N,
const int  num_samples,
Eigen::PlainObjectBase< DerivedS > &  S 
)
109{
110 if(F.rows() < 100)
111 {
112 // Super naive
113 const auto & shoot_ray = [&V,&F](
114 const Eigen::Vector3f& _s,
115 const Eigen::Vector3f& dir)->bool
116 {
117 Eigen::Vector3f s = _s+1e-4*dir;
118 igl::Hit hit;
119 return ray_mesh_intersect(s,dir,V,F,hit);
120 };
121 return ambient_occlusion(shoot_ray,P,N,num_samples,S);
122 }
123 AABB<DerivedV,3> aabb;
124 aabb.init(V,F);
125 return ambient_occlusion(aabb,V,F,P,N,num_samples,S);
126}
IGL_INLINE void ambient_occlusion(const std::function< bool(const Eigen::Vector3f &, const Eigen::Vector3f &) > &shoot_ray, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedN > &N, const int num_samples, Eigen::PlainObjectBase< DerivedS > &S)
Definition ambient_occlusion.cpp:22
IGL_INLINE bool ray_mesh_intersect(const Eigen::MatrixBase< Derivedsource > &source, const Eigen::MatrixBase< Deriveddir > &dir, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, std::vector< igl::Hit > &hits)
Definition ray_mesh_intersect.cpp:20
Definition Hit.h:18

References ambient_occlusion(), igl::AABB< DerivedV, DIM >::init(), and ray_mesh_intersect().

+ Here is the call graph for this function:

◆ ambient_occlusion() [2/3]

template<typename DerivedV , int DIM, typename DerivedF , typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void igl::ambient_occlusion ( const igl::AABB< DerivedV, DIM > &  aabb,
const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedP > &  P,
const Eigen::PlainObjectBase< DerivedN > &  N,
const int  num_samples,
Eigen::PlainObjectBase< DerivedS > &  S 
)
78{
79 const auto & shoot_ray = [&aabb,&V,&F](
80 const Eigen::Vector3f& _s,
81 const Eigen::Vector3f& dir)->bool
82 {
83 Eigen::Vector3f s = _s+1e-4*dir;
84 igl::Hit hit;
85 return aabb.intersect_ray(
86 V,
87 F,
88 s .cast<typename DerivedV::Scalar>().eval(),
89 dir.cast<typename DerivedV::Scalar>().eval(),
90 hit);
91 };
92 return ambient_occlusion(shoot_ray,P,N,num_samples,S);
93
94}
IGL_INLINE bool intersect_ray(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedEle > &Ele, const RowVectorDIMS &origin, const RowVectorDIMS &dir, std::vector< igl::Hit > &hits) const
Definition AABB.cpp:838

References ambient_occlusion(), and igl::AABB< DerivedV, DIM >::intersect_ray().

+ Here is the call graph for this function:

◆ ambient_occlusion() [3/3]

template<typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void igl::ambient_occlusion ( const std::function< bool(const Eigen::Vector3f &, const Eigen::Vector3f &) > &  shoot_ray,
const Eigen::PlainObjectBase< DerivedP > &  P,
const Eigen::PlainObjectBase< DerivedN > &  N,
const int  num_samples,
Eigen::PlainObjectBase< DerivedS > &  S 
)
32{
33 using namespace Eigen;
34 const int n = P.rows();
35 // Resize output
36 S.resize(n,1);
37 // Embree seems to be parallel when constructing but not when tracing rays
38 const MatrixXf D = random_dir_stratified(num_samples).cast<float>();
39
40 const auto & inner = [&P,&N,&num_samples,&D,&S,&shoot_ray](const int p)
41 {
42 const Vector3f origin = P.row(p).template cast<float>();
43 const Vector3f normal = N.row(p).template cast<float>();
44 int num_hits = 0;
45 for(int s = 0;s<num_samples;s++)
46 {
47 Vector3f d = D.row(s);
48 if(d.dot(normal) < 0)
49 {
50 // reverse ray
51 d *= -1;
52 }
53 if(shoot_ray(origin,d))
54 {
55 num_hits++;
56 }
57 }
58 S(p) = (double)num_hits/(double)num_samples;
59 };
60 parallel_for(n,inner,1000);
61}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
Definition PlainObjectBase.h:279
bool parallel_for(const Index loop_size, const FunctionType &func, const size_t min_parallel=0)
Definition parallel_for.h:99
IGL_INLINE Eigen::MatrixXd random_dir_stratified(const int n)
Definition random_dir.cpp:24

References parallel_for(), random_dir_stratified(), Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::rows().

Referenced by ambient_occlusion(), igl::embree::ambient_occlusion(), igl::embree::ambient_occlusion(), and ambient_occlusion().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ angular_distance()

IGL_INLINE double igl::angular_distance ( const Eigen::Quaterniond A,
const Eigen::Quaterniond B 
)
14{
15 assert(fabs(A.norm()-1)<FLOAT_EPS && "A should be unit norm");
16 assert(fabs(B.norm()-1)<FLOAT_EPS && "B should be unit norm");
18 //return acos(fabs(A.dot(B)));
19 return fmod(2.*acos(A.dot(B)),2.*PI);
20}
EIGEN_DEVICE_FUNC const AcosReturnType acos() const
Definition ArrayCwiseUnaryOps.h:262
EIGEN_DEVICE_FUNC Scalar norm() const
Definition Quaternion.h:125
EIGEN_DEVICE_FUNC Scalar dot(const QuaternionBase< OtherDerived > &other) const
Definition Quaternion.h:139
static constexpr double PI
Definition libslic3r.h:58

References acos(), Eigen::QuaternionBase< Derived >::dot(), FLOAT_EPS, Eigen::QuaternionBase< Derived >::norm(), and PI.

+ Here is the call graph for this function:

◆ any()

template<typename AType , typename DerivedB >
IGL_INLINE void igl::any ( const Eigen::SparseMatrix< AType > &  A,
const int  dim,
Eigen::PlainObjectBase< DerivedB > &  B 
)
17{
18 typedef typename DerivedB::Scalar Scalar;
19 igl::redux(A,dim,[](Scalar a, Scalar b){ return a || b!=0;},B);
20}

References redux().

Referenced by limit_faces(), and straighten_seams().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ any_of()

template<typename Mat >
IGL_INLINE bool igl::any_of ( const Mat &  S)
12{
13 return std::any_of(S.data(),S.data()+S.size(),[](bool s){return s;});
14}

◆ arap_dof_precomputation()

template<typename LbsMatrixType , typename SSCALAR >
IGL_INLINE bool igl::arap_dof_precomputation ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const LbsMatrixType &  M,
const Eigen::Matrix< int, Eigen::Dynamic, 1 > &  G,
ArapDOFData< LbsMatrixType, SSCALAR > &  data 
)
46{
47 using namespace Eigen;
48 typedef Matrix<SSCALAR, Dynamic, Dynamic> MatrixXS;
49 // number of mesh (domain) vertices
50 int n = V.rows();
51 // cache problem size
52 data.n = n;
53 // dimension of mesh
54 data.dim = V.cols();
55 assert(data.dim == M.rows()/n);
56 assert(data.dim*n == M.rows());
57 if(data.dim == 3)
58 {
59 // Check if z-coordinate is all zeros
60 if(V.col(2).minCoeff() == 0 && V.col(2).maxCoeff() == 0)
61 {
62 data.effective_dim = 2;
63 }
64 }else
65 {
66 data.effective_dim = data.dim;
67 }
68 // Number of handles
69 data.m = M.cols()/data.dim/(data.dim+1);
70 assert(data.m*data.dim*(data.dim+1) == M.cols());
71 //assert(m == C.rows());
72
73 //printf("n=%d; dim=%d; m=%d;\n",n,data.dim,data.m);
74
75 // Build cotangent laplacian
77 //printf("cotmatrix()\n");
78 cotmatrix(V,F,Lcot);
79 // Discrete laplacian (should be minus matlab version)
80 SparseMatrix<double> Lapl = -2.0*Lcot;
81#ifdef EXTREME_VERBOSE
82 cout<<"LaplIJV=["<<endl;print_ijv(Lapl,1);cout<<endl<<"];"<<
83 endl<<"Lapl=sparse(LaplIJV(:,1),LaplIJV(:,2),LaplIJV(:,3),"<<
84 Lapl.rows()<<","<<Lapl.cols()<<");"<<endl;
85#endif
86
87 // Get group sum scatter matrix, when applied sums all entries of the same
88 // group according to G
90 if(G.size() == 0)
91 {
92 speye(n,G_sum);
93 }else
94 {
95 // groups are defined per vertex, convert to per face using mode
97 if(data.energy == ARAP_ENERGY_TYPE_ELEMENTS)
98 {
99 MatrixXi GF(F.rows(),F.cols());
100 for(int j = 0;j<F.cols();j++)
101 {
103 slice(G,F.col(j),GFj);
104 GF.col(j) = GFj;
105 }
106 mode<int>(GF,2,GG);
107 }else
108 {
109 GG=G;
110 }
111 //printf("group_sum_matrix()\n");
112 group_sum_matrix(GG,G_sum);
113 }
114
115#ifdef EXTREME_VERBOSE
116 cout<<"G_sumIJV=["<<endl;print_ijv(G_sum,1);cout<<endl<<"];"<<
117 endl<<"G_sum=sparse(G_sumIJV(:,1),G_sumIJV(:,2),G_sumIJV(:,3),"<<
118 G_sum.rows()<<","<<G_sum.cols()<<");"<<endl;
119#endif
120
121 // Get covariance scatter matrix, when applied collects the covariance matrices
122 // used to fit rotations to during optimization
124 //printf("covariance_scatter_matrix()\n");
125 covariance_scatter_matrix(V,F,data.energy,CSM);
126#ifdef EXTREME_VERBOSE
127 cout<<"CSMIJV=["<<endl;print_ijv(CSM,1);cout<<endl<<"];"<<
128 endl<<"CSM=sparse(CSMIJV(:,1),CSMIJV(:,2),CSMIJV(:,3),"<<
129 CSM.rows()<<","<<CSM.cols()<<");"<<endl;
130#endif
131
132
133 // Build the covariance matrix "constructor". This is a set of *scatter*
134 // matrices that when multiplied on the right by column of the transformation
135 // matrix entries (the degrees of freedom) L, we get a stack of dim by 1
136 // covariance matrix column, with a column in the stack for each rotation
137 // *group*. The output is a list of matrices because we construct each column
138 // in the stack of covariance matrices with an independent matrix-vector
139 // multiplication.
140 //
141 // We want to build S which is a stack of dim by dim covariance matrices.
142 // Thus S is dim*g by dim, where dim is the number of dimensions and g is the
143 // number of groups. We can precompute dim matrices CSM_M such that column i
144 // in S is computed as S(:,i) = CSM_M{i} * L, where L is a column of the
145 // skinning transformation matrix values. To be clear, the covariance matrix
146 // for group k is then given as the dim by dim matrix pulled from the stack:
147 // S((k-1)*dim + 1:dim,:)
148
149 // Apply group sum to each dimension's block of covariance scatter matrix
150 SparseMatrix<double> G_sum_dim;
151 repdiag(G_sum,data.dim,G_sum_dim);
152 CSM = (G_sum_dim * CSM).eval();
153#ifdef EXTREME_VERBOSE
154 cout<<"CSMIJV=["<<endl;print_ijv(CSM,1);cout<<endl<<"];"<<
155 endl<<"CSM=sparse(CSMIJV(:,1),CSMIJV(:,2),CSMIJV(:,3),"<<
156 CSM.rows()<<","<<CSM.cols()<<");"<<endl;
157#endif
158
159 //printf("CSM_M()\n");
160 // Precompute CSM times M for each dimension
161 data.CSM_M.resize(data.dim);
162#ifdef EXTREME_VERBOSE
163 cout<<"data.CSM_M = cell("<<data.dim<<",1);"<<endl;
164#endif
165 // span of integers from 0 to n-1
167 for(int i = 0;i<n;i++)
168 {
169 span_n(i) = i;
170 }
171
172 // span of integers from 0 to M.cols()-1
173 Eigen::Matrix<int,Eigen::Dynamic,1> span_mlbs_cols(M.cols());
174 for(int i = 0;i<M.cols();i++)
175 {
176 span_mlbs_cols(i) = i;
177 }
178
179 // number of groups
180 int k = CSM.rows()/data.dim;
181 for(int i = 0;i<data.dim;i++)
182 {
183 //printf("CSM_M(): Mi\n");
184 LbsMatrixType M_i;
185 //printf("CSM_M(): slice\n");
186 slice(M,(span_n.array()+i*n).matrix().eval(),span_mlbs_cols,M_i);
187 LbsMatrixType M_i_dim;
188 data.CSM_M[i].resize(k*data.dim,data.m*data.dim*(data.dim+1));
189 assert(data.CSM_M[i].cols() == M.cols());
190 for(int j = 0;j<data.dim;j++)
191 {
193 //printf("CSM_M(): slice\n");
194 slice(
195 CSM,
196 colon<int>(j*k,(j+1)*k-1),
197 colon<int>(j*n,(j+1)*n-1),
198 CSMj);
199 assert(CSMj.rows() == k);
200 assert(CSMj.cols() == n);
201 LbsMatrixType CSMjM_i = CSMj * M_i;
202 if(is_sparse(CSMjM_i))
203 {
204 // Convert to full
205 //printf("CSM_M(): full\n");
206 MatrixXd CSMjM_ifull(CSMjM_i);
207// printf("CSM_M[%d]: %d %d\n",i,data.CSM_M[i].rows(),data.CSM_M[i].cols());
208// printf("CSM_M[%d].block(%d*%d=%d,0,%d,%d): %d %d\n",i,j,k,CSMjM_i.rows(),CSMjM_i.cols(),
209// data.CSM_M[i].block(j*k,0,CSMjM_i.rows(),CSMjM_i.cols()).rows(),
210// data.CSM_M[i].block(j*k,0,CSMjM_i.rows(),CSMjM_i.cols()).cols());
211// printf("CSM_MjMi: %d %d\n",i,CSMjM_i.rows(),CSMjM_i.cols());
212// printf("CSM_MjM_ifull: %d %d\n",i,CSMjM_ifull.rows(),CSMjM_ifull.cols());
213 data.CSM_M[i].block(j*k,0,CSMjM_i.rows(),CSMjM_i.cols()) = CSMjM_ifull;
214 }else
215 {
216 data.CSM_M[i].block(j*k,0,CSMjM_i.rows(),CSMjM_i.cols()) = CSMjM_i;
217 }
218 }
219#ifdef EXTREME_VERBOSE
220 cout<<"CSM_Mi=["<<endl<<data.CSM_M[i]<<endl<<"];"<<endl;
221#endif
222 }
223
224 // precompute arap_rhs matrix
225 //printf("arap_rhs()\n");
227 arap_rhs(V,F,V.cols(),data.energy,K);
228//#ifdef EXTREME_VERBOSE
229// cout<<"KIJV=["<<endl;print_ijv(K,1);cout<<endl<<"];"<<
230// endl<<"K=sparse(KIJV(:,1),KIJV(:,2),KIJV(:,3),"<<
231// K.rows()<<","<<K.cols()<<");"<<endl;
232//#endif
233 // Precompute left muliplication by M and right multiplication by G_sum
234 SparseMatrix<double> G_sumT = G_sum.transpose();
235 SparseMatrix<double> G_sumT_dim_dim;
236 repdiag(G_sumT,data.dim*data.dim,G_sumT_dim_dim);
237 LbsMatrixType MT = M.transpose();
238 // If this is a bottle neck then consider reordering matrix multiplication
239 data.M_KG = -4.0 * (MT * (K * G_sumT_dim_dim));
240//#ifdef EXTREME_VERBOSE
241// cout<<"data.M_KGIJV=["<<endl;print_ijv(data.M_KG,1);cout<<endl<<"];"<<
242// endl<<"data.M_KG=sparse(data.M_KGIJV(:,1),data.M_KGIJV(:,2),data.M_KGIJV(:,3),"<<
243// data.M_KG.rows()<<","<<data.M_KG.cols()<<");"<<endl;
244//#endif
245
246 // Precompute system matrix
247 //printf("A()\n");
249 repdiag(Lapl,data.dim,A);
250 data.Q = MT * (A * M);
251//#ifdef EXTREME_VERBOSE
252// cout<<"QIJV=["<<endl;print_ijv(data.Q,1);cout<<endl<<"];"<<
253// endl<<"Q=sparse(QIJV(:,1),QIJV(:,2),QIJV(:,3),"<<
254// data.Q.rows()<<","<<data.Q.cols()<<");"<<endl;
255//#endif
256
257 // Always do dynamics precomputation so we can hot-switch
258 //if(data.with_dynamics)
259 //{
260 // Build cotangent laplacian
262 //printf("massmatrix()\n");
263 massmatrix(V,F,(F.cols()>3?MASSMATRIX_TYPE_BARYCENTRIC:MASSMATRIX_TYPE_VORONOI),Mass);
264 //cout<<"MIJV=["<<endl;print_ijv(Mass,1);cout<<endl<<"];"<<
265 // endl<<"M=sparse(MIJV(:,1),MIJV(:,2),MIJV(:,3),"<<
266 // Mass.rows()<<","<<Mass.cols()<<");"<<endl;
267 //speye(data.n,Mass);
268 SparseMatrix<double> Mass_rep;
269 repdiag(Mass,data.dim,Mass_rep);
270
271 // Multiply either side by weights matrix (should be dense)
272 data.Mass_tilde = MT * Mass_rep * M;
273 MatrixXd ones(data.dim*data.n,data.dim);
274 for(int i = 0;i<data.n;i++)
275 {
276 for(int d = 0;d<data.dim;d++)
277 {
278 ones(i+d*data.n,d) = 1;
279 }
280 }
281 data.fgrav = MT * (Mass_rep * ones);
282 data.fext = MatrixXS::Zero(MT.rows(),1);
283 //data.fgrav = MT * (ones);
284 //}
285
286
287 // This may/should be superfluous
288 //printf("is_symmetric()\n");
289 if(!is_symmetric(data.Q))
290 {
291 //printf("Fixing symmetry...\n");
292 // "Fix" symmetry
293 LbsMatrixType QT = data.Q.transpose();
294 LbsMatrixType Q_copy = data.Q;
295 data.Q = 0.5*(Q_copy+QT);
296 // Check that ^^^ this really worked. It doesn't always
297 //assert(is_symmetric(*Q));
298 }
299
300 //printf("arap_dof_precomputation() succeeded... so far...\n");
301 verbose("Number of handles: %i\n", data.m);
302 return true;
303}
int verbose
Definition main.c:198
TransposeReturnType transpose()
Definition SparseMatrixBase.h:349
CGAL::Simple_cartesian< double > K
Definition VoronoiUtilsCgal.cpp:19
IGL_INLINE void print_ijv(const Eigen::SparseMatrix< T > &X, const int offset=0)
Definition print_ijv.cpp:14
IGL_INLINE void speye(const int n, const int m, Eigen::SparseMatrix< T > &I)
Definition speye.cpp:11
IGL_INLINE void arap_rhs(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const int dim, const igl::ARAPEnergyType energy, Eigen::SparseMatrix< double > &K)
Definition arap_rhs.cpp:15
IGL_INLINE bool is_symmetric(const Eigen::SparseMatrix< AT > &A)
IGL_INLINE void cotmatrix(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::SparseMatrix< Scalar > &L)
Definition cotmatrix.cpp:19
IGL_INLINE bool is_sparse(const Eigen::SparseMatrix< T > &A)
Definition is_sparse.cpp:10
IGL_INLINE void covariance_scatter_matrix(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const ARAPEnergyType energy, Eigen::SparseMatrix< double > &CSM)
Definition covariance_scatter_matrix.cpp:18
IGL_INLINE void group_sum_matrix(const Eigen::Matrix< int, Eigen::Dynamic, 1 > &G, const int k, Eigen::SparseMatrix< T > &A)
Definition group_sum_matrix.cpp:11
IGL_INLINE void repdiag(const Eigen::SparseMatrix< T > &A, const int d, Eigen::SparseMatrix< T > &B)
Definition repdiag.cpp:12
IGL_INLINE void massmatrix(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const MassMatrixType type, Eigen::SparseMatrix< Scalar > &M)
Definition massmatrix.cpp:17

References ARAP_ENERGY_TYPE_ELEMENTS, arap_rhs(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), cotmatrix(), covariance_scatter_matrix(), group_sum_matrix(), is_sparse(), is_symmetric(), massmatrix(), MASSMATRIX_TYPE_BARYCENTRIC, MASSMATRIX_TYPE_VORONOI, print_ijv(), repdiag(), Eigen::PlainObjectBase< Derived >::rows(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows(), slice(), speye(), Eigen::SparseMatrixBase< Derived >::transpose(), and verbose.

+ Here is the call graph for this function:

◆ arap_dof_recomputation()

template<typename LbsMatrixType , typename SSCALAR >
IGL_INLINE bool igl::arap_dof_recomputation ( const Eigen::Matrix< int, Eigen::Dynamic, 1 > &  fixed_dim,
const Eigen::SparseMatrix< double > &  A_eq,
ArapDOFData< LbsMatrixType, SSCALAR > &  data 
)
500{
501 using namespace Eigen;
502 typedef Matrix<SSCALAR, Dynamic, Dynamic> MatrixXS;
503
504 LbsMatrixType * Q;
505 LbsMatrixType Qdyn;
506 if(data.with_dynamics)
507 {
508 // multiply by 1/timestep and to quadratic coefficients matrix
509 // Might be missing a 0.5 here
510 LbsMatrixType Q_copy = data.Q;
511 Qdyn = Q_copy + (1.0/(data.h*data.h))*data.Mass_tilde;
512 Q = &Qdyn;
513
514 // This may/should be superfluous
515 //printf("is_symmetric()\n");
516 if(!is_symmetric(*Q))
517 {
518 //printf("Fixing symmetry...\n");
519 // "Fix" symmetry
520 LbsMatrixType QT = (*Q).transpose();
521 LbsMatrixType Q_copy = *Q;
522 *Q = 0.5*(Q_copy+QT);
523 // Check that ^^^ this really worked. It doesn't always
524 //assert(is_symmetric(*Q));
525 }
526 }else
527 {
528 Q = &data.Q;
529 }
530
531 assert((int)data.CSM_M.size() == data.dim);
532 assert(A_eq.cols() == data.m*data.dim*(data.dim+1));
533 data.fixed_dim = fixed_dim;
534
535 if(fixed_dim.size() > 0)
536 {
537 assert(fixed_dim.maxCoeff() < data.m*data.dim*(data.dim+1));
538 assert(fixed_dim.minCoeff() >= 0);
539 }
540
541#ifdef EXTREME_VERBOSE
542 cout<<"data.fixed_dim=["<<endl<<data.fixed_dim<<endl<<"]+1;"<<endl;
543#endif
544
545 // Compute dense solve matrix (alternative of matrix factorization)
546 //printf("min_quad_dense_precompute()\n");
547 MatrixXd Qfull(*Q);
548 MatrixXd A_eqfull(A_eq);
549 MatrixXd M_Solve;
550
551 double timer0_start = get_seconds_hires();
552 bool use_lu = data.effective_dim != 2;
553 //use_lu = false;
554 //printf("use_lu: %s\n",(use_lu?"TRUE":"FALSE"));
555 min_quad_dense_precompute(Qfull, A_eqfull, use_lu,M_Solve);
556 double timer0_end = get_seconds_hires();
557 verbose("Bob timing: %.20f\n", (timer0_end - timer0_start)*1000.0);
558
559 // Precompute full solve matrix:
560 const int fsRows = data.m * data.dim * (data.dim + 1); // 12 * number_of_bones
561 const int fsCols1 = data.M_KG.cols(); // 9 * number_of_posConstraints
562 const int fsCols2 = A_eq.rows(); // number_of_posConstraints
563 data.M_FullSolve.resize(fsRows, fsCols1 + fsCols2);
564 // note the magical multiplicative constant "-0.5", I've no idea why it has
565 // to be there :)
566 data.M_FullSolve <<
567 (-0.5 * M_Solve.block(0, 0, fsRows, fsRows) * data.M_KG).template cast<SSCALAR>(),
568 M_Solve.block(0, fsRows, fsRows, fsCols2).template cast<SSCALAR>();
569
570 if(data.with_dynamics)
571 {
572 printf(
573 "---------------------------------------------------------------------\n"
574 "\n\n\nWITH DYNAMICS recomputation\n\n\n"
575 "---------------------------------------------------------------------\n"
576 );
577 // Also need to save Π1 before it gets multiplied by Ktilde (aka M_KG)
578 data.Pi_1 = M_Solve.block(0, 0, fsRows, fsRows).template cast<SSCALAR>();
579 }
580
581 // Precompute condensed matrices,
582 // first CSM:
583 std::vector<MatrixXS> CSM_M_SSCALAR;
584 CSM_M_SSCALAR.resize(data.dim);
585 for (int i=0; i<data.dim; i++) CSM_M_SSCALAR[i] = data.CSM_M[i].template cast<SSCALAR>();
586 SSCALAR maxErr1 = condense_CSM(CSM_M_SSCALAR, data.m, data.dim, data.CSM);
587 verbose("condense_CSM maxErr = %.15f (this should be close to zero)\n", maxErr1);
588 assert(fabs(maxErr1) < 1e-5);
589
590 // and then solveBlock1:
591 // number of groups
592 const int k = data.CSM_M[0].rows()/data.dim;
593 MatrixXS SolveBlock1 = data.M_FullSolve.block(0, 0, data.M_FullSolve.rows(), data.dim * data.dim * k);
594 SSCALAR maxErr2 = condense_Solve1(SolveBlock1, data.m, k, data.dim, data.CSolveBlock1);
595 verbose("condense_Solve1 maxErr = %.15f (this should be close to zero)\n", maxErr2);
596 assert(fabs(maxErr2) < 1e-5);
597
598 return true;
599}
static MatrixXS::Scalar condense_CSM(const std::vector< MatrixXS > &CSM_M_SSCALAR, int numBones, int dim, MatrixXS &CSM)
Definition arap_dof.cpp:346
IGL_INLINE double get_seconds_hires()
Definition get_seconds_hires.cpp:24
IGL_INLINE void min_quad_dense_precompute(const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &A, const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &Aeq, const bool use_lu_decomposition, Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &S)
Definition min_quad_dense.cpp:16
static MatrixXS::Scalar condense_Solve1(MatrixXS &Solve1, int numBones, int numGroups, int dim, MatrixXS &CSolve1)
Definition arap_dof.cpp:456

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), condense_CSM(), condense_Solve1(), get_seconds_hires(), is_symmetric(), min_quad_dense_precompute(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows(), and verbose.

+ Here is the call graph for this function:

◆ arap_dof_update()

template<typename LbsMatrixType , typename SSCALAR >
IGL_INLINE bool igl::arap_dof_update ( const ArapDOFData< LbsMatrixType, SSCALAR > &  data,
const Eigen::Matrix< double, Eigen::Dynamic, 1 > &  B_eq,
const Eigen::MatrixXd &  L0,
const int  max_iters,
const double  tol,
Eigen::MatrixXd &  L 
)
615{
616 using namespace Eigen;
617 typedef Matrix<SSCALAR, Dynamic, Dynamic> MatrixXS;
618#ifdef ARAP_GLOBAL_TIMING
619 double timer_start = get_seconds_hires();
620#endif
621
622 // number of dimensions
623 assert((int)data.CSM_M.size() == data.dim);
624 assert((int)L0.size() == (data.m)*data.dim*(data.dim+1));
625 assert(max_iters >= 0);
626 assert(tol >= 0);
627
628 // timing variables
629 double
630 sec_start,
631 sec_covGather,
632 sec_fitRotations,
633 //sec_rhs,
634 sec_prepMult,
635 sec_solve, sec_end;
636
637 assert(L0.cols() == 1);
638#ifdef EXTREME_VERBOSE
639 cout<<"dim="<<data.dim<<";"<<endl;
640 cout<<"m="<<data.m<<";"<<endl;
641#endif
642
643 // number of groups
644 const int k = data.CSM_M[0].rows()/data.dim;
645 for(int i = 0;i<data.dim;i++)
646 {
647 assert(data.CSM_M[i].rows()/data.dim == k);
648 }
649#ifdef EXTREME_VERBOSE
650 cout<<"k="<<k<<";"<<endl;
651#endif
652
653 // resize output and initialize with initial guess
654 L = L0;
655#ifndef IGL_ARAP_DOF_FIXED_ITERATIONS_COUNT
656 // Keep track of last solution
657 MatrixXS L_prev;
658#endif
659 // We will be iterating on L_SSCALAR, only at the end we convert back to double
660 MatrixXS L_SSCALAR = L.cast<SSCALAR>();
661
662 int iters = 0;
663#ifndef IGL_ARAP_DOF_FIXED_ITERATIONS_COUNT
664 double max_diff = tol+1;
665#endif
666
667 MatrixXS S(k*data.dim,data.dim);
668 MatrixXS R(data.dim,data.dim*k);
669 Eigen::Matrix<SSCALAR,Eigen::Dynamic,1> Rcol(data.dim * data.dim * k);
670 Matrix<SSCALAR,Dynamic,1> B_eq_SSCALAR = B_eq.cast<SSCALAR>();
671 Matrix<SSCALAR,Dynamic,1> B_eq_fix_SSCALAR;
672 Matrix<SSCALAR,Dynamic,1> L0SSCALAR = L0.cast<SSCALAR>();
673 slice(L0SSCALAR, data.fixed_dim, B_eq_fix_SSCALAR);
674 //MatrixXS rhsFull(Rcol.rows() + B_eq.rows() + B_eq_fix_SSCALAR.rows(), 1);
675
676 MatrixXS Lsep(data.m*(data.dim + 1), 3);
677 const MatrixXS L_part2 =
678 data.M_FullSolve.block(0, Rcol.rows(), data.M_FullSolve.rows(), B_eq_SSCALAR.rows()) * B_eq_SSCALAR;
679 const MatrixXS L_part3 =
680 data.M_FullSolve.block(0, Rcol.rows() + B_eq_SSCALAR.rows(), data.M_FullSolve.rows(), B_eq_fix_SSCALAR.rows()) * B_eq_fix_SSCALAR;
681 MatrixXS L_part2and3 = L_part2 + L_part3;
682
683 // preallocate workspace variables:
684 MatrixXS Rxyz(k*data.dim, data.dim);
685 MatrixXS L_part1xyz((data.dim + 1) * data.m, data.dim);
686 MatrixXS L_part1(data.dim * (data.dim + 1) * data.m, 1);
687
688#ifdef ARAP_GLOBAL_TIMING
689 double timer_prepFinished = get_seconds_hires();
690#endif
691
692#ifdef IGL_ARAP_DOF_FIXED_ITERATIONS_COUNT
693 while(iters < max_iters)
694#else
695 while(iters < max_iters && max_diff > tol)
696#endif
697 {
698 if(data.print_timings)
699 {
700 sec_start = get_seconds_hires();
701 }
702
703#ifndef IGL_ARAP_DOF_FIXED_ITERATIONS_COUNT
704 L_prev = L_SSCALAR;
705#endif
707 // Local step: Fix positions, fit rotations
709
710 // Gather covariance matrices
711
712 splitColumns(L_SSCALAR, data.m, data.dim, data.dim + 1, Lsep);
713
714 S = data.CSM * Lsep;
715 // interestingly, this doesn't seem to be so slow, but
716 //MKL is still 2x faster (probably due to AVX)
717 //#ifdef IGL_ARAP_DOF_DOUBLE_PRECISION_SOLVE
718 // MKL_matMatMult_double(S, data.CSM, Lsep);
719 //#else
720 // MKL_matMatMult_single(S, data.CSM, Lsep);
721 //#endif
722
723 if(data.print_timings)
724 {
725 sec_covGather = get_seconds_hires();
726 }
727
728#ifdef EXTREME_VERBOSE
729 cout<<"S=["<<endl<<S<<endl<<"];"<<endl;
730#endif
731 // Fit rotations to covariance matrices
732 if(data.effective_dim == 2)
733 {
735 }else
736 {
737#ifdef __SSE__ // fit_rotations_SSE will convert to float if necessary
738 fit_rotations_SSE(S,R);
739#else
740 fit_rotations(S,false,R);
741#endif
742 }
743
744#ifdef EXTREME_VERBOSE
745 cout<<"R=["<<endl<<R<<endl<<"];"<<endl;
746#endif
747
748 if(data.print_timings)
749 {
750 sec_fitRotations = get_seconds_hires();
751 }
752
754 // "Global" step: fix rotations per mesh vertex, solve for
755 // linear transformations at handles
757
758 // all this shuffling is retarded and not completely negligible time-wise;
759 // TODO: change fit_rotations_XXX so it returns R in the format ready for
760 // CSolveBlock1 multiplication
761 columnize(R, k, 2, Rcol);
762#ifdef EXTREME_VERBOSE
763 cout<<"Rcol=["<<endl<<Rcol<<endl<<"];"<<endl;
764#endif
765 splitColumns(Rcol, k, data.dim, data.dim, Rxyz);
766
767 if(data.print_timings)
768 {
769 sec_prepMult = get_seconds_hires();
770 }
771
772 L_part1xyz = data.CSolveBlock1 * Rxyz;
773 //#ifdef IGL_ARAP_DOF_DOUBLE_PRECISION_SOLVE
774 // MKL_matMatMult_double(L_part1xyz, data.CSolveBlock1, Rxyz);
775 //#else
776 // MKL_matMatMult_single(L_part1xyz, data.CSolveBlock1, Rxyz);
777 //#endif
778 mergeColumns(L_part1xyz, data.m, data.dim, data.dim + 1, L_part1);
779
780 if(data.with_dynamics)
781 {
782 // Consider reordering or precomputing matrix multiplications
783 MatrixXS L_part1_dyn(data.dim * (data.dim + 1) * data.m, 1);
784 // Eigen can't parse this:
785 //L_part1_dyn =
786 // -(2.0/(data.h*data.h)) * data.Pi_1 * data.Mass_tilde * data.L0 +
787 // (1.0/(data.h*data.h)) * data.Pi_1 * data.Mass_tilde * data.Lm1;
788 // -1.0 because we've moved these linear terms to the right hand side
789 //MatrixXS temp = -1.0 *
790 // ((-2.0/(data.h*data.h)) * data.L0.array() +
791 // (1.0/(data.h*data.h)) * data.Lm1.array()).matrix();
792 //MatrixXS temp = -1.0 *
793 // ( (-1.0/(data.h*data.h)) * data.L0.array() +
794 // (1.0/(data.h*data.h)) * data.Lm1.array()
795 // (-1.0/(data.h*data.h)) * data.L0.array() +
796 // ).matrix();
797 //Lvel0 = (1.0/(data.h)) * data.Lm1.array() - data.L0.array();
798 MatrixXS temp = -1.0 *
799 ( (-1.0/(data.h*data.h)) * data.L0.array() +
800 (1.0/(data.h)) * data.Lvel0.array()
801 ).matrix();
802 MatrixXd temp_d = temp.template cast<double>();
803
804 MatrixXd temp_g = data.fgrav*(data.grav_mag*data.grav_dir);
805
806 assert(data.fext.rows() == temp_g.rows());
807 assert(data.fext.cols() == temp_g.cols());
808 MatrixXd temp2 = data.Mass_tilde * temp_d + temp_g + data.fext.template cast<double>();
809 MatrixXS temp2_f = temp2.template cast<SSCALAR>();
810 L_part1_dyn = data.Pi_1 * temp2_f;
811 L_part1.array() = L_part1.array() + L_part1_dyn.array();
812 }
813
814 //L_SSCALAR = L_part1 + L_part2and3;
815 assert(L_SSCALAR.rows() == L_part1.rows() && L_SSCALAR.rows() == L_part2and3.rows());
816 for (int i=0; i<L_SSCALAR.rows(); i++)
817 {
818 L_SSCALAR(i, 0) = L_part1(i, 0) + L_part2and3(i, 0);
819 }
820
821#ifdef EXTREME_VERBOSE
822 cout<<"L=["<<endl<<L<<endl<<"];"<<endl;
823#endif
824
825 if(data.print_timings)
826 {
827 sec_solve = get_seconds_hires();
828 }
829
830#ifndef IGL_ARAP_DOF_FIXED_ITERATIONS_COUNT
831 // Compute maximum absolute difference with last iteration's solution
832 max_diff = (L_SSCALAR-L_prev).eval().array().abs().matrix().maxCoeff();
833#endif
834 iters++;
835
836 if(data.print_timings)
837 {
838 sec_end = get_seconds_hires();
839#ifndef WIN32
840 // trick to get sec_* variables to compile without warning on mac
841 if(false)
842#endif
843 printf(
844 "\ntotal iteration time = %f "
845 "[local: covGather = %f, "
846 "fitRotations = %f, "
847 "global: prep = %f, "
848 "solve = %f, "
849 "error = %f [ms]]\n",
850 (sec_end - sec_start)*1000.0,
851 (sec_covGather - sec_start)*1000.0,
852 (sec_fitRotations - sec_covGather)*1000.0,
853 (sec_prepMult - sec_fitRotations)*1000.0,
854 (sec_solve - sec_prepMult)*1000.0,
855 (sec_end - sec_solve)*1000.0 );
856 }
857 }
858
859
860 L = L_SSCALAR.template cast<double>();
861 assert(L.cols() == 1);
862
863#ifdef ARAP_GLOBAL_TIMING
864 double timer_finito = get_seconds_hires();
865 printf(
866 "ARAP preparation = %f, "
867 "all %i iterations = %f [ms]\n",
868 (timer_prepFinished - timer_start)*1000.0,
869 max_iters,
870 (timer_finito - timer_prepFinished)*1000.0);
871#endif
872
873 return true;
874}
static void splitColumns(const MatL &L, int numBones, int dim, int dimp1, MatLsep &Lsep)
Definition arap_dof.cpp:402
static void mergeColumns(const MatrixXS &Lsep, int numBones, int dim, int dimp1, MatrixXS &L)
Definition arap_dof.cpp:432
IGL_INLINE void fit_rotations(const Eigen::PlainObjectBase< DerivedS > &S, const bool single_precision, Eigen::PlainObjectBase< DerivedD > &R)
Definition fit_rotations.cpp:18
IGL_INLINE void columnize(const Eigen::PlainObjectBase< DerivedA > &A, const int k, const int dim, Eigen::PlainObjectBase< DerivedB > &B)
Definition columnize.cpp:12
IGL_INLINE void fit_rotations_planar(const Eigen::PlainObjectBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedD > &R)
Definition fit_rotations.cpp:66
#define L(s)
Definition I18N.hpp:18

References columnize(), fit_rotations(), fit_rotations_planar(), get_seconds_hires(), L, mergeColumns(), Eigen::PlainObjectBase< Derived >::rows(), slice(), and splitColumns().

+ Here is the call graph for this function:

◆ arap_linear_block()

template<typename MatV , typename MatF , typename Scalar >
IGL_INLINE void igl::arap_linear_block ( const MatV &  V,
const MatF &  F,
const int  d,
const igl::ARAPEnergyType  energy,
Eigen::SparseMatrix< Scalar > &  Kd 
)
20{
21 switch(energy)
22 {
24 return igl::arap_linear_block_spokes(V,F,d,Kd);
25 break;
28 break;
30 return igl::arap_linear_block_elements(V,F,d,Kd);
31 break;
32 default:
33 verbose("Unsupported energy type: %d\n",energy);
34 assert(false);
35 }
36}
IGL_INLINE void arap_linear_block_spokes_and_rims(const MatV &V, const MatF &F, const int d, Eigen::SparseMatrix< Scalar > &Kd)
Definition arap_linear_block.cpp:105
IGL_INLINE void arap_linear_block_spokes(const MatV &V, const MatF &F, const int d, Eigen::SparseMatrix< Scalar > &Kd)
Definition arap_linear_block.cpp:40
IGL_INLINE void arap_linear_block_elements(const MatV &V, const MatF &F, const int d, Eigen::SparseMatrix< Scalar > &Kd)
Definition arap_linear_block.cpp:187

References ARAP_ENERGY_TYPE_ELEMENTS, ARAP_ENERGY_TYPE_SPOKES, ARAP_ENERGY_TYPE_SPOKES_AND_RIMS, arap_linear_block_elements(), arap_linear_block_spokes(), arap_linear_block_spokes_and_rims(), and verbose.

Referenced by arap_rhs(), and covariance_scatter_matrix().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ arap_linear_block_elements()

template<typename MatV , typename MatF , typename Scalar >
IGL_INLINE void igl::arap_linear_block_elements ( const MatV &  V,
const MatF &  F,
const int  d,
Eigen::SparseMatrix< Scalar > &  Kd 
)
192{
193 using namespace std;
194 using namespace Eigen;
195 // simplex size (3: triangles, 4: tetrahedra)
196 int simplex_size = F.cols();
197 // Number of elements
198 int m = F.rows();
199 // Temporary output
200 Kd.resize(V.rows(), F.rows());
201 vector<Triplet<Scalar> > Kd_IJV;
203 if(simplex_size == 3)
204 {
205 // triangles
206 Kd.reserve(7*V.rows());
207 Kd_IJV.reserve(7*V.rows());
208 edges.resize(3,2);
209 edges <<
210 1,2,
211 2,0,
212 0,1;
213 }else if(simplex_size == 4)
214 {
215 // tets
216 Kd.reserve(17*V.rows());
217 Kd_IJV.reserve(17*V.rows());
218 edges.resize(6,2);
219 edges <<
220 1,2,
221 2,0,
222 0,1,
223 3,0,
224 3,1,
225 3,2;
226 }
227 // gather cotangent weights
229 cotmatrix_entries(V,F,C);
230 // should have weights for each edge
231 assert(C.cols() == edges.rows());
232 // loop over elements
233 for(int i = 0;i<m;i++)
234 {
235 // loop over edges of element
236 for(int e = 0;e<edges.rows();e++)
237 {
238 int source = F(i,edges(e,0));
239 int dest = F(i,edges(e,1));
240 double v = C(i,e)*(V(source,d)-V(dest,d));
241 Kd_IJV.push_back(Triplet<Scalar>(source,i,v));
242 Kd_IJV.push_back(Triplet<Scalar>(dest,i,-v));
243 }
244 }
245 Kd.setFromTriplets(Kd_IJV.begin(),Kd_IJV.end());
246 Kd.makeCompressed();
247}
void makeCompressed()
Definition SparseMatrix.h:464
IGL_INLINE void edges(const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedE > &E)
Definition edges.cpp:13
IGL_INLINE void cotmatrix_entries(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedC > &C)
Definition cotmatrix_entries.cpp:20

References Eigen::PlainObjectBase< Derived >::cols(), cotmatrix_entries(), edges(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::makeCompressed(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::reserve(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::resize(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets().

Referenced by arap_linear_block().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ arap_linear_block_spokes()

template<typename MatV , typename MatF , typename Scalar >
IGL_INLINE void igl::arap_linear_block_spokes ( const MatV &  V,
const MatF &  F,
const int  d,
Eigen::SparseMatrix< Scalar > &  Kd 
)
45{
46 using namespace std;
47 using namespace Eigen;
48 // simplex size (3: triangles, 4: tetrahedra)
49 int simplex_size = F.cols();
50 // Number of elements
51 int m = F.rows();
52 // Temporary output
54 Kd.resize(V.rows(), V.rows());
55 vector<Triplet<Scalar> > Kd_IJV;
56 if(simplex_size == 3)
57 {
58 // triangles
59 Kd.reserve(7*V.rows());
60 Kd_IJV.reserve(7*V.rows());
61 edges.resize(3,2);
62 edges <<
63 1,2,
64 2,0,
65 0,1;
66 }else if(simplex_size == 4)
67 {
68 // tets
69 Kd.reserve(17*V.rows());
70 Kd_IJV.reserve(17*V.rows());
71 edges.resize(6,2);
72 edges <<
73 1,2,
74 2,0,
75 0,1,
76 3,0,
77 3,1,
78 3,2;
79 }
80 // gather cotangent weights
82 cotmatrix_entries(V,F,C);
83 // should have weights for each edge
84 assert(C.cols() == edges.rows());
85 // loop over elements
86 for(int i = 0;i<m;i++)
87 {
88 // loop over edges of element
89 for(int e = 0;e<edges.rows();e++)
90 {
91 int source = F(i,edges(e,0));
92 int dest = F(i,edges(e,1));
93 double v = 0.5*C(i,e)*(V(source,d)-V(dest,d));
94 Kd_IJV.push_back(Triplet<Scalar>(source,dest,v));
95 Kd_IJV.push_back(Triplet<Scalar>(dest,source,-v));
96 Kd_IJV.push_back(Triplet<Scalar>(source,source,v));
97 Kd_IJV.push_back(Triplet<Scalar>(dest,dest,-v));
98 }
99 }
100 Kd.setFromTriplets(Kd_IJV.begin(),Kd_IJV.end());
101 Kd.makeCompressed();
102}

References Eigen::PlainObjectBase< Derived >::cols(), cotmatrix_entries(), edges(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::makeCompressed(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::reserve(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::resize(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets().

Referenced by arap_linear_block().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ arap_linear_block_spokes_and_rims()

template<typename MatV , typename MatF , typename Scalar >
IGL_INLINE void igl::arap_linear_block_spokes_and_rims ( const MatV &  V,
const MatF &  F,
const int  d,
Eigen::SparseMatrix< Scalar > &  Kd 
)
110{
111 using namespace std;
112 using namespace Eigen;
113 // simplex size (3: triangles, 4: tetrahedra)
114 int simplex_size = F.cols();
115 // Number of elements
116 int m = F.rows();
117 // Temporary output
118 Kd.resize(V.rows(), V.rows());
119 vector<Triplet<Scalar> > Kd_IJV;
121 if(simplex_size == 3)
122 {
123 // triangles
124 Kd.reserve(7*V.rows());
125 Kd_IJV.reserve(7*V.rows());
126 edges.resize(3,2);
127 edges <<
128 1,2,
129 2,0,
130 0,1;
131 }else if(simplex_size == 4)
132 {
133 // tets
134 Kd.reserve(17*V.rows());
135 Kd_IJV.reserve(17*V.rows());
136 edges.resize(6,2);
137 edges <<
138 1,2,
139 2,0,
140 0,1,
141 3,0,
142 3,1,
143 3,2;
144 // Not implemented yet for tets
145 assert(false);
146 }
147 // gather cotangent weights
149 cotmatrix_entries(V,F,C);
150 // should have weights for each edge
151 assert(C.cols() == edges.rows());
152 // loop over elements
153 for(int i = 0;i<m;i++)
154 {
155 // loop over edges of element
156 for(int e = 0;e<edges.rows();e++)
157 {
158 int source = F(i,edges(e,0));
159 int dest = F(i,edges(e,1));
160 double v = C(i,e)*(V(source,d)-V(dest,d))/3.0;
161 // loop over edges again
162 for(int f = 0;f<edges.rows();f++)
163 {
164 int Rs = F(i,edges(f,0));
165 int Rd = F(i,edges(f,1));
166 if(Rs == source && Rd == dest)
167 {
168 Kd_IJV.push_back(Triplet<Scalar>(Rs,Rd,v));
169 Kd_IJV.push_back(Triplet<Scalar>(Rd,Rs,-v));
170 }else if(Rd == source)
171 {
172 Kd_IJV.push_back(Triplet<Scalar>(Rd,Rs,v));
173 }else if(Rs == dest)
174 {
175 Kd_IJV.push_back(Triplet<Scalar>(Rs,Rd,-v));
176 }
177 }
178 Kd_IJV.push_back(Triplet<Scalar>(source,source,v));
179 Kd_IJV.push_back(Triplet<Scalar>(dest,dest,-v));
180 }
181 }
182 Kd.setFromTriplets(Kd_IJV.begin(),Kd_IJV.end());
183 Kd.makeCompressed();
184}

References Eigen::PlainObjectBase< Derived >::cols(), cotmatrix_entries(), edges(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::makeCompressed(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::reserve(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::resize(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets().

Referenced by arap_linear_block().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ arap_precomputation()

template<typename DerivedV , typename DerivedF , typename Derivedb >
IGL_INLINE bool igl::arap_precomputation ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const int  dim,
const Eigen::PlainObjectBase< Derivedb > &  b,
ARAPData data 
)
35{
36 using namespace std;
37 using namespace Eigen;
38 typedef typename DerivedV::Scalar Scalar;
39 // number of vertices
40 const int n = V.rows();
41 data.n = n;
42 assert((b.size() == 0 || b.maxCoeff() < n) && "b out of bounds");
43 assert((b.size() == 0 || b.minCoeff() >=0) && "b out of bounds");
44 // remember b
45 data.b = b;
46 //assert(F.cols() == 3 && "For now only triangles");
47 // dimension
48 //const int dim = V.cols();
49 assert((dim == 3 || dim ==2) && "dim should be 2 or 3");
50 data.dim = dim;
51 //assert(dim == 3 && "Only 3d supported");
52 // Defaults
53 data.f_ext = MatrixXd::Zero(n,data.dim);
54
55 assert(data.dim <= V.cols() && "solve dim should be <= embedding");
56 bool flat = (V.cols() - data.dim)==1;
57
58 DerivedV plane_V;
59 DerivedF plane_F;
60 typedef SparseMatrix<Scalar> SparseMatrixS;
61 SparseMatrixS ref_map,ref_map_dim;
62 if(flat)
63 {
64 project_isometrically_to_plane(V,F,plane_V,plane_F,ref_map);
65 repdiag(ref_map,dim,ref_map_dim);
66 }
67 const PlainObjectBase<DerivedV>& ref_V = (flat?plane_V:V);
68 const PlainObjectBase<DerivedF>& ref_F = (flat?plane_F:F);
69 SparseMatrixS L;
70 cotmatrix(V,F,L);
71
72 ARAPEnergyType eff_energy = data.energy;
73 if(eff_energy == ARAP_ENERGY_TYPE_DEFAULT)
74 {
75 switch(F.cols())
76 {
77 case 3:
78 if(data.dim == 3)
79 {
80 eff_energy = ARAP_ENERGY_TYPE_SPOKES_AND_RIMS;
81 }else
82 {
83 eff_energy = ARAP_ENERGY_TYPE_ELEMENTS;
84 }
85 break;
86 case 4:
87 eff_energy = ARAP_ENERGY_TYPE_ELEMENTS;
88 break;
89 default:
90 assert(false);
91 }
92 }
93
94
95 // Get covariance scatter matrix, when applied collects the covariance
96 // matrices used to fit rotations to during optimization
97 covariance_scatter_matrix(ref_V,ref_F,eff_energy,data.CSM);
98 if(flat)
99 {
100 data.CSM = (data.CSM * ref_map_dim.transpose()).eval();
101 }
102 assert(data.CSM.cols() == V.rows()*data.dim);
103
104 // Get group sum scatter matrix, when applied sums all entries of the same
105 // group according to G
107 if(data.G.size() == 0)
108 {
109 if(eff_energy == ARAP_ENERGY_TYPE_ELEMENTS)
110 {
111 speye(F.rows(),G_sum);
112 }else
113 {
114 speye(n,G_sum);
115 }
116 }else
117 {
118 // groups are defined per vertex, convert to per face using mode
119 if(eff_energy == ARAP_ENERGY_TYPE_ELEMENTS)
120 {
122 MatrixXi GF(F.rows(),F.cols());
123 for(int j = 0;j<F.cols();j++)
124 {
126 slice(data.G,F.col(j),GFj);
127 GF.col(j) = GFj;
128 }
129 mode<int>(GF,2,GG);
130 data.G=GG;
131 }
132 //printf("group_sum_matrix()\n");
133 group_sum_matrix(data.G,G_sum);
134 }
135 SparseMatrix<double> G_sum_dim;
136 repdiag(G_sum,data.dim,G_sum_dim);
137 assert(G_sum_dim.cols() == data.CSM.rows());
138 data.CSM = (G_sum_dim * data.CSM).eval();
139
140
141 arap_rhs(ref_V,ref_F,data.dim,eff_energy,data.K);
142 if(flat)
143 {
144 data.K = (ref_map_dim * data.K).eval();
145 }
146 assert(data.K.rows() == data.n*data.dim);
147
148 SparseMatrix<double> Q = (-L).eval();
149
150 if(data.with_dynamics)
151 {
152 const double h = data.h;
153 assert(h != 0);
155 massmatrix(V,F,MASSMATRIX_TYPE_DEFAULT,data.M);
156 const double dw = (1./data.ym)*(h*h);
157 SparseMatrix<double> DQ = dw * 1./(h*h)*data.M;
158 Q += DQ;
159 // Dummy external forces
160 data.f_ext = MatrixXd::Zero(n,data.dim);
161 data.vel = MatrixXd::Zero(n,data.dim);
162 }
163
165 Q,b,SparseMatrix<double>(),true,data.solver_data);
166}
Definition PlainObjectBase.h:100
IGL_INLINE void project_isometrically_to_plane(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedU > &U, Eigen::PlainObjectBase< DerivedUF > &UF, Eigen::SparseMatrix< Scalar > &I)
Definition project_isometrically_to_plane.cpp:17

References ARAP_ENERGY_TYPE_DEFAULT, ARAP_ENERGY_TYPE_ELEMENTS, ARAP_ENERGY_TYPE_SPOKES_AND_RIMS, arap_rhs(), Eigen::PlainObjectBase< Derived >::cols(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), cotmatrix(), covariance_scatter_matrix(), group_sum_matrix(), L, massmatrix(), MASSMATRIX_TYPE_DEFAULT, min_quad_with_fixed_precompute(), project_isometrically_to_plane(), repdiag(), Eigen::PlainObjectBase< Derived >::rows(), slice(), and speye().

+ Here is the call graph for this function:

◆ arap_rhs()

IGL_INLINE void igl::arap_rhs ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const int  dim,
const igl::ARAPEnergyType  energy,
Eigen::SparseMatrix< double > &  K 
)
21{
22 using namespace std;
23 using namespace Eigen;
24 // Number of dimensions
25 int Vdim = V.cols();
27 //int n = V.rows();
29 //int m = F.rows();
31 //int nr;
32 switch(energy)
33 {
35 //nr = n;
36 break;
38 //nr = n;
39 break;
41 //nr = m;
42 break;
43 default:
44 fprintf(
45 stderr,
46 "arap_rhs.h: Error: Unsupported arap energy %d\n",
47 energy);
48 return;
49 }
50
51 SparseMatrix<double> KX,KY,KZ;
52 arap_linear_block(V,F,0,energy,KX);
53 arap_linear_block(V,F,1,energy,KY);
54 if(Vdim == 2)
55 {
56 K = cat(2,repdiag(KX,dim),repdiag(KY,dim));
57 }else if(Vdim == 3)
58 {
59 arap_linear_block(V,F,2,energy,KZ);
60 if(dim == 3)
61 {
62 K = cat(2,cat(2,repdiag(KX,dim),repdiag(KY,dim)),repdiag(KZ,dim));
63 }else if(dim ==2)
64 {
65 SparseMatrix<double> ZZ(KX.rows()*2,KX.cols());
66 K = cat(2,cat(2,
67 cat(2,repdiag(KX,dim),ZZ),
68 cat(2,repdiag(KY,dim),ZZ)),
69 cat(2,repdiag(KZ,dim),ZZ));
70 }else
71 {
72 assert(false);
73 fprintf(
74 stderr,
75 "arap_rhs.h: Error: Unsupported dimension %d\n",
76 dim);
77 }
78 }else
79 {
80 assert(false);
81 fprintf(
82 stderr,
83 "arap_rhs.h: Error: Unsupported dimension %d\n",
84 Vdim);
85 return;
86 }
87
88}
IGL_INLINE void arap_linear_block(const MatV &V, const MatF &F, const int d, const igl::ARAPEnergyType energy, Eigen::SparseMatrix< Scalar > &Kd)
Definition arap_linear_block.cpp:14

References ARAP_ENERGY_TYPE_ELEMENTS, ARAP_ENERGY_TYPE_SPOKES, ARAP_ENERGY_TYPE_SPOKES_AND_RIMS, arap_linear_block(), cat(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), repdiag(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows().

Referenced by arap_dof_precomputation(), and arap_precomputation().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ arap_solve()

template<typename Derivedbc , typename DerivedU >
IGL_INLINE bool igl::arap_solve ( const Eigen::PlainObjectBase< Derivedbc > &  bc,
ARAPData data,
Eigen::PlainObjectBase< DerivedU > &  U 
)
175{
176 using namespace Eigen;
177 using namespace std;
178 assert(data.b.size() == bc.rows());
179 if(bc.size() > 0)
180 {
181 assert(bc.cols() == data.dim && "bc.cols() match data.dim");
182 }
183 const int n = data.n;
184 int iter = 0;
185 if(U.size() == 0)
186 {
187 // terrible initial guess.. should at least copy input mesh
188#ifndef NDEBUG
189 cerr<<"arap_solve: Using terrible initial guess for U. Try U = V."<<endl;
190#endif
191 U = MatrixXd::Zero(data.n,data.dim);
192 }else
193 {
194 assert(U.cols() == data.dim && "U.cols() match data.dim");
195 }
196 // changes each arap iteration
197 MatrixXd U_prev = U;
198 // doesn't change for fixed with_dynamics timestep
199 MatrixXd U0;
200 if(data.with_dynamics)
201 {
202 U0 = U_prev;
203 }
204 while(iter < data.max_iter)
205 {
206 U_prev = U;
207 // enforce boundary conditions exactly
208 for(int bi = 0;bi<bc.rows();bi++)
209 {
210 U.row(data.b(bi)) = bc.row(bi);
211 }
212
213 const auto & Udim = U.replicate(data.dim,1);
214 assert(U.cols() == data.dim);
215 // As if U.col(2) was 0
216 MatrixXd S = data.CSM * Udim;
217 // THIS NORMALIZATION IS IMPORTANT TO GET SINGLE PRECISION SVD CODE TO WORK
218 // CORRECTLY.
219 S /= S.array().abs().maxCoeff();
220
221 const int Rdim = data.dim;
222 MatrixXd R(Rdim,data.CSM.rows());
223 if(R.rows() == 2)
224 {
226 }else
227 {
228 fit_rotations(S,true,R);
229//#ifdef __SSE__ // fit_rotations_SSE will convert to float if necessary
230// fit_rotations_SSE(S,R);
231//#else
232// fit_rotations(S,true,R);
233//#endif
234 }
235 //for(int k = 0;k<(data.CSM.rows()/dim);k++)
236 //{
237 // R.block(0,dim*k,dim,dim) = MatrixXd::Identity(dim,dim);
238 //}
239
240
241 // Number of rotations: #vertices or #elements
242 int num_rots = data.K.cols()/Rdim/Rdim;
243 // distribute group rotations to vertices in each group
244 MatrixXd eff_R;
245 if(data.G.size() == 0)
246 {
247 // copy...
248 eff_R = R;
249 }else
250 {
251 eff_R.resize(Rdim,num_rots*Rdim);
252 for(int r = 0;r<num_rots;r++)
253 {
254 eff_R.block(0,Rdim*r,Rdim,Rdim) =
255 R.block(0,Rdim*data.G(r),Rdim,Rdim);
256 }
257 }
258
259 MatrixXd Dl;
260 if(data.with_dynamics)
261 {
262 assert(data.M.rows() == n &&
263 "No mass matrix. Call arap_precomputation if changing with_dynamics");
264 const double h = data.h;
265 assert(h != 0);
266 //Dl = 1./(h*h*h)*M*(-2.*V0 + Vm1) - fext;
267 // data.vel = (V0-Vm1)/h
268 // h*data.vel = (V0-Vm1)
269 // -h*data.vel = -V0+Vm1)
270 // -V0-h*data.vel = -2V0+Vm1
271 const double dw = (1./data.ym)*(h*h);
272 Dl = dw * (1./(h*h)*data.M*(-U0 - h*data.vel) - data.f_ext);
273 }
274
275 VectorXd Rcol;
276 columnize(eff_R,num_rots,2,Rcol);
277 VectorXd Bcol = -data.K * Rcol;
278 assert(Bcol.size() == data.n*data.dim);
279 for(int c = 0;c<data.dim;c++)
280 {
281 VectorXd Uc,Bc,bcc,Beq;
282 Bc = Bcol.block(c*n,0,n,1);
283 if(data.with_dynamics)
284 {
285 Bc += Dl.col(c);
286 }
287 if(bc.size()>0)
288 {
289 bcc = bc.col(c);
290 }
292 data.solver_data,
293 Bc,bcc,Beq,
294 Uc);
295 U.col(c) = Uc;
296 }
297
298 iter++;
299 }
300 if(data.with_dynamics)
301 {
302 // Keep track of velocity for next time
303 data.vel = (U-U0)/data.h;
304 }
305
306 return true;
307}

References Eigen::PlainObjectBase< Derived >::cols(), columnize(), fit_rotations(), fit_rotations_planar(), and min_quad_with_fixed_solve().

+ Here is the call graph for this function:

◆ AtA_cached()

template<typename Scalar >
IGL_INLINE void igl::AtA_cached ( const Eigen::SparseMatrix< Scalar > &  A,
const AtA_cached_data data,
Eigen::SparseMatrix< Scalar > &  AtA 
)
117{
118 for (unsigned i=0; i<data.I_outer.size()-1; ++i)
119 {
120 *(AtA.valuePtr() + i) = 0;
121 for (unsigned j=data.I_outer[i]; j<data.I_outer[i+1]; ++j)
122 *(AtA.valuePtr() + i) += *(A.valuePtr() + data.I_row[j]) * data.W[data.I_w[j]] * *(A.valuePtr() + data.I_col[j]);
123 }
124}
const Scalar * valuePtr() const
Definition SparseMatrix.h:148

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::valuePtr().

Referenced by AtA_cached_precompute(), and igl::slim::build_linear_system().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ AtA_cached_precompute()

template<typename Scalar >
IGL_INLINE void igl::AtA_cached_precompute ( const Eigen::SparseMatrix< Scalar > &  A,
igl::AtA_cached_data data,
Eigen::SparseMatrix< Scalar > &  AtA 
)
19{
20 // 1 Compute At (this could be avoided, but performance-wise it will not make a difference)
21 std::vector<std::vector<int> > Col_RowPtr;
22 std::vector<std::vector<int> > Col_IndexPtr;
23
24 Col_RowPtr.resize(A.cols());
25 Col_IndexPtr.resize(A.cols());
26
27 for (unsigned k=0; k<A.outerSize(); ++k)
28 {
29 unsigned outer_index = *(A.outerIndexPtr()+k);
30 unsigned next_outer_index = (k+1 == A.outerSize()) ? A.nonZeros() : *(A.outerIndexPtr()+k+1);
31
32 for (unsigned l=outer_index; l<next_outer_index; ++l)
33 {
34 int col = k;
35 int row = *(A.innerIndexPtr()+l);
36 int value_index = l;
37 assert(col < A.cols());
38 assert(col >= 0);
39 assert(row < A.rows());
40 assert(row >= 0);
41 assert(value_index >= 0);
42 assert(value_index < A.nonZeros());
43
44 Col_RowPtr[col].push_back(row);
45 Col_IndexPtr[col].push_back(value_index);
46 }
47 }
48
50 At.makeCompressed();
51 AtA = At * A;
52 AtA.makeCompressed();
53
54 assert(AtA.isCompressed());
55
56 // If weights are not provided, use 1
57 if (data.W.size() == 0)
58 data.W = Eigen::VectorXd::Ones(A.rows());
59 assert(data.W.size() == A.rows());
60
61 data.I_outer.reserve(AtA.outerSize());
62 data.I_row.reserve(2*AtA.nonZeros());
63 data.I_col.reserve(2*AtA.nonZeros());
64 data.I_w.reserve(2*AtA.nonZeros());
65
66 // 2 Construct the rules
67 for (unsigned k=0; k<AtA.outerSize(); ++k)
68 {
69 unsigned outer_index = *(AtA.outerIndexPtr()+k);
70 unsigned next_outer_index = (k+1 == AtA.outerSize()) ? AtA.nonZeros() : *(AtA.outerIndexPtr()+k+1);
71
72 for (unsigned l=outer_index; l<next_outer_index; ++l)
73 {
74 int col = k;
75 int row = *(AtA.innerIndexPtr()+l);
76 int value_index = l;
77 assert(col < AtA.cols());
78 assert(col >= 0);
79 assert(row < AtA.rows());
80 assert(row >= 0);
81 assert(value_index >= 0);
82 assert(value_index < AtA.nonZeros());
83
84 data.I_outer.push_back(data.I_row.size());
85
86 // Find correspondences
87 unsigned i=0;
88 unsigned j=0;
89 while (i<Col_RowPtr[row].size() && j<Col_RowPtr[col].size())
90 {
91 if (Col_RowPtr[row][i] == Col_RowPtr[col][j])
92 {
93 data.I_row.push_back(Col_IndexPtr[row][i]);
94 data.I_col.push_back(Col_IndexPtr[col][j]);
95 data.I_w.push_back(Col_RowPtr[col][j]);
96 ++i;
97 ++j;
98 } else
99 if (Col_RowPtr[row][i] > Col_RowPtr[col][j])
100 ++j;
101 else
102 ++i;
103
104 }
105 }
106 }
107 data.I_outer.push_back(data.I_row.size()); // makes it more efficient to iterate later on
108
109 igl::AtA_cached(A,data,AtA);
110}
EIGEN_DEVICE_FUNC RowXpr row(Index i)
This is the const version of row(). *‍/.
Definition BlockMethods.h:859
EIGEN_DEVICE_FUNC ColXpr col(Index i)
This is the const version of col().
Definition BlockMethods.h:838
Index nonZeros() const
Definition SparseCompressedBase.h:56
const StorageIndex * innerIndexPtr() const
Definition SparseMatrix.h:157
const StorageIndex * outerIndexPtr() const
Definition SparseMatrix.h:166
bool isCompressed() const
Definition SparseCompressedBase.h:107
constexpr auto size(const C &c) -> decltype(c.size())
Definition span.hpp:183
IGL_INLINE void AtA_cached(const Eigen::SparseMatrix< Scalar > &A, const AtA_cached_data &data, Eigen::SparseMatrix< Scalar > &AtA)
Definition AtA_cached.cpp:113

References AtA_cached(), col(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::innerIndexPtr(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::isCompressed(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::makeCompressed(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::nonZeros(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::outerIndexPtr(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::outerSize(), row(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows(), and Eigen::SparseMatrixBase< Derived >::transpose().

Referenced by igl::slim::build_linear_system().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ average_onto_faces()

template<typename T , typename I >
IGL_INLINE void igl::average_onto_faces ( const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &  V,
const Eigen::Matrix< I, Eigen::Dynamic, Eigen::Dynamic > &  F,
const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &  S,
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &  SF 
)
15{
16
18
19 for (int i = 0; i <F.rows(); ++i)
20 for (int j = 0; j<F.cols(); ++j)
21 SF.row(i) += S.row(F(i,j));
22
23 SF.array() /= F.cols();
24
25};

References Eigen::PlainObjectBase< Derived >::cols().

+ Here is the call graph for this function:

◆ average_onto_vertices()

template<typename DerivedV , typename DerivedF , typename DerivedS >
IGL_INLINE void igl::average_onto_vertices ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< DerivedS > &  S,
Eigen::MatrixBase< DerivedS > &  SV 
)
15{
16 SV = DerivedS::Zero(V.rows(),S.cols());
18 COUNT.setZero();
19 for (int i = 0; i <F.rows(); ++i)
20 {
21 for (int j = 0; j<F.cols(); ++j)
22 {
23 SV.row(F(i,j)) += S.row(i);
24 COUNT[F(i,j)] ++;
25 }
26 }
27 for (int i = 0; i <V.rows(); ++i)
28 SV.row(i) /= COUNT[i];
29};

References Eigen::PlainObjectBase< Derived >::setZero().

+ Here is the call graph for this function:

◆ avg_edge_length()

template<typename DerivedV , typename DerivedF >
IGL_INLINE double igl::avg_edge_length ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F 
)
16{
17 double avg = 0;
18 long int count = 0;
19
20 // Augh. Technically this is double counting interior edges...
21 for (unsigned i=0;i<F.rows();++i)
22 {
23 for (unsigned j=0;j<F.cols();++j)
24 {
25 ++count;
26 avg += (V.row(F(i,j)) - V.row(F(i,(j+1)%F.cols()))).norm();
27 }
28 }
29
30 return avg / (double) count;
31}

References count().

+ Here is the call graph for this function:

◆ axis_angle_to_quat()

template<typename Q_type >
IGL_INLINE void igl::axis_angle_to_quat ( const Q_type *  axis,
const Q_type  angle,
Q_type *  out 
)
18{
19 Q_type n = axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2];
20 if( fabs(n)>igl::EPS<Q_type>())
21 {
22 Q_type f = 0.5*angle;
23 out[3] = cos(f);
24 f = sin(f)/sqrt(n);
25 out[0] = axis[0]*f;
26 out[1] = axis[1]*f;
27 out[2] = axis[2]*f;
28 }
29 else
30 {
31 out[3] = 1.0;
32 out[0] = out[1] = out[2] = 0.0;
33 }
34}
EIGEN_DEVICE_FUNC const CosReturnType cos() const
Definition ArrayCwiseUnaryOps.h:202
EIGEN_DEVICE_FUNC const SinReturnType sin() const
Definition ArrayCwiseUnaryOps.h:220

References cos(), sin(), and sqrt().

Referenced by trackball().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ barycenter()

template<typename DerivedV , typename DerivedF , typename DerivedBC >
IGL_INLINE void igl::barycenter ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedBC > &  BC 
)
18{
19 BC.setZero(F.rows(),V.cols());
20 // Loop over faces
21 for(int i = 0;i<F.rows();i++)
22 {
23 // loop around face
24 for(int j = 0;j<F.cols();j++)
25 {
26 // Accumulate
27 BC.row(i) += V.row(F(i,j));
28 }
29 // average
30 BC.row(i) /= double(F.cols());
31 }
32}
EIGEN_DEVICE_FUNC Derived & setZero(Index size)
Definition CwiseNullaryOp.h:515

References Eigen::PlainObjectBase< Derived >::setZero().

Referenced by false_barycentric_subdivision(), igl::opengl::ViewerCore::get_scale_and_shift_to_fit_mesh(), igl::WindingNumberAABB< Point, DerivedV, DerivedF >::grow(), igl::AABB< DerivedV, DIM >::init(), orient_outward(), igl::copyleft::cgal::outer_hull_legacy(), shape_diameter_function(), and sort_triangles().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ barycentric_coordinates() [1/2]

template<typename DerivedP , typename DerivedA , typename DerivedB , typename DerivedC , typename DerivedD , typename DerivedL >
IGL_INLINE void igl::barycentric_coordinates ( const Eigen::MatrixBase< DerivedP > &  P,
const Eigen::MatrixBase< DerivedA > &  A,
const Eigen::MatrixBase< DerivedB > &  B,
const Eigen::MatrixBase< DerivedC > &  C,
const Eigen::MatrixBase< DerivedD > &  D,
Eigen::PlainObjectBase< DerivedL > &  L 
)
25{
26 using namespace Eigen;
27 assert(P.cols() == 3 && "query must be in 3d");
28 assert(A.cols() == 3 && "corners must be in 3d");
29 assert(B.cols() == 3 && "corners must be in 3d");
30 assert(C.cols() == 3 && "corners must be in 3d");
31 assert(D.cols() == 3 && "corners must be in 3d");
32 assert(P.rows() == A.rows() && "Must have same number of queries as corners");
33 assert(A.rows() == B.rows() && "Corners must be same size");
34 assert(A.rows() == C.rows() && "Corners must be same size");
35 assert(A.rows() == D.rows() && "Corners must be same size");
37 VectorXS;
38 // Total volume
39 VectorXS vol,LA,LB,LC,LD;
40 volume(B,D,C,P,LA);
41 volume(A,C,D,P,LB);
42 volume(A,D,B,P,LC);
43 volume(A,B,C,P,LD);
44 volume(A,B,C,D,vol);
45 L.resize(P.rows(),4);
46 L<<LA,LB,LC,LD;
47 L.array().colwise() /= vol.array();
48}
IGL_INLINE void volume(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedT > &T, Eigen::PlainObjectBase< Derivedvol > &vol)
Definition volume.cpp:15

References L, and volume().

Referenced by pseudonormal_test().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ barycentric_coordinates() [2/2]

template<typename DerivedP , typename DerivedA , typename DerivedB , typename DerivedC , typename DerivedL >
IGL_INLINE void igl::barycentric_coordinates ( const Eigen::MatrixBase< DerivedP > &  P,
const Eigen::MatrixBase< DerivedA > &  A,
const Eigen::MatrixBase< DerivedB > &  B,
const Eigen::MatrixBase< DerivedC > &  C,
Eigen::PlainObjectBase< DerivedL > &  L 
)
62{
63 using namespace Eigen;
64#ifndef NDEBUG
65 const int DIM = P.cols();
66 assert(A.cols() == DIM && "corners must be in same dimension as query");
67 assert(B.cols() == DIM && "corners must be in same dimension as query");
68 assert(C.cols() == DIM && "corners must be in same dimension as query");
69 assert(P.rows() == A.rows() && "Must have same number of queries as corners");
70 assert(A.rows() == B.rows() && "Corners must be same size");
71 assert(A.rows() == C.rows() && "Corners must be same size");
72#endif
73
74 // http://gamedev.stackexchange.com/a/23745
75 typedef
77 typename DerivedP::Scalar,
78 DerivedP::RowsAtCompileTime,
79 DerivedP::ColsAtCompileTime>
80 ArrayS;
81 typedef
83 typename DerivedP::Scalar,
84 DerivedP::RowsAtCompileTime,
85 1>
86 VectorS;
87
88 const ArrayS v0 = B.array() - A.array();
89 const ArrayS v1 = C.array() - A.array();
90 const ArrayS v2 = P.array() - A.array();
91 VectorS d00 = (v0*v0).rowwise().sum();
92 VectorS d01 = (v0*v1).rowwise().sum();
93 VectorS d11 = (v1*v1).rowwise().sum();
94 VectorS d20 = (v2*v0).rowwise().sum();
95 VectorS d21 = (v2*v1).rowwise().sum();
96 VectorS denom = d00 * d11 - d01 * d01;
97 L.resize(P.rows(),3);
98 L.col(1) = (d11 * d20 - d01 * d21) / denom;
99 L.col(2) = (d00 * d21 - d01 * d20) / denom;
100 L.col(0) = 1.0f -(L.col(1) + L.col(2)).array();
101}
General-purpose arrays with easy API for coefficient-wise operations.
Definition Array.h:47
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ArrayWrapper< Derived > array()
Definition MatrixBase.h:317

References Eigen::MatrixBase< Derived >::array(), and L.

+ Here is the call graph for this function:

◆ barycentric_to_global()

template<typename Scalar , typename Index >
IGL_INLINE Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > igl::barycentric_to_global ( const Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > &  V,
const Eigen::Matrix< Index, Eigen::Dynamic, Eigen::Dynamic > &  F,
const Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > &  bc 
)
21 {
23 R.resize(bc.rows(),3);
24
25 for (unsigned i=0; i<R.rows(); ++i)
26 {
27 unsigned id = round(bc(i,0));
28 double u = bc(i,1);
29 double v = bc(i,2);
30
31 if (id != -1)
32 R.row(i) = V.row(F(id,0)) +
33 ((V.row(F(id,1)) - V.row(F(id,0))) * u +
34 (V.row(F(id,2)) - V.row(F(id,0))) * v );
35 else
36 R.row(i) << 0,0,0;
37 }
38 return R;
39 }
EIGEN_DEVICE_FUNC const RoundReturnType round() const
Definition ArrayCwiseUnaryOps.h:374

References Eigen::PlainObjectBase< Derived >::resize(), round(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ basename()

IGL_INLINE std::string igl::basename ( const std::string &  path)
13{
14 if(path == "")
15 {
16 return std::string("");
17 }
18 // http://stackoverflow.com/questions/5077693/dirnamephp-similar-function-in-c
19 std::string::const_reverse_iterator last_slash =
20 std::find(
21 path.rbegin(),
22 path.rend(), '/');
23 if( last_slash == path.rend() )
24 {
25 // No slashes found
26 return path;
27 }else if(1 == (last_slash.base() - path.begin()))
28 {
29 // Slash is first char
30 return std::string(path.begin()+1,path.end());
31 }else if(path.end() == last_slash.base() )
32 {
33 // Slash is last char
34 std::string redo = std::string(path.begin(),path.end()-1);
35 return igl::basename(redo);
36 }
37 return std::string(last_slash.base(),path.end());
38}
IGL_INLINE std::string basename(const std::string &path)
Definition basename.cpp:12

References basename().

Referenced by basename(), dated_copy(), pathinfo(), and igl::copyleft::tetgen::read_into_tetgenio().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ bbw()

template<typename DerivedV , typename DerivedEle , typename Derivedb , typename Derivedbc , typename DerivedW >
IGL_INLINE bool igl::bbw ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedEle > &  Ele,
const Eigen::PlainObjectBase< Derivedb > &  b,
const Eigen::PlainObjectBase< Derivedbc > &  bc,
igl::BBWData data,
Eigen::PlainObjectBase< DerivedW > &  W 
)
49{
50 using namespace std;
51 using namespace Eigen;
52 assert(!data.partition_unity && "partition_unity not implemented yet");
53 // number of domain vertices
54 int n = V.rows();
55 // number of handles
56 int m = bc.cols();
57 // Build biharmonic operator
59 harmonic(V,Ele,2,Q);
60 W.derived().resize(n,m);
61 // No linear terms
62 VectorXd c = VectorXd::Zero(n);
63 // No linear constraints
64 SparseMatrix<typename DerivedW::Scalar> A(0,n),Aeq(0,n),Aieq(0,n);
65 VectorXd Beq(0,1),Bieq(0,1);
66 // Upper and lower box constraints (Constant bounds)
67 VectorXd ux = VectorXd::Ones(n);
68 VectorXd lx = VectorXd::Zero(n);
69 active_set_params eff_params = data.active_set_params;
70 if(data.verbosity >= 1)
71 {
72 cout<<"BBW: max_iter: "<<data.active_set_params.max_iter<<endl;
73 cout<<"BBW: eff_max_iter: "<<eff_params.max_iter<<endl;
74 }
75 if(data.verbosity >= 1)
76 {
77 cout<<"BBW: Computing initial weights for "<<m<<" handle"<<
78 (m!=1?"s":"")<<"."<<endl;
79 }
80 min_quad_with_fixed_data<typename DerivedW::Scalar > mqwf;
81 min_quad_with_fixed_precompute(Q,b,Aeq,true,mqwf);
82 min_quad_with_fixed_solve(mqwf,c,bc,Beq,W);
83 // decrement
84 eff_params.max_iter--;
85 bool error = false;
86 // Loop over handles
87 std::mutex critical;
88 const auto & optimize_weight = [&](const int i)
89 {
90 // Quicker exit for paralle_for
91 if(error)
92 {
93 return;
94 }
95 if(data.verbosity >= 1)
96 {
97 std::lock_guard<std::mutex> lock(critical);
98 cout<<"BBW: Computing weight for handle "<<i+1<<" out of "<<m<<
99 "."<<endl;
100 }
101 VectorXd bci = bc.col(i);
102 VectorXd Wi;
103 // use initial guess
104 Wi = W.col(i);
106 Q,c,b,bci,Aeq,Beq,Aieq,Bieq,lx,ux,eff_params,Wi);
107 switch(ret)
108 {
110 break;
112 cerr<<"active_set: max iter without convergence."<<endl;
113 break;
115 default:
116 cerr<<"active_set error."<<endl;
117 error = true;
118 }
119 W.col(i) = Wi;
120 };
121 parallel_for(m,optimize_weight,2);
122 if(error)
123 {
124 return false;
125 }
126
127#ifndef NDEBUG
128 const double min_rowsum = W.rowwise().sum().array().abs().minCoeff();
129 if(min_rowsum < 0.1)
130 {
131 cerr<<"bbw.cpp: Warning, minimum row sum is very low. Consider more "
132 "active set iterations or enforcing partition of unity."<<endl;
133 }
134#endif
135
136 return true;
137}
IGL_INLINE bool harmonic(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< Derivedb > &b, const Eigen::MatrixBase< Derivedbc > &bc, const int k, Eigen::PlainObjectBase< DerivedW > &W)
Definition harmonic.cpp:26
IGL_INLINE igl::SolverStatus active_set(const Eigen::SparseMatrix< AT > &A, const Eigen::PlainObjectBase< DerivedB > &B, const Eigen::PlainObjectBase< Derivedknown > &known, const Eigen::PlainObjectBase< DerivedY > &Y, const Eigen::SparseMatrix< AeqT > &Aeq, const Eigen::PlainObjectBase< DerivedBeq > &Beq, const Eigen::SparseMatrix< AieqT > &Aieq, const Eigen::PlainObjectBase< DerivedBieq > &Bieq, const Eigen::PlainObjectBase< Derivedlx > &lx, const Eigen::PlainObjectBase< Derivedux > &ux, const igl::active_set_params &params, Eigen::PlainObjectBase< DerivedZ > &Z)
Definition active_set.cpp:32
Definition active_set.h:83
static char error[256]
Definition tga.cpp:50

References active_set(), error, harmonic(), igl::active_set_params::max_iter, min_quad_with_fixed_precompute(), min_quad_with_fixed_solve(), parallel_for(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), SOLVER_STATUS_CONVERGED, SOLVER_STATUS_ERROR, and SOLVER_STATUS_MAX_ITER.

+ Here is the call graph for this function:

◆ bfs() [1/3]

template<typename AType , typename DerivedD , typename DerivedP >
IGL_INLINE void igl::bfs ( const AType &  A,
const size_t  s,
Eigen::PlainObjectBase< DerivedD > &  D,
Eigen::PlainObjectBase< DerivedP > &  P 
)
15{
16 std::vector<typename DerivedD::Scalar> vD;
17 std::vector<typename DerivedP::Scalar> vP;
18 bfs(A,s,vD,vP);
19 list_to_matrix(vD,D);
20 list_to_matrix(vP,P);
21}
IGL_INLINE void bfs(const AType &A, const size_t s, Eigen::PlainObjectBase< DerivedD > &D, Eigen::PlainObjectBase< DerivedP > &P)
Definition bfs.cpp:10
IGL_INLINE bool list_to_matrix(const std::vector< std::vector< T > > &V, Eigen::PlainObjectBase< Derived > &M)
Definition list_to_matrix.cpp:19

References bfs(), and list_to_matrix().

Referenced by bfs().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ bfs() [2/3]

template<typename AType , typename DType , typename PType >
IGL_INLINE void igl::bfs ( const Eigen::SparseMatrix< AType > &  A,
const size_t  s,
std::vector< DType > &  D,
std::vector< PType > &  P 
)
66{
67 // number of nodes
68 int N = A.rows();
69 assert(A.rows() == A.cols());
70 std::vector<bool> seen(N,false);
71 P.resize(N,-1);
72 std::queue<std::pair<int,int> > Q;
73 Q.push({s,-1});
74 while(!Q.empty())
75 {
76 const int f = Q.front().first;
77 const int p = Q.front().second;
78 Q.pop();
79 if(seen[f])
80 {
81 continue;
82 }
83 D.push_back(f);
84 P[f] = p;
85 seen[f] = true;
86 for(typename Eigen::SparseMatrix<AType>::InnerIterator it (A,f); it; ++it)
87 {
88 if(it.value()) Q.push({it.index(),f});
89 }
90 }
91
92}

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows().

+ Here is the call graph for this function:

◆ bfs() [3/3]

template<typename AType , typename DType , typename PType >
IGL_INLINE void igl::bfs ( const std::vector< std::vector< AType > > &  A,
const size_t  s,
std::vector< DType > &  D,
std::vector< PType > &  P 
)
32{
33 // number of nodes
34 int N = s+1;
35 for(const auto & Ai : A) for(const auto & a : Ai) N = std::max(N,a+1);
36 std::vector<bool> seen(N,false);
37 P.resize(N,-1);
38 std::queue<std::pair<int,int> > Q;
39 Q.push({s,-1});
40 while(!Q.empty())
41 {
42 const int f = Q.front().first;
43 const int p = Q.front().second;
44 Q.pop();
45 if(seen[f])
46 {
47 continue;
48 }
49 D.push_back(f);
50 P[f] = p;
51 seen[f] = true;
52 for(const auto & n : A[f]) Q.push({n,f});
53 }
54}
#define const
Definition getopt.c:38

◆ bfs_orient()

template<typename DerivedF , typename DerivedFF , typename DerivedC >
IGL_INLINE void igl::bfs_orient ( const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedFF > &  FF,
Eigen::PlainObjectBase< DerivedC > &  C 
)
18{
19 using namespace Eigen;
20 using namespace std;
22 orientable_patches(F,C,A);
23
24 // number of faces
25 const int m = F.rows();
26 // number of patches
27 const int num_cc = C.maxCoeff()+1;
28 VectorXi seen = VectorXi::Zero(m);
29
30 // Edge sets
31 const int ES[3][2] = {{1,2},{2,0},{0,1}};
32
33 if(&FF != &F)
34 {
35 FF = F;
36 }
37 // loop over patches
38#pragma omp parallel for
39 for(int c = 0;c<num_cc;c++)
40 {
41 queue<int> Q;
42 // find first member of patch c
43 for(int f = 0;f<FF.rows();f++)
44 {
45 if(C(f) == c)
46 {
47 Q.push(f);
48 break;
49 }
50 }
51 assert(!Q.empty());
52 while(!Q.empty())
53 {
54 const int f = Q.front();
55 Q.pop();
56 if(seen(f) > 0)
57 {
58 continue;
59 }
60 seen(f)++;
61 // loop over neighbors of f
62 for(typename SparseMatrix<int>::InnerIterator it (A,f); it; ++it)
63 {
64 // might be some lingering zeros, and skip self-adjacency
65 if(it.value() != 0 && it.row() != f)
66 {
67 const int n = it.row();
68 assert(n != f);
69 // loop over edges of f
70 for(int efi = 0;efi<3;efi++)
71 {
72 // efi'th edge of face f
73 Vector2i ef(FF(f,ES[efi][0]),FF(f,ES[efi][1]));
74 // loop over edges of n
75 for(int eni = 0;eni<3;eni++)
76 {
77 // eni'th edge of face n
78 Vector2i en(FF(n,ES[eni][0]),FF(n,ES[eni][1]));
79 // Match (half-edges go same direction)
80 if(ef(0) == en(0) && ef(1) == en(1))
81 {
82 // flip face n
83 FF.row(n) = FF.row(n).reverse().eval();
84 }
85 }
86 }
87 // add neighbor to queue
88 Q.push(n);
89 }
90 }
91 }
92 }
93
94 // make sure flip is OK if &FF = &F
95}
IGL_INLINE void orientable_patches(const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedC > &C, Eigen::SparseMatrix< AScalar > &A)
Definition orientable_patches.cpp:16

References orientable_patches(), and Eigen::PlainObjectBase< Derived >::rows().

Referenced by igl::embree::reorient_facets_raycast().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ biharmonic_coordinates() [1/2]

template<typename DerivedV , typename DerivedT , typename SType , typename DerivedW >
IGL_INLINE bool igl::biharmonic_coordinates ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedT > &  T,
const std::vector< std::vector< SType > > &  S,
const int  k,
Eigen::PlainObjectBase< DerivedW > &  W 
)
44{
45 using namespace Eigen;
46 using namespace std;
47 // This is not the most efficient way to build A, but follows "Linear
48 // Subspace Design for Real-Time Shape Deformation" [Wang et al. 2015].
50 {
54 {
56 on_boundary(T,I,C);
57 }
58#ifdef false
59 // Version described in paper is "wrong"
60 // http://www.cs.toronto.edu/~jacobson/images/error-in-linear-subspace-design-for-real-time-shape-deformation-2017-wang-et-al.pdf
62 normal_derivative(V,T,N);
63 {
64 std::vector<Triplet<double> >ZIJV;
65 for(int t =0;t<T.rows();t++)
66 {
67 for(int f =0;f<T.cols();f++)
68 {
69 if(C(t,f))
70 {
71 const int i = t+f*T.rows();
72 for(int c = 1;c<T.cols();c++)
73 {
74 ZIJV.emplace_back(T(t,(f+c)%T.cols()),i,1);
75 }
76 }
77 }
78 }
79 Z.resize(V.rows(),N.rows());
80 Z.setFromTriplets(ZIJV.begin(),ZIJV.end());
81 N = (Z*N).eval();
82 }
83 cotmatrix(V,T,L);
84 K = N+L;
85 massmatrix(V,T,MASSMATRIX_TYPE_DEFAULT,M);
86 // normalize
87 M /= ((VectorXd)M.diagonal()).array().abs().maxCoeff();
88 Minv =
89 ((VectorXd)M.diagonal().array().inverse()).asDiagonal();
90#else
92 Eigen::MatrixXi E;
93 Eigen::VectorXi EMAP;
94 crouzeix_raviart_massmatrix(V,T,M,E,EMAP);
95 crouzeix_raviart_cotmatrix(V,T,E,EMAP,L);
96 // Ad #E by #V facet-vertex incidence matrix
97 Eigen::SparseMatrix<double> Ad(E.rows(),V.rows());
98 {
99 std::vector<Eigen::Triplet<double> > AIJV(E.size());
100 for(int e = 0;e<E.rows();e++)
101 {
102 for(int c = 0;c<E.cols();c++)
103 {
104 AIJV[e+c*E.rows()] = Eigen::Triplet<double>(e,E(e,c),1);
105 }
106 }
107 Ad.setFromTriplets(AIJV.begin(),AIJV.end());
108 }
109 // Degrees
110 Eigen::VectorXd De;
111 sum(Ad,2,De);
113 De.array().inverse().matrix().asDiagonal();
114 K = L*(De_diag*Ad);
115 // normalize
116 M /= ((VectorXd)M.diagonal()).array().abs().maxCoeff();
117 Minv = ((VectorXd)M.diagonal().array().inverse()).asDiagonal();
118 // kill boundary edges
119 for(int f = 0;f<T.rows();f++)
120 {
121 for(int c = 0;c<T.cols();c++)
122 {
123 if(C(f,c))
124 {
125 const int e = EMAP(f+T.rows()*c);
126 Minv.diagonal()(e) = 0;
127 }
128 }
129 }
130
131#endif
132 switch(k)
133 {
134 default:
135 assert(false && "unsupported");
136 case 2:
137 // For C1 smoothness in 2D, one should use bi-harmonic
138 A = K.transpose() * (Minv * K);
139 break;
140 case 3:
141 // For C1 smoothness in 3D, one should use tri-harmonic
142 A = K.transpose() * (Minv * (-L * (Minv * K)));
143 break;
144 }
145 }
146 // Vertices in point handles
147 const size_t mp =
148 count_if(S.begin(),S.end(),[](const vector<int> & h){return h.size()==1;});
149 // number of region handles
150 const size_t r = S.size()-mp;
151 // Vertices in region handles
152 size_t mr = 0;
153 for(const auto & h : S)
154 {
155 if(h.size() > 1)
156 {
157 mr += h.size();
158 }
159 }
160 const size_t dim = T.cols()-1;
161 // Might as well be dense... I think...
162 MatrixXd J = MatrixXd::Zero(mp+mr,mp+r*(dim+1));
163 VectorXi b(mp+mr);
164 MatrixXd H(mp+r*(dim+1),dim);
165 {
166 int v = 0;
167 int c = 0;
168 for(int h = 0;h<S.size();h++)
169 {
170 if(S[h].size()==1)
171 {
172 H.row(c) = V.block(S[h][0],0,1,dim);
173 J(v,c++) = 1;
174 b(v) = S[h][0];
175 v++;
176 }else
177 {
178 assert(S[h].size() >= dim+1);
179 for(int p = 0;p<S[h].size();p++)
180 {
181 for(int d = 0;d<dim;d++)
182 {
183 J(v,c+d) = V(S[h][p],d);
184 }
185 J(v,c+dim) = 1;
186 b(v) = S[h][p];
187 v++;
188 }
189 H.block(c,0,dim+1,dim).setIdentity();
190 c+=dim+1;
191 }
192 }
193 }
194 // minimize ½ W' A W'
195 // subject to W(b,:) = J
196 return min_quad_with_fixed(
197 A,VectorXd::Zero(A.rows()).eval(),b,J,SparseMatrix<double>(),VectorXd(),true,W);
198}
EIGEN_DEVICE_FUNC const InverseReturnType inverse() const
Definition DiagonalMatrix.h:69
Represents a diagonal matrix with its storage.
Definition DiagonalMatrix.h:118
EIGEN_DEVICE_FUNC const DiagonalVectorType & diagonal() const
Definition DiagonalMatrix.h:136
const ConstDiagonalReturnType diagonal() const
Definition SparseMatrix.h:650
@ E
Definition libslic3r.h:101
IGL_INLINE void on_boundary(const std::vector< std::vector< IntegerT > > &T, std::vector< bool > &I, std::vector< std::vector< bool > > &C)
Definition on_boundary.cpp:17
void crouzeix_raviart_massmatrix(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::SparseMatrix< MT > &M, Eigen::PlainObjectBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedEMAP > &EMAP)
Definition crouzeix_raviart_massmatrix.cpp:20
IGL_INLINE bool min_quad_with_fixed(const Eigen::SparseMatrix< T > &A, const Eigen::MatrixBase< DerivedB > &B, const Eigen::MatrixBase< Derivedknown > &known, const Eigen::MatrixBase< DerivedY > &Y, const Eigen::SparseMatrix< T > &Aeq, const Eigen::MatrixBase< DerivedBeq > &Beq, const bool pd, Eigen::PlainObjectBase< DerivedZ > &Z)
Definition min_quad_with_fixed.cpp:565
void crouzeix_raviart_cotmatrix(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::SparseMatrix< LT > &L, Eigen::PlainObjectBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedEMAP > &EMAP)
Definition crouzeix_raviart_cotmatrix.cpp:15
IGL_INLINE void sum(const Eigen::SparseMatrix< T > &X, const int dim, Eigen::SparseVector< T > &S)
Definition sum.cpp:12

References Eigen::PlainObjectBase< Derived >::cols(), cotmatrix(), crouzeix_raviart_cotmatrix(), crouzeix_raviart_massmatrix(), Eigen::DiagonalMatrix< _Scalar, SizeAtCompileTime, MaxSizeAtCompileTime >::diagonal(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::diagonal(), Eigen::SparseMatrixBase< Derived >::eval(), Eigen::DiagonalBase< Derived >::inverse(), L, massmatrix(), MASSMATRIX_TYPE_DEFAULT, min_quad_with_fixed(), normal_derivative(), on_boundary(), Eigen::PlainObjectBase< Derived >::rows(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets(), and sum().

+ Here is the call graph for this function:

◆ biharmonic_coordinates() [2/2]

template<typename DerivedV , typename DerivedT , typename SType , typename DerivedW >
IGL_INLINE bool igl::biharmonic_coordinates ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedT > &  T,
const std::vector< std::vector< SType > > &  S,
Eigen::PlainObjectBase< DerivedW > &  W 
)
29{
30 return biharmonic_coordinates(V,T,S,2,W);
31}
IGL_INLINE bool biharmonic_coordinates(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedT > &T, const std::vector< std::vector< SType > > &S, Eigen::PlainObjectBase< DerivedW > &W)
Definition biharmonic_coordinates.cpp:24

References biharmonic_coordinates().

Referenced by biharmonic_coordinates().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ bijective_composite_harmonic_mapping() [1/2]

template<typename DerivedV , typename DerivedF , typename Derivedb , typename Derivedbc , typename DerivedU >
IGL_INLINE bool igl::bijective_composite_harmonic_mapping ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< Derivedb > &  b,
const Eigen::MatrixBase< Derivedbc > &  bc,
const int  min_steps,
const int  max_steps,
const int  num_inner_iters,
const bool  test_for_flips,
Eigen::PlainObjectBase< DerivedU > &  U 
)
48{
49 typedef typename Derivedbc::Scalar Scalar;
50 assert(V.cols() == 2 && bc.cols() == 2 && "Input should be 2D");
51 assert(F.cols() == 3 && "F should contain triangles");
52 int tries = 0;
53 int nsteps = min_steps;
54 Derivedbc bc0;
55 slice(V,b,1,bc0);
56
57 // It's difficult to check for flips "robustly" in the sense that the input
58 // mesh might not have positive/consistent sign to begin with.
59
60 while(nsteps<=max_steps)
61 {
62 U = V;
63 int flipped = 0;
64 int nans = 0;
65 int step = 0;
66 for(;step<=nsteps;step++)
67 {
68 const Scalar t = ((Scalar)step)/((Scalar)nsteps);
69 // linearly interpolate boundary conditions
70 // TODO: replace this with something that guarantees a homotopic "morph"
71 // of the boundary conditions. Something like "Homotopic Morphing of
72 // Planar Curves" [Dym et al. 2015] but also handling multiple connected
73 // components.
74 Derivedbc bct = bc0 + t*(bc - bc0);
75 // Compute dsicrete harmonic map using metric of previous step
76 for(int iter = 0;iter<num_inner_iters;iter++)
77 {
78 //std::cout<<nsteps<<" t: "<<t<<" iter: "<<iter;
79 //igl::matlab::MatlabWorkspace mw;
80 //mw.save(U,"U");
81 //mw.save_index(F,"F");
82 //mw.save_index(b,"b");
83 //mw.save(bct,"bct");
84 //mw.write("numerical.mat");
85 harmonic(DerivedU(U),F,b,bct,1,U);
86 igl::slice(U,b,1,bct);
87 nans = (U.array() != U.array()).count();
88 if(test_for_flips)
89 {
91 doublearea(U,F,A);
92 flipped = (A.array() < 0 ).count();
93 //std::cout<<" "<<flipped<<" nan? "<<(U.array() != U.array()).any()<<std::endl;
94 if(flipped == 0 && nans == 0) break;
95 }
96 }
97 if(flipped > 0 || nans>0) break;
98 }
99 if(flipped == 0 && nans == 0)
100 {
101 return step == nsteps+1;
102 }
103 nsteps *= 2;
104 }
105 //std::cout<<"failed to finish in "<<nsteps<<"..."<<std::endl;
106 return false;
107}
IGL_INLINE void doublearea(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DeriveddblA > &dblA)
Definition doublearea.cpp:17
Coord step(const Coord &crd, Dir d)
Definition MarchingSquares.hpp:137

References count(), doublearea(), harmonic(), and slice().

+ Here is the call graph for this function:

◆ bijective_composite_harmonic_mapping() [2/2]

template<typename DerivedV , typename DerivedF , typename Derivedb , typename Derivedbc , typename DerivedU >
IGL_INLINE bool igl::bijective_composite_harmonic_mapping ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< Derivedb > &  b,
const Eigen::MatrixBase< Derivedbc > &  bc,
Eigen::PlainObjectBase< DerivedU > &  U 
)
28{
29 return bijective_composite_harmonic_mapping(V,F,b,bc,1,200,20,true,U);
30}
IGL_INLINE bool bijective_composite_harmonic_mapping(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< Derivedb > &b, const Eigen::MatrixBase< Derivedbc > &bc, Eigen::PlainObjectBase< DerivedU > &U)
Definition bijective_composite_harmonic_mapping.cpp:22

References bijective_composite_harmonic_mapping().

Referenced by bijective_composite_harmonic_mapping().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ bone_parents()

template<typename DerivedBE , typename DerivedP >
IGL_INLINE void igl::bone_parents ( const Eigen::PlainObjectBase< DerivedBE > &  BE,
Eigen::PlainObjectBase< DerivedP > &  P 
)
14{
15 P.resize(BE.rows(),1);
16 // Stupid O(n²) version
17 for(int e = 0;e<BE.rows();e++)
18 {
19 P(e) = -1;
20 for(int f = 0;f<BE.rows();f++)
21 {
22 if(BE(e,0) == BE(f,1))
23 {
24 P(e) = f;
25 }
26 }
27 }
28}

References Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ boundary_conditions()

IGL_INLINE bool igl::boundary_conditions ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  Ele,
const Eigen::MatrixXd &  C,
const Eigen::VectorXi &  P,
const Eigen::MatrixXi &  BE,
const Eigen::MatrixXi &  CE,
Eigen::VectorXi &  b,
Eigen::MatrixXd &  bc 
)
27{
28 using namespace Eigen;
29 using namespace std;
30
31 if(P.size()+BE.rows() == 0)
32 {
33 verbose("^%s: Error: no handles found\n",__FUNCTION__);
34 return false;
35 }
36
37 vector<int> bci;
38 vector<int> bcj;
39 vector<double> bcv;
40
41 // loop over points
42 for(int p = 0;p<P.size();p++)
43 {
44 VectorXd pos = C.row(P(p));
45 // loop over domain vertices
46 for(int i = 0;i<V.rows();i++)
47 {
48 // Find samples just on pos
49 //Vec3 vi(V(i,0),V(i,1),V(i,2));
50 // EIGEN GOTCHA:
51 // double sqrd = (V.row(i)-pos).array().pow(2).sum();
52 // Must first store in temporary
53 VectorXd vi = V.row(i);
54 double sqrd = (vi-pos).squaredNorm();
55 if(sqrd <= FLOAT_EPS)
56 {
57 //cout<<"sum((["<<
58 // V(i,0)<<" "<<
59 // V(i,1)<<" "<<
60 // V(i,2)<<"] - ["<<
61 // pos(0)<<" "<<
62 // pos(1)<<" "<<
63 // pos(2)<<"]).^2) = "<<sqrd<<endl;
64 bci.push_back(i);
65 bcj.push_back(p);
66 bcv.push_back(1.0);
67 }
68 }
69 }
70
71 // loop over bone edges
72 for(int e = 0;e<BE.rows();e++)
73 {
74 // loop over domain vertices
75 for(int i = 0;i<V.rows();i++)
76 {
77 // Find samples from tip up to tail
78 VectorXd tip = C.row(BE(e,0));
79 VectorXd tail = C.row(BE(e,1));
80 // Compute parameter along bone and squared distance
81 double t,sqrd;
83 V(i,0),V(i,1),V(i,2),
84 tip(0),tip(1),tip(2),
85 tail(0),tail(1),tail(2),
86 t,sqrd);
87 if(t>=-FLOAT_EPS && t<=(1.0f+FLOAT_EPS) && sqrd<=FLOAT_EPS)
88 {
89 bci.push_back(i);
90 bcj.push_back(P.size()+e);
91 bcv.push_back(1.0);
92 }
93 }
94 }
95
96 // loop over cage edges
97 for(int e = 0;e<CE.rows();e++)
98 {
99 // loop over domain vertices
100 for(int i = 0;i<V.rows();i++)
101 {
102 // Find samples from tip up to tail
103 VectorXd tip = C.row(P(CE(e,0)));
104 VectorXd tail = C.row(P(CE(e,1)));
105 // Compute parameter along bone and squared distance
106 double t,sqrd;
108 V(i,0),V(i,1),V(i,2),
109 tip(0),tip(1),tip(2),
110 tail(0),tail(1),tail(2),
111 t,sqrd);
112 if(t>=-FLOAT_EPS && t<=(1.0f+FLOAT_EPS) && sqrd<=FLOAT_EPS)
113 {
114 bci.push_back(i);
115 bcj.push_back(CE(e,0));
116 bcv.push_back(1.0-t);
117 bci.push_back(i);
118 bcj.push_back(CE(e,1));
119 bcv.push_back(t);
120 }
121 }
122 }
123
124 // find unique boundary indices
125 vector<int> vb = bci;
126 sort(vb.begin(),vb.end());
127 vb.erase(unique(vb.begin(), vb.end()), vb.end());
128
129 b.resize(vb.size());
130 bc = MatrixXd::Zero(vb.size(),P.size()+BE.rows());
131 // Map from boundary index to index in boundary
132 map<int,int> bim;
133 int i = 0;
134 // Also fill in b
135 for(vector<int>::iterator bit = vb.begin();bit != vb.end();bit++)
136 {
137 b(i) = *bit;
138 bim[*bit] = i;
139 i++;
140 }
141
142 // Build BC
143 for(i = 0;i < (int)bci.size();i++)
144 {
145 assert(bim.find(bci[i]) != bim.end());
146 bc(bim[bci[i]],bcj[i]) = bcv[i];
147 }
148
149 // Normalize across rows so that conditions sum to one
150 for(i = 0;i<bc.rows();i++)
151 {
152 double sum = bc.row(i).sum();
153 assert(sum != 0 && "Some boundary vertex getting all zero BCs");
154 bc.row(i).array() /= sum;
155 }
156
157 if(bc.size() == 0)
158 {
159 verbose("^%s: Error: boundary conditions are empty.\n",__FUNCTION__);
160 return false;
161 }
162
163 // If there's only a single boundary condition, the following tests
164 // are overzealous.
165 if(bc.cols() == 1)
166 {
167 // If there is only one weight function,
168 // then we expect that there is only one handle.
169 assert(P.rows() + BE.rows() == 1);
170 return true;
171 }
172
173 // Check that every Weight function has at least one boundary value of 1 and
174 // one value of 0
175 for(i = 0;i<bc.cols();i++)
176 {
177 double min_abs_c = bc.col(i).array().abs().minCoeff();
178 double max_c = bc.col(i).maxCoeff();
179 if(min_abs_c > FLOAT_EPS)
180 {
181 verbose("^%s: Error: handle %d does not receive 0 weight\n",__FUNCTION__,i);
182 return false;
183 }
184 if(max_c< (1-FLOAT_EPS))
185 {
186 verbose("^%s: Error: handle %d does not receive 1 weight\n",__FUNCTION__,i);
187 return false;
188 }
189 }
190
191 return true;
192}
EIGEN_DEVICE_FUNC SegmentReturnType tail(Index n)
This is the const version of tail(Index).
Definition BlockMethods.h:949
IGL_INLINE void sort(const Eigen::DenseBase< DerivedX > &X, const int dim, const bool ascending, Eigen::PlainObjectBase< DerivedY > &Y, Eigen::PlainObjectBase< DerivedIX > &IX)
Definition sort.cpp:21
IGL_INLINE void unique(const std::vector< T > &A, std::vector< T > &C, std::vector< size_t > &IA, std::vector< size_t > &IC)
Definition unique.cpp:21
IGL_INLINE void project_to_line(const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedS > &S, const Eigen::MatrixBase< DerivedD > &D, Eigen::PlainObjectBase< Derivedt > &t, Eigen::PlainObjectBase< DerivedsqrD > &sqrD)
Definition project_to_line.cpp:18

References FLOAT_EPS, project_to_line(), sort(), sum(), tail(), unique(), and verbose.

+ Here is the call graph for this function:

◆ boundary_facets() [1/3]

template<typename DerivedT , typename Ret >
Ret igl::boundary_facets ( const Eigen::PlainObjectBase< DerivedT > &  T)
123{
124 Ret F;
126 return F;
127}
IGL_INLINE void boundary_facets(const std::vector< std::vector< IntegerT > > &T, std::vector< std::vector< IntegerF > > &F)
Definition boundary_facets.cpp:19

References boundary_facets().

+ Here is the call graph for this function:

◆ boundary_facets() [2/3]

template<typename DerivedT , typename DerivedF >
IGL_INLINE void igl::boundary_facets ( const Eigen::PlainObjectBase< DerivedT > &  T,
Eigen::PlainObjectBase< DerivedF > &  F 
)
108{
109 assert(T.cols() == 0 || T.cols() == 4 || T.cols() == 3);
110 using namespace std;
111 using namespace Eigen;
112 // Cop out: use vector of vectors version
113 vector<vector<typename DerivedT::Scalar> > vT;
114 matrix_to_list(T,vT);
115 vector<vector<typename DerivedF::Scalar> > vF;
116 boundary_facets(vT,vF);
117 list_to_matrix(vF,F);
118}
IGL_INLINE void matrix_to_list(const Eigen::DenseBase< DerivedM > &M, std::vector< std::vector< typename DerivedM::Scalar > > &V)
Definition matrix_to_list.cpp:13

References boundary_facets(), Eigen::PlainObjectBase< Derived >::cols(), list_to_matrix(), and matrix_to_list().

+ Here is the call graph for this function:

◆ boundary_facets() [3/3]

template<typename IntegerT , typename IntegerF >
IGL_INLINE void igl::boundary_facets ( const std::vector< std::vector< IntegerT > > &  T,
std::vector< std::vector< IntegerF > > &  F 
)
22{
23 using namespace std;
24
25 if(T.size() == 0)
26 {
27 F.clear();
28 return;
29 }
30
31 int simplex_size = T[0].size();
32 // Get a list of all faces
33 vector<vector<IntegerF> > allF(
34 T.size()*simplex_size,
35 vector<IntegerF>(simplex_size-1));
36
37 // Gather faces, loop over tets
38 for(int i = 0; i< (int)T.size();i++)
39 {
40 assert((int)T[i].size() == simplex_size);
41 switch(simplex_size)
42 {
43 case 4:
44 // get face in correct order
45 allF[i*simplex_size+0][0] = T[i][1];
46 allF[i*simplex_size+0][1] = T[i][3];
47 allF[i*simplex_size+0][2] = T[i][2];
48 // get face in correct order
49 allF[i*simplex_size+1][0] = T[i][0];
50 allF[i*simplex_size+1][1] = T[i][2];
51 allF[i*simplex_size+1][2] = T[i][3];
52 // get face in correct order
53 allF[i*simplex_size+2][0] = T[i][0];
54 allF[i*simplex_size+2][1] = T[i][3];
55 allF[i*simplex_size+2][2] = T[i][1];
56 // get face in correct order
57 allF[i*simplex_size+3][0] = T[i][0];
58 allF[i*simplex_size+3][1] = T[i][1];
59 allF[i*simplex_size+3][2] = T[i][2];
60 break;
61 case 3:
62 allF[i*simplex_size+0][0] = T[i][1];
63 allF[i*simplex_size+0][1] = T[i][2];
64 allF[i*simplex_size+1][0] = T[i][2];
65 allF[i*simplex_size+1][1] = T[i][0];
66 allF[i*simplex_size+2][0] = T[i][0];
67 allF[i*simplex_size+2][1] = T[i][1];
68 break;
69 }
70 }
71
72 // Counts
73 vector<int> C;
74 face_occurrences(allF,C);
75
76 // Q: Why not just count the number of ones?
77 // A: because we are including non-manifold edges as boundary edges
78 int twos = (int) count(C.begin(),C.end(),2);
79 //int ones = (int) count(C.begin(),C.end(),1);
80 // Resize output to fit number of ones
81 F.resize(allF.size() - twos);
82 //F.resize(ones);
83 int k = 0;
84 for(int i = 0;i< (int)allF.size();i++)
85 {
86 if(C[i] != 2)
87 {
88 assert(k<(int)F.size());
89 F[k] = allF[i];
90 k++;
91 }
92 }
93 assert(k==(int)F.size());
94 //if(k != F.size())
95 //{
96 // printf("%d =? %d\n",k,F.size());
97 //}
98
99}
IGL_INLINE void face_occurrences(const std::vector< std::vector< IntegerF > > &F, std::vector< IntegerC > &C)
Definition face_occurrences.cpp:15

References count(), and face_occurrences().

Referenced by boundary_facets(), boundary_facets(), connect_boundary_to_infinity(), read_triangle_mesh(), and vector_area_matrix().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ boundary_loop() [1/3]

template<typename DerivedF , typename DerivedL >
IGL_INLINE void igl::boundary_loop ( const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedL > &  L 
)
135{
136 using namespace Eigen;
137 using namespace std;
138
139 if(F.rows() == 0)
140 return;
141
142 vector<int> Lvec;
143 boundary_loop(F,Lvec);
144
145 L.resize(Lvec.size());
146 for (size_t i = 0; i < Lvec.size(); ++i)
147 L(i) = Lvec[i];
148}
IGL_INLINE void boundary_loop(const Eigen::PlainObjectBase< DerivedF > &F, std::vector< std::vector< Index > > &L)
Definition boundary_loop.cpp:16

References boundary_loop(), and L.

+ Here is the call graph for this function:

◆ boundary_loop() [2/3]

template<typename DerivedF , typename Index >
IGL_INLINE void igl::boundary_loop ( const Eigen::PlainObjectBase< DerivedF > &  F,
std::vector< Index > &  L 
)
96{
97 using namespace Eigen;
98 using namespace std;
99
100 if(F.rows() == 0)
101 return;
102
103 vector<vector<int> > Lall;
104 boundary_loop(F,Lall);
105
106 int idxMax = -1;
107 size_t maxLen = 0;
108 for (size_t i = 0; i < Lall.size(); ++i)
109 {
110 if (Lall[i].size() > maxLen)
111 {
112 maxLen = Lall[i].size();
113 idxMax = i;
114 }
115 }
116
117 //Check for meshes without boundary
118 if (idxMax == -1)
119 {
120 L.clear();
121 return;
122 }
123
124 L.resize(Lall[idxMax].size());
125 for (size_t i = 0; i < Lall[idxMax].size(); ++i)
126 {
127 L[i] = Lall[idxMax][i];
128 }
129}

References boundary_loop(), and L.

+ Here is the call graph for this function:

◆ boundary_loop() [3/3]

template<typename DerivedF , typename Index >
IGL_INLINE void igl::boundary_loop ( const Eigen::PlainObjectBase< DerivedF > &  F,
std::vector< std::vector< Index > > &  L 
)
19{
20 using namespace std;
21 using namespace Eigen;
22
23 if(F.rows() == 0)
24 return;
25
26 VectorXd Vdummy(F.maxCoeff()+1,1);
27 DerivedF TT,TTi;
28 vector<std::vector<int> > VF, VFi;
30 vertex_triangle_adjacency(Vdummy,F,VF,VFi);
31
32 vector<bool> unvisited = is_border_vertex(Vdummy,F);
33 set<int> unseen;
34 for (size_t i = 0; i < unvisited.size(); ++i)
35 {
36 if (unvisited[i])
37 unseen.insert(unseen.end(),i);
38 }
39
40 while (!unseen.empty())
41 {
42 vector<Index> l;
43
44 // Get first vertex of loop
45 int start = *unseen.begin();
46 unseen.erase(unseen.begin());
47 unvisited[start] = false;
48 l.push_back(start);
49
50 bool done = false;
51 while (!done)
52 {
53 // Find next vertex
54 bool newBndEdge = false;
55 int v = l[l.size()-1];
56 int next;
57 for (int i = 0; i < (int)VF[v].size() && !newBndEdge; i++)
58 {
59 int fid = VF[v][i];
60
61 if (TT.row(fid).minCoeff() < 0.) // Face contains boundary edge
62 {
63 int vLoc = -1;
64 if (F(fid,0) == v) vLoc = 0;
65 if (F(fid,1) == v) vLoc = 1;
66 if (F(fid,2) == v) vLoc = 2;
67
68 int vNext = F(fid,(vLoc + 1) % F.cols());
69
70 newBndEdge = false;
71 if (unvisited[vNext] && TT(fid,vLoc) < 0)
72 {
73 next = vNext;
74 newBndEdge = true;
75 }
76 }
77 }
78
79 if (newBndEdge)
80 {
81 l.push_back(next);
82 unseen.erase(next);
83 unvisited[next] = false;
84 }
85 else
86 done = true;
87 }
88 L.push_back(l);
89 }
90}
static volatile int done
Definition bitbang.c:50
IGL_INLINE void vertex_triangle_adjacency(const typename DerivedF::Scalar n, const Eigen::MatrixBase< DerivedF > &F, std::vector< std::vector< VFType > > &VF, std::vector< std::vector< VFiType > > &VFi)
Definition vertex_triangle_adjacency.cpp:12
IGL_INLINE std::vector< bool > is_border_vertex(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F)
Definition is_border_vertex.cpp:14
IGL_INLINE void triangle_triangle_adjacency(const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedTT > &TT, Eigen::PlainObjectBase< DerivedTTi > &TTi)
Definition triangle_triangle_adjacency.cpp:116

References done, is_border_vertex(), L, triangle_triangle_adjacency(), and vertex_triangle_adjacency().

Referenced by boundary_loop(), boundary_loop(), and hessian_energy().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ bounding_box() [1/2]

template<typename DerivedV , typename DerivedBV , typename DerivedBF >
IGL_INLINE void igl::bounding_box ( const Eigen::MatrixBase< DerivedV > &  V,
const typename DerivedV::Scalar  pad,
Eigen::PlainObjectBase< DerivedBV > &  BV,
Eigen::PlainObjectBase< DerivedBF > &  BF 
)
26{
27 using namespace std;
28
29 const int dim = V.cols();
30 const auto & minV = V.colwise().minCoeff().array()-pad;
31 const auto & maxV = V.colwise().maxCoeff().array()+pad;
32 // 2^n vertices
33 BV.resize((1<<dim),dim);
34
35 // Recursive lambda to generate all 2^n combinations
36 const std::function<void(const int,const int,int*,int)> combos =
37 [&BV,&minV,&maxV,&combos](
38 const int dim,
39 const int i,
40 int * X,
41 const int pre_index)
42 {
43 for(X[i] = 0;X[i]<2;X[i]++)
44 {
45 int index = pre_index*2+X[i];
46 if((i+1)<dim)
47 {
48 combos(dim,i+1,X,index);
49 }else
50 {
51 for(int d = 0;d<dim;d++)
52 {
53 BV(index,d) = (X[d]?minV[d]:maxV[d]);
54 }
55 }
56 }
57 };
58
59 Eigen::VectorXi X(dim);
60 combos(dim,0,X.data(),0);
61 switch(dim)
62 {
63 case 2:
64 BF.resize(4,2);
65 BF<<
66 3,1,
67 1,0,
68 0,2,
69 2,3;
70 break;
71 case 3:
72 BF.resize(12,3);
73 BF<<
74 2,0,6,
75 0,4,6,
76 5,4,0,
77 5,0,1,
78 6,4,5,
79 5,7,6,
80 3,0,2,
81 1,0,3,
82 3,2,6,
83 6,7,3,
84 5,1,3,
85 3,7,5;
86 break;
87 default:
88 assert(false && "Unsupported dimension.");
89 break;
90 }
91}
EIGEN_DEVICE_FUNC ConstColwiseReturnType colwise() const
Definition DenseBase.h:516
EIGEN_DEVICE_FUNC const MinCoeffReturnType minCoeff() const
Definition VectorwiseOp.h:304
EIGEN_DEVICE_FUNC const MaxCoeffReturnType maxCoeff() const
Definition VectorwiseOp.h:317
typedef void(GLAPIENTRYP _GLUfuncptr)(void)
@ X
Definition libslic3r.h:98

References Eigen::DenseBase< Derived >::colwise(), Eigen::VectorwiseOp< ExpressionType, Direction >::maxCoeff(), Eigen::VectorwiseOp< ExpressionType, Direction >::minCoeff(), Eigen::PlainObjectBase< Derived >::resize(), and void().

+ Here is the call graph for this function:

◆ bounding_box() [2/2]

template<typename DerivedV , typename DerivedBV , typename DerivedBF >
IGL_INLINE void igl::bounding_box ( const Eigen::MatrixBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedBV > &  BV,
Eigen::PlainObjectBase< DerivedBF > &  BF 
)
16{
17 return bounding_box(V,0.,BV,BF);
18}
IGL_INLINE void bounding_box(const Eigen::MatrixBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedBV > &BV, Eigen::PlainObjectBase< DerivedBF > &BF)
Definition bounding_box.cpp:12

References bounding_box().

Referenced by bounding_box(), igl::copyleft::tetgen::cdt(), and igl::copyleft::cgal::outer_hull_legacy().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ bounding_box_diagonal()

IGL_INLINE double igl::bounding_box_diagonal ( const Eigen::MatrixXd &  V)
15{
16 using namespace Eigen;
17 VectorXd maxV,minV;
18 VectorXi maxVI,minVI;
19 mat_max(V,1,maxV,maxVI);
20 mat_min(V,1,minV,minVI);
21 return sqrt((maxV-minV).array().square().sum());
22}
EIGEN_DEVICE_FUNC const SquareReturnType square() const
Definition ArrayCwiseUnaryOps.h:346
IGL_INLINE void mat_max(const Eigen::DenseBase< DerivedX > &X, const int dim, Eigen::PlainObjectBase< DerivedY > &Y, Eigen::PlainObjectBase< DerivedI > &I)
Definition mat_max.cpp:11
IGL_INLINE void mat_min(const Eigen::DenseBase< DerivedX > &X, const int dim, Eigen::PlainObjectBase< DerivedY > &Y, Eigen::PlainObjectBase< DerivedI > &I)
Definition mat_min.cpp:11

References mat_max(), mat_min(), sqrt(), square(), and sum().

Referenced by collapse_small_triangles().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ CANONICAL_VIEW_QUAT()

template<typename Q_type >
IGL_INLINE Q_type igl::CANONICAL_VIEW_QUAT ( int  i,
int  j 
)

◆ CANONICAL_VIEW_QUAT< double >()

template<>
IGL_INLINE double igl::CANONICAL_VIEW_QUAT< double > ( int  i,
int  j 
)
15{
16 return (double)igl::CANONICAL_VIEW_QUAT_D[i][j];
17}
const double CANONICAL_VIEW_QUAT_D[][4]
Definition canonical_quaternions.h:71

References CANONICAL_VIEW_QUAT_D.

◆ CANONICAL_VIEW_QUAT< float >()

template<>
IGL_INLINE float igl::CANONICAL_VIEW_QUAT< float > ( int  i,
int  j 
)
11{
12 return (float)igl::CANONICAL_VIEW_QUAT_F[i][j];
13}
const float CANONICAL_VIEW_QUAT_F[][4]
Definition canonical_quaternions.h:27

References CANONICAL_VIEW_QUAT_F.

◆ cat() [1/4]

template<typename Derived , class MatC >
IGL_INLINE void igl::cat ( const int  dim,
const Eigen::MatrixBase< Derived > &  A,
const Eigen::MatrixBase< Derived > &  B,
MatC &  C 
)
195{
196 assert(dim == 1 || dim == 2);
197 // Special case if B or A is empty
198 if(A.size() == 0)
199 {
200 C = B;
201 return;
202 }
203 if(B.size() == 0)
204 {
205 C = A;
206 return;
207 }
208
209 if(dim == 1)
210 {
211 assert(A.cols() == B.cols());
212 C.resize(A.rows()+B.rows(),A.cols());
213 C << A,B;
214 }else if(dim == 2)
215 {
216 assert(A.rows() == B.rows());
217 C.resize(A.rows(),A.cols()+B.cols());
218 C << A,B;
219 }else
220 {
221 fprintf(stderr,"cat.h: Error: Unsupported dimension %d\n",dim);
222 }
223}

◆ cat() [2/4]

template<typename Scalar >
IGL_INLINE void igl::cat ( const int  dim,
const Eigen::SparseMatrix< Scalar > &  A,
const Eigen::SparseMatrix< Scalar > &  B,
Eigen::SparseMatrix< Scalar > &  C 
)
26{
27
28 assert(dim == 1 || dim == 2);
29 using namespace Eigen;
30 // Special case if B or A is empty
31 if(A.size() == 0)
32 {
33 C = B;
34 return;
35 }
36 if(B.size() == 0)
37 {
38 C = A;
39 return;
40 }
41
42#if false
43 // This **must** be DynamicSparseMatrix, otherwise this implementation is
44 // insanely slow
46 if(dim == 1)
47 {
48 assert(A.cols() == B.cols());
49 dyn_C.resize(A.rows()+B.rows(),A.cols());
50 }else if(dim == 2)
51 {
52 assert(A.rows() == B.rows());
53 dyn_C.resize(A.rows(),A.cols()+B.cols());
54 }else
55 {
56 fprintf(stderr,"cat.h: Error: Unsupported dimension %d\n",dim);
57 }
58
59 dyn_C.reserve(A.nonZeros()+B.nonZeros());
60
61 // Iterate over outside of A
62 for(int k=0; k<A.outerSize(); ++k)
63 {
64 // Iterate over inside
65 for(typename SparseMatrix<Scalar>::InnerIterator it (A,k); it; ++it)
66 {
67 dyn_C.coeffRef(it.row(),it.col()) += it.value();
68 }
69 }
70
71 // Iterate over outside of B
72 for(int k=0; k<B.outerSize(); ++k)
73 {
74 // Iterate over inside
75 for(typename SparseMatrix<Scalar>::InnerIterator it (B,k); it; ++it)
76 {
77 int r = (dim == 1 ? A.rows()+it.row() : it.row());
78 int c = (dim == 2 ? A.cols()+it.col() : it.col());
79 dyn_C.coeffRef(r,c) += it.value();
80 }
81 }
82
83 C = SparseMatrix<Scalar>(dyn_C);
84#elif false
85 std::vector<Triplet<Scalar> > CIJV;
86 CIJV.reserve(A.nonZeros() + B.nonZeros());
87 {
88 // Iterate over outside of A
89 for(int k=0; k<A.outerSize(); ++k)
90 {
91 // Iterate over inside
92 for(typename SparseMatrix<Scalar>::InnerIterator it (A,k); it; ++it)
93 {
94 CIJV.emplace_back(it.row(),it.col(),it.value());
95 }
96 }
97 // Iterate over outside of B
98 for(int k=0; k<B.outerSize(); ++k)
99 {
100 // Iterate over inside
101 for(typename SparseMatrix<Scalar>::InnerIterator it (B,k); it; ++it)
102 {
103 int r = (dim == 1 ? A.rows()+it.row() : it.row());
104 int c = (dim == 2 ? A.cols()+it.col() : it.col());
105 CIJV.emplace_back(r,c,it.value());
106 }
107 }
108
109 }
110
112 dim == 1 ? A.rows()+B.rows() : A.rows(),
113 dim == 1 ? A.cols() : A.cols()+B.cols());
114 C.reserve(A.nonZeros() + B.nonZeros());
115 C.setFromTriplets(CIJV.begin(),CIJV.end());
116#else
118 dim == 1 ? A.rows()+B.rows() : A.rows(),
119 dim == 1 ? A.cols() : A.cols()+B.cols());
120 Eigen::VectorXi per_col = Eigen::VectorXi::Zero(C.cols());
121 if(dim == 1)
122 {
123 assert(A.outerSize() == B.outerSize());
124 for(int k = 0;k<A.outerSize();++k)
125 {
126 for(typename SparseMatrix<Scalar>::InnerIterator it (A,k); it; ++it)
127 {
128 per_col(k)++;
129 }
130 for(typename SparseMatrix<Scalar>::InnerIterator it (B,k); it; ++it)
131 {
132 per_col(k)++;
133 }
134 }
135 }else
136 {
137 for(int k = 0;k<A.outerSize();++k)
138 {
139 for(typename SparseMatrix<Scalar>::InnerIterator it (A,k); it; ++it)
140 {
141 per_col(k)++;
142 }
143 }
144 for(int k = 0;k<B.outerSize();++k)
145 {
146 for(typename SparseMatrix<Scalar>::InnerIterator it (B,k); it; ++it)
147 {
148 per_col(A.cols() + k)++;
149 }
150 }
151 }
152 C.reserve(per_col);
153 if(dim == 1)
154 {
155 for(int k = 0;k<A.outerSize();++k)
156 {
157 for(typename SparseMatrix<Scalar>::InnerIterator it (A,k); it; ++it)
158 {
159 C.insert(it.row(),k) = it.value();
160 }
161 for(typename SparseMatrix<Scalar>::InnerIterator it (B,k); it; ++it)
162 {
163 C.insert(A.rows()+it.row(),k) = it.value();
164 }
165 }
166 }else
167 {
168 for(int k = 0;k<A.outerSize();++k)
169 {
170 for(typename SparseMatrix<Scalar>::InnerIterator it (A,k); it; ++it)
171 {
172 C.insert(it.row(),k) = it.value();
173 }
174 }
175 for(int k = 0;k<B.outerSize();++k)
176 {
177 for(typename SparseMatrix<Scalar>::InnerIterator it (B,k); it; ++it)
178 {
179 C.insert(it.row(),A.cols()+k) = it.value();
180 }
181 }
182 }
183 C.makeCompressed();
184
185#endif
186
187}
A sparse matrix class designed for matrix assembly purpose.
Definition DynamicSparseMatrix.h:58
Scalar & coeffRef(Index row, Index col)
Definition DynamicSparseMatrix.h:105
void reserve(Index reserveSize=1000)
Definition DynamicSparseMatrix.h:132
void resize(Index rows, Index cols)
Definition DynamicSparseMatrix.h:199
Scalar & insert(Index row, Index col)
Definition SparseMatrix.h:1129
size_t cols(const T &raster)
Definition MarchingSquares.hpp:60
size_t rows(const T &raster)
Definition MarchingSquares.hpp:55

References Eigen::DynamicSparseMatrix< _Scalar, _Options, _StorageIndex >::coeffRef(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::insert(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::makeCompressed(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::nonZeros(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::outerSize(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::reserve(), Eigen::DynamicSparseMatrix< _Scalar, _Options, _StorageIndex >::reserve(), Eigen::DynamicSparseMatrix< _Scalar, _Options, _StorageIndex >::resize(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets(), and Eigen::SparseMatrixBase< Derived >::size().

Referenced by active_set(), arap_rhs(), cat(), cat(), covariance_scatter_matrix(), igl::copyleft::tetgen::mesh_with_skeleton(), min_quad_with_fixed_precompute(), shapeup_precomputation(), and uniformly_sample_two_manifold().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cat() [3/4]

template<class Mat >
IGL_INLINE Mat igl::cat ( const int  dim,
const Mat &  A,
const Mat &  B 
)
227{
228 assert(dim == 1 || dim == 2);
229 Mat C;
230 igl::cat(dim,A,B,C);
231 return C;
232}

References cat().

+ Here is the call graph for this function:

◆ cat() [4/4]

template<class Mat >
IGL_INLINE void igl::cat ( const std::vector< std::vector< Mat > > &  A,
Mat &  C 
)
236{
237 using namespace std;
238 // Start with empty matrix
239 C.resize(0,0);
240 for(const auto & row_vec : A)
241 {
242 // Concatenate each row horizontally
243 // Start with empty matrix
244 Mat row(0,0);
245 for(const auto & element : row_vec)
246 {
247 row = cat(2,row,element);
248 }
249 // Concatenate rows vertically
250 C = cat(1,C,row);
251 }
252}

References cat(), and row().

+ Here is the call graph for this function:

◆ ceil()

template<typename DerivedX , typename DerivedY >
IGL_INLINE void igl::ceil ( const Eigen::PlainObjectBase< DerivedX > &  X,
Eigen::PlainObjectBase< DerivedY > &  Y 
)
15{
16 using namespace std;
17 //Y = DerivedY::Zero(m,n);
18//#pragma omp parallel for
19 //for(int i = 0;i<m;i++)
20 //{
21 // for(int j = 0;j<n;j++)
22 // {
23 // Y(i,j) = std::ceil(X(i,j));
24 // }
25 //}
26 typedef typename DerivedX::Scalar Scalar;
27 Y = X.unaryExpr([](const Scalar &x)->Scalar{return std::ceil(x);}).template cast<typename DerivedY::Scalar >();
28}

◆ centroid() [1/2]

template<typename DerivedV , typename DerivedF , typename Derivedc >
IGL_INLINE void igl::centroid ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< Derivedc > &  c 
)
57{
58 typename Derivedc::Scalar vol;
59 return centroid(V,F,c,vol);
60}
IGL_INLINE void centroid(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< Derivedc > &c, Derivedvol &vol)
Definition centroid.cpp:16

References centroid().

+ Here is the call graph for this function:

◆ centroid() [2/2]

template<typename DerivedV , typename DerivedF , typename Derivedc , typename Derivedvol >
IGL_INLINE void igl::centroid ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< Derivedc > &  c,
Derivedvol &  vol 
)
21{
22 using namespace Eigen;
23 assert(F.cols() == 3 && "F should contain triangles.");
24 assert(V.cols() == 3 && "V should contain 3d points.");
25 const int m = F.rows();
26 cen.setZero();
27 vol = 0;
28 // loop over faces
29 for(int f = 0;f<m;f++)
30 {
31 // "Calculating the volume and centroid of a polyhedron in 3d" [Nuernberg 2013]
32 // http://www2.imperial.ac.uk/~rn/centroid.pdf
33 // rename corners
35 const RowVector3S & a = V.row(F(f,0));
36 const RowVector3S & b = V.row(F(f,1));
37 const RowVector3S & c = V.row(F(f,2));
38 // un-normalized normal
39 const RowVector3S & n = (b-a).cross(c-a);
40 // total volume via divergence theorem: ∫ 1
41 vol += n.dot(a)/6.;
42 // centroid via divergence theorem and midpoint quadrature: ∫ x
43 cen.array() += (1./24.*n.array()*((a+b).array().square() + (b+c).array().square() +
44 (c+a).array().square()).array());
45 }
46 cen *= 1./(2.*vol);
47}
IGL_INLINE void cross(const double *a, const double *b, double *out)
Definition cross.cpp:11

References cross(), and Eigen::PlainObjectBase< Derived >::setZero().

Referenced by centroid(), igl::copyleft::cgal::complex_to_mesh(), igl::opengl::ViewerCore::get_scale_and_shift_to_fit_mesh(), and igl::copyleft::cgal::relabel_small_immersed_cells().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ circulation() [1/2]

IGL_INLINE std::vector< int > igl::circulation ( const int  e,
const bool  ccw,
const Eigen::MatrixXi &  F,
const Eigen::MatrixXi &  E,
const Eigen::VectorXi &  EMAP,
const Eigen::MatrixXi &  EF,
const Eigen::MatrixXi &  EI 
)
19{
20 // prepare output
21 std::vector<int> N;
22 N.reserve(6);
23 const int m = F.rows();
24 const auto & step = [&](
25 const int e,
26 const int ff,
27 int & ne,
28 int & nf)
29 {
30 assert((EF(e,1) == ff || EF(e,0) == ff) && "e should touch ff");
31 //const int fside = EF(e,1)==ff?1:0;
32 const int nside = EF(e,0)==ff?1:0;
33 const int nv = EI(e,nside);
34 // get next face
35 nf = EF(e,nside);
36 // get next edge
37 const int dir = ccw?-1:1;
38 ne = EMAP(nf+m*((nv+dir+3)%3));
39 };
40 // Always start with first face (ccw in step will be sure to turn right
41 // direction)
42 const int f0 = EF(e,0);
43 int fi = f0;
44 int ei = e;
45 while(true)
46 {
47 step(ei,fi,ei,fi);
48 N.push_back(fi);
49 // back to start?
50 if(fi == f0)
51 {
52 assert(ei == e);
53 break;
54 }
55 }
56 return N;
57}

Referenced by circulation(), collapse_edge(), collapse_edge(), edge_collapse_is_valid(), igl::copyleft::progressive_hulls_cost_and_placement(), and simplify_polyhedron().

+ Here is the caller graph for this function:

◆ circulation() [2/2]

IGL_INLINE void igl::circulation ( const int  e,
const bool  ccw,
const Eigen::MatrixXi &  F,
const Eigen::MatrixXi &  E,
const Eigen::VectorXi &  EMAP,
const Eigen::MatrixXi &  EF,
const Eigen::MatrixXi &  EI,
Eigen::VectorXi &  vN 
)
68{
69 std::vector<int> N = circulation(e,ccw,F,E,EMAP,EF,EI);
71}
IGL_INLINE std::vector< int > circulation(const int e, const bool ccw, const Eigen::MatrixXi &F, const Eigen::MatrixXi &E, const Eigen::VectorXi &EMAP, const Eigen::MatrixXi &EF, const Eigen::MatrixXi &EI)
Definition circulation.cpp:11

References circulation(), and list_to_matrix().

+ Here is the call graph for this function:

◆ circumradius()

template<typename DerivedV , typename DerivedF , typename DerivedR >
IGL_INLINE void igl::circumradius ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedR > &  R 
)
19{
21 igl::edge_lengths(V,F,l);
22 DerivedR A;
23 igl::doublearea(l,0.,A);
24 // use formula: R=abc/(4*area) to compute the circum radius
25 R = l.col(0).array() * l.col(1).array() * l.col(2).array() / (2.0*A.array());
26}
IGL_INLINE void edge_lengths(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedL > &L)
Definition edge_lengths.cpp:12

References doublearea(), and edge_lengths().

+ Here is the call graph for this function:

◆ collapse_edge() [1/5]

IGL_INLINE bool igl::collapse_edge ( const int  e,
const Eigen::RowVectorXd &  p,
Eigen::MatrixXd &  V,
Eigen::MatrixXi &  F,
Eigen::MatrixXi &  E,
Eigen::VectorXi &  EMAP,
Eigen::MatrixXi &  EF,
Eigen::MatrixXi &  EI 
)
152{
153 int e1,e2,f1,f2;
154 return collapse_edge(e,p,V,F,E,EMAP,EF,EI,e1,e2,f1,f2);
155}
IGL_INLINE bool collapse_edge(const int e, const Eigen::RowVectorXd &p, Eigen::MatrixXd &V, Eigen::MatrixXi &F, Eigen::MatrixXi &E, Eigen::VectorXi &EMAP, Eigen::MatrixXi &EF, Eigen::MatrixXi &EI, int &e1, int &e2, int &f1, int &f2)
Definition collapse_edge.cpp:13

References collapse_edge().

+ Here is the call graph for this function:

◆ collapse_edge() [2/5]

IGL_INLINE bool igl::collapse_edge ( const int  e,
const Eigen::RowVectorXd &  p,
Eigen::MatrixXd &  V,
Eigen::MatrixXi &  F,
Eigen::MatrixXi &  E,
Eigen::VectorXi &  EMAP,
Eigen::MatrixXi &  EF,
Eigen::MatrixXi &  EI,
int &  e1,
int &  e2,
int &  f1,
int &  f2 
)
26{
27 // Assign this to 0 rather than, say, -1 so that deleted elements will get
28 // draw as degenerate elements at vertex 0 (which should always exist and
29 // never get collapsed to anything else since it is the smallest index)
30 using namespace Eigen;
31 using namespace std;
32 const int eflip = E(e,0)>E(e,1);
33 // source and destination
34 const int s = eflip?E(e,1):E(e,0);
35 const int d = eflip?E(e,0):E(e,1);
36
37 if(!edge_collapse_is_valid(e,F,E,EMAP,EF,EI))
38 {
39 return false;
40 }
41
42 // Important to grab neighbors of d before monkeying with edges
43 const std::vector<int> nV2Fd = circulation(e,!eflip,F,E,EMAP,EF,EI);
44
45 // The following implementation strongly relies on s<d
46 assert(s<d && "s should be less than d");
47 // move source and destination to midpoint
48 V.row(s) = p;
49 V.row(d) = p;
50
51 // Helper function to replace edge and associate information with NULL
52 const auto & kill_edge = [&E,&EI,&EF](const int e)
53 {
56 EF(e,0) = IGL_COLLAPSE_EDGE_NULL;
57 EF(e,1) = IGL_COLLAPSE_EDGE_NULL;
58 EI(e,0) = IGL_COLLAPSE_EDGE_NULL;
59 EI(e,1) = IGL_COLLAPSE_EDGE_NULL;
60 };
61
62 // update edge info
63 // for each flap
64 const int m = F.rows();
65 for(int side = 0;side<2;side++)
66 {
67 const int f = EF(e,side);
68 const int v = EI(e,side);
69 const int sign = (eflip==0?1:-1)*(1-2*side);
70 // next edge emanating from d
71 const int e1 = EMAP(f+m*((v+sign*1+3)%3));
72 // prev edge pointing to s
73 const int e2 = EMAP(f+m*((v+sign*2+3)%3));
74 assert(E(e1,0) == d || E(e1,1) == d);
75 assert(E(e2,0) == s || E(e2,1) == s);
76 // face adjacent to f on e1, also incident on d
77 const bool flip1 = EF(e1,1)==f;
78 const int f1 = flip1 ? EF(e1,0) : EF(e1,1);
79 assert(f1!=f);
80 assert(F(f1,0)==d || F(f1,1)==d || F(f1,2) == d);
81 // across from which vertex of f1 does e1 appear?
82 const int v1 = flip1 ? EI(e1,0) : EI(e1,1);
83 // Kill e1
84 kill_edge(e1);
85 // Kill f
89 // map f1's edge on e1 to e2
90 assert(EMAP(f1+m*v1) == e1);
91 EMAP(f1+m*v1) = e2;
92 // side opposite f2, the face adjacent to f on e2, also incident on s
93 const int opp2 = (EF(e2,0)==f?0:1);
94 assert(EF(e2,opp2) == f);
95 EF(e2,opp2) = f1;
96 EI(e2,opp2) = v1;
97 // remap e2 from d to s
98 E(e2,0) = E(e2,0)==d ? s : E(e2,0);
99 E(e2,1) = E(e2,1)==d ? s : E(e2,1);
100 if(side==0)
101 {
102 a_e1 = e1;
103 a_f1 = f;
104 }else
105 {
106 a_e2 = e1;
107 a_f2 = f;
108 }
109 }
110
111 // finally, reindex faces and edges incident on d. Do this last so asserts
112 // make sense.
113 //
114 // Could actually skip first and last, since those are always the two
115 // collpased faces.
116 for(auto f : nV2Fd)
117 {
118 for(int v = 0;v<3;v++)
119 {
120 if(F(f,v) == d)
121 {
122 const int flip1 = (EF(EMAP(f+m*((v+1)%3)),0)==f)?1:0;
123 const int flip2 = (EF(EMAP(f+m*((v+2)%3)),0)==f)?0:1;
124 assert(
125 E(EMAP(f+m*((v+1)%3)),flip1) == d ||
126 E(EMAP(f+m*((v+1)%3)),flip1) == s);
127 E(EMAP(f+m*((v+1)%3)),flip1) = s;
128 assert(
129 E(EMAP(f+m*((v+2)%3)),flip2) == d ||
130 E(EMAP(f+m*((v+2)%3)),flip2) == s);
131 E(EMAP(f+m*((v+2)%3)),flip2) = s;
132 F(f,v) = s;
133 break;
134 }
135 }
136 }
137 // Finally, "remove" this edge and its information
138 kill_edge(e);
139
140 return true;
141}
EIGEN_DEVICE_FUNC const SignReturnType sign() const
Definition ArrayCwiseUnaryOps.h:184
#define IGL_COLLAPSE_EDGE_NULL
p dim list of vertex position where to place merged vertex
Definition collapse_edge.h:44
Definition flip1.c:78
Definition flip2.c:63
IGL_INLINE bool edge_collapse_is_valid(const int e, const Eigen::MatrixXi &F, const Eigen::MatrixXi &E, const Eigen::VectorXi &EMAP, const Eigen::MatrixXi &EF, const Eigen::MatrixXi &EI)
Definition edge_collapse_is_valid.cpp:16
CGAL::SM_Edge_index EI
Definition CutSurface.cpp:77

References circulation(), edge_collapse_is_valid(), IGL_COLLAPSE_EDGE_NULL, and sign().

Referenced by collapse_edge(), collapse_edge(), collapse_edge(), collapse_edge(), and decimate().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ collapse_edge() [3/5]

IGL_INLINE bool igl::collapse_edge ( const std::function< void(const int, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> &  cost_and_placement,
const std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int)> &  pre_collapse,
const std::function< void(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int, const bool)> &  post_collapse,
Eigen::MatrixXd &  V,
Eigen::MatrixXi &  F,
Eigen::MatrixXi &  E,
Eigen::VectorXi &  EMAP,
Eigen::MatrixXi &  EF,
Eigen::MatrixXi &  EI,
std::set< std::pair< double, int > > &  Q,
std::vector< std::set< std::pair< double, int > >::iterator > &  Qit,
Eigen::MatrixXd &  C 
)
263{
264 int e,e1,e2,f1,f2;
265 return
267 cost_and_placement,pre_collapse,post_collapse,
268 V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2);
269}

References collapse_edge().

+ Here is the call graph for this function:

◆ collapse_edge() [4/5]

IGL_INLINE bool igl::collapse_edge ( const std::function< void(const int, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> &  cost_and_placement,
const std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int)> &  pre_collapse,
const std::function< void(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int, const bool)> &  post_collapse,
Eigen::MatrixXd &  V,
Eigen::MatrixXi &  F,
Eigen::MatrixXi &  E,
Eigen::VectorXi &  EMAP,
Eigen::MatrixXi &  EF,
Eigen::MatrixXi &  EI,
std::set< std::pair< double, int > > &  Q,
std::vector< std::set< std::pair< double, int > >::iterator > &  Qit,
Eigen::MatrixXd &  C,
int &  e,
int &  e1,
int &  e2,
int &  f1,
int &  f2 
)
326{
327 using namespace Eigen;
328 if(Q.empty())
329 {
330 // no edges to collapse
331 return false;
332 }
333 std::pair<double,int> p = *(Q.begin());
334 if(p.first == std::numeric_limits<double>::infinity())
335 {
336 // min cost edge is infinite cost
337 return false;
338 }
339 Q.erase(Q.begin());
340 e = p.second;
341 Qit[e] = Q.end();
342 std::vector<int> N = circulation(e, true,F,E,EMAP,EF,EI);
343 std::vector<int> Nd = circulation(e,false,F,E,EMAP,EF,EI);
344 N.insert(N.begin(),Nd.begin(),Nd.end());
345 bool collapsed = true;
346 if(pre_collapse(V,F,E,EMAP,EF,EI,Q,Qit,C,e))
347 {
348 collapsed = collapse_edge(e,C.row(e),V,F,E,EMAP,EF,EI,e1,e2,f1,f2);
349 }else
350 {
351 // Aborted by pre collapse callback
352 collapsed = false;
353 }
354 post_collapse(V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2,collapsed);
355 if(collapsed)
356 {
357 // Erase the two, other collapsed edges
358 Q.erase(Qit[e1]);
359 Qit[e1] = Q.end();
360 Q.erase(Qit[e2]);
361 Qit[e2] = Q.end();
362 // update local neighbors
363 // loop over original face neighbors
364 for(auto n : N)
365 {
366 if(F(n,0) != IGL_COLLAPSE_EDGE_NULL ||
367 F(n,1) != IGL_COLLAPSE_EDGE_NULL ||
369 {
370 for(int v = 0;v<3;v++)
371 {
372 // get edge id
373 const int ei = EMAP(v*F.rows()+n);
374 // erase old entry
375 Q.erase(Qit[ei]);
376 // compute cost and potential placement
377 double cost;
378 RowVectorXd place;
379 cost_and_placement(ei,V,F,E,EMAP,EF,EI,cost,place);
380 // Replace in queue
381 Qit[ei] = Q.insert(std::pair<double,int>(cost,ei)).first;
382 C.row(ei) = place;
383 }
384 }
385 }
386 }else
387 {
388 // reinsert with infinite weight (the provided cost function must **not**
389 // have given this un-collapsable edge inf cost already)
390 p.first = std::numeric_limits<double>::infinity();
391 Qit[e] = Q.insert(p).first;
392 }
393 return collapsed;
394}

References circulation(), collapse_edge(), and IGL_COLLAPSE_EDGE_NULL.

+ Here is the call graph for this function:

◆ collapse_edge() [5/5]

IGL_INLINE bool igl::collapse_edge ( const std::function< void(const int, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> &  cost_and_placement,
Eigen::MatrixXd &  V,
Eigen::MatrixXi &  F,
Eigen::MatrixXi &  E,
Eigen::VectorXi &  EMAP,
Eigen::MatrixXi &  EF,
Eigen::MatrixXi &  EI,
std::set< std::pair< double, int > > &  Q,
std::vector< std::set< std::pair< double, int > >::iterator > &  Qit,
Eigen::MatrixXd &  C 
)
177{
178 int e,e1,e2,f1,f2;
179 const auto always_try = [](
180 const Eigen::MatrixXd & ,/*V*/
181 const Eigen::MatrixXi & ,/*F*/
182 const Eigen::MatrixXi & ,/*E*/
183 const Eigen::VectorXi & ,/*EMAP*/
184 const Eigen::MatrixXi & ,/*EF*/
185 const Eigen::MatrixXi & ,/*EI*/
186 const std::set<std::pair<double,int> > & ,/*Q*/
187 const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
188 const Eigen::MatrixXd & ,/*C*/
189 const int /*e*/
190 ) -> bool { return true;};
191 const auto never_care = [](
192 const Eigen::MatrixXd & , /*V*/
193 const Eigen::MatrixXi & , /*F*/
194 const Eigen::MatrixXi & , /*E*/
195 const Eigen::VectorXi & ,/*EMAP*/
196 const Eigen::MatrixXi & , /*EF*/
197 const Eigen::MatrixXi & , /*EI*/
198 const std::set<std::pair<double,int> > & , /*Q*/
199 const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
200 const Eigen::MatrixXd & , /*C*/
201 const int , /*e*/
202 const int , /*e1*/
203 const int , /*e2*/
204 const int , /*f1*/
205 const int , /*f2*/
206 const bool /*collapsed*/
207 )-> void { };
208 return
210 cost_and_placement,always_try,never_care,
211 V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2);
212}

References collapse_edge().

+ Here is the call graph for this function:

◆ collapse_small_triangles()

void igl::collapse_small_triangles ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const double  eps,
Eigen::MatrixXi &  FF 
)
25{
26 using namespace Eigen;
27 using namespace std;
28
29 // Compute bounding box diagonal length
30 double bbd = bounding_box_diagonal(V);
31 MatrixXd l;
32 edge_lengths(V,F,l);
33 VectorXd dblA;
34 doublearea(l,0.,dblA);
35
36 // Minimum area tolerance
37 const double min_dblarea = 2.0*eps*bbd*bbd;
38
39 Eigen::VectorXi FIM = colon<int>(0,V.rows()-1);
40 int num_edge_collapses = 0;
41 // Loop over triangles
42 for(int f = 0;f<F.rows();f++)
43 {
44 if(dblA(f) < min_dblarea)
45 {
46 double minl = 0;
47 int minli = -1;
48 // Find shortest edge
49 for(int e = 0;e<3;e++)
50 {
51 if(minli==-1 || l(f,e)<minl)
52 {
53 minli = e;
54 minl = l(f,e);
55 }
56 }
57 double maxl = 0;
58 int maxli = -1;
59 // Find longest edge
60 for(int e = 0;e<3;e++)
61 {
62 if(maxli==-1 || l(f,e)>maxl)
63 {
64 maxli = e;
65 maxl = l(f,e);
66 }
67 }
68 // Be sure that min and max aren't the same
69 maxli = (minli==maxli?(minli+1)%3:maxli);
70
71 // Collapse min edge maintaining max edge: i-->j
72 // Q: Why this direction?
73 int i = maxli;
74 int j = ((minli+1)%3 == maxli ? (minli+2)%3: (minli+1)%3);
75 assert(i != minli);
76 assert(j != minli);
77 assert(i != j);
78 FIM(F(f,i)) = FIM(F(f,j));
79 num_edge_collapses++;
80 }
81 }
82
83 // Reindex faces
84 MatrixXi rF = F;
85 // Loop over triangles
86 for(int f = 0;f<rF.rows();f++)
87 {
88 for(int i = 0;i<rF.cols();i++)
89 {
90 rF(f,i) = FIM(rF(f,i));
91 }
92 }
93
94 FF.resizeLike(rF);
95 int num_face_collapses=0;
96 // Only keep uncollapsed faces
97 {
98 int ff = 0;
99 // Loop over triangles
100 for(int f = 0;f<rF.rows();f++)
101 {
102 bool collapsed = false;
103 // Check if any indices are the same
104 for(int i = 0;i<rF.cols();i++)
105 {
106 for(int j = i+1;j<rF.cols();j++)
107 {
108 if(rF(f,i)==rF(f,j))
109 {
110 collapsed = true;
111 num_face_collapses++;
112 break;
113 }
114 }
115 }
116 if(!collapsed)
117 {
118 FF.row(ff++) = rF.row(f);
119 }
120 }
121 // Use conservative resize
122 FF.conservativeResize(ff,FF.cols());
123 }
124 //cout<<"num_edge_collapses: "<<num_edge_collapses<<endl;
125 //cout<<"num_face_collapses: "<<num_face_collapses<<endl;
126 if(num_edge_collapses == 0)
127 {
128 // There must have been a "collapsed edge" in the input
129 assert(num_face_collapses==0);
130 // Base case
131 return;
132 }
133
135 //return;
136
137 MatrixXi recFF = FF;
138 return collapse_small_triangles(V,recFF,eps,FF);
139}
IGL_INLINE double bounding_box_diagonal(const Eigen::MatrixXd &V)
Definition bounding_box_diagonal.cpp:13
void collapse_small_triangles(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const double eps, Eigen::MatrixXi &FF)
Definition collapse_small_triangles.cpp:20

References bounding_box_diagonal(), collapse_small_triangles(), doublearea(), and edge_lengths().

Referenced by collapse_small_triangles().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ colon() [1/3]

template<typename T , typename L , typename H >
IGL_INLINE Eigen::Matrix< T, Eigen::Dynamic, 1 > igl::colon ( const L  low,
const hi 
)
37{
39 igl::colon(low,hi,I);
40 return I;
41}
IGL_INLINE void colon(const L low, const S step, const H hi, Eigen::Matrix< T, Eigen::Dynamic, 1 > &I)
Definition colon.cpp:14

References colon().

+ Here is the call graph for this function:

◆ colon() [2/3]

template<typename L , typename H , typename T >
IGL_INLINE void igl::colon ( const L  low,
const hi,
Eigen::Matrix< T, Eigen::Dynamic, 1 > &  I 
)
29{
30 return igl::colon(low,(T)1,hi,I);
31}

References colon().

+ Here is the call graph for this function:

◆ colon() [3/3]

template<typename L , typename S , typename H , typename T >
IGL_INLINE void igl::colon ( const L  low,
const step,
const hi,
Eigen::Matrix< T, Eigen::Dynamic, 1 > &  I 
)
19{
20 const int size = ((hi-low)/step)+1;
21 I = igl::LinSpaced<Eigen::Matrix<T,Eigen::Dynamic,1> >(size,low,low+step*(size-1));
22}

Referenced by colon(), colon(), randperm(), slice(), slice_into(), and sort_new().

+ Here is the caller graph for this function:

◆ colormap() [1/5]

template<typename DerivedZ , typename DerivedC >
IGL_INLINE void igl::colormap ( const ColorMapType  cm,
const Eigen::MatrixBase< DerivedZ > &  Z,
const bool  normalize,
Eigen::PlainObjectBase< DerivedC > &  C 
)
1379{
1380 const double min_z = normalize ? Z.minCoeff() : 0;
1381 const double max_z = normalize ? Z.maxCoeff() : 1;
1382 return colormap(cm, Z, min_z, max_z, C);
1383}
IGL_INLINE void colormap(const ColorMapType cm, const T f, T *rgb)
Definition colormap.cpp:1314

References colormap().

+ Here is the call graph for this function:

◆ colormap() [2/5]

template<typename DerivedZ , typename DerivedC >
IGL_INLINE void igl::colormap ( const ColorMapType  cm,
const Eigen::MatrixBase< DerivedZ > &  Z,
const double  min_Z,
const double  max_Z,
Eigen::PlainObjectBase< DerivedC > &  C 
)
1392{
1393 C.resize(Z.rows(),3);
1394 double denom = (max_z - min_z);
1395 denom = (denom == 0) ? 1 : denom;
1396 for(int r = 0; r < Z.rows(); ++r) {
1397 colormap(
1398 cm,
1399 (typename DerivedC::Scalar)((-min_z + Z(r,0)) / denom),
1400 C(r,0),
1401 C(r,1),
1402 C(r,2));
1403 }
1404}

References colormap(), and Eigen::PlainObjectBase< Derived >::resize().

+ Here is the call graph for this function:

◆ colormap() [3/5]

template<typename T >
IGL_INLINE void igl::colormap ( const ColorMapType  cm,
const f,
T &  r,
T &  g,
T &  b 
)
1322{
1323 switch (cm)
1324 {
1326 colormap(inferno_cm, x_in, r, g, b);
1327 break;
1328 case COLOR_MAP_TYPE_JET:
1329 jet(x_in, r, g, b);
1330 break;
1332 colormap(magma_cm, x_in, r, g, b);
1333 break;
1335 colormap(parula_cm, x_in, r, g, b);
1336 break;
1338 colormap(plasma_cm, x_in, r, g, b);
1339 break;
1341 colormap(viridis_cm, x_in, r, g, b);
1342 break;
1343 default:
1344 throw std::invalid_argument("igl::colormap(): Selected colormap is unsupported!");
1345 break;
1346 }
1347}
IGL_INLINE void jet(const T f, T *rgb)
Definition jet.cpp:12

References COLOR_MAP_TYPE_INFERNO, COLOR_MAP_TYPE_JET, COLOR_MAP_TYPE_MAGMA, COLOR_MAP_TYPE_PARULA, COLOR_MAP_TYPE_PLASMA, COLOR_MAP_TYPE_VIRIDIS, colormap(), inferno_cm, jet(), magma_cm, parula_cm, plasma_cm, and viridis_cm.

+ Here is the call graph for this function:

◆ colormap() [4/5]

template<typename T >
IGL_INLINE void igl::colormap ( const ColorMapType  cm,
const f,
T *  rgb 
)
1315{
1316 return colormap(cm,x,rgb[0],rgb[1],rgb[2]);
1317}

References colormap().

Referenced by colormap(), colormap(), colormap(), colormap(), jet(), jet(), jet(), parula(), parula(), parula(), and parula().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ colormap() [5/5]

template<typename T >
IGL_INLINE void igl::colormap ( const double  palette[256][3],
const x_in,
T &  r,
T &  g,
T &  b 
)
1352{
1353 static const unsigned int pal = 256;
1354 const T zero = 0.0;
1355 const T one = 1.0;
1356 T x_in_clamped = static_cast<T>(std::max(zero, std::min(one, x_in)));
1357
1358 // simple rgb lerp from palette
1359 unsigned int least = std::floor(x_in_clamped * static_cast<T>(pal - 1));
1360 unsigned int most = std::ceil(x_in_clamped * static_cast<T>(pal - 1));
1361
1362 T _r[2] = { static_cast<T>(palette[least][0]), static_cast<T>(palette[most][0]) };
1363 T _g[2] = { static_cast<T>(palette[least][1]), static_cast<T>(palette[most][1]) };
1364 T _b[2] = { static_cast<T>(palette[least][2]), static_cast<T>(palette[most][2]) };
1365
1366 T t = std::max(zero, std::min(one, static_cast<T>(fmod(x_in_clamped * static_cast<T>(pal), one))));
1367
1368 r = std::max(zero, std::min(one, (one - t) * _r[0] + t * _r[1]));
1369 g = std::max(zero, std::min(one, (one - t) * _g[0] + t * _g[1]));
1370 b = std::max(zero, std::min(one, (one - t) * _b[0] + t * _b[1]));
1371}
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T fmod(const T &a, const T &b)
Definition MathFunctions.h:1242

◆ column_to_quats()

IGL_INLINE bool igl::column_to_quats ( const Eigen::VectorXd &  Q,
std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > &  vQ 
)
13{
14 using namespace Eigen;
15 if(Q.size() % 4 != 0)
16 {
17 return false;
18 }
19 const int nQ = Q.size()/4;
20 vQ.resize(nQ);
21 for(int q=0;q<nQ;q++)
22 {
23 // Constructor uses wxyz
24 vQ[q] = Quaterniond( Q(q*4+3), Q(q*4+0), Q(q*4+1), Q(q*4+2));
25 }
26 return true;
27}
The quaternion class used to represent 3D orientations and rotations.
Definition Quaternion.h:233

◆ columnize()

template<typename DerivedA , typename DerivedB >
IGL_INLINE void igl::columnize ( const Eigen::PlainObjectBase< DerivedA > &  A,
const int  k,
const int  dim,
Eigen::PlainObjectBase< DerivedB > &  B 
)
17{
18 // Eigen matrices must be 2d so dim must be only 1 or 2
19 assert(dim == 1 || dim == 2);
20
21 // block height, width, and number of blocks
22 int m,n;
23 if(dim == 1)
24 {
25 m = A.rows()/k;
26 assert(m*(int)k == (int)A.rows());
27 n = A.cols();
28 }else// dim == 2
29 {
30 m = A.rows();
31 n = A.cols()/k;
32 assert(n*(int)k == (int)A.cols());
33 }
34
35 // resize output
36 B.resize(A.rows()*A.cols(),1);
37
38 for(int b = 0;b<(int)k;b++)
39 {
40 for(int i = 0;i<m;i++)
41 {
42 for(int j = 0;j<n;j++)
43 {
44 if(dim == 1)
45 {
46 B(j*m*k+i*k+b) = A(i+b*m,j);
47 }else
48 {
49 B(j*m*k+i*k+b) = A(i,b*n+j);
50 }
51 }
52 }
53 }
54}

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::rows().

Referenced by arap_dof_update(), and arap_solve().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ comb_cross_field()

template<typename DerivedV , typename DerivedF >
IGL_INLINE void igl::comb_cross_field ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedV > &  PD1in,
const Eigen::PlainObjectBase< DerivedV > &  PD2in,
Eigen::PlainObjectBase< DerivedV > &  PD1out,
Eigen::PlainObjectBase< DerivedV > &  PD2out 
)
139{
140 igl::Comb<DerivedV, DerivedF> cmb(V, F, PD1, PD2);
141 cmb.comb(PD1out, PD2out);
142}
Definition comb_cross_field.cpp:23

References igl::Comb< DerivedV, DerivedF >::comb().

Referenced by cross_field_missmatch(), and igl::copyleft::comiso::miq().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ comb_frame_field()

template<typename DerivedV , typename DerivedF , typename DerivedP >
IGL_INLINE void igl::comb_frame_field ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedP > &  PD1,
const Eigen::PlainObjectBase< DerivedP > &  PD2,
const Eigen::PlainObjectBase< DerivedP > &  BIS1_combed,
const Eigen::PlainObjectBase< DerivedP > &  BIS2_combed,
Eigen::PlainObjectBase< DerivedP > &  PD1_combed,
Eigen::PlainObjectBase< DerivedP > &  PD2_combed 
)
27{
28 DerivedV B1, B2, B3;
29 igl::local_basis(V,F,B1,B2,B3);
30
31 PD1_combed.resize(BIS1_combed.rows(),3);
32 PD2_combed.resize(BIS2_combed.rows(),3);
33
34 for (unsigned i=0; i<PD1.rows();++i)
35 {
37 DIRs <<
38 PD1.row(i),
39 -PD1.row(i),
40 PD2.row(i),
41 -PD2.row(i);
42
43 std::vector<double> a(4);
44
45
46 double a_combed = atan2(B2.row(i).dot(BIS1_combed.row(i)),B1.row(i).dot(BIS1_combed.row(i)));
47
48 // center on the combed sector center
49 for (unsigned j=0;j<4;++j)
50 {
51 a[j] = atan2(B2.row(i).dot(DIRs.row(j)),B1.row(i).dot(DIRs.row(j))) - a_combed;
52 //make it positive by adding some multiple of 2pi
53 a[j] += std::ceil (std::max(0., -a[j]) / (igl::PI*2.)) * (igl::PI*2.);
54 //take modulo 2pi
55 a[j] = fmod(a[j], (igl::PI*2.));
56 }
57 // now the max is u and the min is v
58
59 int m = std::min_element(a.begin(),a.end())-a.begin();
60 int M = std::max_element(a.begin(),a.end())-a.begin();
61
62 assert(
63 ((m>=0 && m<=1) && (M>=2 && M<=3))
64 ||
65 ((m>=2 && m<=3) && (M>=0 && M<=1))
66 );
67
68 PD1_combed.row(i) = DIRs.row(m);
69 PD2_combed.row(i) = DIRs.row(M);
70
71 }
72
73
74 // PD1_combed = BIS1_combed;
75 // PD2_combed = BIS2_combed;
76}
const double PI
Definition PI.h:16
IGL_INLINE void local_basis(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedV > &B1, Eigen::PlainObjectBase< DerivedV > &B2, Eigen::PlainObjectBase< DerivedV > &B3)
Definition local_basis.cpp:19

References local_basis(), PI, Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::rows().

Referenced by igl::copyleft::comiso::miq().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ comb_line_field()

template<typename DerivedV , typename DerivedF >
IGL_INLINE void igl::comb_line_field ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedV > &  PD1in,
Eigen::PlainObjectBase< DerivedV > &  PD1out 
)
125{
127 cmb.comb(PD1out);
128}
Definition comb_line_field.cpp:22

References igl::CombLine< DerivedV, DerivedF >::comb().

Referenced by line_field_missmatch().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ combine() [1/2]

template<typename DerivedVV , typename DerivedFF , typename DerivedV , typename DerivedF >
IGL_INLINE void igl::combine ( const std::vector< DerivedVV > &  VV,
const std::vector< DerivedFF > &  FF,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F 
)
84{
85 Eigen::VectorXi Vsizes,Fsizes;
86 return igl::combine(VV,FF,V,F,Vsizes,Fsizes);
87}
IGL_INLINE void combine(const std::vector< DerivedVV > &VV, const std::vector< DerivedFF > &FF, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedVsizes > &Vsizes, Eigen::PlainObjectBase< DerivedFsizes > &Fsizes)
Definition combine.cpp:18

References combine().

+ Here is the call graph for this function:

◆ combine() [2/2]

template<typename DerivedVV , typename DerivedFF , typename DerivedV , typename DerivedF , typename DerivedVsizes , typename DerivedFsizes >
IGL_INLINE void igl::combine ( const std::vector< DerivedVV > &  VV,
const std::vector< DerivedFF > &  FF,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedVsizes > &  Vsizes,
Eigen::PlainObjectBase< DerivedFsizes > &  Fsizes 
)
25{
26 assert(VV.size() == FF.size() &&
27 "Lists of verex lists and face lists should be same size");
28 Vsizes.resize(VV.size());
29 Fsizes.resize(FF.size());
30 // Dimension of vertex positions
31 const int dim = VV.size() > 0 ? VV[0].cols() : 0;
32 // Simplex/element size
33 const int ss = FF.size() > 0 ? FF[0].cols() : 0;
34 int n = 0;
35 int m = 0;
36 for(int i = 0;i<VV.size();i++)
37 {
38 const auto & Vi = VV[i];
39 const auto & Fi = FF[i];
40 Vsizes(i) = Vi.rows();
41 n+=Vi.rows();
42 assert((Vi.size()==0 || dim == Vi.cols()) && "All vertex lists should have same #columns");
43 Fsizes(i) = Fi.rows();
44 m+=Fi.rows();
45 assert((Fi.size()==0 || ss == Fi.cols()) && "All face lists should have same #columns");
46 }
47 V.resize(n,dim);
48 F.resize(m,ss);
49 {
50 int kv = 0;
51 int kf = 0;
52 for(int i = 0;i<VV.size();i++)
53 {
54 const auto & Vi = VV[i];
55 const int ni = Vi.rows();
56 const auto & Fi = FF[i];
57 const int mi = Fi.rows();
58 if(Fi.size() >0)
59 {
60 F.block(kf,0,mi,ss) = Fi.array()+kv;
61 }
62 kf+=mi;
63 if(Vi.size() >0)
64 {
65 V.block(kv,0,ni,dim) = Vi;
66 }
67 kv+=ni;
68 }
69 assert(kv == V.rows());
70 assert(kf == F.rows());
71 }
72}

References Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::rows().

Referenced by combine(), igl::copyleft::cgal::mesh_boolean(), and igl::copyleft::cgal::mesh_boolean().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ components() [1/3]

template<typename DerivedF , typename DerivedC >
IGL_INLINE void igl::components ( const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedC > &  C 
)
83{
86 return components(A,C);
87}
IGL_INLINE void components(const Eigen::SparseMatrix< AScalar > &A, Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< Derivedcounts > &counts)
Definition components.cpp:14
IGL_INLINE void adjacency_matrix(const Eigen::MatrixBase< DerivedF > &F, Eigen::SparseMatrix< T > &A)
Definition adjacency_matrix.cpp:15

References adjacency_matrix(), and components().

+ Here is the call graph for this function:

◆ components() [2/3]

template<typename AScalar , typename DerivedC >
IGL_INLINE void igl::components ( const Eigen::SparseMatrix< AScalar > &  A,
Eigen::PlainObjectBase< DerivedC > &  C 
)
74{
75 Eigen::VectorXi counts;
76 return components(A,C,counts);
77}

References components().

+ Here is the call graph for this function:

◆ components() [3/3]

template<typename AScalar , typename DerivedC , typename Derivedcounts >
IGL_INLINE void igl::components ( const Eigen::SparseMatrix< AScalar > &  A,
Eigen::PlainObjectBase< DerivedC > &  C,
Eigen::PlainObjectBase< Derivedcounts > &  counts 
)
18{
19 using namespace Eigen;
20 using namespace std;
21 assert(A.rows() == A.cols() && "A should be square.");
22 const size_t n = A.rows();
24 C.resize(n,1);
25 typename DerivedC::Scalar id = 0;
26 vector<typename Derivedcounts::Scalar> vcounts;
27 // breadth first search
28 for(int k=0; k<A.outerSize(); ++k)
29 {
30 if(seen(k))
31 {
32 continue;
33 }
34 queue<int> Q;
35 Q.push(k);
36 vcounts.push_back(0);
37 while(!Q.empty())
38 {
39 const int f = Q.front();
40 Q.pop();
41 if(seen(f))
42 {
43 continue;
44 }
45 seen(f) = true;
46 C(f,0) = id;
47 vcounts[id]++;
48 // Iterate over inside
49 for(typename SparseMatrix<AScalar>::InnerIterator it (A,f); it; ++it)
50 {
51 const int g = it.index();
52 if(!seen(g) && it.value())
53 {
54 Q.push(g);
55 }
56 }
57 }
58 id++;
59 }
60 assert((size_t) id == vcounts.size());
61 const size_t ncc = vcounts.size();
62 assert((size_t)C.maxCoeff()+1 == ncc);
63 counts.resize(ncc,1);
64 for(size_t i = 0;i<ncc;i++)
65 {
66 counts(i) = vcounts[i];
67 }
68}

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::outerSize(), Eigen::PlainObjectBase< Derived >::resize(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows().

Referenced by components(), components(), igl::copyleft::cgal::extract_cells(), igl::opengl::gliReadTGA(), orientable_patches(), igl::opengl::render_to_tga(), straighten_seams(), and igl::opengl::writeTGA().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compute_frame_field_bisectors() [1/2]

template<typename DerivedV , typename DerivedF >
IGL_INLINE void igl::compute_frame_field_bisectors ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedV > &  B1,
const Eigen::PlainObjectBase< DerivedV > &  B2,
const Eigen::PlainObjectBase< DerivedV > &  PD1,
const Eigen::PlainObjectBase< DerivedV > &  PD2,
Eigen::PlainObjectBase< DerivedV > &  BIS1,
Eigen::PlainObjectBase< DerivedV > &  BIS2 
)
28{
29 BIS1.resize(PD1.rows(),3);
30 BIS2.resize(PD1.rows(),3);
31
32 for (unsigned i=0; i<PD1.rows();++i)
33 {
34 // project onto the tangent plane and convert to angle
35 // Convert to angle
36 double a1 = atan2(B2.row(i).dot(PD1.row(i)),B1.row(i).dot(PD1.row(i)));
37 //make it positive by adding some multiple of 2pi
38 a1 += std::ceil (std::max(0., -a1) / (igl::PI*2.)) * (igl::PI*2.);
39 //take modulo 2pi
40 a1 = fmod(a1, (igl::PI*2.));
41 double a2 = atan2(B2.row(i).dot(PD2.row(i)),B1.row(i).dot(PD2.row(i)));
42 //make it positive by adding some multiple of 2pi
43 a2 += std::ceil (std::max(0., -a2) / (igl::PI*2.)) * (igl::PI*2.);
44 //take modulo 2pi
45 a2 = fmod(a2, (igl::PI*2.));
46
47 double b1 = (a1+a2)/2.0;
48 //make it positive by adding some multiple of 2pi
49 b1 += std::ceil (std::max(0., -b1) / (igl::PI*2.)) * (igl::PI*2.);
50 //take modulo 2pi
51 b1 = fmod(b1, (igl::PI*2.));
52
53 double b2 = b1+(igl::PI/2.);
54 //make it positive by adding some multiple of 2pi
55 b2 += std::ceil (std::max(0., -b2) / (igl::PI*2.)) * (igl::PI*2.);
56 //take modulo 2pi
57 b2 = fmod(b2, (igl::PI*2.));
58
59 BIS1.row(i) = cos(b1) * B1.row(i) + sin(b1) * B2.row(i);
60 BIS2.row(i) = cos(b2) * B1.row(i) + sin(b2) * B2.row(i);
61
62 }
63}

References cos(), PI, Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), and sin().

Referenced by compute_frame_field_bisectors(), and igl::copyleft::comiso::miq().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compute_frame_field_bisectors() [2/2]

template<typename DerivedV , typename DerivedF >
IGL_INLINE void igl::compute_frame_field_bisectors ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedV > &  PD1,
const Eigen::PlainObjectBase< DerivedV > &  PD2,
Eigen::PlainObjectBase< DerivedV > &  BIS1,
Eigen::PlainObjectBase< DerivedV > &  BIS2 
)
73{
74 DerivedV B1, B2, B3;
75 igl::local_basis(V,F,B1,B2,B3);
76
77 compute_frame_field_bisectors( V, F, B1, B2, PD1, PD2, BIS1, BIS2);
78
79}
IGL_INLINE void compute_frame_field_bisectors(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedV > &B1, const Eigen::PlainObjectBase< DerivedV > &B2, const Eigen::PlainObjectBase< DerivedV > &PD1, const Eigen::PlainObjectBase< DerivedV > &PD2, Eigen::PlainObjectBase< DerivedV > &BIS1, Eigen::PlainObjectBase< DerivedV > &BIS2)
Definition compute_frame_field_bisectors.cpp:19

References compute_frame_field_bisectors(), and local_basis().

+ Here is the call graph for this function:

◆ condense_CSM()

template<typename MatrixXS >
static MatrixXS::Scalar igl::condense_CSM ( const std::vector< MatrixXS > &  CSM_M_SSCALAR,
int  numBones,
int  dim,
MatrixXS &  CSM 
)
static
351 {
352 const int numRows = CSM_M_SSCALAR[0].rows();
353 assert(CSM_M_SSCALAR[0].cols() == dim*(dim+1)*numBones);
354 assert(CSM_M_SSCALAR[1].cols() == dim*(dim+1)*numBones);
355 assert(CSM_M_SSCALAR[2].cols() == dim*(dim+1)*numBones);
356 assert(CSM_M_SSCALAR[1].rows() == numRows);
357 assert(CSM_M_SSCALAR[2].rows() == numRows);
358
359 const int numCols = (dim + 1)*numBones;
360 CSM.resize(numRows, numCols);
361
362 typedef typename MatrixXS::Scalar SSCALAR;
363 SSCALAR maxDiff = 0.0f;
364
365 for (int r=0; r<numRows; r++)
366 {
367 for (int coord=0; coord<dim+1; coord++)
368 {
369 for (int b=0; b<numBones; b++)
370 {
371 // this is just a test if we really have a multiple of 3x3 identity
372 Eigen::Matrix3f blok;
373 for (int v=0; v<3; v++)
374 {
375 for (int w=0; w<3; w++)
376 {
377 blok(v,w) = CSM_M_SSCALAR[v](r, coord*(numBones*dim) + b + w*numBones);
378 }
379 }
380
381 //SSCALAR value[3];
382 //for (int v=0; v<3; v++)
383 // CSM_M_SSCALAR[v](r, coord*(numBones*dim) + b + v*numBones);
384
385 SSCALAR mD = maxBlokErr<SSCALAR>(blok);
386 if (mD > maxDiff) maxDiff = mD;
387
388 // use the first value:
389 CSM(r, coord*numBones + b) = blok(0,0);
390 }
391 }
392 }
393
394 return maxDiff;
395 }

Referenced by arap_dof_recomputation().

+ Here is the caller graph for this function:

◆ condense_Solve1()

template<typename MatrixXS >
static MatrixXS::Scalar igl::condense_Solve1 ( MatrixXS &  Solve1,
int  numBones,
int  numGroups,
int  dim,
MatrixXS &  CSolve1 
)
static
457 {
458 assert(Solve1.rows() == dim*(dim + 1)*numBones);
459 assert(Solve1.cols() == dim*dim*numGroups);
460
461 typedef typename MatrixXS::Scalar SSCALAR;
462 SSCALAR maxDiff = 0.0f;
463
464 CSolve1.resize((dim + 1)*numBones, dim*numGroups);
465 for (int rowCoord=0; rowCoord<dim+1; rowCoord++)
466 {
467 for (int b=0; b<numBones; b++)
468 {
469 for (int colCoord=0; colCoord<dim; colCoord++)
470 {
471 for (int g=0; g<numGroups; g++)
472 {
473 Eigen::Matrix3f blok;
474 for (int r=0; r<3; r++)
475 {
476 for (int c=0; c<3; c++)
477 {
478 blok(r, c) = Solve1(rowCoord*numBones*dim + r*numBones + b, colCoord*numGroups*dim + c*numGroups + g);
479 }
480 }
481
482 SSCALAR mD = maxBlokErr<SSCALAR>(blok);
483 if (mD > maxDiff) maxDiff = mD;
484
485 CSolve1(rowCoord*numBones + b, colCoord*numGroups + g) = blok(0,0);
486 }
487 }
488 }
489 }
490
491 return maxDiff;
492 }

Referenced by arap_dof_recomputation().

+ Here is the caller graph for this function:

◆ connect_boundary_to_infinity() [1/3]

template<typename DerivedF , typename DerivedFO >
IGL_INLINE void igl::connect_boundary_to_infinity ( const Eigen::PlainObjectBase< DerivedF > &  F,
const typename DerivedF::Scalar  inf_index,
Eigen::PlainObjectBase< DerivedFO > &  FO 
)
23{
24 // Determine boundary edges
26 boundary_facets(F,O);
27 FO.resize(F.rows()+O.rows(),F.cols());
29 FO.topLeftCorner(F.rows(),F.cols()) = F;
30 FO.bottomLeftCorner(O.rows(),O.cols()) = O.rowwise().reverse();
31 FO.bottomRightCorner(O.rows(),1).setConstant(inf_index);
32}
EIGEN_DEVICE_FUNC Derived & setConstant(Index size, const Scalar &val)
Definition CwiseNullaryOp.h:341

References boundary_facets(), Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), and Eigen::PlainObjectBase< Derived >::setConstant().

+ Here is the call graph for this function:

◆ connect_boundary_to_infinity() [2/3]

template<typename DerivedF , typename DerivedFO >
IGL_INLINE void igl::connect_boundary_to_infinity ( const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedFO > &  FO 
)
15{
16 return connect_boundary_to_infinity(F,F.maxCoeff(),FO);
17}
IGL_INLINE void connect_boundary_to_infinity(const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedFO > &FO)
Definition connect_boundary_to_infinity.cpp:12

References connect_boundary_to_infinity().

Referenced by connect_boundary_to_infinity(), connect_boundary_to_infinity(), decimate(), and qslim().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ connect_boundary_to_infinity() [3/3]

template<typename DerivedV , typename DerivedF , typename DerivedVO , typename DerivedFO >
IGL_INLINE void igl::connect_boundary_to_infinity ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedVO > &  VO,
Eigen::PlainObjectBase< DerivedFO > &  FO 
)
44{
45 typename DerivedV::Index inf_index = V.rows();
46 connect_boundary_to_infinity(F,inf_index,FO);
47 VO.resize(V.rows()+1,V.cols());
48 VO.topLeftCorner(V.rows(),V.cols()) = V;
49 auto inf = std::numeric_limits<typename DerivedVO::Scalar>::infinity();
50 VO.row(V.rows()).setConstant(inf);
51}

References Eigen::PlainObjectBase< Derived >::cols(), connect_boundary_to_infinity(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), and Eigen::PlainObjectBase< Derived >::setConstant().

+ Here is the call graph for this function:

◆ cotmatrix()

template<typename DerivedV , typename DerivedF , typename Scalar >
IGL_INLINE void igl::cotmatrix ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::SparseMatrix< Scalar > &  L 
)
23{
24 using namespace Eigen;
25 using namespace std;
26
27 L.resize(V.rows(),V.rows());
29 int simplex_size = F.cols();
30 // 3 for triangles, 4 for tets
31 assert(simplex_size == 3 || simplex_size == 4);
32 if(simplex_size == 3)
33 {
34 // This is important! it could decrease the comptuation time by a factor of 2
35 // Laplacian for a closed 2d manifold mesh will have on average 7 entries per
36 // row
37 L.reserve(10*V.rows());
38 edges.resize(3,2);
39 edges <<
40 1,2,
41 2,0,
42 0,1;
43 }else if(simplex_size == 4)
44 {
45 L.reserve(17*V.rows());
46 edges.resize(6,2);
47 edges <<
48 1,2,
49 2,0,
50 0,1,
51 3,0,
52 3,1,
53 3,2;
54 }else
55 {
56 return;
57 }
58 // Gather cotangents
60 cotmatrix_entries(V,F,C);
61
62 vector<Triplet<Scalar> > IJV;
63 IJV.reserve(F.rows()*edges.rows()*4);
64 // Loop over triangles
65 for(int i = 0; i < F.rows(); i++)
66 {
67 // loop over edges of element
68 for(int e = 0;e<edges.rows();e++)
69 {
70 int source = F(i,edges(e,0));
71 int dest = F(i,edges(e,1));
72 IJV.push_back(Triplet<Scalar>(source,dest,C(i,e)));
73 IJV.push_back(Triplet<Scalar>(dest,source,C(i,e)));
74 IJV.push_back(Triplet<Scalar>(source,source,-C(i,e)));
75 IJV.push_back(Triplet<Scalar>(dest,dest,-C(i,e)));
76 }
77 }
78 L.setFromTriplets(IJV.begin(),IJV.end());
79}

References cotmatrix_entries(), edges(), and L.

Referenced by arap_dof_precomputation(), arap_precomputation(), biharmonic_coordinates(), igl::embree::bone_heat(), harmonic(), harmonic(), lscm(), and igl::Frame_field_deformer::precompute_opt().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cotmatrix_entries()

template<typename DerivedV , typename DerivedF , typename DerivedC >
IGL_INLINE void igl::cotmatrix_entries ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedC > &  C 
)
24{
25 using namespace std;
26 using namespace Eigen;
27 // simplex size (3: triangles, 4: tetrahedra)
28 int simplex_size = F.cols();
29 // Number of elements
30 int m = F.rows();
31
32 // Law of cosines + law of sines
33 switch(simplex_size)
34 {
35 case 3:
36 {
37 // Triangles
38 //Compute Squared Edge lengths
41 //Compute Edge lengths
43 l = l2.array().sqrt();
44
45 // double area
47 doublearea(l,0.,dblA);
48 // cotangents and diagonal entries for element matrices
49 // correctly divided by 4 (alec 2010)
50 C.resize(m,3);
51 for(int i = 0;i<m;i++)
52 {
53 C(i,0) = (l2(i,1) + l2(i,2) - l2(i,0))/dblA(i)/4.0;
54 C(i,1) = (l2(i,2) + l2(i,0) - l2(i,1))/dblA(i)/4.0;
55 C(i,2) = (l2(i,0) + l2(i,1) - l2(i,2))/dblA(i)/4.0;
56 }
57 break;
58 }
59 case 4:
60 {
61
62 // edge lengths numbered same as opposite vertices
64 edge_lengths(V,F,l);
66 face_areas(l,s);
68 dihedral_angles_intrinsic(l,s,theta,cos_theta);
69
70 // volume
72 volume(l,vol);
73
74
75 // Law of sines
76 // http://mathworld.wolfram.com/Tetrahedron.html
78 sin_theta.col(0) = vol.array() / ((2./(3.*l.col(0).array())).array() * s.col(1).array() * s.col(2).array());
79 sin_theta.col(1) = vol.array() / ((2./(3.*l.col(1).array())).array() * s.col(2).array() * s.col(0).array());
80 sin_theta.col(2) = vol.array() / ((2./(3.*l.col(2).array())).array() * s.col(0).array() * s.col(1).array());
81 sin_theta.col(3) = vol.array() / ((2./(3.*l.col(3).array())).array() * s.col(3).array() * s.col(0).array());
82 sin_theta.col(4) = vol.array() / ((2./(3.*l.col(4).array())).array() * s.col(3).array() * s.col(1).array());
83 sin_theta.col(5) = vol.array() / ((2./(3.*l.col(5).array())).array() * s.col(3).array() * s.col(2).array());
84
85
86 // http://arxiv.org/pdf/1208.0354.pdf Page 18
87 C = (1./6.) * l.array() * cos_theta.array() / sin_theta.array();
88
89 break;
90 }
91 default:
92 {
93 fprintf(stderr,
94 "cotmatrix_entries.h: Error: Simplex size (%d) not supported\n", simplex_size);
95 assert(false);
96 }
97 }
98}
IGL_INLINE void squared_edge_lengths(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedL > &L)
Definition squared_edge_lengths.cpp:13
IGL_INLINE void face_areas(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedT > &T, Eigen::PlainObjectBase< DerivedA > &A)
Definition face_areas.cpp:13
IGL_INLINE void dihedral_angles_intrinsic(Eigen::PlainObjectBase< DerivedL > &L, Eigen::PlainObjectBase< DerivedA > &A, Eigen::PlainObjectBase< Derivedtheta > &theta, Eigen::PlainObjectBase< Derivedcos_theta > &cos_theta)
Definition dihedral_angles.cpp:36

References dihedral_angles_intrinsic(), doublearea(), edge_lengths(), face_areas(), Eigen::PlainObjectBase< Derived >::resize(), squared_edge_lengths(), and volume().

Referenced by arap_linear_block_elements(), arap_linear_block_spokes(), arap_linear_block_spokes_and_rims(), cotmatrix(), crouzeix_raviart_cotmatrix(), normal_derivative(), and igl::Frame_field_deformer::precompute_opt().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ count() [1/2]

template<typename XType , typename DerivedS >
IGL_INLINE void igl::count ( const Eigen::SparseMatrix< XType > &  X,
const int  dim,
Eigen::PlainObjectBase< DerivedS > &  S 
)

◆ count() [2/2]

template<typename XType , typename SType >
IGL_INLINE void igl::count ( const Eigen::SparseMatrix< XType > &  X,
const int  dim,
Eigen::SparseVector< SType > &  S 
)
16{
17 // dim must be 2 or 1
18 assert(dim == 1 || dim == 2);
19 // Get size of input
20 int m = X.rows();
21 int n = X.cols();
22 // resize output
23 if(dim==1)
24 {
26 }else
27 {
29 }
30
31 // Iterate over outside
32 for(int k=0; k<X.outerSize(); ++k)
33 {
34 // Iterate over inside
35 for(typename Eigen::SparseMatrix<XType>::InnerIterator it (X,k); it; ++it)
36 {
37 if(dim == 1)
38 {
39 S.coeffRef(it.col()) += (it.value() == 0? 0: 1);
40 }else
41 {
42 S.coeffRef(it.row()) += (it.value() == 0? 0: 1);
43 }
44 }
45 }
46
47}
a sparse vector class
Definition SparseVector.h:66
Scalar & coeffRef(Index row, Index col)
Definition SparseVector.h:113

References Eigen::SparseVector< _Scalar, _Options, _StorageIndex >::coeffRef().

Referenced by igl::copyleft::cgal::SelfIntersectMesh< Kernel, DerivedV, DerivedF, DerivedVV, DerivedFF, DerivedIF, DerivedJ, DerivedIM >::SelfIntersectMesh(), active_set(), avg_edge_length(), bijective_composite_harmonic_mapping(), boundary_facets(), igl::geodesic::Mesh::build_adjacencies(), igl::copyleft::cgal::SelfIntersectMesh< Kernel, DerivedV, DerivedF, DerivedVV, DerivedFF, DerivedIF, DerivedJ, DerivedIM >::count_intersection(), igl::opengl::destroy_shader_program(), igl::opengl::ViewerCore::draw_buffer(), exterior_edges(), igl::copyleft::cgal::extract_cells(), igl::copyleft::cgal::extract_cells_single_component(), igl::WindingNumberAABB< Point, DerivedV, DerivedF >::grow(), is_edge_manifold(), is_irregular_vertex(), igl::copyleft::cgal::minkowski_sum(), igl::matlab::mlsetmatrix(), igl::geodesic::IntervalList::number_of_intervals(), igl::copyleft::cgal::BinaryWindingNumberOperations< MESH_BOOLEAN_TYPE_XOR >::operator()(), piecewise_constant_winding_number(), pinv(), igl::copyleft::comiso::NRosyField::prepareSystemMatrix(), igl::copyleft::cgal::projected_cdt(), readBF(), readOBJ(), readTGF(), remesh_along_isoline(), remove_duplicates(), remove_unreferenced(), setunion(), and straighten_seams().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ covariance_scatter_matrix()

IGL_INLINE void igl::covariance_scatter_matrix ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const ARAPEnergyType  energy,
Eigen::SparseMatrix< double > &  CSM 
)
23{
24 using namespace Eigen;
25 // number of mesh vertices
26 int n = V.rows();
27 assert(n > F.maxCoeff());
28 // dimension of mesh
29 int dim = V.cols();
30 // Number of mesh elements
31 int m = F.rows();
32
33 // number of rotations
34 int nr;
35 switch(energy)
36 {
38 nr = n;
39 break;
41 nr = n;
42 break;
44 nr = m;
45 break;
46 default:
47 fprintf(
48 stderr,
49 "covariance_scatter_matrix.h: Error: Unsupported arap energy %d\n",
50 energy);
51 return;
52 }
53
54 SparseMatrix<double> KX,KY,KZ;
55 arap_linear_block(V,F,0,energy,KX);
56 arap_linear_block(V,F,1,energy,KY);
58 if(dim == 2)
59 {
60 CSM = cat(1,cat(2,KX,Z),cat(2,Z,KY)).transpose();
61 }else if(dim == 3)
62 {
63 arap_linear_block(V,F,2,energy,KZ);
64 SparseMatrix<double>ZZ(n,nr*2);
65 CSM =
66 cat(1,cat(1,cat(2,KX,ZZ),cat(2,cat(2,Z,KY),Z)),cat(2,ZZ,KZ)).transpose();
67 }else
68 {
69 fprintf(
70 stderr,
71 "covariance_scatter_matrix.h: Error: Unsupported dimension %d\n",
72 dim);
73 return;
74 }
75
76}

References ARAP_ENERGY_TYPE_ELEMENTS, ARAP_ENERGY_TYPE_SPOKES, ARAP_ENERGY_TYPE_SPOKES_AND_RIMS, arap_linear_block(), and cat().

Referenced by arap_dof_precomputation(), and arap_precomputation().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cross() [1/2]

IGL_INLINE void igl::cross ( const double *  a,
const double *  b,
double *  out 
)
15{
16 out[0] = a[1]*b[2]-a[2]*b[1];
17 out[1] = a[2]*b[0]-a[0]*b[2];
18 out[2] = a[0]*b[1]-a[1]*b[0];
19}

Referenced by centroid(), igl::copyleft::comiso::MIQ_class< DerivedV, DerivedF, DerivedU >::Distortion(), per_face_normals_stable(), quad_planarity(), segments_intersect(), trackball(), and volume().

+ Here is the caller graph for this function:

◆ cross() [2/2]

template<typename DerivedA , typename DerivedB , typename DerivedC >
IGL_INLINE void igl::cross ( const Eigen::PlainObjectBase< DerivedA > &  A,
const Eigen::PlainObjectBase< DerivedB > &  B,
Eigen::PlainObjectBase< DerivedC > &  C 
)
29{
30 assert(A.cols() == 3 && "#cols should be 3");
31 assert(B.cols() == 3 && "#cols should be 3");
32 assert(A.rows() == B.rows() && "#rows in A and B should be equal");
33 C.resize(A.rows(),3);
34 for(int d = 0;d<3;d++)
35 {
36 C.col(d) =
37 A.col((d+1)%3).array() * B.col((d+2)%3).array() -
38 A.col((d+2)%3).array() * B.col((d+1)%3).array();
39 }
40}

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ cross_field_missmatch()

template<typename DerivedV , typename DerivedF , typename DerivedM >
IGL_INLINE void igl::cross_field_missmatch ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedV > &  PD1,
const Eigen::PlainObjectBase< DerivedV > &  PD2,
const bool  isCombed,
Eigen::PlainObjectBase< DerivedM > &  missmatch 
)
121{
122 DerivedV PD1_combed;
123 DerivedV PD2_combed;
124
125 if (!isCombed)
126 igl::comb_cross_field(V,F,PD1,PD2,PD1_combed,PD2_combed);
127 else
128 {
129 PD1_combed = PD1;
130 PD2_combed = PD2;
131 }
132 igl::MissMatchCalculator<DerivedV, DerivedF, DerivedM> sf(V, F, PD1_combed, PD2_combed);
133 sf.calculateMissmatch(missmatch);
134}
Definition cross_field_missmatch.cpp:25
IGL_INLINE void comb_cross_field(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedV > &PD1in, const Eigen::PlainObjectBase< DerivedV > &PD2in, Eigen::PlainObjectBase< DerivedV > &PD1out, Eigen::PlainObjectBase< DerivedV > &PD2out)
Definition comb_cross_field.cpp:133

References igl::MissMatchCalculator< DerivedV, DerivedF, DerivedM >::calculateMissmatch(), and comb_cross_field().

Referenced by find_cross_field_singularities(), and igl::copyleft::comiso::miq().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crouzeix_raviart_cotmatrix() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedE , typename DerivedEMAP , typename LT >
void igl::crouzeix_raviart_cotmatrix ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< DerivedE > &  E,
const Eigen::MatrixBase< DerivedEMAP > &  EMAP,
Eigen::SparseMatrix< LT > &  L 
)
37{
38 // number of rows
39 const int m = F.rows();
40 // Element simplex size
41 const int ss = F.cols();
42 // Mesh should be edge-manifold
43 assert(F.cols() != 3 || is_edge_manifold(F));
45 MatrixXS C;
46 cotmatrix_entries(V,F,C);
47 Eigen::MatrixXi F2E(m,ss);
48 {
49 int k =0;
50 for(int c = 0;c<ss;c++)
51 {
52 for(int f = 0;f<m;f++)
53 {
54 F2E(f,c) = k++;
55 }
56 }
57 }
58 // number of entries inserted per facet
59 const int k = ss*(ss-1)*2;
60 std::vector<Eigen::Triplet<LT> > LIJV;LIJV.reserve(k*m);
61 Eigen::VectorXi LI(k),LJ(k),LV(k);
62 // Compensation factor to match scales in matlab version
63 double factor = 2.0;
64
65 switch(ss)
66 {
67 default: assert(false && "unsupported simplex size");
68 case 3:
69 factor = 4.0;
70 LI<<0,1,2,1,2,0,0,1,2,1,2,0;
71 LJ<<1,2,0,0,1,2,0,1,2,1,2,0;
72 LV<<2,0,1,2,0,1,2,0,1,2,0,1;
73 break;
74 case 4:
75 factor *= -1.0;
76 LI<<0,3,3,3,1,2,1,0,1,2,2,0,0,3,3,3,1,2,1,0,1,2,2,0;
77 LJ<<1,0,1,2,2,0,0,3,3,3,1,2,0,3,3,3,1,2,1,0,1,2,2,0;
78 LV<<2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5,0,1;
79 break;
80 }
81
82 for(int f=0;f<m;f++)
83 {
84 for(int c = 0;c<k;c++)
85 {
86 LIJV.emplace_back(
87 EMAP(F2E(f,LI(c))),
88 EMAP(F2E(f,LJ(c))),
89 (c<(k/2)?-1.:1.) * factor *C(f,LV(c)));
90 }
91 }
92 L.resize(E.rows(),E.rows());
93 L.setFromTriplets(LIJV.begin(),LIJV.end());
94}
IGL_INLINE bool is_edge_manifold(const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedBF > &BF, Eigen::PlainObjectBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedEMAP > &EMAP, Eigen::PlainObjectBase< DerivedBE > &BE)
Definition is_edge_manifold.cpp:21

References cotmatrix_entries(), is_edge_manifold(), and L.

+ Here is the call graph for this function:

◆ crouzeix_raviart_cotmatrix() [2/2]

template<typename DerivedV , typename DerivedF , typename LT , typename DerivedE , typename DerivedEMAP >
void igl::crouzeix_raviart_cotmatrix ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::SparseMatrix< LT > &  L,
Eigen::PlainObjectBase< DerivedE > &  E,
Eigen::PlainObjectBase< DerivedEMAP > &  EMAP 
)
21{
22 // All occurrences of directed "facets"
23 Eigen::MatrixXi allE;
24 oriented_facets(F,allE);
25 Eigen::VectorXi _1;
26 unique_simplices(allE,E,_1,EMAP);
27 return crouzeix_raviart_cotmatrix(V,F,E,EMAP,L);
28}
IGL_INLINE void unique_simplices(const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedFF > &FF, Eigen::PlainObjectBase< DerivedIA > &IA, Eigen::PlainObjectBase< DerivedIC > &IC)
Definition unique_simplices.cpp:18

References crouzeix_raviart_cotmatrix(), L, oriented_facets(), and unique_simplices().

Referenced by biharmonic_coordinates(), and crouzeix_raviart_cotmatrix().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crouzeix_raviart_massmatrix() [1/2]

template<typename MT , typename DerivedV , typename DerivedF , typename DerivedE , typename DerivedEMAP >
void igl::crouzeix_raviart_massmatrix ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< DerivedE > &  E,
const Eigen::MatrixBase< DerivedEMAP > &  EMAP,
Eigen::SparseMatrix< MT > &  M 
)
42{
43 using namespace Eigen;
44 using namespace std;
45 // Mesh should be edge-manifold (TODO: replace `is_edge_manifold` with
46 // `is_facet_manifold`)
47 assert(F.cols() != 3 || is_edge_manifold(F));
48 // number of elements (triangles)
49 const int m = F.rows();
50 // Get triangle areas/volumes
51 VectorXd TA;
52 // Element simplex size
53 const int ss = F.cols();
54 switch(ss)
55 {
56 default:
57 assert(false && "Unsupported simplex size");
58 case 3:
59 doublearea(V,F,TA);
60 TA *= 0.5;
61 break;
62 case 4:
63 volume(V,F,TA);
64 break;
65 }
66 vector<Triplet<MT> > MIJV(ss*m);
67 assert(EMAP.size() == m*ss);
68 for(int f = 0;f<m;f++)
69 {
70 for(int c = 0;c<ss;c++)
71 {
72 MIJV[f+m*c] = Triplet<MT>(EMAP(f+m*c),EMAP(f+m*c),TA(f)/(double)(ss));
73 }
74 }
75 M.resize(E.rows(),E.rows());
76 M.setFromTriplets(MIJV.begin(),MIJV.end());
77}

References doublearea(), is_edge_manifold(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::resize(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets(), and volume().

+ Here is the call graph for this function:

◆ crouzeix_raviart_massmatrix() [2/2]

template<typename MT , typename DerivedV , typename DerivedF , typename DerivedE , typename DerivedEMAP >
void igl::crouzeix_raviart_massmatrix ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::SparseMatrix< MT > &  M,
Eigen::PlainObjectBase< DerivedE > &  E,
Eigen::PlainObjectBase< DerivedEMAP > &  EMAP 
)
26{
27 // All occurrences of directed "facets"
28 Eigen::MatrixXi allE;
29 oriented_facets(F,allE);
30 Eigen::VectorXi _1;
31 unique_simplices(allE,E,_1,EMAP);
32 return crouzeix_raviart_massmatrix(V,F,E,EMAP,M);
33}

References crouzeix_raviart_massmatrix(), oriented_facets(), and unique_simplices().

Referenced by biharmonic_coordinates(), and crouzeix_raviart_massmatrix().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cumsum()

template<typename DerivedX , typename DerivedY >
IGL_INLINE void igl::cumsum ( const Eigen::MatrixBase< DerivedX > &  X,
const int  dim,
Eigen::PlainObjectBase< DerivedY > &  Y 
)
17{
18 using namespace Eigen;
19 using namespace std;
20 Y.resizeLike(X);
21 // get number of columns (or rows)
22 int num_outer = (dim == 1 ? X.cols() : X.rows() );
23 // get number of rows (or columns)
24 int num_inner = (dim == 1 ? X.rows() : X.cols() );
25 // This has been optimized so that dim = 1 or 2 is roughly the same cost.
26 // (Optimizations assume ColMajor order)
27 if(dim == 1)
28 {
29#pragma omp parallel for
30 for(int o = 0;o<num_outer;o++)
31 {
32 typename DerivedX::Scalar sum = 0;
33 for(int i = 0;i<num_inner;i++)
34 {
35 sum += X(i,o);
36 Y(i,o) = sum;
37 }
38 }
39 }else
40 {
41 for(int i = 0;i<num_inner;i++)
42 {
43 // Notice that it is *not* OK to put this above the inner loop
44 // Though here it doesn't seem to pay off...
45//#pragma omp parallel for
46 for(int o = 0;o<num_outer;o++)
47 {
48 if(i == 0)
49 {
50 Y(o,i) = X(o,i);
51 }else
52 {
53 Y(o,i) = Y(o,i-1) + X(o,i);
54 }
55 }
56 }
57 }
58}

References sum().

Referenced by igl::copyleft::cgal::mesh_boolean(), ramer_douglas_peucker(), random_points_on_mesh(), and vertex_triangle_adjacency().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cut_mesh() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedC >
IGL_INLINE void igl::cut_mesh ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedC > &  cuts,
Eigen::PlainObjectBase< DerivedV > &  Vcut,
Eigen::PlainObjectBase< DerivedF > &  Fcut 
)
312{
313 std::vector<std::vector<int> > VF, VFi;
315 // Alec: Cast? Why? This is likely to break.
316 Eigen::MatrixXd Vt = V;
317 Eigen::MatrixXi Ft = F;
318 Eigen::MatrixXi TT, TTi;
320 std::vector<bool> V_border = igl::is_border_vertex(V,F);
321 igl::cut_mesh(V, F, VF, VFi, TT, TTi, V_border, cuts, Vcut, Fcut);
322}
IGL_INLINE void cut_mesh(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const std::vector< std::vector< VFType > > &VF, const std::vector< std::vector< VFType > > &VFi, const Eigen::PlainObjectBase< DerivedTT > &TT, const Eigen::PlainObjectBase< DerivedTT > &TTi, const std::vector< bool > &V_border, const Eigen::PlainObjectBase< DerivedC > &cuts, Eigen::PlainObjectBase< DerivedV > &Vcut, Eigen::PlainObjectBase< DerivedF > &Fcut)
Definition cut_mesh.cpp:264

References cut_mesh(), is_border_vertex(), triangle_triangle_adjacency(), and vertex_triangle_adjacency().

+ Here is the call graph for this function:

◆ cut_mesh() [2/2]

template<typename DerivedV , typename DerivedF , typename VFType , typename DerivedTT , typename DerivedC >
IGL_INLINE void igl::cut_mesh ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const std::vector< std::vector< VFType > > &  VF,
const std::vector< std::vector< VFType > > &  VFi,
const Eigen::PlainObjectBase< DerivedTT > &  TT,
const Eigen::PlainObjectBase< DerivedTT > &  TTi,
const std::vector< bool > &  V_border,
const Eigen::PlainObjectBase< DerivedC > &  cuts,
Eigen::PlainObjectBase< DerivedV > &  Vcut,
Eigen::PlainObjectBase< DerivedF > &  Fcut 
)
275{
276 //finding the cuts is done, now we need to actually generate a cut mesh
277 igl::MeshCutterMini<DerivedV, DerivedF, VFType, DerivedTT, DerivedC> mc(V, F, TT, TTi, VF, VFi, V_border, cuts);
278 mc.InitMappingSeam();
279
280 Fcut = mc.HandleS_Index;
281 //we have the faces, we need the vertices;
282 int newNumV = Fcut.maxCoeff()+1;
283 Vcut.setZero(newNumV,3);
284 for (int vi=0; vi<V.rows(); ++vi)
285 for (int i=0; i<mc.HandleV_Integer[vi].size();++i)
286 Vcut.row(mc.HandleV_Integer[vi][i]) = V.row(vi);
287
288 //ugly hack to fix some problematic cases (border vertex that is also on the boundary of the hole
289 for (int fi =0; fi<Fcut.rows(); ++fi)
290 for (int k=0; k<3; ++k)
291 if (Fcut(fi,k)==-1)
292 {
293 //we need to add a vertex
294 Fcut(fi,k) = newNumV;
295 newNumV ++;
296 Vcut.conservativeResize(newNumV, Eigen::NoChange);
297 Vcut.row(newNumV-1) = V.row(F(fi,k));
298 }
299
300
301}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void conservativeResize(Index rows, Index cols)
Definition PlainObjectBase.h:390
Definition cut_mesh.cpp:22
@ NoChange
Definition Constants.h:350

References Eigen::PlainObjectBase< Derived >::conservativeResize(), igl::MeshCutterMini< DerivedV, DerivedF, VFType, DerivedTT, DerivedC >::HandleS_Index, igl::MeshCutterMini< DerivedV, DerivedF, VFType, DerivedTT, DerivedC >::HandleV_Integer, igl::MeshCutterMini< DerivedV, DerivedF, VFType, DerivedTT, DerivedC >::InitMappingSeam(), Eigen::NoChange, Eigen::PlainObjectBase< Derived >::rows(), and Eigen::PlainObjectBase< Derived >::setZero().

Referenced by igl::copyleft::comiso::MIQ_class< DerivedV, DerivedF, DerivedU >::MIQ_class(), and cut_mesh().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cut_mesh_from_singularities()

template<typename DerivedV , typename DerivedF , typename DerivedM , typename DerivedO >
IGL_INLINE void igl::cut_mesh_from_singularities ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedM > &  MMatch,
Eigen::PlainObjectBase< DerivedO > &  seams 
)
191{
193 mc.cut(Handle_Seams);
194
195}
Definition cut_mesh_from_singularities.cpp:26

References igl::MeshCutter< DerivedV, DerivedF, DerivedM, DerivedO >::cut().

Referenced by igl::copyleft::comiso::miq().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cylinder()

template<typename DerivedV , typename DerivedF >
IGL_INLINE void igl::cylinder ( const int  axis_devisions,
const int  height_devisions,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F 
)
19{
20 V.resize(axis_devisions*height_devisions,3);
21 F.resize(2*(axis_devisions*(height_devisions-1)),3);
22 int f = 0;
23 typedef typename DerivedV::Scalar Scalar;
24 for(int th = 0;th<axis_devisions;th++)
25 {
26 Scalar x = cos(2.*igl::PI*Scalar(th)/Scalar(axis_devisions));
27 Scalar y = sin(2.*igl::PI*Scalar(th)/Scalar(axis_devisions));
28 for(int h = 0;h<height_devisions;h++)
29 {
30 Scalar z = Scalar(h)/Scalar(height_devisions-1);
31 V(th+h*axis_devisions,0) = x;
32 V(th+h*axis_devisions,1) = y;
33 V(th+h*axis_devisions,2) = z;
34 if(h > 0)
35 {
36 F(f,0) = ((th+0)%axis_devisions)+(h-1)*axis_devisions;
37 F(f,1) = ((th+1)%axis_devisions)+(h-1)*axis_devisions;
38 F(f,2) = ((th+0)%axis_devisions)+(h+0)*axis_devisions;
39 f++;
40 F(f,0) = ((th+1)%axis_devisions)+(h-1)*axis_devisions;
41 F(f,1) = ((th+1)%axis_devisions)+(h+0)*axis_devisions;
42 F(f,2) = ((th+0)%axis_devisions)+(h+0)*axis_devisions;
43 f++;
44 }
45 }
46 }
47 assert(f == F.rows());
48}

References cos(), PI, Eigen::PlainObjectBase< Derived >::resize(), and sin().

+ Here is the call graph for this function:

◆ dated_copy() [1/2]

IGL_INLINE bool igl::dated_copy ( const std::string &  src_path)
87{
88 return dated_copy(src_path,dirname(src_path));
89}
IGL_INLINE bool dated_copy(const std::string &src_path, const std::string &dir)
Definition dated_copy.cpp:21
IGL_INLINE std::string dirname(const std::string &path)
Definition dirname.cpp:13

References dated_copy(), and dirname().

+ Here is the call graph for this function:

◆ dated_copy() [2/2]

IGL_INLINE bool igl::dated_copy ( const std::string &  src_path,
const std::string &  dir 
)
22{
23 using namespace std;
24 // Get time and date as string
25 char buffer[80];
26 time_t rawtime;
27 struct tm * timeinfo;
28 time (&rawtime);
29 timeinfo = localtime (&rawtime);
30 // ISO 8601 format with hyphens instead of colons and no timezone offset
31 strftime (buffer,80,"%Y-%m-%dT%H-%M-%S",timeinfo);
32 string src_basename = basename(src_path);
33 string dst_basename = src_basename+"-"+buffer;
34 string dst_path = dir+"/"+dst_basename;
35 cerr<<"Saving binary to "<<dst_path;
36 {
37 // http://stackoverflow.com/a/10195497/148668
38 ifstream src(src_path,ios::binary);
39 if (!src.is_open())
40 {
41 cerr<<" failed."<<endl;
42 return false;
43 }
44 ofstream dst(dst_path,ios::binary);
45 if(!dst.is_open())
46 {
47 cerr<<" failed."<<endl;
48 return false;
49 }
50 dst << src.rdbuf();
51 }
52 cerr<<" succeeded."<<endl;
53 cerr<<"Setting permissions of "<<dst_path;
54 {
55 int src_posix = fileno(fopen(src_path.c_str(),"r"));
56 if(src_posix == -1)
57 {
58 cerr<<" failed."<<endl;
59 return false;
60 }
61 struct stat fst;
62 fstat(src_posix,&fst);
63 int dst_posix = fileno(fopen(dst_path.c_str(),"r"));
64 if(dst_posix == -1)
65 {
66 cerr<<" failed."<<endl;
67 return false;
68 }
69 //update to the same uid/gid
70 if(fchown(dst_posix,fst.st_uid,fst.st_gid))
71 {
72 cerr<<" failed."<<endl;
73 return false;
74 }
75 //update the permissions
76 if(fchmod(dst_posix,fst.st_mode) == -1)
77 {
78 cerr<<" failed."<<endl;
79 return false;
80 }
81 cerr<<" succeeded."<<endl;
82 }
83 return true;
84}
#define stat
Definition unistd.h:53
#define fileno
Definition unistd.h:43

References basename(), fileno, and stat.

Referenced by dated_copy().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ decimate() [1/5]

IGL_INLINE bool igl::decimate ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const size_t  max_m,
Eigen::MatrixXd &  U,
Eigen::MatrixXi &  G,
Eigen::VectorXi &  J 
)
69{
70 Eigen::VectorXi I;
71 return igl::decimate(V,F,max_m,U,G,J,I);
72}
IGL_INLINE bool decimate(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const size_t max_m, Eigen::MatrixXd &U, Eigen::MatrixXi &G, Eigen::VectorXi &J, Eigen::VectorXi &I)
Definition decimate.cpp:19

References decimate().

+ Here is the call graph for this function:

◆ decimate() [2/5]

IGL_INLINE bool igl::decimate ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const size_t  max_m,
Eigen::MatrixXd &  U,
Eigen::MatrixXi &  G,
Eigen::VectorXi &  J,
Eigen::VectorXi &  I 
)
27{
28 // Original number of faces
29 const int orig_m = F.rows();
30 // Tracking number of faces
31 int m = F.rows();
32 typedef Eigen::MatrixXd DerivedV;
33 typedef Eigen::MatrixXi DerivedF;
34 DerivedV VO;
35 DerivedF FO;
37 // decimate will not work correctly on non-edge-manifold meshes. By extension
38 // this includes meshes with non-manifold vertices on the boundary since these
39 // will create a non-manifold edge when connected to infinity.
40 if(!is_edge_manifold(FO))
41 {
42 return false;
43 }
44 bool ret = decimate(
45 VO,
46 FO,
47 shortest_edge_and_midpoint,
48 max_faces_stopping_condition(m,orig_m,max_m),
49 U,
50 G,
51 J,
52 I);
53 const Eigen::Array<bool,Eigen::Dynamic,1> keep = (J.array()<orig_m);
54 igl::slice_mask(Eigen::MatrixXi(G),keep,1,G);
55 igl::slice_mask(Eigen::VectorXi(J),keep,1,J);
56 Eigen::VectorXi _1,I2;
57 igl::remove_unreferenced(Eigen::MatrixXd(U),Eigen::MatrixXi(G),U,G,_1,I2);
58 igl::slice(Eigen::VectorXi(I),I2,1,I);
59 return ret;
60}
IGL_INLINE void remove_unreferenced(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedNV > &NV, Eigen::PlainObjectBase< DerivedNF > &NF, Eigen::PlainObjectBase< DerivedI > &I)
Definition remove_unreferenced.cpp:18
IGL_INLINE void slice_mask(const Eigen::DenseBase< DerivedX > &X, const Eigen::Array< bool, Eigen::Dynamic, 1 > &R, const Eigen::Array< bool, Eigen::Dynamic, 1 > &C, Eigen::PlainObjectBase< DerivedY > &Y)
Definition slice_mask.cpp:14

References connect_boundary_to_infinity(), decimate(), is_edge_manifold(), max_faces_stopping_condition(), remove_unreferenced(), shortest_edge_and_midpoint(), slice(), and slice_mask().

Referenced by decimate(), decimate(), decimate(), decimate(), igl::copyleft::progressive_hulls(), qslim(), and simplify_polyhedron().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ decimate() [3/5]

IGL_INLINE bool igl::decimate ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const std::function< void(const int, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> &  cost_and_placement,
const std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int)> &  stopping_condition,
const std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int)> &  pre_collapse,
const std::function< void(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int, const bool)> &  post_collapse,
const Eigen::MatrixXi &  E,
const Eigen::VectorXi &  EMAP,
const Eigen::MatrixXi &  EF,
const Eigen::MatrixXi &  EI,
Eigen::MatrixXd &  U,
Eigen::MatrixXi &  G,
Eigen::VectorXi &  J,
Eigen::VectorXi &  I 
)
283{
284
285 // Decimate 1
286 using namespace Eigen;
287 using namespace std;
288 // Working copies
289 Eigen::MatrixXd V = OV;
290 Eigen::MatrixXi F = OF;
291 Eigen::MatrixXi E = OE;
292 Eigen::VectorXi EMAP = OEMAP;
293 Eigen::MatrixXi EF = OEF;
294 Eigen::MatrixXi EI = OEI;
295 typedef std::set<std::pair<double,int> > PriorityQueue;
296 PriorityQueue Q;
297 std::vector<PriorityQueue::iterator > Qit;
298 Qit.resize(E.rows());
299 // If an edge were collapsed, we'd collapse it to these points:
300 MatrixXd C(E.rows(),V.cols());
301 for(int e = 0;e<E.rows();e++)
302 {
303 double cost = e;
304 RowVectorXd p(1,3);
305 cost_and_placement(e,V,F,E,EMAP,EF,EI,cost,p);
306 C.row(e) = p;
307 Qit[e] = Q.insert(std::pair<double,int>(cost,e)).first;
308 }
309 int prev_e = -1;
310 bool clean_finish = false;
311
312 while(true)
313 {
314 if(Q.empty())
315 {
316 break;
317 }
318 if(Q.begin()->first == std::numeric_limits<double>::infinity())
319 {
320 // min cost edge is infinite cost
321 break;
322 }
323 int e,e1,e2,f1,f2;
324 if(collapse_edge(
325 cost_and_placement, pre_collapse, post_collapse,
326 V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2))
327 {
328 if(stopping_condition(V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2))
329 {
330 clean_finish = true;
331 break;
332 }
333 }else
334 {
335 if(prev_e == e)
336 {
337 assert(false && "Edge collapse no progress... bad stopping condition?");
338 break;
339 }
340 // Edge was not collapsed... must have been invalid. collapse_edge should
341 // have updated its cost to inf... continue
342 }
343 prev_e = e;
344 }
345 // remove all IGL_COLLAPSE_EDGE_NULL faces
346 MatrixXi F2(F.rows(),3);
347 J.resize(F.rows());
348 int m = 0;
349 for(int f = 0;f<F.rows();f++)
350 {
351 if(
352 F(f,0) != IGL_COLLAPSE_EDGE_NULL ||
353 F(f,1) != IGL_COLLAPSE_EDGE_NULL ||
355 {
356 F2.row(m) = F.row(f);
357 J(m) = f;
358 m++;
359 }
360 }
361 F2.conservativeResize(m,F2.cols());
362 J.conservativeResize(m);
363 VectorXi _1;
364 remove_unreferenced(V,F2,U,G,_1,I);
365 return clean_finish;
366}

References collapse_edge(), IGL_COLLAPSE_EDGE_NULL, and remove_unreferenced().

+ Here is the call graph for this function:

◆ decimate() [4/5]

IGL_INLINE bool igl::decimate ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const std::function< void(const int, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> &  cost_and_placement,
const std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int)> &  stopping_condition,
const std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int)> &  pre_collapse,
const std::function< void(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int, const bool)> &  post_collapse,
Eigen::MatrixXd &  U,
Eigen::MatrixXi &  G,
Eigen::VectorXi &  J,
Eigen::VectorXi &  I 
)
203{
204 using namespace Eigen;
205 using namespace std;
206 VectorXi EMAP;
207 MatrixXi E,EF,EI;
208 edge_flaps(OF,E,EMAP,EF,EI);
209 return igl::decimate(
210 OV,OF,
211 cost_and_placement,stopping_condition,pre_collapse,post_collapse,
212 E,EMAP,EF,EI,
213 U,G,J,I);
214}
IGL_INLINE void edge_flaps(const Eigen::MatrixXi &F, const Eigen::MatrixXi &E, const Eigen::VectorXi &EMAP, Eigen::MatrixXi &EF, Eigen::MatrixXi &EI)
Definition edge_flaps.cpp:13

References decimate(), and edge_flaps().

+ Here is the call graph for this function:

◆ decimate() [5/5]

IGL_INLINE bool igl::decimate ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const std::function< void(const int, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> &  cost_and_placement,
const std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int)> &  stopping_condition,
Eigen::MatrixXd &  U,
Eigen::MatrixXi &  G,
Eigen::VectorXi &  J,
Eigen::VectorXi &  I 
)
107{
108 const auto always_try = [](
109 const Eigen::MatrixXd & ,/*V*/
110 const Eigen::MatrixXi & ,/*F*/
111 const Eigen::MatrixXi & ,/*E*/
112 const Eigen::VectorXi & ,/*EMAP*/
113 const Eigen::MatrixXi & ,/*EF*/
114 const Eigen::MatrixXi & ,/*EI*/
115 const std::set<std::pair<double,int> > & ,/*Q*/
116 const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
117 const Eigen::MatrixXd & ,/*C*/
118 const int /*e*/
119 ) -> bool { return true;};
120 const auto never_care = [](
121 const Eigen::MatrixXd & , /*V*/
122 const Eigen::MatrixXi & , /*F*/
123 const Eigen::MatrixXi & , /*E*/
124 const Eigen::VectorXi & ,/*EMAP*/
125 const Eigen::MatrixXi & , /*EF*/
126 const Eigen::MatrixXi & , /*EI*/
127 const std::set<std::pair<double,int> > & , /*Q*/
128 const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
129 const Eigen::MatrixXd & , /*C*/
130 const int , /*e*/
131 const int , /*e1*/
132 const int , /*e2*/
133 const int , /*f1*/
134 const int , /*f2*/
135 const bool /*collapsed*/
136 )-> void { };
137 return igl::decimate(
138 OV,OF,cost_and_placement,stopping_condition,always_try,never_care,U,G,J,I);
139}

References decimate().

+ Here is the call graph for this function:

◆ deform_skeleton() [1/2]

IGL_INLINE void igl::deform_skeleton ( const Eigen::MatrixXd &  C,
const Eigen::MatrixXi &  BE,
const Eigen::MatrixXd &  T,
Eigen::MatrixXd &  CT,
Eigen::MatrixXi &  BET 
)
40{
41 using namespace Eigen;
42 //assert(BE.rows() == (int)vA.size());
43 CT.resize(2*BE.rows(),C.cols());
44 BET.resize(BE.rows(),2);
45 for(int e = 0;e<BE.rows();e++)
46 {
47 BET(e,0) = 2*e;
48 BET(e,1) = 2*e+1;
49 Matrix4d t;
50 t << T.block(e*4,0,4,3).transpose(), 0,0,0,0;
51 Affine3d a;
52 a.matrix() = t;
53 Vector3d c0 = C.row(BE(e,0));
54 Vector3d c1 = C.row(BE(e,1));
55 CT.row(2*e) = a * c0;
56 CT.row(2*e+1) = a * c1;
57 }
58}
Represents an homogeneous transformation in a N dimensional space.
Definition Transform.h:202

◆ deform_skeleton() [2/2]

void igl::deform_skeleton ( const Eigen::MatrixXd &  C,
const Eigen::MatrixXi &  BE,
const std::vector< Eigen::Affine3d, Eigen::aligned_allocator< Eigen::Affine3d > > &  vA,
Eigen::MatrixXd &  CT,
Eigen::MatrixXi &  BET 
)
16{
17 using namespace Eigen;
18 assert(BE.rows() == (int)vA.size());
19 CT.resize(2*BE.rows(),C.cols());
20 BET.resize(BE.rows(),2);
21 for(int e = 0;e<BE.rows();e++)
22 {
23 BET(e,0) = 2*e;
24 BET(e,1) = 2*e+1;
25 Affine3d a = vA[e];
26 Vector3d c0 = C.row(BE(e,0));
27 Vector3d c1 = C.row(BE(e,1));
28 CT.row(2*e) = a * c0;
29 CT.row(2*e+1) = a * c1;
30 }
31
32}

◆ delaunay_triangulation()

template<typename DerivedV , typename Orient2D , typename InCircle , typename DerivedF >
IGL_INLINE void igl::delaunay_triangulation ( const Eigen::PlainObjectBase< DerivedV > &  V,
Orient2D  orient2D,
InCircle  incircle,
Eigen::PlainObjectBase< DerivedF > &  F 
)
27{
28 assert(V.cols() == 2);
29 typedef typename DerivedF::Scalar Index;
30 typedef typename DerivedV::Scalar Scalar;
32 const size_t num_faces = F.rows();
33 if (num_faces == 0) {
34 // Input points are degenerate. No faces will be generated.
35 return;
36 }
37 assert(F.cols() == 3);
38
39 Eigen::MatrixXi E;
40 Eigen::MatrixXi uE;
41 Eigen::VectorXi EMAP;
42 std::vector<std::vector<Index> > uE2E;
43 igl::unique_edge_map(F, E, uE, EMAP, uE2E);
44
45 auto is_delaunay = [&V,&F,&uE2E,num_faces,&incircle](size_t uei) {
46 auto& half_edges = uE2E[uei];
47 if (half_edges.size() != 2) {
48 throw "Cannot flip non-manifold or boundary edge";
49 }
50
51 const size_t f1 = half_edges[0] % num_faces;
52 const size_t f2 = half_edges[1] % num_faces;
53 const size_t c1 = half_edges[0] / num_faces;
54 const size_t c2 = half_edges[1] / num_faces;
55 assert(c1 < 3);
56 assert(c2 < 3);
57 assert(f1 != f2);
58 const size_t v1 = F(f1, (c1+1)%3);
59 const size_t v2 = F(f1, (c1+2)%3);
60 const size_t v4 = F(f1, c1);
61 const size_t v3 = F(f2, c2);
62 const Scalar p1[] = {V(v1, 0), V(v1, 1)};
63 const Scalar p2[] = {V(v2, 0), V(v2, 1)};
64 const Scalar p3[] = {V(v3, 0), V(v3, 1)};
65 const Scalar p4[] = {V(v4, 0), V(v4, 1)};
66 auto orientation = incircle(p1, p2, p4, p3);
67 return orientation <= 0;
68 };
69
70 bool all_delaunay = false;
71 while(!all_delaunay) {
72 all_delaunay = true;
73 for (size_t i=0; i<uE2E.size(); i++) {
74 if (uE2E[i].size() == 2) {
75 if (!is_delaunay(i)) {
76 all_delaunay = false;
77 flip_edge(F, E, uE, EMAP, uE2E, i);
78 }
79 }
80 }
81 }
82}
typename Traits< remove_cvref_t< L > >::Scalar Scalar
Definition Line.hpp:36
IGL_INLINE short incircle(const Scalar pa[2], const Scalar pb[2], const Scalar pc[2], const Scalar pd[2])
Definition incircle.cpp:14
IGL_INLINE void unique_edge_map(const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedE > &E, Eigen::PlainObjectBase< DeriveduE > &uE, Eigen::PlainObjectBase< DerivedEMAP > &EMAP, std::vector< std::vector< uE2EType > > &uE2E)
Definition unique_edge_map.cpp:19
IGL_INLINE void flip_edge(Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedE > &E, Eigen::PlainObjectBase< DeriveduE > &uE, Eigen::PlainObjectBase< DerivedEMAP > &EMAP, std::vector< std::vector< uE2EType > > &uE2E, const size_t uei)
Definition flip_edge.cpp:17
IGL_INLINE void lexicographic_triangulation(const Eigen::PlainObjectBase< DerivedP > &P, Orient2D orient2D, Eigen::PlainObjectBase< DerivedF > &F)
Definition lexicographic_triangulation.cpp:21

References Eigen::PlainObjectBase< Derived >::cols(), flip_edge(), lexicographic_triangulation(), and unique_edge_map().

Referenced by igl::copyleft::cgal::delaunay_triangulation().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ deserialize() [1/3]

template<typename T >
bool igl::deserialize ( T &  obj,
const std::string &  filename 
)
inline
485 {
486 return deserialize(obj,"obj",filename);
487 }

References deserialize().

Referenced by igl::xml::XMLSerializable::XMLSerializationObject< T >::Deserialize(), igl::Serializable::SerializationObject< T >::Deserialize(), deserialize(), deserialize(), igl::xml::deserialize_xml(), igl::opengl::glfw::Viewer::load_scene(), serializer(), serializer(), and serializer().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ deserialize() [2/3]

template<typename T >
bool igl::deserialize ( T &  obj,
const std::string &  objectName,
const std::string &  filename 
)
inline
491 {
492 bool success = false;
493
494 std::ifstream file(filename.c_str(),std::ios::binary);
495
496 if(file.is_open())
497 {
498 file.seekg(0,std::ios::end);
499 std::streamoff size = file.tellg();
500 file.seekg(0,std::ios::beg);
501
502 std::vector<char> buffer(size);
503 file.read(&buffer[0],size);
504
505 deserialize(obj,objectName,buffer);
506 file.close();
507
508 success = true;
509 }
510 else
511 {
512 std::cerr << "serialization: file " << filename << " not found!" << std::endl;
513 }
514
515 return success;
516 }

References deserialize().

+ Here is the call graph for this function:

◆ deserialize() [3/3]

template<typename T >
bool igl::deserialize ( T &  obj,
const std::string &  objectName,
const std::vector< char > &  buffer 
)
inline
520 {
521 bool success = false;
522
523 // find suitable object header
524 auto objectIter = buffer.cend();
525 auto iter = buffer.cbegin();
526 while(iter != buffer.end())
527 {
528 std::string name;
529 std::string type;
530 size_t size;
531 serialization::deserialize(name,iter);
532 serialization::deserialize(type,iter);
533 serialization::deserialize(size,iter);
534
535 if(name == objectName && type == typeid(obj).name())
536 {
537 objectIter = iter;
538 //break; // find first suitable object header
539 }
540
541 iter+=size;
542 }
543
544 if(objectIter != buffer.end())
545 {
546 serialization::deserialize(obj,objectIter);
547 success = true;
548 }
549 else
550 {
551 obj = T();
552 }
553
554 return success;
555 }

References igl::serialization::deserialize().

+ Here is the call graph for this function:

◆ dfs() [1/2]

template<typename AType , typename DerivedD , typename DerivedP , typename DerivedC >
IGL_INLINE void igl::dfs ( const std::vector< std::vector< AType > > &  A,
const size_t  s,
Eigen::PlainObjectBase< DerivedD > &  D,
Eigen::PlainObjectBase< DerivedP > &  P,
Eigen::PlainObjectBase< DerivedC > &  C 
)
16{
17 std::vector<typename DerivedD::Scalar> vD;
18 std::vector<typename DerivedP::Scalar> vP;
19 std::vector<typename DerivedC::Scalar> vC;
20 dfs(A,s,vD,vP,vC);
21 list_to_matrix(vD,D);
22 list_to_matrix(vP,P);
23 list_to_matrix(vC,C);
24}
IGL_INLINE void dfs(const std::vector< std::vector< AType > > &A, const size_t s, Eigen::PlainObjectBase< DerivedD > &D, Eigen::PlainObjectBase< DerivedP > &P, Eigen::PlainObjectBase< DerivedC > &C)
Definition dfs.cpp:10

References dfs(), and list_to_matrix().

Referenced by dfs(), and edges_to_path().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dfs() [2/2]

template<typename AType , typename DType , typename PType , typename CType >
IGL_INLINE void igl::dfs ( const std::vector< std::vector< AType > > &  A,
const size_t  s,
std::vector< DType > &  D,
std::vector< PType > &  P,
std::vector< CType > &  C 
)
37{
38 // number of nodes
39 int N = s+1;
40 for(const auto & Ai : A) for(const auto & a : Ai) N = std::max(N,a+1);
41 std::vector<bool> seen(N,false);
42 P.resize(N,-1);
43 std::function<void(const size_t, const size_t)> dfs_helper;
44 dfs_helper = [&D,&P,&C,&dfs_helper,&seen,&A](const size_t s, const size_t p)
45 {
46 if(seen[s]) return;
47 seen[s] = true;
48 D.push_back(s);
49 P[s] = p;
50 for(const auto n : A[s]) dfs_helper(n,s);
51 C.push_back(s);
52 };
53 dfs_helper(s,-1);
54}

References void().

+ Here is the call graph for this function:

◆ diag() [1/4]

template<typename T , typename DerivedV >
IGL_INLINE void igl::diag ( const Eigen::MatrixBase< DerivedV > &  V,
Eigen::SparseMatrix< T > &  X 
)
89{
90 assert(V.rows() == 1 || V.cols() == 1);
91 // clear and resize output
93 dyn_X.reserve(V.size());
94 // loop over non-zeros
95 for(int i = 0;i<V.size();i++)
96 {
97 dyn_X.coeffRef(i,i) += V[i];
98 }
99 X = Eigen::SparseMatrix<T>(dyn_X);
100}

References Eigen::DynamicSparseMatrix< _Scalar, _Options, _StorageIndex >::coeffRef(), and Eigen::DynamicSparseMatrix< _Scalar, _Options, _StorageIndex >::reserve().

+ Here is the call graph for this function:

◆ diag() [2/4]

template<typename T , typename DerivedV >
IGL_INLINE void igl::diag ( const Eigen::SparseMatrix< T > &  X,
Eigen::MatrixBase< DerivedV > &  V 
)
47{
48 assert(false && "Just call X.diagonal() directly");
49 V = X.diagonal();
51 //int m = X.rows();
52 //int n = X.cols();
53 //V.derived().resize((m>n?n:m),1);
54
56 //for(int k=0; k<X.outerSize(); ++k)
57 //{
58 // // Iterate over inside
59 // for(typename Eigen::SparseMatrix<T>::InnerIterator it (X,k); it; ++it)
60 // {
61 // if(it.col() == it.row())
62 // {
63 // V(it.col()) = it.value();
64 // }
65 // }
66 //}
67}

◆ diag() [3/4]

template<typename T >
IGL_INLINE void igl::diag ( const Eigen::SparseMatrix< T > &  X,
Eigen::SparseVector< T > &  V 
)
20{
21 assert(false && "Just call X.diagonal().sparseView() directly");
22 V = X.diagonal().sparseView();
24 //int m = X.rows();
25 //int n = X.cols();
26 //V = Eigen::SparseVector<T>((m>n?n:m));
27 //V.reserve(V.size());
28
30 //for(int k=0; k<X.outerSize(); ++k)
31 //{
32 // // Iterate over inside
33 // for(typename Eigen::SparseMatrix<T>::InnerIterator it (X,k); it; ++it)
34 // {
35 // if(it.col() == it.row())
36 // {
37 // V.coeffRef(it.col()) += it.value();
38 // }
39 // }
40 //}
41}

Referenced by harmonic().

+ Here is the caller graph for this function:

◆ diag() [4/4]

template<typename T >
IGL_INLINE void igl::diag ( const Eigen::SparseVector< T > &  V,
Eigen::SparseMatrix< T > &  X 
)
73{
74 // clear and resize output
76 dyn_X.reserve(V.size());
77 // loop over non-zeros
78 for(typename Eigen::SparseVector<T>::InnerIterator it(V); it; ++it)
79 {
80 dyn_X.coeffRef(it.index(),it.index()) += it.value();
81 }
82 X = Eigen::SparseMatrix<T>(dyn_X);
83}

References Eigen::DynamicSparseMatrix< _Scalar, _Options, _StorageIndex >::coeffRef(), Eigen::DynamicSparseMatrix< _Scalar, _Options, _StorageIndex >::reserve(), and Eigen::SparseMatrixBase< Derived >::size().

+ Here is the call graph for this function:

◆ dihedral_angles()

template<typename DerivedV , typename DerivedT , typename Derivedtheta , typename Derivedcos_theta >
IGL_INLINE void igl::dihedral_angles ( Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedT > &  T,
Eigen::PlainObjectBase< Derivedtheta > &  theta,
Eigen::PlainObjectBase< Derivedcos_theta > &  cos_theta 
)
21{
22 using namespace Eigen;
23 assert(T.cols() == 4);
25 edge_lengths(V,T,l);
27 face_areas(l,s);
28 return dihedral_angles_intrinsic(l,s,theta,cos_theta);
29}

References Eigen::PlainObjectBase< Derived >::cols(), dihedral_angles_intrinsic(), edge_lengths(), and face_areas().

+ Here is the call graph for this function:

◆ dihedral_angles_intrinsic()

template<typename DerivedL , typename DerivedA , typename Derivedtheta , typename Derivedcos_theta >
IGL_INLINE void igl::dihedral_angles_intrinsic ( Eigen::PlainObjectBase< DerivedL > &  L,
Eigen::PlainObjectBase< DerivedA > &  A,
Eigen::PlainObjectBase< Derivedtheta > &  theta,
Eigen::PlainObjectBase< Derivedcos_theta > &  cos_theta 
)
41{
42 using namespace Eigen;
43 const int m = L.rows();
44 assert(m == A.rows());
45 // Law of cosines
46 // http://math.stackexchange.com/a/49340/35376
48 H_sqr.col(0) = (1./16.) * (4. * L.col(3).array().square() * L.col(0).array().square() -
49 ((L.col(1).array().square() + L.col(4).array().square()) -
50 (L.col(2).array().square() + L.col(5).array().square())).square());
51 H_sqr.col(1) = (1./16.) * (4. * L.col(4).array().square() * L.col(1).array().square() -
52 ((L.col(2).array().square() + L.col(5).array().square()) -
53 (L.col(3).array().square() + L.col(0).array().square())).square());
54 H_sqr.col(2) = (1./16.) * (4. * L.col(5).array().square() * L.col(2).array().square() -
55 ((L.col(3).array().square() + L.col(0).array().square()) -
56 (L.col(4).array().square() + L.col(1).array().square())).square());
57 H_sqr.col(3) = (1./16.) * (4. * L.col(0).array().square() * L.col(3).array().square() -
58 ((L.col(4).array().square() + L.col(1).array().square()) -
59 (L.col(5).array().square() + L.col(2).array().square())).square());
60 H_sqr.col(4) = (1./16.) * (4. * L.col(1).array().square() * L.col(4).array().square() -
61 ((L.col(5).array().square() + L.col(2).array().square()) -
62 (L.col(0).array().square() + L.col(3).array().square())).square());
63 H_sqr.col(5) = (1./16.) * (4. * L.col(2).array().square() * L.col(5).array().square() -
64 ((L.col(0).array().square() + L.col(3).array().square()) -
65 (L.col(1).array().square() + L.col(4).array().square())).square());
66 cos_theta.resize(m,6);
67 cos_theta.col(0) = (H_sqr.col(0).array() -
68 A.col(1).array().square() - A.col(2).array().square()).array() /
69 (-2.*A.col(1).array() * A.col(2).array());
70 cos_theta.col(1) = (H_sqr.col(1).array() -
71 A.col(2).array().square() - A.col(0).array().square()).array() /
72 (-2.*A.col(2).array() * A.col(0).array());
73 cos_theta.col(2) = (H_sqr.col(2).array() -
74 A.col(0).array().square() - A.col(1).array().square()).array() /
75 (-2.*A.col(0).array() * A.col(1).array());
76 cos_theta.col(3) = (H_sqr.col(3).array() -
77 A.col(3).array().square() - A.col(0).array().square()).array() /
78 (-2.*A.col(3).array() * A.col(0).array());
79 cos_theta.col(4) = (H_sqr.col(4).array() -
80 A.col(3).array().square() - A.col(1).array().square()).array() /
81 (-2.*A.col(3).array() * A.col(1).array());
82 cos_theta.col(5) = (H_sqr.col(5).array() -
83 A.col(3).array().square() - A.col(2).array().square()).array() /
84 (-2.*A.col(3).array() * A.col(2).array());
85
86 theta = cos_theta.array().acos();
87
88 cos_theta.resize(m,6);
89
90}

References L, Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::rows().

Referenced by cotmatrix_entries(), and dihedral_angles().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dijkstra_compute_paths()

template<typename IndexType , typename DerivedD , typename DerivedP >
IGL_INLINE int igl::dijkstra_compute_paths ( const IndexType &  source,
const std::set< IndexType > &  targets,
const std::vector< std::vector< IndexType > > &  VV,
Eigen::PlainObjectBase< DerivedD > &  min_distance,
Eigen::PlainObjectBase< DerivedP > &  previous 
)
16{
17 int numV = VV.size();
18 min_distance.setConstant(numV, 1, std::numeric_limits<typename DerivedD::Scalar>::infinity());
19 min_distance[source] = 0;
20 previous.setConstant(numV, 1, -1);
21 std::set<std::pair<typename DerivedD::Scalar, IndexType> > vertex_queue;
22 vertex_queue.insert(std::make_pair(min_distance[source], source));
23
24 while (!vertex_queue.empty())
25 {
26 typename DerivedD::Scalar dist = vertex_queue.begin()->first;
27 IndexType u = vertex_queue.begin()->second;
28 vertex_queue.erase(vertex_queue.begin());
29
30 if (targets.find(u)!= targets.end())
31 return u;
32
33 // Visit each edge exiting u
34 const std::vector<int> &neighbors = VV[u];
35 for (std::vector<int>::const_iterator neighbor_iter = neighbors.begin();
36 neighbor_iter != neighbors.end();
37 neighbor_iter++)
38 {
39 IndexType v = *neighbor_iter;
40 typename DerivedD::Scalar distance_through_u = dist + 1.;
41 if (distance_through_u < min_distance[v]) {
42 vertex_queue.erase(std::make_pair(min_distance[v], v));
43
44 min_distance[v] = distance_through_u;
45 previous[v] = u;
46 vertex_queue.insert(std::make_pair(min_distance[v], v));
47
48 }
49
50 }
51 }
52 //we should never get here
53 return -1;
54}

References Eigen::PlainObjectBase< Derived >::setConstant().

+ Here is the call graph for this function:

◆ dijkstra_get_shortest_path_to()

template<typename IndexType , typename DerivedP >
IGL_INLINE void igl::dijkstra_get_shortest_path_to ( const IndexType &  vertex,
const Eigen::PlainObjectBase< DerivedP > &  previous,
std::vector< IndexType > &  path 
)
60{
61 IndexType source = vertex;
62 path.clear();
63 for ( ; source != -1; source = previous[source])
64 path.push_back(source);
65}

◆ directed_edge_orientations()

template<typename DerivedC , typename DerivedE >
IGL_INLINE void igl::directed_edge_orientations ( const Eigen::PlainObjectBase< DerivedC > &  C,
const Eigen::PlainObjectBase< DerivedE > &  E,
std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > &  Q 
)
16{
17 using namespace Eigen;
18 Q.resize(E.rows());
19 for(int e = 0;e<E.rows();e++)
20 {
21 const auto & b = C.row(E(e,1)) - C.row(E(e,0));
22 Q[e].setFromTwoVectors( RowVector3d(1,0,0),b);
23 }
24}

◆ directed_edge_parents()

template<typename DerivedE , typename DerivedP >
IGL_INLINE void igl::directed_edge_parents ( const Eigen::PlainObjectBase< DerivedE > &  E,
Eigen::PlainObjectBase< DerivedP > &  P 
)
19{
20 using namespace Eigen;
21 using namespace std;
22 VectorXi I = VectorXi::Constant(E.maxCoeff()+1,1,-1);
23 //I(E.col(1)) = 0:E.rows()-1
24 slice_into(colon<int>(0,E.rows()-1),E.col(1).eval(),I);
25 VectorXi roots,_;
26 setdiff(E.col(0).eval(),E.col(1).eval(),roots,_);
27 std::for_each(roots.data(),roots.data()+roots.size(),[&](int r){I(r)=-1;});
28 slice(I,E.col(0).eval(),P);
29}
#define _(msgid)
Definition getopt.c:87
IGL_INLINE void setdiff(const Eigen::DenseBase< DerivedA > &A, const Eigen::DenseBase< DerivedB > &B, Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedIA > &IA)
Definition setdiff.cpp:19

References _, setdiff(), slice(), and slice_into().

+ Here is the call graph for this function:

◆ dirname()

IGL_INLINE std::string igl::dirname ( const std::string &  path)
14{
15 if(path == "")
16 {
17 return std::string("");
18 }
19#if defined (WIN32)
20 char del('\\');
21#else
22 char del('/');
23#endif
24 // http://stackoverflow.com/questions/5077693/dirnamephp-similar-function-in-c
25 std::string::const_reverse_iterator last_slash =
26 std::find(
27 path.rbegin(),
28 path.rend(),del);
29 if( last_slash == path.rend() )
30 {
31 // No slashes found
32 return std::string(".");
33 }else if(1 == (last_slash.base() - path.begin()))
34 {
35 // Slash is first char
36 return std::string(&del);
37 }else if(path.end() == last_slash.base() )
38 {
39 // Slash is last char
40 std::string redo = std::string(path.begin(),path.end()-1);
41 return igl::dirname(redo);
42 }
43 return std::string(path.begin(),last_slash.base()-1);
44}

References dirname().

Referenced by dated_copy(), dirname(), pathinfo(), and igl::copyleft::tetgen::read_into_tetgenio().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dot()

IGL_INLINE double igl::dot ( const double *  a,
const double *  b 
)
14{
15 return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
16}

Referenced by igl::opengl2::RotateWidget::drag(), igl::opengl2::RotateWidget::draw(), orient_outward(), igl::copyleft::cgal::point_segment_squared_distance(), rotation_matrix_from_directions(), trackball(), igl::opengl2::RotateWidget::unproject_onto(), volume(), and volume_single().

+ Here is the caller graph for this function:

◆ dot_row()

template<typename DerivedV >
IGL_INLINE DerivedV igl::dot_row ( const Eigen::PlainObjectBase< DerivedV > &  A,
const Eigen::PlainObjectBase< DerivedV > &  B 
)
15{
16 assert(A.rows() == B.rows());
17 assert(A.cols() == B.cols());
18
19 return (A.array() * B.array()).rowwise().sum();
20}

References Eigen::PlainObjectBase< Derived >::cols(), and Eigen::PlainObjectBase< Derived >::rows().

Referenced by frame_to_cross_field().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ doublearea() [1/4]

template<typename DerivedA , typename DerivedB , typename DerivedC , typename DerivedD >
IGL_INLINE void igl::doublearea ( const Eigen::MatrixBase< DerivedA > &  A,
const Eigen::MatrixBase< DerivedB > &  B,
const Eigen::MatrixBase< DerivedC > &  C,
Eigen::PlainObjectBase< DerivedD > &  D 
)
88{
89 assert((B.cols() == A.cols()) && "dimensions of A and B should match");
90 assert((C.cols() == A.cols()) && "dimensions of A and C should match");
91 assert(A.rows() == B.rows() && "corners should have same length");
92 assert(A.rows() == C.rows() && "corners should have same length");
93 switch(A.cols())
94 {
95 case 2:
96 {
97 // For 2d compute signed area
98 const auto & R = A-C;
99 const auto & S = B-C;
100 D = (R.col(0).array()*S.col(1).array() -
101 R.col(1).array()*S.col(0).array()).template cast<
102 typename DerivedD::Scalar>();
103 break;
104 }
105 default:
106 {
108 uL(A.rows(),3);
109 uL.col(0) = ((B-C).rowwise().norm()).template cast<typename DerivedD::Scalar>();
110 uL.col(1) = ((C-A).rowwise().norm()).template cast<typename DerivedD::Scalar>();
111 uL.col(2) = ((A-B).rowwise().norm()).template cast<typename DerivedD::Scalar>();
112 doublearea(uL,D);
113 }
114 }
115}
EIGEN_DEVICE_FUNC CastXpr< NewType >::Type cast() const
Definition CommonCwiseUnaryOps.h:62

References cast(), and doublearea().

+ Here is the call graph for this function:

◆ doublearea() [2/4]

template<typename Derivedl , typename DeriveddblA >
IGL_INLINE void igl::doublearea ( const Eigen::MatrixBase< Derivedl > &  l,
const typename Derivedl::Scalar  nan_replacement,
Eigen::PlainObjectBase< DeriveddblA > &  dblA 
)
149{
150 using namespace Eigen;
151 using namespace std;
152 typedef typename Derivedl::Index Index;
153 // Only support triangles
154 assert(ul.cols() == 3);
155 // Number of triangles
156 const Index m = ul.rows();
158 MatrixXi _;
159 //
160 // "Miscalculating Area and Angles of a Needle-like Triangle"
161 // https://people.eecs.berkeley.edu/~wkahan/Triangle.pdf
162 igl::sort(ul,2,false,l,_);
163 // semiperimeters
164 //Matrix<typename Derivedl::Scalar,Dynamic,1> s = l.rowwise().sum()*0.5;
165 //assert((Index)s.rows() == m);
166 // resize output
167 dblA.resize(l.rows(),1);
169 m,
170 [&l,&dblA,&nan_replacement](const int i)
171 {
172 // Kahan's Heron's formula
173 typedef typename Derivedl::Scalar Scalar;
174 const Scalar arg =
175 (l(i,0)+(l(i,1)+l(i,2)))*
176 (l(i,2)-(l(i,0)-l(i,1)))*
177 (l(i,2)+(l(i,0)-l(i,1)))*
178 (l(i,0)+(l(i,1)-l(i,2)));
179 dblA(i) = 2.0*0.25*sqrt(arg);
180 // Alec: If the input edge lengths were computed from floating point
181 // vertex positions then there's no guarantee that they fulfill the
182 // triangle inequality (in their floating point approximations). For
183 // nearly degenerate triangles the round-off error during side-length
184 // computation may be larger than (or rather smaller) than the height of
185 // the triangle. In "Lecture Notes on Geometric Robustness" Shewchuck 09,
186 // Section 3.1 http://www.cs.berkeley.edu/~jrs/meshpapers/robnotes.pdf,
187 // he recommends computing the triangle areas for 2D and 3D using 2D
188 // signed areas computed with determinants.
189 assert(
190 (nan_replacement == nan_replacement ||
191 (l(i,2) - (l(i,0)-l(i,1)))>=0)
192 && "Side lengths do not obey the triangle inequality.");
193 if(dblA(i) != dblA(i))
194 {
195 dblA(i) = nan_replacement;
196 }
197 assert(dblA(i) == dblA(i) && "DOUBLEAREA() PRODUCED NaN");
198 },
199 1000l);
200}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const ArgReturnType arg() const
Definition ArrayCwiseUnaryOps.h:57

References _, arg(), parallel_for(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), sort(), and sqrt().

+ Here is the call graph for this function:

◆ doublearea() [3/4]

template<typename Derivedl , typename DeriveddblA >
IGL_INLINE void igl::doublearea ( const Eigen::MatrixBase< Derivedl > &  l,
Eigen::PlainObjectBase< DeriveddblA > &  dblA 
)
138{
139 // Default is to leave NaNs and fire asserts in debug mode
140 return doublearea(
141 ul,std::numeric_limits<typename Derivedl::Scalar>::quiet_NaN(),dblA);
142}

References doublearea().

+ Here is the call graph for this function:

◆ doublearea() [4/4]

template<typename DerivedV , typename DerivedF , typename DeriveddblA >
IGL_INLINE void igl::doublearea ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DeriveddblA > &  dblA 
)
21{
22 // quads are handled by a specialized function
23 if (F.cols() == 4) return doublearea_quad(V,F,dblA);
24
25 const int dim = V.cols();
26 // Only support triangles
27 assert(F.cols() == 3);
28 const size_t m = F.rows();
29 // Compute edge lengths
31
32 // Projected area helper
33 const auto & proj_doublearea =
34 [&V,&F](const int x, const int y, const int f)
35 ->typename DerivedV::Scalar
36 {
37 auto rx = V(F(f,0),x)-V(F(f,2),x);
38 auto sx = V(F(f,1),x)-V(F(f,2),x);
39 auto ry = V(F(f,0),y)-V(F(f,2),y);
40 auto sy = V(F(f,1),y)-V(F(f,2),y);
41 return rx*sy - ry*sx;
42 };
43
44 switch(dim)
45 {
46 case 3:
47 {
48 dblA = DeriveddblA::Zero(m,1);
49 for(size_t f = 0;f<m;f++)
50 {
51 for(int d = 0;d<3;d++)
52 {
53 const auto dblAd = proj_doublearea(d,(d+1)%3,f);
54 dblA(f) += dblAd*dblAd;
55 }
56 }
57 dblA = dblA.array().sqrt().eval();
58 break;
59 }
60 case 2:
61 {
62 dblA.resize(m,1);
63 for(size_t f = 0;f<m;f++)
64 {
65 dblA(f) = proj_doublearea(0,1,f);
66 }
67 break;
68 }
69 default:
70 {
71 edge_lengths(V,F,l);
72 return doublearea(l,0.,dblA);
73 }
74 }
75}
IGL_INLINE void doublearea_quad(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DeriveddblA > &dblA)
Definition doublearea.cpp:203

References doublearea(), doublearea_quad(), edge_lengths(), and Eigen::PlainObjectBase< Derived >::resize().

Referenced by bijective_composite_harmonic_mapping(), igl::copyleft::comiso::PoissonSolver< DerivedV, DerivedF >::BuildLaplacianMatrix(), circumradius(), collapse_small_triangles(), cotmatrix_entries(), crouzeix_raviart_massmatrix(), doublearea(), doublearea(), doublearea(), doublearea_quad(), face_areas(), grad_tet(), hessian(), igl::WindingNumberAABB< Point, DerivedV, DerivedF >::init(), inradius(), massmatrix(), orient_outward(), per_edge_normals(), per_vertex_normals(), pseudonormal_test(), random_points_on_mesh(), igl::embree::reorient_facets_raycast(), and slim_precompute().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ doublearea_quad()

template<typename DerivedV , typename DerivedF , typename DeriveddblA >
IGL_INLINE void igl::doublearea_quad ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DeriveddblA > &  dblA 
)
207{
208 assert(V.cols() == 3); // Only supports points in 3D
209 assert(F.cols() == 4); // Only support quads
210 const size_t m = F.rows();
211
212 // Split the quads into triangles
213 Eigen::MatrixXi Ft(F.rows()*2,3);
214
215 for(size_t i=0; i<m;++i)
216 {
217 Ft.row(i*2 ) << F(i,0), F(i,1), F(i,2);
218 Ft.row(i*2 + 1) << F(i,2), F(i,3), F(i,0);
219 }
220
221 // Compute areas
222 Eigen::VectorXd doublearea_tri;
223 igl::doublearea(V,Ft,doublearea_tri);
224
225 dblA.resize(F.rows(),1);
226 for(unsigned i=0; i<F.rows();++i)
227 {
228 dblA(i) = doublearea_tri(i*2) + doublearea_tri(i*2 + 1);
229 }
230}

References doublearea(), and Eigen::PlainObjectBase< Derived >::resize().

Referenced by doublearea().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ doublearea_single()

template<typename DerivedA , typename DerivedB , typename DerivedC >
IGL_INLINE DerivedA::Scalar igl::doublearea_single ( const Eigen::MatrixBase< DerivedA > &  A,
const Eigen::MatrixBase< DerivedB > &  B,
const Eigen::MatrixBase< DerivedC > &  C 
)
125{
126 assert(A.size() == 2 && "Vertices should be 2D");
127 assert(B.size() == 2 && "Vertices should be 2D");
128 assert(C.size() == 2 && "Vertices should be 2D");
129 auto r = A-C;
130 auto s = B-C;
131 return r(0)*s(1) - r(1)*s(0);
132}

Referenced by igl::AABB< DerivedV, DIM >::find().

+ Here is the caller graph for this function:

◆ dqs()

template<typename DerivedV , typename DerivedW , typename Q , typename QAlloc , typename T , typename DerivedU >
IGL_INLINE void igl::dqs ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedW > &  W,
const std::vector< Q, QAlloc > &  vQ,
const std::vector< T > &  vT,
Eigen::PlainObjectBase< DerivedU > &  U 
)
23{
24 using namespace std;
25 assert(V.rows() <= W.rows());
26 assert(W.cols() == (int)vQ.size());
27 assert(W.cols() == (int)vT.size());
28 // resize output
29 U.resizeLike(V);
30
31 // Convert quats + trans into dual parts
32 vector<Q> vD(vQ.size());
33 for(int c = 0;c<W.cols();c++)
34 {
35 const Q & q = vQ[c];
36 vD[c].w() = -0.5*( vT[c](0)*q.x() + vT[c](1)*q.y() + vT[c](2)*q.z());
37 vD[c].x() = 0.5*( vT[c](0)*q.w() + vT[c](1)*q.z() - vT[c](2)*q.y());
38 vD[c].y() = 0.5*(-vT[c](0)*q.z() + vT[c](1)*q.w() + vT[c](2)*q.x());
39 vD[c].z() = 0.5*( vT[c](0)*q.y() - vT[c](1)*q.x() + vT[c](2)*q.w());
40 }
41
42 // Loop over vertices
43 const int nv = V.rows();
44#pragma omp parallel for if (nv>10000)
45 for(int i = 0;i<nv;i++)
46 {
47 Q b0(0,0,0,0);
48 Q be(0,0,0,0);
49 // Loop over handles
50 for(int c = 0;c<W.cols();c++)
51 {
52 b0.coeffs() += W(i,c) * vQ[c].coeffs();
53 be.coeffs() += W(i,c) * vD[c].coeffs();
54 }
55 Q ce = be;
56 ce.coeffs() /= b0.norm();
57 Q c0 = b0;
58 c0.coeffs() /= b0.norm();
59 // See algorithm 1 in "Geometric skinning with approximate dual quaternion
60 // blending" by Kavan et al
61 T v = V.row(i);
62 T d0 = c0.vec();
63 T de = ce.vec();
64 typename Q::Scalar a0 = c0.w();
65 typename Q::Scalar ae = ce.w();
66 U.row(i) = v + 2*d0.cross(d0.cross(v) + a0*v) + 2*(a0*de - ae*d0 + d0.cross(de));
67 }
68
69}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resizeLike(const EigenBase< OtherDerived > &_other)
Definition PlainObjectBase.h:362

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::resizeLike(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ ears()

template<typename DerivedF , typename Derivedear , typename Derivedear_opp >
IGL_INLINE void igl::ears ( const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< Derivedear > &  ear,
Eigen::PlainObjectBase< Derivedear_opp > &  ear_opp 
)
16{
17 assert(F.cols() == 3 && "F should contain triangles");
19 {
21 on_boundary(F,I,B);
22 }
23 find(B.rowwise().count() == 2,ear);
25 slice(B,ear,1,Bear);
27 mat_min(Bear,2,M,ear_opp);
28}

References find(), mat_min(), on_boundary(), and slice().

Referenced by straighten_seams().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ edge_collapse_is_valid()

IGL_INLINE bool igl::edge_collapse_is_valid ( const int  e,
const Eigen::MatrixXi &  F,
const Eigen::MatrixXi &  E,
const Eigen::VectorXi &  EMAP,
const Eigen::MatrixXi &  EF,
const Eigen::MatrixXi &  EI 
)
23{
24 using namespace Eigen;
25 using namespace std;
26 // For consistency with collapse_edge.cpp, let's determine edge flipness
27 // (though not needed to check validity)
28 const int eflip = E(e,0)>E(e,1);
29 // source and destination
30 const int s = eflip?E(e,1):E(e,0);
31 const int d = eflip?E(e,0):E(e,1);
32
34 {
35 return false;
36 }
37 // check if edge collapse is valid: intersection of vertex neighbors of s and
38 // d should be exactly 2+(s,d) = 4
39 // http://stackoverflow.com/a/27049418/148668
40 {
41 // all vertex neighbors around edge, including the two vertices of the edge
42 const auto neighbors = [](
43 const int e,
44 const bool ccw,
45 const Eigen::MatrixXi & F,
46 const Eigen::MatrixXi & E,
47 const Eigen::VectorXi & EMAP,
48 const Eigen::MatrixXi & EF,
49 const Eigen::MatrixXi & EI)
50 {
51 vector<int> N,uN;
52 vector<int> V2Fe = circulation(e, ccw,F,E,EMAP,EF,EI);
53 for(auto f : V2Fe)
54 {
55 N.push_back(F(f,0));
56 N.push_back(F(f,1));
57 N.push_back(F(f,2));
58 }
59 vector<size_t> _1,_2;
60 igl::unique(N,uN,_1,_2);
61 VectorXi uNm;
62 list_to_matrix(uN,uNm);
63 return uNm;
64 };
65 VectorXi Ns = neighbors(e, eflip,F,E,EMAP,EF,EI);
66 VectorXi Nd = neighbors(e,!eflip,F,E,EMAP,EF,EI);
67 VectorXi Nint = igl::intersect(Ns,Nd);
68 if(Nint.size() != 4)
69 {
70 return false;
71 }
72 if(Ns.size() == 4 && Nd.size() == 4)
73 {
74 VectorXi NsNd(8);
75 NsNd<<Ns,Nd;
76 VectorXi Nun,_1,_2;
77 igl::unique(NsNd,Nun,_1,_2);
78 // single tet, don't collapse
79 if(Nun.size() == 4)
80 {
81 return false;
82 }
83 }
84 }
85 return true;
86}
IGL_INLINE void intersect(const M &A, const M &B, M &C)
Definition intersect.cpp:10

References circulation(), IGL_COLLAPSE_EDGE_NULL, intersect(), list_to_matrix(), and unique().

Referenced by collapse_edge().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ edge_flaps() [1/2]

IGL_INLINE void igl::edge_flaps ( const Eigen::MatrixXi &  F,
const Eigen::MatrixXi &  E,
const Eigen::VectorXi &  EMAP,
Eigen::MatrixXi &  EF,
Eigen::MatrixXi &  EI 
)
19{
20 // Initialize to boundary value
21 EF.setConstant(E.rows(),2,-1);
22 EI.setConstant(E.rows(),2,-1);
23 // loop over all faces
24 for(int f = 0;f<F.rows();f++)
25 {
26 // loop over edges across from corners
27 for(int v = 0;v<3;v++)
28 {
29 // get edge id
30 const int e = EMAP(v*F.rows()+f);
31 // See if this is left or right flap w.r.t. edge orientation
32 if( F(f,(v+1)%3) == E(e,0) && F(f,(v+2)%3) == E(e,1))
33 {
34 EF(e,0) = f;
35 EI(e,0) = v;
36 }else
37 {
38 assert(F(f,(v+1)%3) == E(e,1) && F(f,(v+2)%3) == E(e,0));
39 EF(e,1) = f;
40 EI(e,1) = v;
41 }
42 }
43 }
44}

Referenced by decimate(), edge_flaps(), and qslim().

+ Here is the caller graph for this function:

◆ edge_flaps() [2/2]

IGL_INLINE void igl::edge_flaps ( const Eigen::MatrixXi &  F,
Eigen::MatrixXi &  E,
Eigen::VectorXi &  EMAP,
Eigen::MatrixXi &  EF,
Eigen::MatrixXi &  EI 
)
52{
53 Eigen::MatrixXi allE;
54 std::vector<std::vector<int> > uE2E;
55 igl::unique_edge_map(F,allE,E,EMAP,uE2E);
56 // Const-ify to call overload
57 const auto & cE = E;
58 const auto & cEMAP = EMAP;
59 return edge_flaps(F,cE,cEMAP,EF,EI);
60}

References edge_flaps(), and unique_edge_map().

+ Here is the call graph for this function:

◆ edge_lengths()

template<typename DerivedV , typename DerivedF , typename DerivedL >
IGL_INLINE void igl::edge_lengths ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedL > &  L 
)
16 {
18 L=L.array().sqrt().eval();
19 }

References L, and squared_edge_lengths().

Referenced by circumradius(), collapse_small_triangles(), cotmatrix_entries(), dihedral_angles(), doublearea(), face_areas(), inradius(), and project_isometrically_to_plane().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ edge_topology()

template<typename DerivedV , typename DerivedF >
IGL_INLINE void igl::edge_topology ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::MatrixXi &  EV,
Eigen::MatrixXi &  FE,
Eigen::MatrixXi &  EF 
)
19{
20 // Only needs to be edge-manifold
21 if (V.rows() ==0 || F.rows()==0)
22 {
23 EV = Eigen::MatrixXi::Constant(0,2,-1);
24 FE = Eigen::MatrixXi::Constant(0,3,-1);
25 EF = Eigen::MatrixXi::Constant(0,2,-1);
26 return;
27 }
28 assert(igl::is_edge_manifold(F));
29 std::vector<std::vector<int> > ETT;
30 for(int f=0;f<F.rows();++f)
31 for (int i=0;i<3;++i)
32 {
33 // v1 v2 f vi
34 int v1 = F(f,i);
35 int v2 = F(f,(i+1)%3);
36 if (v1 > v2) std::swap(v1,v2);
37 std::vector<int> r(4);
38 r[0] = v1; r[1] = v2;
39 r[2] = f; r[3] = i;
40 ETT.push_back(r);
41 }
42 std::sort(ETT.begin(),ETT.end());
43
44 // count the number of edges (assume manifoldness)
45 int En = 1; // the last is always counted
46 for(int i=0;i<int(ETT.size())-1;++i)
47 if (!((ETT[i][0] == ETT[i+1][0]) && (ETT[i][1] == ETT[i+1][1])))
48 ++En;
49
50 EV = Eigen::MatrixXi::Constant((int)(En),2,-1);
51 FE = Eigen::MatrixXi::Constant((int)(F.rows()),3,-1);
52 EF = Eigen::MatrixXi::Constant((int)(En),2,-1);
53 En = 0;
54
55 for(unsigned i=0;i<ETT.size();++i)
56 {
57 if (i == ETT.size()-1 ||
58 !((ETT[i][0] == ETT[i+1][0]) && (ETT[i][1] == ETT[i+1][1]))
59 )
60 {
61 // Border edge
62 std::vector<int>& r1 = ETT[i];
63 EV(En,0) = r1[0];
64 EV(En,1) = r1[1];
65 EF(En,0) = r1[2];
66 FE(r1[2],r1[3]) = En;
67 }
68 else
69 {
70 std::vector<int>& r1 = ETT[i];
71 std::vector<int>& r2 = ETT[i+1];
72 EV(En,0) = r1[0];
73 EV(En,1) = r1[1];
74 EF(En,0) = r1[2];
75 EF(En,1) = r2[2];
76 FE(r1[2],r1[3]) = En;
77 FE(r2[2],r2[3]) = En;
78 ++i; // skip the next one
79 }
80 ++En;
81 }
82
83 // Sort the relation EF, accordingly to EV
84 // the first one is the face on the left of the edge
85 for(unsigned i=0; i<EF.rows(); ++i)
86 {
87 int fid = EF(i,0);
88 bool flip = true;
89 // search for edge EV.row(i)
90 for (unsigned j=0; j<3; ++j)
91 {
92 if ((F(fid,j) == EV(i,0)) && (F(fid,(j+1)%3) == EV(i,1)))
93 flip = false;
94 }
95
96 if (flip)
97 {
98 int tmp = EF(i,0);
99 EF(i,0) = EF(i,1);
100 EF(i,1) = tmp;
101 }
102 }
103
104}

References is_edge_manifold(), and Eigen::PlainObjectBase< Derived >::rows().

Referenced by igl::copyleft::comiso::FrameInterpolator::FrameInterpolator(), igl::MeshCutter< DerivedV, DerivedF, DerivedM, DerivedO >::MeshCutter(), igl::copyleft::comiso::NRosyField::NRosyField(), and euler_characteristic().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ edges()

template<typename DerivedF , typename DerivedE >
IGL_INLINE void igl::edges ( const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedE > &  E 
)
16{
17 // build adjacency matrix
18 typedef typename DerivedF::Scalar Index;
21 // Number of non zeros should be twice number of edges
22 assert(A.nonZeros()%2 == 0);
23 // Resize to fit edges
24 E.resize(A.nonZeros()/2,2);
25 int i = 0;
26 // Iterate over outside
27 for(int k=0; k<A.outerSize(); ++k)
28 {
29 // Iterate over inside
30 for(typename Eigen::SparseMatrix<Index>::InnerIterator it (A,k); it; ++it)
31 {
32 // only add edge in one direction
33 if(it.row()<it.col())
34 {
35 E(i,0) = it.row();
36 E(i,1) = it.col();
37 i++;
38 }
39 }
40 }
41}

References adjacency_matrix(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::nonZeros(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::outerSize().

Referenced by arap_linear_block_elements(), arap_linear_block_spokes(), arap_linear_block_spokes_and_rims(), cotmatrix(), euler_characteristic(), and igl::copyleft::cgal::minkowski_sum().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ edges_to_path()

template<typename DerivedE , typename DerivedI , typename DerivedJ , typename DerivedK >
IGL_INLINE void igl::edges_to_path ( const Eigen::MatrixBase< DerivedE > &  E,
Eigen::PlainObjectBase< DerivedI > &  I,
Eigen::PlainObjectBase< DerivedJ > &  J,
Eigen::PlainObjectBase< DerivedK > &  K 
)
19{
20 assert(OE.rows()>=1);
21 if(OE.rows() == 1)
22 {
23 I.resize(2);
24 I(0) = OE(0);
25 I(1) = OE(1);
26 J.resize(1);
27 J(0) = 0;
28 K.resize(1);
29 K(0) = 0;
30 }
31
32 // Compute on reduced graph
33 DerivedI U;
34 Eigen::VectorXi vE;
35 {
36 Eigen::VectorXi IA;
37 unique(OE,U,IA,vE);
38 }
39
40 Eigen::VectorXi V = Eigen::VectorXi::Zero(vE.maxCoeff()+1);
41 for(int e = 0;e<vE.size();e++)
42 {
43 V(vE(e))++;
44 assert(V(vE(e))<=2);
45 }
46 // Try to find a vertex with valence = 1
47 int c = 2;
48 int s = vE(0);
49 for(int v = 0;v<V.size();v++)
50 {
51 if(V(v) == 1)
52 {
53 c = V(v);
54 s = v;
55 break;
56 }
57 }
58 assert(V(s) == c);
59 assert(c == 2 || c == 1);
60
61 // reshape E to be #E by 2
62 DerivedE E = Eigen::Map<DerivedE>(vE.data(),OE.rows(),OE.cols()).eval();
63 {
64 std::vector<std::vector<int> > A;
66 Eigen::VectorXi P,C;
67 dfs(A,s,I,P,C);
68 }
69 if(c == 2)
70 {
71 I.conservativeResize(I.size()+1);
72 I(I.size()-1) = I(0);
73 }
74
75 DerivedE sE;
77 {
78 Eigen::MatrixXi _;
79 sort(E,2,true,sE,_);
81 EI.col(0) = I.head(I.size()-1);
82 EI.col(1) = I.tail(I.size()-1);
83 sort(EI,2,true,sEI,_);
84 }
85 {
87 ismember_rows(sEI,sE,F,J);
88 }
89 K.resize(I.size()-1);
90 for(int k = 0;k<K.size();k++)
91 {
92 K(k) = (E(J(k),0) != I(k) ? 1 : 0);
93 }
94
95 // Map vertex indices onto original graph
96 slice(U,DerivedI(I),1,I);
97}
A matrix or vector expression mapping an existing array of data.
Definition Map.h:96
IGL_INLINE void adjacency_list(const Eigen::PlainObjectBase< Index > &F, std::vector< std::vector< IndexVector > > &A, bool sorted=false)
Definition adjacency_list.cpp:14
IGL_INLINE void ismember_rows(const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &B, Eigen::PlainObjectBase< DerivedIA > &IA, Eigen::PlainObjectBase< DerivedLOCB > &LOCB)
Definition ismember.cpp:101

References _, adjacency_list(), Eigen::PlainObjectBase< Derived >::conservativeResize(), dfs(), ismember_rows(), Eigen::PlainObjectBase< Derived >::resize(), slice(), sort(), and unique().

Referenced by straighten_seams().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ eigs()

template<typename Atype , typename Btype , typename DerivedU , typename DerivedS >
IGL_INLINE bool igl::eigs ( const Eigen::SparseMatrix< Atype > &  A,
const Eigen::SparseMatrix< Btype > &  B,
const size_t  k,
const EigsType  type,
Eigen::PlainObjectBase< DerivedU > &  sU,
Eigen::PlainObjectBase< DerivedS > &  sS 
)
28{
29 using namespace Eigen;
30 using namespace std;
31 const size_t n = A.rows();
32 assert(A.cols() == n && "A should be square.");
33 assert(iB.rows() == n && "B should be match A's dims.");
34 assert(iB.cols() == n && "B should be square.");
35 assert(type == EIGS_TYPE_SM && "Only low frequencies are supported");
36 DerivedU U(n,k);
37 DerivedS S(k,1);
38 typedef Atype Scalar;
40 // Rescale B for better numerics
41 const Scalar rescale = std::abs(iB.diagonal().maxCoeff());
42 const Eigen::SparseMatrix<Btype> B = iB/rescale;
43
44 Scalar tol = 1e-4;
45 Scalar conv = 1e-14;
46 int max_iter = 100;
47 int i = 0;
48 //std::cout<<"start"<<std::endl;
49 while(true)
50 {
51 //std::cout<<i<<std::endl;
52 // Random initial guess
53 VectorXS y = VectorXS::Random(n,1);
54 Scalar eff_sigma = 0;
55 if(i>0)
56 {
57 eff_sigma = 1e-8+std::abs(S(i-1));
58 }
59 // whether to use rayleigh quotient method
60 bool ray = false;
61 Scalar err = std::numeric_limits<Scalar>::infinity();
62 int iter;
63 Scalar sigma = std::numeric_limits<Scalar>::infinity();
64 VectorXS x;
65 for(iter = 0;iter<max_iter;iter++)
66 {
67 if(i>0 && !ray)
68 {
69 // project-out existing modes
70 for(int j = 0;j<i;j++)
71 {
72 const VectorXS u = U.col(j);
73 y = (y - u*u.dot(B*y)/u.dot(B * u)).eval();
74 }
75 }
76 // normalize
77 x = y/sqrt(y.dot(B*y));
78
79 // current guess at eigen value
80 sigma = x.dot(A*x)/x.dot(B*x);
81 //x *= sigma>0?1.:-1.;
82
83 Scalar err_prev = err;
84 err = (A*x-sigma*B*x).array().abs().maxCoeff();
85 if(err<conv)
86 {
87 break;
88 }
89 if(ray || err<tol)
90 {
91 eff_sigma = sigma;
92 ray = true;
93 }
94
95 Scalar tikhonov = std::abs(eff_sigma)<1e-12?1e-10:0;
96 switch(type)
97 {
98 default:
99 assert(false && "Not supported");
100 break;
101 case EIGS_TYPE_SM:
102 {
104 const SparseMatrix<Scalar> C = A-eff_sigma*B+tikhonov*B;
105 //mw.save(C,"C");
106 //mw.save(eff_sigma,"eff_sigma");
107 //mw.save(tikhonov,"tikhonov");
108 solver.compute(C);
109 switch(solver.info())
110 {
111 case Eigen::Success:
112 break;
114 cerr<<"Error: Numerical issue."<<endl;
115 return false;
116 default:
117 cerr<<"Error: Other."<<endl;
118 return false;
119 }
120 const VectorXS rhs = B*x;
121 y = solver.solve(rhs);
122 //mw.save(rhs,"rhs");
123 //mw.save(y,"y");
124 //mw.save(x,"x");
125 //mw.write("eigs.mat");
126 //if(i == 1)
127 //return false;
128 break;
129 }
130 }
131 }
132 if(iter == max_iter)
133 {
134 cerr<<"Failed to converge."<<endl;
135 return false;
136 }
137 if(
138 i==0 ||
139 (S.head(i).array()-sigma).abs().maxCoeff()>1e-14 ||
140 ((U.leftCols(i).transpose()*B*x).array().abs()<=1e-7).all()
141 )
142 {
143 //cout<<"Found "<<i<<"th mode"<<endl;
144 U.col(i) = x;
145 S(i) = sigma;
146 i++;
147 if(i == k)
148 {
149 break;
150 }
151 }else
152 {
153 //std::cout<<"i: "<<i<<std::endl;
154 //std::cout<<" "<<S.head(i).transpose()<<" << "<<sigma<<std::endl;
155 //std::cout<<" "<<(S.head(i).array()-sigma).abs().maxCoeff()<<std::endl;
156 //std::cout<<" "<<(U.leftCols(i).transpose()*B*x).array().abs().transpose()<<std::endl;
157 // restart with new random guess.
158 cout<<"igl::eigs RESTART"<<endl;
159 }
160 }
161 // finally sort
162 VectorXi I;
163 igl::sort(S,1,false,sS,I);
164 igl::slice(U,I,2,sU);
165 sS /= rescale;
166 sU /= sqrt(rescale);
167 return true;
168}
ComputationInfo info() const
Reports whether previous computation was successful.
Definition SimplicialCholesky.h:107
A direct sparse LDLT Cholesky factorizations without square root.
Definition SimplicialCholesky.h:422
SimplicialLDLT & compute(const MatrixType &matrix)
Definition SimplicialCholesky.h:461
const Solve< Derived, Rhs > solve(const MatrixBase< Rhs > &b) const
Definition SparseSolverBase.h:88
@ NumericalIssue
Definition Constants.h:434
@ Success
Definition Constants.h:432
const Scalar & y
Definition MathFunctions.h:552
TCoord< P > x(const P &p)
Definition geometry_traits.hpp:297

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), Eigen::SimplicialLDLT< _MatrixType, _UpLo, _Ordering >::compute(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::diagonal(), EIGS_TYPE_SM, Eigen::SimplicialCholeskyBase< Derived >::info(), Eigen::NumericalIssue, Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows(), slice(), Eigen::SparseSolverBase< Derived >::solve(), sort(), sqrt(), and Eigen::Success.

+ Here is the call graph for this function:

◆ EPS()

template<typename S_type >
IGL_INLINE S_type igl::EPS ( )

Referenced by mvc(), and igl::copyleft::cgal::order_facets_around_edges().

+ Here is the caller graph for this function:

◆ EPS< double >()

template<>
IGL_INLINE double igl::EPS< double > ( )

◆ EPS< float >()

template<>
IGL_INLINE float igl::EPS< float > ( )

◆ EPS_SQ()

template<typename S_type >
IGL_INLINE S_type igl::EPS_SQ ( )

◆ EPS_SQ< double >()

template<>
IGL_INLINE double igl::EPS_SQ< double > ( )

◆ EPS_SQ< float >()

template<>
IGL_INLINE float igl::EPS_SQ< float > ( )

◆ euler_characteristic() [1/2]

template<typename DerivedF >
IGL_INLINE int igl::euler_characteristic ( const Eigen::MatrixBase< DerivedF > &  F)
33{
34 const int nf = F.rows();
35 const int nv = F.maxCoeff()+1;
37 edges(F,E);
38 const int ne = E.rows();
39 return nv - ne + nf;
40}

References edges().

+ Here is the call graph for this function:

◆ euler_characteristic() [2/2]

template<typename Scalar , typename Index >
IGL_INLINE int igl::euler_characteristic ( const Eigen::PlainObjectBase< Scalar > &  V,
const Eigen::PlainObjectBase< Index > &  F 
)
17{
18
19 int euler_v = V.rows();
20 Eigen::MatrixXi EV, FE, EF;
21 igl::edge_topology(V, F, EV, FE, EF);
22 int euler_e = EV.rows();
23 int euler_f = F.rows();
24
25 int euler_char = euler_v - euler_e + euler_f;
26 return euler_char;
27
28}
IGL_INLINE void edge_topology(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::MatrixXi &EV, Eigen::MatrixXi &FE, Eigen::MatrixXi &EF)
Definition edge_topology.cpp:13

References edge_topology(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ exact_geodesic()

template<typename DerivedV , typename DerivedF , typename DerivedVS , typename DerivedFS , typename DerivedVT , typename DerivedFT , typename DerivedD >
IGL_INLINE void igl::exact_geodesic ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< DerivedVS > &  VS,
const Eigen::MatrixBase< DerivedFS > &  FS,
const Eigen::MatrixBase< DerivedVT > &  VT,
const Eigen::MatrixBase< DerivedFT > &  FT,
Eigen::PlainObjectBase< DerivedD > &  D 
)
3174{
3175 assert(V.cols() == 3 && F.cols() == 3 && "Only support 3D triangle mesh");
3176 assert(VS.cols() ==1 && FS.cols() == 1 && VT.cols() == 1 && FT.cols() ==1 && "Only support one dimensional inputs");
3177 std::vector<typename DerivedV::Scalar> points(V.rows() * V.cols());
3178 std::vector<typename DerivedF::Scalar> faces(F.rows() * F.cols());
3179 for (int i = 0; i < points.size(); i++)
3180 {
3181 points[i] = V(i / 3, i % 3);
3182 }
3183 for (int i = 0; i < faces.size(); i++)
3184 {
3185 faces[i] = F(i / 3, i % 3);
3186 }
3187
3189 mesh.initialize_mesh_data(points, faces);
3190 igl::geodesic::GeodesicAlgorithmExact exact_algorithm(&mesh);
3191
3192 std::vector<igl::geodesic::SurfacePoint> source(VS.rows() + FS.rows());
3193 std::vector<igl::geodesic::SurfacePoint> target(VT.rows() + FT.rows());
3194 for (int i = 0; i < VS.rows(); i++)
3195 {
3196 source[i] = (igl::geodesic::SurfacePoint(&mesh.vertices()[VS(i)]));
3197 }
3198 for (int i = 0; i < FS.rows(); i++)
3199 {
3200 source[i] = (igl::geodesic::SurfacePoint(&mesh.faces()[FS(i)]));
3201 }
3202
3203 for (int i = 0; i < VT.rows(); i++)
3204 {
3205 target[i] = (igl::geodesic::SurfacePoint(&mesh.vertices()[VT(i)]));
3206 }
3207 for (int i = 0; i < FT.rows(); i++)
3208 {
3209 target[i] = (igl::geodesic::SurfacePoint(&mesh.faces()[FT(i)]));
3210 }
3211
3212 exact_algorithm.propagate(source);
3213 std::vector<igl::geodesic::SurfacePoint> path;
3214 D.resize(target.size(), 1);
3215 for (int i = 0; i < target.size(); i++)
3216 {
3217 exact_algorithm.trace_back(target[i], path);
3218 D(i) = igl::geodesic::length(path);
3219 }
3220}
Definition exact_geodesic.cpp:1793
Definition exact_geodesic.cpp:688
std::vector< Vertex > & vertices()
Definition exact_geodesic.cpp:704
std::vector< Face > & faces()
Definition exact_geodesic.cpp:706
void initialize_mesh_data(unsigned num_vertices, Points &p, unsigned num_faces, Faces &tri)
Definition exact_geodesic.cpp:787
Definition exact_geodesic.cpp:550
double length(std::vector< SurfacePoint > &path)
Definition exact_geodesic.cpp:1682

References igl::geodesic::Mesh::faces(), igl::geodesic::Mesh::initialize_mesh_data(), igl::geodesic::length(), igl::geodesic::GeodesicAlgorithmExact::propagate(), Eigen::PlainObjectBase< Derived >::resize(), igl::geodesic::GeodesicAlgorithmExact::trace_back(), and igl::geodesic::Mesh::vertices().

+ Here is the call graph for this function:

◆ example_fun()

template<typename Printable >
IGL_INLINE bool igl::example_fun ( const Printable &  input)
13{
14 using namespace std;
15 cout<<"example_fun: "<<input<<endl;
16 return true;
17}
static int input(void)

References input().

+ Here is the call graph for this function:

◆ exterior_edges() [1/2]

IGL_INLINE Eigen::MatrixXi igl::exterior_edges ( const Eigen::MatrixXi &  F)
101{
102 using namespace Eigen;
103 MatrixXi E;
104 exterior_edges(F,E);
105 return E;
106}
IGL_INLINE void exterior_edges(const Eigen::MatrixXi &F, Eigen::MatrixXi &E)
Definition exterior_edges.cpp:44

References exterior_edges().

+ Here is the call graph for this function:

◆ exterior_edges() [2/2]

IGL_INLINE void igl::exterior_edges ( const Eigen::MatrixXi &  F,
Eigen::MatrixXi &  E 
)
47{
48 using namespace Eigen;
49 using namespace std;
50 assert(F.cols() == 3);
51 const size_t m = F.rows();
52 MatrixXi all_E,sall_E,sort_order;
53 // Sort each edge by index
54 oriented_facets(F,all_E);
55 sort(all_E,2,true,sall_E,sort_order);
56 // Find unique edges
57 MatrixXi uE;
58 VectorXi IA,EMAP;
59 unique_rows(sall_E,uE,IA,EMAP);
60 VectorXi counts = VectorXi::Zero(uE.rows());
61 for(size_t a = 0;a<3*m;a++)
62 {
63 counts(EMAP(a)) += (sort_order(a)==0?1:-1);
64 }
65
66 E.resize(all_E.rows(),2);
67 {
68 int e = 0;
69 const size_t nue = uE.rows();
70 // Append each unique edge with a non-zero amount of signed occurrences
71 for(size_t ue = 0; ue<nue; ue++)
72 {
73 const int count = counts(ue);
74 size_t i,j;
75 if(count == 0)
76 {
77 continue;
78 }else if(count < 0)
79 {
80 i = uE(ue,1);
81 j = uE(ue,0);
82 }else if(count > 0)
83 {
84 i = uE(ue,0);
85 j = uE(ue,1);
86 }
87 // Append edge for every repeated entry
88 const int abs_count = abs(count);
89 for(int k = 0;k<abs_count;k++)
90 {
91 E(e,0) = i;
92 E(e,1) = j;
93 e++;
94 }
95 }
96 E.conservativeResize(e,2);
97 }
98}
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half abs(const half &a)
Definition Half.h:445
IGL_INLINE void unique_rows(const Eigen::DenseBase< DerivedA > &A, Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedIA > &IA, Eigen::PlainObjectBase< DerivedIC > &IC)
Definition unique_rows.cpp:17

References count(), oriented_facets(), sort(), and unique_rows().

Referenced by exterior_edges(), and igl::WindingNumberTree< Point, DerivedV, DerivedF >::set_mesh().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ extract_manifold_patches() [1/2]

template<typename DerivedF , typename DerivedEMAP , typename uE2EType , typename DerivedP >
IGL_INLINE size_t igl::extract_manifold_patches ( const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedEMAP > &  EMAP,
const std::vector< std::vector< uE2EType > > &  uE2E,
Eigen::PlainObjectBase< DerivedP > &  P 
)
24{
25 assert(F.cols() == 3);
26 const size_t num_faces = F.rows();
27
28 auto edge_index_to_face_index = [&](size_t ei) { return ei % num_faces; };
29 auto face_and_corner_index_to_edge_index = [&](size_t fi, size_t ci) {
30 return ci*num_faces + fi;
31 };
32 auto is_manifold_edge = [&](size_t fi, size_t ci) -> bool {
33 const size_t ei = face_and_corner_index_to_edge_index(fi, ci);
34 return uE2E[EMAP(ei, 0)].size() == 2;
35 };
36 auto get_adj_face_index = [&](size_t fi, size_t ci) -> size_t {
37 const size_t ei = face_and_corner_index_to_edge_index(fi, ci);
38 const auto& adj_faces = uE2E[EMAP(ei, 0)];
39 assert(adj_faces.size() == 2);
40 if (adj_faces[0] == ei) {
41 return edge_index_to_face_index(adj_faces[1]);
42 } else {
43 assert(adj_faces[1] == ei);
44 return edge_index_to_face_index(adj_faces[0]);
45 }
46 };
47
48 typedef typename DerivedP::Scalar Scalar;
49 const Scalar INVALID = std::numeric_limits<Scalar>::max();
50 P.resize(num_faces,1);
51 P.setConstant(INVALID);
52 size_t num_patches = 0;
53 for (size_t i=0; i<num_faces; i++) {
54 if (P(i,0) != INVALID) continue;
55
56 std::queue<size_t> Q;
57 Q.push(i);
58 P(i,0) = num_patches;
59 while (!Q.empty()) {
60 const size_t fid = Q.front();
61 Q.pop();
62 for (size_t j=0; j<3; j++) {
63 if (is_manifold_edge(fid, j)) {
64 const size_t adj_fid = get_adj_face_index(fid, j);
65 if (P(adj_fid,0) == INVALID) {
66 Q.push(adj_fid);
67 P(adj_fid,0) = num_patches;
68 }
69 }
70 }
71 }
72 num_patches++;
73 }
74 assert((P.array() != INVALID).all());
75
76 return num_patches;
77}

References Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::setConstant().

Referenced by igl::copyleft::cgal::extract_cells(), extract_manifold_patches(), igl::copyleft::cgal::mesh_boolean(), igl::copyleft::cgal::propagate_winding_numbers(), and igl::copyleft::cgal::trim_with_solid().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ extract_manifold_patches() [2/2]

template<typename DerivedF , typename DerivedP >
IGL_INLINE size_t igl::extract_manifold_patches ( const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedP > &  P 
)
85{
86 Eigen::MatrixXi E, uE;
87 Eigen::VectorXi EMAP;
88 std::vector<std::vector<size_t> > uE2E;
89 igl::unique_edge_map(F, E, uE, EMAP, uE2E);
90 return igl::extract_manifold_patches(F, EMAP, uE2E, P);
91}
IGL_INLINE size_t extract_manifold_patches(const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedEMAP > &EMAP, const std::vector< std::vector< uE2EType > > &uE2E, Eigen::PlainObjectBase< DerivedP > &P)
Definition extract_manifold_patches.cpp:19

References extract_manifold_patches(), and unique_edge_map().

+ Here is the call graph for this function:

◆ extract_non_manifold_edge_curves()

template<typename DerivedF , typename DerivedEMAP , typename uE2EType >
IGL_INLINE void igl::extract_non_manifold_edge_curves ( const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedEMAP > &  EMAP,
const std::vector< std::vector< uE2EType > > &  uE2E,
std::vector< std::vector< size_t > > &  curves 
)
23 {
24 const size_t num_faces = F.rows();
25 assert(F.cols() == 3);
26 //typedef std::pair<size_t, size_t> Edge;
27 auto edge_index_to_face_index = [&](size_t ei) { return ei % num_faces; };
28 auto edge_index_to_corner_index = [&](size_t ei) { return ei / num_faces; };
29 auto get_edge_end_points = [&](size_t ei, size_t& s, size_t& d) {
30 const size_t fi = edge_index_to_face_index(ei);
31 const size_t ci = edge_index_to_corner_index(ei);
32 s = F(fi, (ci+1)%3);
33 d = F(fi, (ci+2)%3);
34 };
35
36 curves.clear();
37 const size_t num_unique_edges = uE2E.size();
38 std::unordered_multimap<size_t, size_t> vertex_edge_adjacency;
39 std::vector<size_t> non_manifold_edges;
40 for (size_t i=0; i<num_unique_edges; i++) {
41 const auto& adj_edges = uE2E[i];
42 if (adj_edges.size() == 2) continue;
43
44 const size_t ei = adj_edges[0];
45 size_t s,d;
46 get_edge_end_points(ei, s, d);
47 vertex_edge_adjacency.insert({{s, i}, {d, i}});
48 non_manifold_edges.push_back(i);
49 assert(vertex_edge_adjacency.count(s) > 0);
50 assert(vertex_edge_adjacency.count(d) > 0);
51 }
52
53 auto expand_forward = [&](std::list<size_t>& edge_curve,
54 size_t& front_vertex, size_t& end_vertex) {
55 while(vertex_edge_adjacency.count(front_vertex) == 2 &&
56 front_vertex != end_vertex) {
57 auto adj_edges = vertex_edge_adjacency.equal_range(front_vertex);
58 for (auto itr = adj_edges.first; itr!=adj_edges.second; itr++) {
59 const size_t uei = itr->second;
60 assert(uE2E.at(uei).size() != 2);
61 const size_t ei = uE2E[uei][0];
62 if (uei == edge_curve.back()) continue;
63 size_t s,d;
64 get_edge_end_points(ei, s, d);
65 edge_curve.push_back(uei);
66 if (s == front_vertex) {
67 front_vertex = d;
68 } else if (d == front_vertex) {
69 front_vertex = s;
70 } else {
71 throw "Invalid vertex/edge adjacency!";
72 }
73 break;
74 }
75 }
76 };
77
78 auto expand_backward = [&](std::list<size_t>& edge_curve,
79 size_t& front_vertex, size_t& end_vertex) {
80 while(vertex_edge_adjacency.count(front_vertex) == 2 &&
81 front_vertex != end_vertex) {
82 auto adj_edges = vertex_edge_adjacency.equal_range(front_vertex);
83 for (auto itr = adj_edges.first; itr!=adj_edges.second; itr++) {
84 const size_t uei = itr->second;
85 assert(uE2E.at(uei).size() != 2);
86 const size_t ei = uE2E[uei][0];
87 if (uei == edge_curve.front()) continue;
88 size_t s,d;
89 get_edge_end_points(ei, s, d);
90 edge_curve.push_front(uei);
91 if (s == front_vertex) {
92 front_vertex = d;
93 } else if (d == front_vertex) {
94 front_vertex = s;
95 } else {
96 throw "Invalid vertex/edge adjcency!";
97 }
98 break;
99 }
100 }
101 };
102
103 std::vector<bool> visited(num_unique_edges, false);
104 for (const size_t i : non_manifold_edges) {
105 if (visited[i]) continue;
106 std::list<size_t> edge_curve;
107 edge_curve.push_back(i);
108
109 const auto& adj_edges = uE2E[i];
110 assert(adj_edges.size() != 2);
111 const size_t ei = adj_edges[0];
112 size_t s,d;
113 get_edge_end_points(ei, s, d);
114
115 expand_forward(edge_curve, d, s);
116 expand_backward(edge_curve, s, d);
117 curves.emplace_back(edge_curve.begin(), edge_curve.end());
118 for (auto itr = edge_curve.begin(); itr!=edge_curve.end(); itr++) {
119 visited[*itr] = true;
120 }
121 }
122
123}

◆ face_areas() [1/3]

template<typename DerivedL , typename DerivedA >
IGL_INLINE void igl::face_areas ( const Eigen::MatrixBase< DerivedL > &  L,
const typename DerivedL::Scalar  doublearea_nan_replacement,
Eigen::PlainObjectBase< DerivedA > &  A 
)
38{
39 using namespace Eigen;
40 assert(L.cols() == 6);
41 const int m = L.rows();
42 // (unsigned) face Areas (opposite vertices: 1 2 3 4)
44 A0(m,1), A1(m,1), A2(m,1), A3(m,1);
46 L0(m,3), L1(m,3), L2(m,3), L3(m,3);
47 L0<<L.col(1),L.col(2),L.col(3);
48 L1<<L.col(0),L.col(2),L.col(4);
49 L2<<L.col(0),L.col(1),L.col(5);
50 L3<<L.col(3),L.col(4),L.col(5);
51 doublearea(L0,doublearea_nan_replacement,A0);
52 doublearea(L1,doublearea_nan_replacement,A1);
53 doublearea(L2,doublearea_nan_replacement,A2);
54 doublearea(L3,doublearea_nan_replacement,A3);
55 A.resize(m,4);
56 A.col(0) = 0.5*A0;
57 A.col(1) = 0.5*A1;
58 A.col(2) = 0.5*A2;
59 A.col(3) = 0.5*A3;
60}

References doublearea(), L, and Eigen::PlainObjectBase< Derived >::resize().

+ Here is the call graph for this function:

◆ face_areas() [2/3]

template<typename DerivedL , typename DerivedA >
IGL_INLINE void igl::face_areas ( const Eigen::MatrixBase< DerivedL > &  L,
Eigen::PlainObjectBase< DerivedA > &  A 
)
28{
29 return face_areas(
30 L,std::numeric_limits<typename DerivedL::Scalar>::quiet_NaN(),A);
31}

References face_areas(), and L.

+ Here is the call graph for this function:

◆ face_areas() [3/3]

template<typename DerivedV , typename DerivedT , typename DerivedA >
IGL_INLINE void igl::face_areas ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedT > &  T,
Eigen::PlainObjectBase< DerivedA > &  A 
)
17{
18 assert(T.cols() == 4);
19 DerivedA L;
20 edge_lengths(V,T,L);
21 return face_areas(L,A);
22}

References edge_lengths(), face_areas(), and L.

Referenced by cotmatrix_entries(), dihedral_angles(), face_areas(), and face_areas().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ face_occurrences()

template<typename IntegerF , typename IntegerC >
IGL_INLINE void igl::face_occurrences ( const std::vector< std::vector< IntegerF > > &  F,
std::vector< IntegerC > &  C 
)
18{
19 using namespace std;
20
21 // Get a list of sorted faces
22 vector<vector<IntegerF> > sortedF = F;
23 for(int i = 0; i < (int)F.size();i++)
24 {
25 sort(sortedF[i].begin(),sortedF[i].end());
26 }
27 // Count how many times each sorted face occurs
28 map<vector<IntegerF>,int> counts;
29 for(int i = 0; i < (int)sortedF.size();i++)
30 {
31 if(counts.find(sortedF[i]) == counts.end())
32 {
33 // initialize to count of 1
34 counts[sortedF[i]] = 1;
35 }else
36 {
37 // increment count
38 counts[sortedF[i]]++;
39 assert(counts[sortedF[i]] == 2 && "Input should be manifold");
40 }
41 }
42
43 // Resize output to fit number of ones
44 C.resize(F.size());
45 for(int i = 0;i< (int)F.size();i++)
46 {
47 // sorted face should definitely be in counts map
48 assert(counts.find(sortedF[i]) != counts.end());
49 C[i] = counts[sortedF[i]];
50 }
51}

References sort().

Referenced by boundary_facets(), and on_boundary().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ faces_first() [1/2]

template<typename MatV , typename MatF , typename VecI >
IGL_INLINE void igl::faces_first ( const MatV &  V,
const MatF &  F,
MatV &  RV,
MatF &  RF,
VecI &  IM 
)
20{
21 assert(&V != &RV);
22 assert(&F != &RF);
23 using namespace std;
24 using namespace Eigen;
25 vector<bool> in_face(V.rows());
26 for(int i = 0; i<F.rows(); i++)
27 {
28 for(int j = 0; j<F.cols(); j++)
29 {
30 in_face[F(i,j)] = true;
31 }
32 }
33 // count number of vertices not in faces
34 int num_in_F = 0;
35 for(int i = 0;i<V.rows();i++)
36 {
37 num_in_F += (in_face[i]?1:0);
38 }
39 // list of unique vertices that occur in F
40 VectorXi U(num_in_F);
41 // list of unique vertices that do not occur in F
42 VectorXi NU(V.rows()-num_in_F);
43 int Ui = 0;
44 int NUi = 0;
45 // loop over vertices
46 for(int i = 0;i<V.rows();i++)
47 {
48 if(in_face[i])
49 {
50 U(Ui) = i;
51 Ui++;
52 }else
53 {
54 NU(NUi) = i;
55 NUi++;
56 }
57 }
58 IM.resize(V.rows());
59 // reindex vertices that occur in faces to be first
60 for(int i = 0;i<U.size();i++)
61 {
62 IM(U(i)) = i;
63 }
64 // reindex vertices that do not occur in faces to come after those that do
65 for(int i = 0;i<NU.size();i++)
66 {
67 IM(NU(i)) = i+U.size();
68 }
69 RF.resizeLike(F);
70 // Reindex faces
71 for(int i = 0; i<F.rows(); i++)
72 {
73 for(int j = 0; j<F.cols(); j++)
74 {
75 RF(i,j) = IM(F(i,j));
76 }
77 }
78 RV.resizeLike(V);
79 // Reorder vertices
80 for(int i = 0;i<V.rows();i++)
81 {
82 RV.row(IM(i)) = V.row(i);
83 }
84}

Referenced by faces_first().

+ Here is the caller graph for this function:

◆ faces_first() [2/2]

template<typename MatV , typename MatF , typename VecI >
IGL_INLINE void igl::faces_first ( MatV &  V,
MatF &  F,
VecI &  IM 
)
91{
92 MatV RV;
93 // Copying F may not be needed, seems RF = F is safe (whereas RV = V is not)
94 MatF RF;
95 igl::faces_first(V,F,RV,RF,IM);
96 V = RV;
97 F = RF;
98}
IGL_INLINE void faces_first(const MatV &V, const MatF &F, MatV &RV, MatF &RF, VecI &IM)
Definition faces_first.cpp:14

References faces_first().

+ Here is the call graph for this function:

◆ facet_components() [1/2]

template<typename DerivedF , typename DerivedC >
IGL_INLINE void igl::facet_components ( const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedC > &  C 
)
16{
17 using namespace std;
18 typedef typename DerivedF::Index Index;
19 vector<vector<vector<Index > > > TT;
20 vector<vector<vector<Index > > > TTi;
22 Eigen::VectorXi counts;
23 return facet_components(TT,C,counts);
24}
IGL_INLINE void facet_components(const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedC > &C)
Definition facet_components.cpp:13

References facet_components(), and triangle_triangle_adjacency().

Referenced by igl::copyleft::cgal::extract_cells(), facet_components(), and igl::copyleft::cgal::outer_hull_legacy().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ facet_components() [2/2]

template<typename TTIndex , typename DerivedC , typename Derivedcounts >
IGL_INLINE void igl::facet_components ( const std::vector< std::vector< std::vector< TTIndex > > > &  TT,
Eigen::PlainObjectBase< DerivedC > &  C,
Eigen::PlainObjectBase< Derivedcounts > &  counts 
)
34{
35 using namespace std;
36 typedef TTIndex Index;
37 const Index m = TT.size();
38 C.resize(m,1);
39 vector<bool> seen(m,false);
40 Index id = 0;
41 vector<Index> vcounts;
42 for(Index g = 0;g<m;g++)
43 {
44 if(seen[g])
45 {
46 continue;
47 }
48 vcounts.push_back(0);
49 queue<Index> Q;
50 Q.push(g);
51 while(!Q.empty())
52 {
53 const Index f = Q.front();
54 Q.pop();
55 if(seen[f])
56 {
57 continue;
58 }
59 seen[f] = true;
60 vcounts[id]++;
61 C(f,0) = id;
62 // Face f's neighbor lists opposite opposite each corner
63 for(const auto & c : TT[f])
64 {
65 // Each neighbor
66 for(const auto & n : c)
67 {
68 if(!seen[n])
69 {
70 Q.push(n);
71 }
72 }
73 }
74 }
75 id++;
76 }
77 assert((size_t) id == vcounts.size());
78 const size_t ncc = vcounts.size();
79 assert((size_t)C.maxCoeff()+1 == ncc);
80 counts.resize(ncc,1);
81 for(size_t i = 0;i<ncc;i++)
82 {
83 counts(i) = vcounts[i];
84 }
85}

References Eigen::PlainObjectBase< Derived >::resize().

+ Here is the call graph for this function:

◆ false_barycentric_subdivision()

template<typename Scalar , typename Index >
IGL_INLINE void igl::false_barycentric_subdivision ( const Eigen::PlainObjectBase< Scalar > &  V,
const Eigen::PlainObjectBase< Index > &  F,
Eigen::PlainObjectBase< Scalar > &  VD,
Eigen::PlainObjectBase< Index > &  FD 
)
20{
21 using namespace Eigen;
22 // Compute face barycenter
23 Eigen::MatrixXd BC;
24 igl::barycenter(V,F,BC);
25
26 // Add the barycenters to the vertices
27 VD.resize(V.rows()+F.rows(),3);
28 VD.block(0,0,V.rows(),3) = V;
29 VD.block(V.rows(),0,F.rows(),3) = BC;
30
31 // Each face is split four ways
32 FD.resize(F.rows()*3,3);
33
34 for (unsigned i=0; i<F.rows(); ++i)
35 {
36 int i0 = F(i,0);
37 int i1 = F(i,1);
38 int i2 = F(i,2);
39 int i3 = V.rows() + i;
40
41 Vector3i F0,F1,F2;
42 F0 << i0,i1,i3;
43 F1 << i1,i2,i3;
44 F2 << i2,i0,i3;
45
46 FD.row(i*3 + 0) = F0;
47 FD.row(i*3 + 1) = F1;
48 FD.row(i*3 + 2) = F2;
49 }
50
51
52}
Definition Voronoi.hpp:23
IGL_INLINE void barycenter(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedBC > &BC)
Definition barycenter.cpp:14

References barycenter(), Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ fast_winding_number() [1/6]

template<typename DerivedP , typename DerivedA , typename DerivedN , typename DerivedQ , typename BetaType , typename DerivedWN >
IGL_INLINE void igl::fast_winding_number ( const Eigen::MatrixBase< DerivedP > &  P,
const Eigen::MatrixBase< DerivedN > &  N,
const Eigen::MatrixBase< DerivedA > &  A,
const Eigen::MatrixBase< DerivedQ > &  Q,
const int  expansion_order,
const BetaType  beta,
Eigen::PlainObjectBase< DerivedWN > &  WN 
)
271 {
272 typedef typename DerivedWN::Scalar real;
273
274 std::vector<std::vector<int> > point_indices;
278
279 octree(P,point_indices,CH,CN,W);
280
284
285 fast_winding_number(P,N,A,point_indices,CH,expansion_order,CM,R,EC);
286 fast_winding_number(P,N,A,point_indices,CH,CM,R,EC,Q,beta,WN);
287 }
EIGEN_DEVICE_FUNC RealReturnType real() const
Definition CommonCwiseUnaryOps.h:86
IGL_INLINE void octree(const Eigen::MatrixBase< DerivedP > &P, std::vector< std::vector< IndexType > > &point_indices, Eigen::PlainObjectBase< DerivedCH > &CH, Eigen::PlainObjectBase< DerivedCN > &CN, Eigen::PlainObjectBase< DerivedW > &W)
Definition octree.cpp:8

References fast_winding_number(), octree(), and real().

+ Here is the call graph for this function:

◆ fast_winding_number() [2/6]

template<typename DerivedP , typename DerivedA , typename DerivedN , typename DerivedQ , typename DerivedWN >
IGL_INLINE void igl::fast_winding_number ( const Eigen::MatrixBase< DerivedP > &  P,
const Eigen::MatrixBase< DerivedN > &  N,
const Eigen::MatrixBase< DerivedA > &  A,
const Eigen::MatrixBase< DerivedQ > &  Q,
Eigen::PlainObjectBase< DerivedWN > &  WN 
)
296 {
297 fast_winding_number(P,N,A,Q,2,2.0,WN);
298 }

References fast_winding_number().

+ Here is the call graph for this function:

◆ fast_winding_number() [3/6]

template<typename DerivedP , typename DerivedA , typename DerivedN , typename Index , typename DerivedCH , typename DerivedCM , typename DerivedR , typename DerivedEC , typename DerivedQ , typename BetaType , typename DerivedWN >
IGL_INLINE void igl::fast_winding_number ( const Eigen::MatrixBase< DerivedP > &  P,
const Eigen::MatrixBase< DerivedN > &  N,
const Eigen::MatrixBase< DerivedA > &  A,
const std::vector< std::vector< Index > > &  point_indices,
const Eigen::MatrixBase< DerivedCH > &  CH,
const Eigen::MatrixBase< DerivedCM > &  CM,
const Eigen::MatrixBase< DerivedR > &  R,
const Eigen::MatrixBase< DerivedEC > &  EC,
const Eigen::MatrixBase< DerivedQ > &  Q,
const BetaType  beta,
Eigen::PlainObjectBase< DerivedWN > &  WN 
)
129 {
130
131 typedef typename DerivedP::Scalar real_p;
132 typedef typename DerivedN::Scalar real_n;
133 typedef typename DerivedA::Scalar real_a;
134 typedef typename DerivedCM::Scalar real_cm;
135 typedef typename DerivedR::Scalar real_r;
136 typedef typename DerivedEC::Scalar real_ec;
137 typedef typename DerivedQ::Scalar real_q;
138 typedef typename DerivedWN::Scalar real_wn;
139
140 typedef Eigen::Matrix<real_q,1,3> RowVec;
141 typedef Eigen::Matrix<real_ec,3,3> EC_3by3;
142
143 auto direct_eval = [](const RowVec & loc,
144 const Eigen::Matrix<real_ec,1,3> & anorm){
145 real_wn wn = (loc(0)*anorm(0)+loc(1)*anorm(1)+loc(2)*anorm(2))
146 /(4.0*igl::PI*std::pow(loc.norm(),3));
147 if(std::isnan(wn)){
148 return 0.5;
149 }else{
150 return wn;
151 }
152 };
153
154 auto expansion_eval = [&direct_eval](const RowVec & loc,
155 const Eigen::RowVectorXd & EC){
156 real_wn wn = direct_eval(loc,EC.head<3>());
157 double r = loc.norm();
158 if(EC.size()>3){
159 Eigen::Matrix<real_ec,3,3> SecondDerivative =
160 Eigen::Matrix<real_ec,3,3>::Identity()/(4.0*igl::PI*std::pow(r,3));
161 SecondDerivative += -3.0*loc.transpose()*loc/(4.0*igl::PI*std::pow(r,5));
162 Eigen::Matrix<real_ec,1,9> derivative_vector =
163 Eigen::Map<Eigen::Matrix<real_ec,1,9> >(SecondDerivative.data(),
164 SecondDerivative.size());
165 wn += derivative_vector.cwiseProduct(EC.segment<9>(3)).sum();
166 }
167 if(EC.size()>3+9){
168 Eigen::Matrix<real_ec,3,3> ThirdDerivative;
169 for(int i = 0; i < 3; i++){
170 ThirdDerivative =
171 15.0*loc(i)*loc.transpose()*loc/(4.0*igl::PI*std::pow(r,7));
173 Diagonal << loc(i), 0, 0,
174 0, loc(i), 0,
175 0, 0, loc(i);
177 RowCol.setZero(3,3);
178 RowCol.row(i) = loc;
179 Eigen::Matrix<real_ec,3,3> RowColT = RowCol.transpose();
180 RowCol = RowCol + RowColT;
181 ThirdDerivative +=
182 -3.0/(4.0*igl::PI*std::pow(r,5))*(RowCol+Diagonal);
183 Eigen::Matrix<real_ec,1,9> derivative_vector =
185 ThirdDerivative.size());
186 wn += derivative_vector.cwiseProduct(
187 EC.segment<9>(12 + i*9)).sum();
188 }
189 }
190 return wn;
191 };
192
193 int m = Q.rows();
194 WN.resize(m,1);
195
196 std::function< real_wn(const RowVec, const std::vector<int>) > helper;
197 helper = [&helper,
198 &P,&N,&A,
199 &point_indices,&CH,
200 &CM,&R,&EC,&beta,
201 &direct_eval,&expansion_eval]
202 (const RowVec query, const std::vector<int> near_indices)-> real_wn
203 {
204 std::vector<int> new_near_indices;
205 real_wn wn = 0;
206 for(int i = 0; i < near_indices.size(); i++){
207 int index = near_indices.at(i);
208 //Leaf Case, Brute force
209 if(CH(index,0) == -1){
210 for(int j = 0; j < point_indices.at(index).size(); j++){
211 int curr_row = point_indices.at(index).at(j);
212 wn += direct_eval(P.row(curr_row)-query,
213 N.row(curr_row)*A(curr_row));
214 }
215 }
216 //Non-Leaf Case
217 else {
218 for(int child = 0; child < 8; child++){
219 int child_index = CH(index,child);
220 if(point_indices.at(child_index).size() > 0){
221 if((CM.row(child_index)-query).norm() > beta*R(child_index)){
222 if(CH(child_index,0) == -1){
223 for(int j=0;j<point_indices.at(child_index).size();j++){
224 int curr_row = point_indices.at(child_index).at(j);
225 wn += direct_eval(P.row(curr_row)-query,
226 N.row(curr_row)*A(curr_row));
227 }
228 }else{
229 wn += expansion_eval(CM.row(child_index)-query,
230 EC.row(child_index));
231 }
232 }else {
233 new_near_indices.emplace_back(child_index);
234 }
235 }
236 }
237 }
238 }
239 if(new_near_indices.size() > 0){
240 wn += helper(query,new_near_indices);
241 }
242 return wn;
243 };
244
245
246 if(beta > 0){
247 std::vector<int> near_indices_start = {0};
248 igl::parallel_for(m,[&](int iter){
249 WN(iter) = helper(Q.row(iter),near_indices_start);
250 },1000);
251 } else {
252 igl::parallel_for(m,[&](int iter){
253 double wn = 0;
254 for(int j = 0; j <P.rows(); j++){
255 wn += direct_eval(P.row(j)-Q.row(iter),N.row(j)*A(j));
256 }
257 WN(iter) = wn;
258 },1000);
259 }
260 }

References Eigen::PlainObjectBase< Derived >::data(), parallel_for(), PI, Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::setZero(), and sum().

+ Here is the call graph for this function:

◆ fast_winding_number() [4/6]

template<typename DerivedP , typename DerivedA , typename DerivedN , typename Index , typename DerivedCH , typename DerivedCM , typename DerivedR , typename DerivedEC >
IGL_INLINE void igl::fast_winding_number ( const Eigen::MatrixBase< DerivedP > &  P,
const Eigen::MatrixBase< DerivedN > &  N,
const Eigen::MatrixBase< DerivedA > &  A,
const std::vector< std::vector< Index > > &  point_indices,
const Eigen::MatrixBase< DerivedCH > &  CH,
const int  expansion_order,
Eigen::PlainObjectBase< DerivedCM > &  CM,
Eigen::PlainObjectBase< DerivedR > &  R,
Eigen::PlainObjectBase< DerivedEC > &  EC 
)
21 {
22 typedef typename DerivedP::Scalar real_p;
23 typedef typename DerivedN::Scalar real_n;
24 typedef typename DerivedA::Scalar real_a;
25 typedef typename DerivedCM::Scalar real_cm;
26 typedef typename DerivedR::Scalar real_r;
27 typedef typename DerivedEC::Scalar real_ec;
28
29 typedef Eigen::Matrix<real_p,1,3> RowVec3p;
30
31 int m = CH.size();
32 int num_terms;
33
34 assert(expansion_order < 3 && expansion_order >= 0 && "m must be less than n");
35 if(expansion_order == 0){
36 num_terms = 3;
37 } else if(expansion_order ==1){
38 num_terms = 3 + 9;
39 } else if(expansion_order == 2){
40 num_terms = 3 + 9 + 27;
41 }
42
43 R.resize(m);
44 CM.resize(m,3);
45 EC.resize(m,num_terms);
46 EC.setZero(m,num_terms);
47 std::function< void(const int) > helper;
48 helper = [&helper,
49 &P,&N,&A,&expansion_order,&point_indices,&CH,&EC,&R,&CM]
50 (const int index)-> void
51 {
53 masscenter << 0,0,0;
54 Eigen::Matrix<real_ec,1,3> zeroth_expansion;
55 zeroth_expansion << 0,0,0;
56 real_p areatotal = 0.0;
57 for(int j = 0; j < point_indices.at(index).size(); j++){
58 int curr_point_index = point_indices.at(index).at(j);
59
60 areatotal += A(curr_point_index);
61 masscenter += A(curr_point_index)*P.row(curr_point_index);
62 zeroth_expansion += A(curr_point_index)*N.row(curr_point_index);
63 }
64
65 masscenter = masscenter/areatotal;
66 CM.row(index) = masscenter;
67 EC.block(index,0,1,3) = zeroth_expansion;
68
69 real_r max_norm = 0;
70 real_r curr_norm;
71
72 for(int i = 0; i < point_indices.at(index).size(); i++){
73 //Get max distance from center of mass:
74 int curr_point_index = point_indices.at(index).at(i);
76 P.row(curr_point_index)-masscenter;
77 curr_norm = point.norm();
78 if(curr_norm > max_norm){
79 max_norm = curr_norm;
80 }
81
82 //Calculate higher order terms if necessary
84 if(EC.cols() >= (3+9)){
85 TempCoeffs = A(curr_point_index)*point.transpose()*
86 N.row(curr_point_index);
87 EC.block(index,3,1,9) +=
89 TempCoeffs.size());
90 }
91
92 if(EC.cols() == (3+9+27)){
93 for(int k = 0; k < 3; k++){
94 TempCoeffs = 0.5 * point(k) * (A(curr_point_index)*
95 point.transpose()*N.row(curr_point_index));
96 EC.block(index,12+9*k,1,9) += Eigen::Map<
97 Eigen::Matrix<real_ec,1,9> >(TempCoeffs.data(),
98 TempCoeffs.size());
99 }
100 }
101 }
102
103 R(index) = max_norm;
104 if(CH(index,0) != -1)
105 {
106 for(int i = 0; i < 8; i++){
107 int child = CH(index,i);
108 helper(child);
109 }
110 }
111 };
112 helper(0);
113 }

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::data(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::setZero(), and void().

+ Here is the call graph for this function:

◆ fast_winding_number() [5/6]

template<typename DerivedP , typename DerivedN , typename DerivedQ , typename BetaType , typename DerivedWN >
IGL_INLINE void igl::fast_winding_number ( const Eigen::MatrixBase< DerivedP > &  P,
const Eigen::MatrixBase< DerivedN > &  N,
const Eigen::MatrixBase< DerivedQ > &  Q,
const int  expansion_order,
const BetaType  beta,
Eigen::PlainObjectBase< DerivedWN > &  WN 
)

Referenced by fast_winding_number(), fast_winding_number(), and igl::copyleft::cgal::fast_winding_number().

+ Here is the caller graph for this function:

◆ fast_winding_number() [6/6]

template<typename DerivedP , typename DerivedN , typename DerivedQ , typename DerivedWN >
IGL_INLINE void igl::fast_winding_number ( const Eigen::MatrixBase< DerivedP > &  P,
const Eigen::MatrixBase< DerivedN > &  N,
const Eigen::MatrixBase< DerivedQ > &  Q,
Eigen::PlainObjectBase< DerivedWN > &  WN 
)

◆ file_contents_as_string() [1/2]

IGL_INLINE std::string igl::file_contents_as_string ( const std::string  file_name)
37{
38 std::string content;
39#ifndef NDEBUG
40 bool ret =
41#endif
42 file_contents_as_string(file_name,content);
43 assert(ret && "file_contents_as_string failed to read string from file");
44 return content;
45}
IGL_INLINE bool file_contents_as_string(const std::string file_name, std::string &content)
Definition file_contents_as_string.cpp:14

References file_contents_as_string().

+ Here is the call graph for this function:

◆ file_contents_as_string() [2/2]

IGL_INLINE bool igl::file_contents_as_string ( const std::string  file_name,
std::string &  content 
)
17{
18 std::ifstream ifs(file_name.c_str());
19 // Check that opening the stream worked successfully
20 if(!ifs.good())
21 {
22 fprintf(
23 stderr,
24 "IOError: file_contents_as_string() cannot open %s\n",
25 file_name.c_str());
26 return false;
27 }
28 // Stream file contents into string
29 content = std::string(
30 (std::istreambuf_iterator<char>(ifs)),
31 (std::istreambuf_iterator<char>()));
32 return true;
33}

Referenced by file_contents_as_string().

+ Here is the caller graph for this function:

◆ file_dialog_open()

IGL_INLINE std::string igl::file_dialog_open ( )
21{
22 const int FILE_DIALOG_MAX_BUFFER = 1024;
23 char buffer[FILE_DIALOG_MAX_BUFFER];
24
25#ifdef __APPLE__
26 // For apple use applescript hack
27 FILE * output = popen(
28 "osascript -e \""
29 " tell application \\\"System Events\\\"\n"
30 " activate\n"
31 " set existing_file to choose file\n"
32 " end tell\n"
33 " set existing_file_path to (POSIX path of (existing_file))\n"
34 "\" 2>/dev/null | tr -d '\n' ","r");
35 while ( fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) != NULL )
36 {
37 }
38#elif defined _WIN32
39
40 // Use native windows file dialog box
41 // (code contributed by Tino Weinkauf)
42
43 OPENFILENAME ofn; // common dialog box structure
44 char szFile[260]; // buffer for file name
45
46 // Initialize OPENFILENAME
47 ZeroMemory(&ofn, sizeof(ofn));
48 ofn.lStructSize = sizeof(ofn);
49 ofn.hwndOwner = NULL;
50 ofn.lpstrFile = new char[100];
51 // Set lpstrFile[0] to '\0' so that GetOpenFileName does not
52 // use the contents of szFile to initialize itself.
53 ofn.lpstrFile[0] = '\0';
54 ofn.nMaxFile = sizeof(szFile);
55 ofn.lpstrFilter = "*.*\0";//off\0*.off\0obj\0*.obj\0mp\0*.mp\0";
56 ofn.nFilterIndex = 1;
57 ofn.lpstrFileTitle = NULL;
58 ofn.nMaxFileTitle = 0;
59 ofn.lpstrInitialDir = NULL;
60 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
61
62 // Display the Open dialog box.
63 int pos = 0;
64 if (GetOpenFileName(&ofn)==TRUE)
65 {
66 while(ofn.lpstrFile[pos] != '\0')
67 {
68 buffer[pos] = (char)ofn.lpstrFile[pos];
69 pos++;
70 }
71 }
72 buffer[pos] = 0;
73#else
74
75 // For linux use zenity
76 FILE * output = popen("/usr/bin/zenity --file-selection","r");
77 while ( fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) != NULL )
78 {
79 }
80
81 if (strlen(buffer) > 0)
82 {
83 buffer[strlen(buffer)-1] = 0;
84 }
85#endif
86 return std::string(buffer);
87}
#define TRUE
Definition mesh.c:42
Vec3d pos(const Pt &p)
Definition ReprojectPointsOnMesh.hpp:14

References TRUE.

Referenced by igl::opengl::glfw::Viewer::load_scene(), and igl::opengl::glfw::Viewer::open_dialog_load_mesh().

+ Here is the caller graph for this function:

◆ file_dialog_save()

IGL_INLINE std::string igl::file_dialog_save ( )
18{
19 const int FILE_DIALOG_MAX_BUFFER = 1024;
20 char buffer[FILE_DIALOG_MAX_BUFFER];
21#ifdef __APPLE__
22 // For apple use applescript hack
23 // There is currently a bug in Applescript that strips extensions off
24 // of chosen existing files in the "choose file name" dialog
25 // I'm assuming that will be fixed soon
26 FILE * output = popen(
27 "osascript -e \""
28 " tell application \\\"System Events\\\"\n"
29 " activate\n"
30 " set existing_file to choose file name\n"
31 " end tell\n"
32 " set existing_file_path to (POSIX path of (existing_file))\n"
33 "\" 2>/dev/null | tr -d '\n' ","r");
34 while ( fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) != NULL )
35 {
36 }
37#elif defined _WIN32
38
39 // Use native windows file dialog box
40 // (code contributed by Tino Weinkauf)
41
42 OPENFILENAME ofn; // common dialog box structure
43 char szFile[260]; // buffer for file name
44
45 // Initialize OPENFILENAME
46 ZeroMemory(&ofn, sizeof(ofn));
47 ofn.lStructSize = sizeof(ofn);
48 ofn.hwndOwner = NULL;//hwnd;
49 ofn.lpstrFile = new char[100];
50 // Set lpstrFile[0] to '\0' so that GetOpenFileName does not
51 // use the contents of szFile to initialize itself.
52 ofn.lpstrFile[0] = '\0';
53 ofn.nMaxFile = sizeof(szFile);
54 ofn.lpstrFilter = "";
55 ofn.nFilterIndex = 1;
56 ofn.lpstrFileTitle = NULL;
57 ofn.nMaxFileTitle = 0;
58 ofn.lpstrInitialDir = NULL;
59 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
60
61 // Display the Open dialog box.
62 int pos = 0;
63 if (GetSaveFileName(&ofn)==TRUE)
64 {
65 while(ofn.lpstrFile[pos] != '\0')
66 {
67 buffer[pos] = (char)ofn.lpstrFile[pos];
68 pos++;
69 }
70 buffer[pos] = 0;
71 }
72
73#else
74 // For every other machine type use zenity
75 FILE * output = popen("/usr/bin/zenity --file-selection --save","r");
76 while ( fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) != NULL )
77 {
78 }
79
80 if (strlen(buffer) > 0)
81 {
82 buffer[strlen(buffer)-1] = 0;
83 }
84#endif
85 return std::string(buffer);
86}

References TRUE.

Referenced by igl::opengl::glfw::Viewer::open_dialog_save_mesh(), and igl::opengl::glfw::Viewer::save_scene().

+ Here is the caller graph for this function:

◆ file_exists()

IGL_INLINE bool igl::file_exists ( const std::string  filename)
13{
14 struct stat status;
15 return (stat(filename.c_str(),&status)==0);
16}

References stat.

Referenced by next_filename().

+ Here is the caller graph for this function:

◆ find() [1/4]

template<typename DerivedX , typename DerivedI >
IGL_INLINE void igl::find ( const Eigen::DenseBase< DerivedX > &  X,
Eigen::PlainObjectBase< DerivedI > &  I 
)
83{
84 const int nnz = X.count();
85 I.resize(nnz,1);
86 {
87 int k = 0;
88 for(int j = 0;j<X.cols();j++)
89 {
90 for(int i = 0;i<X.rows();i++)
91 {
92 if(X(i,j))
93 {
94 I(k) = i+X.rows()*j;
95 k++;
96 }
97 }
98 }
99 }
100}

References Eigen::PlainObjectBase< Derived >::resize().

+ Here is the call graph for this function:

◆ find() [2/4]

template<typename DerivedX , typename DerivedI , typename DerivedJ , typename DerivedV >
IGL_INLINE void igl::find ( const Eigen::DenseBase< DerivedX > &  X,
Eigen::PlainObjectBase< DerivedI > &  I,
Eigen::PlainObjectBase< DerivedJ > &  J,
Eigen::PlainObjectBase< DerivedV > &  V 
)
54{
55 const int nnz = X.count();
56 I.resize(nnz,1);
57 J.resize(nnz,1);
58 V.resize(nnz,1);
59 {
60 int k = 0;
61 for(int j = 0;j<X.cols();j++)
62 {
63 for(int i = 0;i<X.rows();i++)
64 {
65 if(X(i,j))
66 {
67 I(k) = i;
68 J(k) = j;
69 V(k) = X(i,j);
70 k++;
71 }
72 }
73 }
74 }
75}

References Eigen::PlainObjectBase< Derived >::resize().

+ Here is the call graph for this function:

◆ find() [3/4]

template<typename T , typename DerivedI , typename DerivedJ , typename DerivedV >
IGL_INLINE void igl::find ( const Eigen::SparseMatrix< T > &  X,
Eigen::DenseBase< DerivedI > &  I,
Eigen::DenseBase< DerivedJ > &  J,
Eigen::DenseBase< DerivedV > &  V 
)
23{
24 // Resize outputs to fit nonzeros
25 I.derived().resize(X.nonZeros(),1);
26 J.derived().resize(X.nonZeros(),1);
27 V.derived().resize(X.nonZeros(),1);
28
29 int i = 0;
30 // Iterate over outside
31 for(int k=0; k<X.outerSize(); ++k)
32 {
33 // Iterate over inside
34 for(typename Eigen::SparseMatrix<T>::InnerIterator it (X,k); it; ++it)
35 {
36 V(i) = it.value();
37 I(i) = it.row();
38 J(i) = it.col();
39 i++;
40 }
41 }
42}
EIGEN_DEVICE_FUNC void resize(Index newSize)
Definition DenseBase.h:241
EIGEN_DEVICE_FUNC CoeffReturnType value() const
Definition DenseBase.h:480

References Eigen::DenseBase< Derived >::resize(), and Eigen::DenseBase< Derived >::value().

Referenced by ears(), igl::copyleft::cgal::extract_cells_single_component(), igl::matlab::MatlabWorkspace::find_index(), linprog(), matlab_format(), min_quad_with_fixed_precompute(), igl::mosek::mosek_quadprog(), print_ijv(), ramer_douglas_peucker(), slice_mask(), slice_mask(), straighten_seams(), and igl::copyleft::cgal::string_to_mesh_boolean_type().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ find() [4/4]

template<typename T >
IGL_INLINE void igl::find ( const Eigen::SparseVector< T > &  X,
Eigen::Matrix< int, Eigen::Dynamic, 1 > &  I,
Eigen::Matrix< T, Eigen::Dynamic, 1 > &  V 
)
107{
108 // Resize outputs to fit nonzeros
109 I.resize(X.nonZeros());
110 V.resize(X.nonZeros());
111
112 int i = 0;
113 // loop over non-zeros
114 for(typename Eigen::SparseVector<T>::InnerIterator it(X); it; ++it)
115 {
116 I(i) = it.index();
117 V(i) = it.value();
118 i++;
119 }
120}

References Eigen::PlainObjectBase< Derived >::resize().

+ Here is the call graph for this function:

◆ find_cross_field_singularities() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedM , typename DerivedO >
IGL_INLINE void igl::find_cross_field_singularities ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedM > &  Handle_MMatch,
Eigen::PlainObjectBase< DerivedO > &  isSingularity,
Eigen::PlainObjectBase< DerivedO > &  singularityIndex 
)

check that is on border..

25{
26 std::vector<bool> V_border = igl::is_border_vertex(V,F);
27
28 std::vector<std::vector<int> > VF;
29 std::vector<std::vector<int> > VFi;
31
32
33 isSingularity.setZero(V.rows(),1);
34 singularityIndex.setZero(V.rows(),1);
35 for (unsigned int vid=0;vid<V.rows();vid++)
36 {
38 if (V_border[vid])
39 continue;
40
41 int missmatch=0;
42 for (unsigned int i=0;i<VF[vid].size();i++)
43 {
44 // look for the vertex
45 int j=-1;
46 for (unsigned z=0; z<3; ++z)
47 if (F(VF[vid][i],z) == vid)
48 j=z;
49 assert(j!=-1);
50
51 missmatch+=Handle_MMatch(VF[vid][i],j);
52 }
53 missmatch=missmatch%4;
54
55 isSingularity(vid)=(missmatch!=0);
56 singularityIndex(vid)=missmatch;
57 }
58
59
60}

References is_border_vertex(), Eigen::PlainObjectBase< Derived >::rows(), Eigen::PlainObjectBase< Derived >::setZero(), and vertex_triangle_adjacency().

Referenced by find_cross_field_singularities(), and igl::copyleft::comiso::miq().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ find_cross_field_singularities() [2/2]

template<typename DerivedV , typename DerivedF , typename DerivedO >
IGL_INLINE void igl::find_cross_field_singularities ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedV > &  PD1,
const Eigen::PlainObjectBase< DerivedV > &  PD2,
Eigen::PlainObjectBase< DerivedO > &  isSingularity,
Eigen::PlainObjectBase< DerivedO > &  singularityIndex,
bool  isCombed = false 
)
70{
72
73 igl::cross_field_missmatch(V, F, PD1, PD2, isCombed, Handle_MMatch);
74 igl::find_cross_field_singularities(V, F, Handle_MMatch, isSingularity, singularityIndex);
75}
IGL_INLINE void find_cross_field_singularities(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedM > &Handle_MMatch, Eigen::PlainObjectBase< DerivedO > &isSingularity, Eigen::PlainObjectBase< DerivedO > &singularityIndex)
Definition find_cross_field_singularities.cpp:20
IGL_INLINE void cross_field_missmatch(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedV > &PD1, const Eigen::PlainObjectBase< DerivedV > &PD2, const bool isCombed, Eigen::PlainObjectBase< DerivedM > &missmatch)
Definition cross_field_missmatch.cpp:115

References cross_field_missmatch(), and find_cross_field_singularities().

+ Here is the call graph for this function:

◆ find_zero()

template<typename AType , typename DerivedI >
IGL_INLINE void igl::find_zero ( const Eigen::SparseMatrix< AType > &  A,
const int  dim,
Eigen::PlainObjectBase< DerivedI > &  I 
)
10{
11 assert((dim == 1 || dim == 2) && "dim must be 2 or 1");
12 // Get size of input
13 int m = A.rows();
14 int n = A.cols();
15 // I starts by containing guess where 0 might be
16 I = DerivedI::Zero(dim==1?n:m);
19 const auto func = [&I,&found,&dim](int i, int j, const int v)
20 {
21 if(dim == 2)
22 {
23 std::swap(i,j);
24 }
25 // Coded as if dim == 1, assuming swap for dim == 2
26 // Have we already found a zero?
27 if(!found(j))
28 {
29 if(I(j) != i || v == 0)
30 {
31 // either there was an implicit zero between the last element and this
32 // one, or this one is zero
33 found(j) = true;
34 }else
35 {
36 // If not found, then guess that next element will be zero
37 I(j) = I(j)+1;
38 }
39 }
40 };
41 for_each(A,func);
42}
void for_each(const Eigen::SparseMatrix< AType > &A, const Func &func)
Definition for_each.h:31

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), for_each(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows().

Referenced by max(), and min().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fit_plane()

IGL_INLINE void igl::fit_plane ( const Eigen::MatrixXd &  V,
Eigen::RowVector3d &  N,
Eigen::RowVector3d &  C 
)
16{
17 assert(V.rows()>0);
18
19 Eigen::Vector3d sum = V.colwise().sum();
20
21 Eigen::Vector3d center = sum.array()/(double(V.rows()));
22
23 C = center;
24
25 double sumXX=0.0f,sumXY=0.0f,sumXZ=0.0f;
26 double sumYY=0.0f,sumYZ=0.0f;
27 double sumZZ=0.0f;
28
29 for(int i=0;i<V.rows();i++)
30 {
31 double diffX=V(i,0)-center(0);
32 double diffY=V(i,1)-center(1);
33 double diffZ=V(i,2)-center(2);
34 sumXX+=diffX*diffX;
35 sumXY+=diffX*diffY;
36 sumXZ+=diffX*diffZ;
37 sumYY+=diffY*diffY;
38 sumYZ+=diffY*diffZ;
39 sumZZ+=diffZ*diffZ;
40 }
41
42 Eigen::MatrixXd m(3,3);
43 m << sumXX,sumXY,sumXZ,
44 sumXY,sumYY,sumYZ,
45 sumXZ,sumYZ,sumZZ;
46
48
49 N = es.eigenvectors().col(0);
50}
Computes eigenvalues and eigenvectors of selfadjoint matrices.
Definition SelfAdjointEigenSolver.h:71

References Eigen::SelfAdjointEigenSolver< _MatrixType >::eigenvectors(), and sum().

+ Here is the call graph for this function:

◆ fit_rotations()

template<typename DerivedS , typename DerivedD >
IGL_INLINE void igl::fit_rotations ( const Eigen::PlainObjectBase< DerivedS > &  S,
const bool  single_precision,
Eigen::PlainObjectBase< DerivedD > &  R 
)
22{
23 using namespace std;
24 const int dim = S.cols();
25 const int nr = S.rows()/dim;
26 assert(nr * dim == S.rows());
27 assert(dim == 3);
28
29 // resize output
30 R.resize(dim,dim*nr); // hopefully no op (should be already allocated)
31
32 //std::cout<<"S=["<<std::endl<<S<<std::endl<<"];"<<std::endl;
33 //MatrixXd si(dim,dim);
34 Eigen::Matrix<typename DerivedS::Scalar,3,3> si;// = Eigen::Matrix3d::Identity();
35 // loop over number of rotations we're computing
36 for(int r = 0;r<nr;r++)
37 {
38 // build this covariance matrix
39 for(int i = 0;i<dim;i++)
40 {
41 for(int j = 0;j<dim;j++)
42 {
43 si(i,j) = S(i*nr+r,j);
44 }
45 }
48 Mat3 ri;
49 if(single_precision)
50 {
51 polar_svd3x3(si, ri);
52 }else
53 {
54 Mat3 ti,ui,vi;
55 Vec3 _;
56 igl::polar_svd(si,ri,ti,ui,_,vi);
57 }
58 assert(ri.determinant() >= 0);
59 R.block(0,r*dim,dim,dim) = ri.block(0,0,dim,dim).transpose();
60 //cout<<matlab_format(si,C_STR("si_"<<r))<<endl;
61 //cout<<matlab_format(ri.transpose().eval(),C_STR("ri_"<<r))<<endl;
62 }
63}
IGL_INLINE void polar_svd3x3(const Mat &A, Mat &R)
Definition polar_svd3x3.cpp:18
IGL_INLINE void polar_svd(const Eigen::PlainObjectBase< DerivedA > &A, Eigen::PlainObjectBase< DerivedR > &R, Eigen::PlainObjectBase< DerivedT > &T, Eigen::PlainObjectBase< DerivedU > &U, Eigen::PlainObjectBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedV > &V)
Definition polar_svd.cpp:36

References _, Eigen::PlainObjectBase< Derived >::cols(), polar_svd(), polar_svd3x3(), Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::rows().

Referenced by arap_dof_update(), and arap_solve().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fit_rotations_planar()

template<typename DerivedS , typename DerivedD >
IGL_INLINE void igl::fit_rotations_planar ( const Eigen::PlainObjectBase< DerivedS > &  S,
Eigen::PlainObjectBase< DerivedD > &  R 
)
69{
70 using namespace std;
71 const int dim = S.cols();
72 const int nr = S.rows()/dim;
73 //assert(dim == 2 && "_planar input should be 2D");
74 assert(nr * dim == S.rows());
75
76 // resize output
77 R.resize(dim,dim*nr); // hopefully no op (should be already allocated)
78
80 // loop over number of rotations we're computing
81 for(int r = 0;r<nr;r++)
82 {
83 // build this covariance matrix
84 for(int i = 0;i<2;i++)
85 {
86 for(int j = 0;j<2;j++)
87 {
88 si(i,j) = S(i*nr+r,j);
89 }
90 }
93 Mat2 ri,ti,ui,vi;
94 Vec2 _;
95 igl::polar_svd(si,ri,ti,ui,_,vi);
96#ifndef FIT_ROTATIONS_ALLOW_FLIPS
97 // Check for reflection
98 if(ri.determinant() < 0)
99 {
100 vi.col(1) *= -1.;
101 ri = ui * vi.transpose();
102 }
103 assert(ri.determinant() >= 0);
104#endif
105
106 // Not sure why polar_dec computes transpose...
107 R.block(0,r*dim,dim,dim).setIdentity();
108 R.block(0,r*dim,2,2) = ri.transpose();
109 }
110}

References _, Eigen::PlainObjectBase< Derived >::cols(), polar_svd(), Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::rows().

Referenced by arap_dof_update(), and arap_solve().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ flip_avoiding_line_search()

IGL_INLINE double igl::flip_avoiding_line_search ( const Eigen::MatrixXi  F,
Eigen::MatrixXd &  cur_v,
Eigen::MatrixXd &  dst_v,
std::function< double(Eigen::MatrixXd &)>  energy,
double  cur_energy = -1 
)
309{
310 using namespace std;
311 Eigen::MatrixXd d = dst_v - cur_v;
312
313 double min_step_to_singularity = igl::flip_avoiding::compute_max_step_from_singularities(cur_v,F,d);
314 double max_step_size = std::min(1., min_step_to_singularity*0.8);
315
316 return igl::line_search(cur_v,d,max_step_size, energy, cur_energy);
317}
IGL_INLINE double compute_max_step_from_singularities(const Eigen::MatrixXd &uv, const Eigen::MatrixXi &F, Eigen::MatrixXd &d)
Definition flip_avoiding_line_search.cpp:274
IGL_INLINE double line_search(Eigen::MatrixXd &x, const Eigen::MatrixXd &d, double i_step_size, std::function< double(Eigen::MatrixXd &)> energy, double cur_energy=-1)
Definition line_search.cpp:10

References igl::flip_avoiding::compute_max_step_from_singularities(), and line_search().

Referenced by slim_solve().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ flip_edge()

template<typename DerivedF , typename DerivedE , typename DeriveduE , typename DerivedEMAP , typename uE2EType >
IGL_INLINE void igl::flip_edge ( Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedE > &  E,
Eigen::PlainObjectBase< DeriveduE > &  uE,
Eigen::PlainObjectBase< DerivedEMAP > &  EMAP,
std::vector< std::vector< uE2EType > > &  uE2E,
const size_t  uei 
)
24{
25 typedef typename DerivedF::Scalar Index;
26 const size_t num_faces = F.rows();
27 assert(F.cols() == 3);
28 // v1 v1
29 // /|\ / \
30 // / | \ /f1 \
31 // v3 /f2|f1\ v4 => v3 /_____\ v4
32 // \ | / \ f2 /
33 // \ | / \ /
34 // \|/ \ /
35 // v2 v2
36 auto& half_edges = uE2E[uei];
37 if (half_edges.size() != 2) {
38 throw "Cannot flip non-manifold or boundary edge";
39 }
40
41 const size_t f1 = half_edges[0] % num_faces;
42 const size_t f2 = half_edges[1] % num_faces;
43 const size_t c1 = half_edges[0] / num_faces;
44 const size_t c2 = half_edges[1] / num_faces;
45 assert(c1 < 3);
46 assert(c2 < 3);
47
48 assert(f1 != f2);
49 const size_t v1 = F(f1, (c1+1)%3);
50 const size_t v2 = F(f1, (c1+2)%3);
51 const size_t v4 = F(f1, c1);
52 const size_t v3 = F(f2, c2);
53 assert(F(f2, (c2+2)%3) == v1);
54 assert(F(f2, (c2+1)%3) == v2);
55
56 const size_t e_12 = half_edges[0];
57 const size_t e_24 = f1 + ((c1 + 1) % 3) * num_faces;
58 const size_t e_41 = f1 + ((c1 + 2) % 3) * num_faces;
59 const size_t e_21 = half_edges[1];
60 const size_t e_13 = f2 + ((c2 + 1) % 3) * num_faces;
61 const size_t e_32 = f2 + ((c2 + 2) % 3) * num_faces;
62 assert(E(e_12, 0) == v1);
63 assert(E(e_12, 1) == v2);
64 assert(E(e_24, 0) == v2);
65 assert(E(e_24, 1) == v4);
66 assert(E(e_41, 0) == v4);
67 assert(E(e_41, 1) == v1);
68 assert(E(e_21, 0) == v2);
69 assert(E(e_21, 1) == v1);
70 assert(E(e_13, 0) == v1);
71 assert(E(e_13, 1) == v3);
72 assert(E(e_32, 0) == v3);
73 assert(E(e_32, 1) == v2);
74
75 const size_t ue_24 = EMAP(e_24);
76 const size_t ue_41 = EMAP(e_41);
77 const size_t ue_13 = EMAP(e_13);
78 const size_t ue_32 = EMAP(e_32);
79
80 F(f1, 0) = v1;
81 F(f1, 1) = v3;
82 F(f1, 2) = v4;
83 F(f2, 0) = v2;
84 F(f2, 1) = v4;
85 F(f2, 2) = v3;
86
87 uE(uei, 0) = v3;
88 uE(uei, 1) = v4;
89
90 const size_t new_e_34 = f1;
91 const size_t new_e_41 = f1 + num_faces;
92 const size_t new_e_13 = f1 + num_faces*2;
93 const size_t new_e_43 = f2;
94 const size_t new_e_32 = f2 + num_faces;
95 const size_t new_e_24 = f2 + num_faces*2;
96
97 E(new_e_34, 0) = v3;
98 E(new_e_34, 1) = v4;
99 E(new_e_41, 0) = v4;
100 E(new_e_41, 1) = v1;
101 E(new_e_13, 0) = v1;
102 E(new_e_13, 1) = v3;
103 E(new_e_43, 0) = v4;
104 E(new_e_43, 1) = v3;
105 E(new_e_32, 0) = v3;
106 E(new_e_32, 1) = v2;
107 E(new_e_24, 0) = v2;
108 E(new_e_24, 1) = v4;
109
110 EMAP(new_e_34) = uei;
111 EMAP(new_e_43) = uei;
112 EMAP(new_e_41) = ue_41;
113 EMAP(new_e_13) = ue_13;
114 EMAP(new_e_32) = ue_32;
115 EMAP(new_e_24) = ue_24;
116
117 auto replace = [](std::vector<Index>& array, Index old_v, Index new_v) {
118 std::replace(array.begin(), array.end(), old_v, new_v);
119 };
120 replace(uE2E[uei], e_12, new_e_34);
121 replace(uE2E[uei], e_21, new_e_43);
122 replace(uE2E[ue_13], e_13, new_e_13);
123 replace(uE2E[ue_32], e_32, new_e_32);
124 replace(uE2E[ue_24], e_24, new_e_24);
125 replace(uE2E[ue_41], e_41, new_e_41);
126
127#ifndef NDEBUG
128 auto sanity_check = [&](size_t ue) {
129 const auto& adj_faces = uE2E[ue];
130 if (adj_faces.size() == 2) {
131 const size_t first_f = adj_faces[0] % num_faces;
132 const size_t first_c = adj_faces[0] / num_faces;
133 const size_t second_f = adj_faces[1] % num_faces;
134 const size_t second_c = adj_faces[1] / num_faces;
135 const size_t vertex_0 = F(first_f, (first_c+1) % 3);
136 const size_t vertex_1 = F(first_f, (first_c+2) % 3);
137 assert(vertex_0 == F(second_f, (second_c+2) % 3));
138 assert(vertex_1 == F(second_f, (second_c+1) % 3));
139 }
140 };
141
142 sanity_check(uei);
143 sanity_check(ue_13);
144 sanity_check(ue_32);
145 sanity_check(ue_24);
146 sanity_check(ue_41);
147#endif
148}

Referenced by delaunay_triangulation().

+ Here is the caller graph for this function:

◆ flipped_triangles() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedX >
IGL_INLINE void igl::flipped_triangles ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedX > &  X 
)
17{
18 assert(V.cols() == 2 && "V should contain 2D positions");
19 std::vector<typename DerivedX::Scalar> flip_idx;
20 for (int i = 0; i < F.rows(); i++)
21 {
22 // https://www.cs.cmu.edu/~quake/robust.html
24 RowVector2S v1_n = V.row(F(i,0));
25 RowVector2S v2_n = V.row(F(i,1));
26 RowVector2S v3_n = V.row(F(i,2));
28 T2_Homo.col(0) << v1_n(0),v1_n(1),1.;
29 T2_Homo.col(1) << v2_n(0),v2_n(1),1.;
30 T2_Homo.col(2) << v3_n(0),v3_n(1),1.;
31 double det = T2_Homo.determinant();
32 assert(det == det && "det should not be NaN");
33 if (det < 0)
34 {
35 flip_idx.push_back(i);
36 }
37 }
38 igl::list_to_matrix(flip_idx,X);
39}

References Eigen::PlainObjectBase< Derived >::cols(), and list_to_matrix().

+ Here is the call graph for this function:

◆ flipped_triangles() [2/2]

template<typename Scalar , typename Index >
IGL_INLINE Eigen::VectorXi igl::flipped_triangles ( const Eigen::PlainObjectBase< Scalar > &  V,
const Eigen::PlainObjectBase< Index > &  F 
)

◆ flood_fill()

template<typename Derivedres , typename DerivedS >
IGL_INLINE void igl::flood_fill ( const Eigen::MatrixBase< Derivedres > &  res,
Eigen::PlainObjectBase< DerivedS > &  S 
)
15{
16 using namespace Eigen;
17 using namespace std;
18 typedef typename DerivedS::Scalar Scalar;
19 const auto flood = [&res,&S] (
20 const int xi,
21 const int yi,
22 const int zi,
23 const int signed_xi,
24 const int signed_yi,
25 const int signed_zi,
26 const Scalar s)
27 {
28 // flood fill this value back on this row
29 for(int bxi = xi;signed_xi<--bxi;)
30 {
31 S(bxi+res(0)*(yi + res(1)*zi)) = s;
32 }
33 // flood fill this value back on any previous rows
34 for(int byi = yi;signed_yi<--byi;)
35 {
36 for(int xi = 0;xi<res(0);xi++)
37 {
38 S(xi+res(0)*(byi + res(1)*zi)) = s;
39 }
40 }
41 // flood fill this value back on any previous "sheets"
42 for(int bzi = zi;signed_zi<--bzi;)
43 {
44 for(int yi = 0;yi<res(1);yi++)
45 {
46 for(int xi = 0;xi<res(0);xi++)
47 {
48 S(xi+res(0)*(yi + res(1)*bzi)) = s;
49 }
50 }
51 }
52 };
53 int signed_zi = -1;
54 Scalar s = numeric_limits<Scalar>::quiet_NaN();
55 for(int zi = 0;zi<res(2);zi++)
56 {
57 int signed_yi = -1;
58 if(zi != 0)
59 {
60 s = S(0+res(0)*(0 + res(1)*(zi-1)));
61 }
62 for(int yi = 0;yi<res(1);yi++)
63 {
64 // index of last signed item on this row
65 int signed_xi = -1;
66 if(yi != 0)
67 {
68 s = S(0+res(0)*(yi-1 + res(1)*zi));
69 }
70 for(int xi = 0;xi<res(0);xi++)
71 {
72 int i = xi+res(0)*(yi + res(1)*zi);
73 if(S(i)!=S(i))
74 {
75 if(s == s)
76 {
77 S(i) = s;
78 }
79 continue;
80 }
81 s = S(i);
82 flood(xi,yi,zi,signed_xi,signed_yi,signed_zi,s);
83 // remember this position
84 signed_xi = xi;
85 signed_yi = yi;
86 signed_zi = zi;
87 }
88 }
89 }
90}

Referenced by igl::copyleft::offset_surface(), and swept_volume_signed_distance().

+ Here is the caller graph for this function:

◆ floor()

template<typename DerivedX , typename DerivedY >
IGL_INLINE void igl::floor ( const Eigen::PlainObjectBase< DerivedX > &  X,
Eigen::PlainObjectBase< DerivedY > &  Y 
)
16{
17 using namespace std;
18 //Y = DerivedY::Zero(m,n);
19//#pragma omp parallel for
20 //for(int i = 0;i<m;i++)
21 //{
22 // for(int j = 0;j<n;j++)
23 // {
24 // Y(i,j) = std::floor(X(i,j));
25 // }
26 //}
27 typedef typename DerivedX::Scalar Scalar;
28 Y = X.unaryExpr([](const Scalar &x)->Scalar{return std::floor(x);}).template cast<typename DerivedY::Scalar >();
29}

◆ for_each() [1/2]

template<typename DerivedA , typename Func >
void igl::for_each ( const Eigen::DenseBase< DerivedA > &  A,
const Func &  func 
)
inline
51{
52 // Can **not** use parallel for because this must be _in order_
53 if(A.IsRowMajor)
54 {
55 for(typename DerivedA::Index i = 0;i<A.rows();i++)
56 {
57 for(typename DerivedA::Index j = 0;j<A.cols();j++)
58 {
59 func(i,j,A(i,j));
60 }
61 }
62 }else
63 {
64 for(typename DerivedA::Index j = 0;j<A.cols();j++)
65 {
66 for(typename DerivedA::Index i = 0;i<A.rows();i++)
67 {
68 func(i,j,A(i,j));
69 }
70 }
71 }
72
73}
@ IsRowMajor
Definition DenseBase.h:165

References Eigen::DenseBase< Derived >::IsRowMajor.

◆ for_each() [2/2]

template<typename AType , typename Func >
void igl::for_each ( const Eigen::SparseMatrix< AType > &  A,
const Func &  func 
)
inline
34{
35 // Can **not** use parallel for because this must be _in order_
36 // Iterate over outside
37 for(int k=0; k<A.outerSize(); ++k)
38 {
39 // Iterate over inside
40 for(typename Eigen::SparseMatrix<AType>::InnerIterator it (A,k); it; ++it)
41 {
42 func(it.row(),it.col(),it.value());
43 }
44 }
45}

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::outerSize().

Referenced by igl::matlab::MatlabWorkspace::clear(), find_zero(), max(), min(), igl::copyleft::cgal::minkowski_sum(), redux(), igl::copyleft::cgal::snap_rounding(), igl::copyleft::cgal::subdivide_segments(), and unique_edge_map().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ forward_kinematics() [1/4]

IGL_INLINE void igl::forward_kinematics ( const Eigen::MatrixXd &  C,
const Eigen::MatrixXi &  BE,
const Eigen::VectorXi &  P,
const std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > &  dQ,
const std::vector< Eigen::Vector3d > &  dT,
Eigen::MatrixXd &  T 
)
83{
84 using namespace Eigen;
85 using namespace std;
86 vector< Quaterniond,aligned_allocator<Quaterniond> > vQ;
87 vector< Vector3d> vT;
88 forward_kinematics(C,BE,P,dQ,dT,vQ,vT);
89 const int dim = C.cols();
90 T.resize(BE.rows()*(dim+1),dim);
91 for(int e = 0;e<BE.rows();e++)
92 {
93 Affine3d a = Affine3d::Identity();
94 a.translate(vT[e]);
95 a.rotate(vQ[e]);
96 T.block(e*(dim+1),0,dim+1,dim) =
97 a.matrix().transpose().block(0,0,dim+1,dim);
98 }
99}
IGL_INLINE void forward_kinematics(const Eigen::MatrixXd &C, const Eigen::MatrixXi &BE, const Eigen::VectorXi &P, const std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > &dQ, const std::vector< Eigen::Vector3d > &dT, std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > &vQ, std::vector< Eigen::Vector3d > &vT)
Definition forward_kinematics.cpp:12

References forward_kinematics().

+ Here is the call graph for this function:

◆ forward_kinematics() [2/4]

IGL_INLINE void igl::forward_kinematics ( const Eigen::MatrixXd &  C,
const Eigen::MatrixXi &  BE,
const Eigen::VectorXi &  P,
const std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > &  dQ,
const std::vector< Eigen::Vector3d > &  dT,
std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > &  vQ,
std::vector< Eigen::Vector3d > &  vT 
)
22{
23 using namespace std;
24 using namespace Eigen;
25 const int m = BE.rows();
26 assert(m == P.rows());
27 assert(m == (int)dQ.size());
28 assert(m == (int)dT.size());
29 vector<bool> computed(m,false);
30 vQ.resize(m);
31 vT.resize(m);
32 // Dynamic programming
33 function<void (int) > fk_helper = [&] (int b)
34 {
35 if(!computed[b])
36 {
37 if(P(b) < 0)
38 {
39 // base case for roots
40 vQ[b] = dQ[b];
41 const Vector3d r = C.row(BE(b,0)).transpose();
42 vT[b] = r-dQ[b]*r + dT[b];
43 }else
44 {
45 // Otherwise first compute parent's
46 const int p = P(b);
47 fk_helper(p);
48 vQ[b] = vQ[p] * dQ[b];
49 const Vector3d r = C.row(BE(b,0)).transpose();
50 vT[b] = vT[p] - vQ[b]*r + vQ[p]*(r + dT[b]);
51 }
52 computed[b] = true;
53 }
54 };
55 for(int b = 0;b<m;b++)
56 {
57 fk_helper(b);
58 }
59}

References void().

Referenced by forward_kinematics(), forward_kinematics(), forward_kinematics(), igl::opengl2::MouseController::set_selection(), and igl::opengl2::MouseController::set_selection_from_last_drag().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ forward_kinematics() [3/4]

IGL_INLINE void igl::forward_kinematics ( const Eigen::MatrixXd &  C,
const Eigen::MatrixXi &  BE,
const Eigen::VectorXi &  P,
const std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > &  dQ,
Eigen::MatrixXd &  T 
)
108{
109 std::vector<Eigen::Vector3d> dT(BE.rows(),Eigen::Vector3d(0,0,0));
110 return forward_kinematics(C,BE,P,dQ,dT,T);
111}

References forward_kinematics().

+ Here is the call graph for this function:

◆ forward_kinematics() [4/4]

IGL_INLINE void igl::forward_kinematics ( const Eigen::MatrixXd &  C,
const Eigen::MatrixXi &  BE,
const Eigen::VectorXi &  P,
const std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > &  dQ,
std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > &  vQ,
std::vector< Eigen::Vector3d > &  vT 
)
70{
71 std::vector<Eigen::Vector3d> dT(BE.rows(),Eigen::Vector3d(0,0,0));
72 return forward_kinematics(C,BE,P,dQ,dT,vQ,vT);
73}

References forward_kinematics().

+ Here is the call graph for this function:

◆ frame_field_deformer()

IGL_INLINE void igl::frame_field_deformer ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const Eigen::MatrixXd &  FF1,
const Eigen::MatrixXd &  FF2,
Eigen::MatrixXd &  V_d,
Eigen::MatrixXd &  FF1_d,
Eigen::MatrixXd &  FF2_d,
const int  iterations = 50,
const double  lambda = 0.1,
const bool  perturb_initial_guess = true 
)
383{
384 using namespace Eigen;
385 // Solvers
386 Frame_field_deformer deformer;
387
388 // Init optimizer
389 deformer.init(V, F, FF1, FF2, lambda, perturb_initial_guess ? 0.1 : 0);
390
391 // Optimize
392 deformer.optimize(iterations,true);
393
394 // Copy positions
395 V_d = deformer.V_w;
396
397 // Allocate
398 FF1_d.resize(F.rows(),3);
399 FF2_d.resize(F.rows(),3);
400
401 // Copy frame field
402 for(unsigned i=0; i<deformer.XF.size(); ++i)
403 {
404 FF1_d.row(i) = deformer.XF[i].col(0);
405 FF2_d.row(i) = deformer.XF[i].col(1);
406 }
407}
Definition frame_field_deformer.cpp:22
IGL_INLINE void init(const Eigen::MatrixXd &_V, const Eigen::MatrixXi &_F, const Eigen::MatrixXd &_D1, const Eigen::MatrixXd &_D2, double _Lambda, double _perturb_rotations, int _fixed=1)
Definition frame_field_deformer.cpp:103
IGL_INLINE void optimize(int N, bool reset=false)
Definition frame_field_deformer.cpp:134
std::vector< Eigen::Matrix< double, 3, 2 > > XF
Definition frame_field_deformer.cpp:77
Eigen::MatrixXd V_w
Definition frame_field_deformer.cpp:73

References igl::Frame_field_deformer::init(), igl::Frame_field_deformer::optimize(), igl::Frame_field_deformer::V_w, and igl::Frame_field_deformer::XF.

+ Here is the call graph for this function:

◆ frame_to_cross_field()

IGL_INLINE void igl::frame_to_cross_field ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const Eigen::MatrixXd &  FF1,
const Eigen::MatrixXd &  FF2,
Eigen::MatrixXd &  X 
)
18{
19 using namespace Eigen;
20
21 // Generate local basis
22 MatrixXd B1, B2, B3;
23
24 igl::local_basis(V,F,B1,B2,B3);
25
26 // Project the frame fields in the local basis
27 MatrixXd d1, d2;
28 d1.resize(F.rows(),2);
29 d2.resize(F.rows(),2);
30
31 d1 << igl::dot_row(B1,FF1), igl::dot_row(B2,FF1);
32 d2 << igl::dot_row(B1,FF2), igl::dot_row(B2,FF2);
33
34 X.resize(F.rows(), 3);
35
36 for (int i=0;i<F.rows();i++)
37 {
38 Vector2d v1 = d1.row(i);
39 Vector2d v2 = d2.row(i);
40
41 // define inverse map that maps the canonical axis to the given frame directions
42 Matrix2d A;
43 A << v1[0], v2[0],
44 v1[1], v2[1];
45
46 // find the closest rotation
48 Matrix2d C = svd.matrixU() * svd.matrixV().transpose();
49
50 Vector2d v = C.col(0);
51 X.row(i) = v(0) * B1.row(i) + v(1) * B2.row(i);
52 }
53}
Two-sided Jacobi SVD decomposition of a rectangular matrix.
Definition JacobiSVD.h:489
@ ComputeFullV
Definition Constants.h:387
@ ComputeFullU
Definition Constants.h:383
IGL_INLINE DerivedV dot_row(const Eigen::PlainObjectBase< DerivedV > &A, const Eigen::PlainObjectBase< DerivedV > &B)
Definition dot_row.cpp:11

References Eigen::ComputeFullU, Eigen::ComputeFullV, dot_row(), local_basis(), Eigen::SVDBase< Derived >::matrixU(), and Eigen::SVDBase< Derived >::matrixV().

+ Here is the call graph for this function:

◆ frustum()

template<typename DerivedP >
IGL_INLINE void igl::frustum ( const typename DerivedP::Scalar  left,
const typename DerivedP::Scalar  right,
const typename DerivedP::Scalar  bottom,
const typename DerivedP::Scalar  top,
const typename DerivedP::Scalar  nearVal,
const typename DerivedP::Scalar  farVal,
Eigen::PlainObjectBase< DerivedP > &  P 
)
18{
19 P.setConstant(4,4,0.);
20 P(0,0) = (2.0 * nearVal) / (right - left);
21 P(1,1) = (2.0 * nearVal) / (top - bottom);
22 P(0,2) = (right + left) / (right - left);
23 P(1,2) = (top + bottom) / (top - bottom);
24 P(2,2) = -(farVal + nearVal) / (farVal - nearVal);
25 P(3,2) = -1.0;
26 P(2,3) = -(2.0 * farVal * nearVal) / (farVal - nearVal);
27}

References Eigen::PlainObjectBase< Derived >::setConstant().

Referenced by igl::opengl::ViewerCore::draw().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ gaussian_curvature()

template<typename DerivedV , typename DerivedF , typename DerivedK >
IGL_INLINE void igl::gaussian_curvature ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedK > &  K 
)
17{
18 using namespace Eigen;
19 using namespace std;
20 // internal corner angles
21 Matrix<
22 typename DerivedV::Scalar,
23 DerivedF::RowsAtCompileTime,
24 DerivedF::ColsAtCompileTime> A;
25 internal_angles(V,F,A);
26 K.resize(V.rows(),1);
27 K.setConstant(V.rows(),1,2.*PI);
28 assert(A.rows() == F.rows());
29 assert(A.cols() == F.cols());
30 assert(K.rows() == V.rows());
31 assert(F.maxCoeff() < V.rows());
32 assert(K.cols() == 1);
33 const int Frows = F.rows();
34 //K_G(x_i) = (2π - ∑θj)
35//#ifndef IGL_GAUSSIAN_CURVATURE_OMP_MIN_VALUE
36//# define IGL_GAUSSIAN_CURVATURE_OMP_MIN_VALUE 1000
37//#endif
38//#pragma omp parallel for if (Frows>IGL_GAUSSIAN_CURVATURE_OMP_MIN_VALUE)
39 for(int f = 0;f<Frows;f++)
40 {
41 // throw normal at each corner
42 for(int j = 0; j < 3;j++)
43 {
44 // Q: Does this need to be critical?
45 // H: I think so, sadly. Maybe there's a way to use reduction
46//#pragma omp critical
47 K(F(f,j),0) -= A(f,j);
48 }
49 }
50}
IGL_INLINE void internal_angles(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedK > &K)
Definition internal_angles.cpp:15

References internal_angles(), PI, and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ get_seconds()

◆ get_seconds_hires()

IGL_INLINE double igl::get_seconds_hires ( )
25{
26 // Sorry I've no idea how performance counters work on Mac...
27 return igl::get_seconds();
28}
IGL_INLINE double get_seconds()
Definition get_seconds.cpp:10

References get_seconds().

Referenced by arap_dof_recomputation(), and arap_dof_update().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ grad()

template<typename DerivedV , typename DerivedF >
IGL_INLINE void igl::grad ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::SparseMatrix< typename DerivedV::Scalar > &  G,
bool  uniform = false 
)
231{
232 assert(F.cols() == 3 || F.cols() == 4);
233 if (F.cols() == 3)
234 return grad_tri(V,F,G,uniform);
235 if (F.cols() == 4)
236 return grad_tet(V,F,G,uniform);
237}
IGL_INLINE void grad_tet(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &T, Eigen::SparseMatrix< typename DerivedV::Scalar > &G, bool uniform)
Definition grad.cpp:18
IGL_INLINE void grad_tri(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::SparseMatrix< typename DerivedV::Scalar > &G, bool uniform)
Definition grad.cpp:119

References grad_tet(), and grad_tri().

Referenced by igl::copyleft::comiso::PoissonSolver< DerivedV, DerivedF >::BuildLaplacianMatrix(), igl::slim::compute_surface_gradient_matrix(), hessian(), and igl::slim::pre_calc().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ grid()

template<typename Derivedres , typename DerivedGV >
IGL_INLINE void igl::grid ( const Eigen::MatrixBase< Derivedres > &  res,
Eigen::PlainObjectBase< DerivedGV > &  GV 
)
16{
17 using namespace Eigen;
18 typedef typename DerivedGV::Scalar Scalar;
19 GV.resize(res(0)*res(1)*res(2),3);
20 for(int zi = 0;zi<res(2);zi++)
21 {
22 const auto lerp =
23 [&](const Scalar di, const int d)->Scalar{return di/(Scalar)(res(d)-1);};
24 const Scalar z = lerp(zi,2);
25 for(int yi = 0;yi<res(1);yi++)
26 {
27 const Scalar y = lerp(yi,1);
28 for(int xi = 0;xi<res(0);xi++)
29 {
30 const Scalar x = lerp(xi,0);
31 const int gi = xi+res(0)*(yi + res(1)*zi);
32 GV.row(gi) =
34 }
35 }
36 }
37}

References Eigen::PlainObjectBase< Derived >::resize().

Referenced by voxel_grid().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ grid_search()

template<typename Scalar , typename DerivedX , typename DerivedLB , typename DerivedUB , typename DerivedI >
IGL_INLINE Scalar igl::grid_search ( const std::function< Scalar(DerivedX &) >  f,
const Eigen::MatrixBase< DerivedLB > &  LB,
const Eigen::MatrixBase< DerivedUB > &  UB,
const Eigen::MatrixBase< DerivedI > &  I,
DerivedX &  X 
)
17{
18 Scalar fval = std::numeric_limits<Scalar>::max();
19 const int dim = LB.size();
20 assert(UB.size() == dim && "UB should match LB size");
21 assert(I.size() == dim && "I should match LB size");
22 X.resize(dim);
23
24 // Working X value
25 DerivedX Xrun(dim);
26 std::function<void(const int, DerivedX &)> looper;
27 int calls = 0;
28 looper = [&](
29 const int d,
30 DerivedX & Xrun)
31 {
32 assert(d < dim);
35 for(int c = 0;c<I(d);c++)
36 {
37 Xrun(d) = vals(c);
38 if(d+1 < dim)
39 {
40 looper(d+1,Xrun);
41 }else
42 {
43 //std::cout<<"call: "<<calls<<std::endl;
44 // Base case
45 const Scalar val = f(Xrun);
46 calls++;
47 if(val < fval)
48 {
49 fval = val;
50 X = Xrun;
51 std::cout<<calls<<": "<<fval<<" | "<<X<<std::endl;
52 }
53 }
54 }
55 };
56 looper(0,Xrun);
57
58 return fval;
59}

References void().

+ Here is the call graph for this function:

◆ group_sum_matrix() [1/2]

template<typename T >
IGL_INLINE void igl::group_sum_matrix ( const Eigen::Matrix< int, Eigen::Dynamic, 1 > &  G,
const int  k,
Eigen::SparseMatrix< T > &  A 
)
15{
16 // number of vertices
17 int n = G.rows();
18 assert(k > G.maxCoeff());
19
20 A.resize(k,n);
21
22 // builds A such that A(i,j) = 1 where i corresponds to group i and j
23 // corresponds to vertex j
24
25 // Loop over vertices
26 for(int j = 0;j<n;j++)
27 {
28 A.insert(G(j),j) = 1;
29 }
30
32}

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::insert(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::makeCompressed(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::resize(), and Eigen::PlainObjectBase< Derived >::rows().

Referenced by arap_dof_precomputation(), arap_precomputation(), and group_sum_matrix().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ group_sum_matrix() [2/2]

template<typename T >
IGL_INLINE void igl::group_sum_matrix ( const Eigen::Matrix< int, Eigen::Dynamic, 1 > &  G,
Eigen::SparseMatrix< T > &  A 
)
38{
39 return group_sum_matrix(G,G.maxCoeff()+1,A);
40}

References group_sum_matrix().

+ Here is the call graph for this function:

◆ guess_extension() [1/2]

IGL_INLINE std::string igl::guess_extension ( FILE *  fp)
102{
103 std::string guess;
104 guess_extension(fp,guess);
105 return guess;
106}
IGL_INLINE void guess_extension(FILE *fp, std::string &guess)
Definition guess_extension.cpp:8

References guess_extension().

+ Here is the call graph for this function:

◆ guess_extension() [2/2]

IGL_INLINE void igl::guess_extension ( FILE *  fp,
std::string &  guess 
)
9{
10 const auto is_off = [](FILE * fp)-> bool
11 {
12 char header[1000];
13 const std::string OFF("OFF");
14 const std::string NOFF("NOFF");
15 const std::string COFF("COFF");
16 bool f = (fscanf(fp,"%s\n",header)==1 && (
17 std::string(header).compare(0, OFF.length(), OFF)==0 ||
18 std::string(header).compare(0, COFF.length(), COFF)==0 ||
19 std::string(header).compare(0,NOFF.length(),NOFF)==0));
20 rewind(fp);
21 return f;
22 };
23 const auto is_ply = [](FILE * ply_file) -> bool
24 {
25 int nelems;
26 char ** elem_names;
27 igl::ply::PlyFile * in_ply = igl::ply::ply_read(ply_file,&nelems,&elem_names);
28 if(in_ply==NULL)
29 {
30 return false;
31 }
32 free(in_ply);
33 rewind(ply_file);
34 return true;
35 };
36 const auto is_wrl = [](FILE * wrl_file)->bool
37 {
38 bool still_comments = true;
39 char line[1000];
40 std::string needle("point [");
41 std::string haystack;
42 while(still_comments)
43 {
44 if(fgets(line,1000,wrl_file) == NULL)
45 {
46 rewind(wrl_file);
47 return false;
48 }
49 haystack = std::string(line);
50 still_comments = std::string::npos == haystack.find(needle);
51 }
52 rewind(wrl_file);
53 return true;
54 };
55 const auto is_mesh = [](FILE * mesh_file )->bool
56 {
57 char line[2048];
58 // eat comments at beginning of file
59 bool still_comments= true;
60 while(still_comments)
61 {
62 if(fgets(line,2048,mesh_file) == NULL)
63 {
64 rewind(mesh_file);
65 return false;
66 }
67 still_comments = (line[0] == '#' || line[0] == '\n');
68 }
69 char str[2048];
70 sscanf(line," %s",str);
71 // check that first word is MeshVersionFormatted
72 if(0!=strcmp(str,"MeshVersionFormatted"))
73 {
74 rewind(mesh_file);
75 return false;
76 }
77 rewind(mesh_file);
78 return true;
79 };
80 guess = "obj";
81 if(is_mesh(fp))
82 {
83 guess = "mesh";
84 }else if(is_off(fp))
85 {
86 guess = "off";
87 }else if(is_ply(fp))
88 {
89 guess = "ply";
90 }else if(igl::is_stl(fp))
91 {
92 guess = "stl";
93 }else if(is_wrl(fp))
94 {
95 guess = "wrl";
96 }
97 // else obj
98 rewind(fp);
99}
void free(void *)
#define OFF
Definition libavrdude.h:585
PlyFile * ply_read(FILE *, int *, char ***)
Definition ply.h:1023
Definition ply.h:160
IGL_INLINE bool is_stl(FILE *stl_file, bool &is_ascii)
Definition is_stl.cpp:3

References free(), is_stl(), OFF, and igl::ply::ply_read().

Referenced by guess_extension().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ harmonic() [1/5]

template<typename DerivedF , typename Derivedb , typename Derivedbc , typename DerivedW >
IGL_INLINE bool igl::harmonic ( const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< Derivedb > &  b,
const Eigen::MatrixBase< Derivedbc > &  bc,
const int  k,
Eigen::PlainObjectBase< DerivedW > &  W 
)
56{
57 using namespace Eigen;
58 typedef typename Derivedbc::Scalar Scalar;
61 // sum each row
63 sum(A,1,Asum);
64 // Convert row sums into diagonal of sparse matrix
66 diag(Asum,Adiag);
67 SparseMatrix<Scalar> L = A-Adiag;
69 speye(L.rows(),M);
70 return harmonic(L,M,b,bc,k,W);
71}
IGL_INLINE void diag(const Eigen::SparseMatrix< T > &X, Eigen::SparseVector< T > &V)
Definition diag.cpp:17

References adjacency_matrix(), diag(), harmonic(), L, speye(), and sum().

+ Here is the call graph for this function:

◆ harmonic() [2/5]

template<typename DerivedV , typename DerivedF , typename Derivedb , typename Derivedbc , typename DerivedW >
IGL_INLINE bool igl::harmonic ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< Derivedb > &  b,
const Eigen::MatrixBase< Derivedbc > &  bc,
const int  k,
Eigen::PlainObjectBase< DerivedW > &  W 
)
33{
34 using namespace Eigen;
35 typedef typename DerivedV::Scalar Scalar;
37 cotmatrix(V,F,L);
38 if(k>1)
39 {
40 massmatrix(V,F,MASSMATRIX_TYPE_DEFAULT,M);
41 }
42 return harmonic(L,M,b,bc,k,W);
43}

References cotmatrix(), harmonic(), L, massmatrix(), and MASSMATRIX_TYPE_DEFAULT.

Referenced by bbw(), igl::mosek::bbw(), bijective_composite_harmonic_mapping(), harmonic(), harmonic(), harmonic(), and harmonic().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ harmonic() [3/5]

template<typename DerivedV , typename DerivedF , typename DerivedQ >
IGL_INLINE void igl::harmonic ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const int  k,
Eigen::SparseMatrix< DerivedQ > &  Q 
)
150{
152 cotmatrix(V,F,L);
153 if(k>1)
154 {
155 massmatrix(V,F,MASSMATRIX_TYPE_DEFAULT,M);
156 }
157 return harmonic(L,M,k,Q);
158}

References cotmatrix(), harmonic(), L, massmatrix(), and MASSMATRIX_TYPE_DEFAULT.

+ Here is the call graph for this function:

◆ harmonic() [4/5]

template<typename DerivedL , typename DerivedM , typename Derivedb , typename Derivedbc , typename DerivedW >
IGL_INLINE bool igl::harmonic ( const Eigen::SparseMatrix< DerivedL > &  L,
const Eigen::SparseMatrix< DerivedM > &  M,
const Eigen::MatrixBase< Derivedb > &  b,
const Eigen::MatrixBase< Derivedbc > &  bc,
const int  k,
Eigen::PlainObjectBase< DerivedW > &  W 
)
86{
87 const int n = L.rows();
88 assert(n == L.cols() && "L must be square");
89 assert((k==1 || n == M.cols() ) && "M must be same size as L");
90 assert((k==1 || n == M.rows() ) && "M must be square");
91 assert((k==1 || igl::isdiag(M)) && "Mass matrix should be diagonal");
92
94 igl::harmonic(L,M,k,Q);
95
96 typedef DerivedL Scalar;
99 W.resize(n,bc.cols());
101 const VectorXS B = VectorXS::Zero(n,1);
102 for(int w = 0;w<bc.cols();w++)
103 {
104 const VectorXS bcw = bc.col(w);
105 VectorXS Ww;
106 if(!min_quad_with_fixed_solve(data,B,bcw,VectorXS(),Ww))
107 {
108 return false;
109 }
110 W.col(w) = Ww;
111 }
112 return true;
113}
IGL_INLINE bool isdiag(const Eigen::SparseMatrix< Scalar > &A)
Definition isdiag.cpp:11
Definition min_quad_with_fixed.h:124

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), harmonic(), isdiag(), L, min_quad_with_fixed_precompute(), min_quad_with_fixed_solve(), Eigen::PlainObjectBase< Derived >::resize(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows().

+ Here is the call graph for this function:

◆ harmonic() [5/5]

template<typename DerivedL , typename DerivedM , typename DerivedQ >
IGL_INLINE void igl::harmonic ( const Eigen::SparseMatrix< DerivedL > &  L,
const Eigen::SparseMatrix< DerivedM > &  M,
const int  k,
Eigen::SparseMatrix< DerivedQ > &  Q 
)
124{
125 assert(L.rows() == L.cols()&&"L should be square");
126 Q = -L;
127 if(k == 1) return;
128 assert(L.rows() == M.rows()&&"L should match M's dimensions");
129 assert(M.rows() == M.cols()&&"M should be square");
131 invert_diag(M,Mi);
132 // This is **not** robust for k>2. See KKT system in [Jacobson et al. 2010]
133 // of the kharmonic function in gptoolbox
134 for(int p = 1;p<k;p++)
135 {
136 Q = (Q*Mi*-L).eval();
137 }
138}
IGL_INLINE void invert_diag(const Eigen::SparseMatrix< T > &X, Eigen::SparseMatrix< T > &Y)
Definition invert_diag.cpp:11

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), invert_diag(), L, and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows().

+ Here is the call graph for this function:

◆ harwell_boeing()

template<typename Scalar , typename Index >
IGL_INLINE void igl::harwell_boeing ( const Eigen::SparseMatrix< Scalar > &  A,
int &  num_rows,
std::vector< Scalar > &  V,
std::vector< Index > &  R,
std::vector< Index > &  C 
)
17{
18 num_rows = A.rows();
19 int num_cols = A.cols();
20 int nnz = A.nonZeros();
21 V.resize(nnz);
22 R.resize(nnz);
23 C.resize(num_cols+1);
24
25 // Assumes outersize is columns
26 assert(A.cols() == A.outerSize());
27 int column_pointer = 0;
28 int i = 0;
29 int k = 0;
30 // Iterate over outside
31 for(; k<A.outerSize(); ++k)
32 {
33 C[k] = column_pointer;
34 // Iterate over inside
35 for(typename Eigen::SparseMatrix<Scalar>::InnerIterator it (A,k); it; ++it)
36 {
37 V[i] = it.value();
38 R[i] = it.row();
39 i++;
40 // Also increment column pointer
41 column_pointer++;
42 }
43 }
44 // by convention C[num_cols] = nnz
45 C[k] = column_pointer;
46}

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::nonZeros(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::outerSize(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows().

Referenced by igl::mosek::mosek_linprog(), and igl::mosek::mosek_quadprog().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hausdorff() [1/2]

template<typename DerivedV , typename Scalar >
IGL_INLINE void igl::hausdorff ( const Eigen::MatrixBase< DerivedV > &  V,
const std::function< Scalar(const Scalar &, const Scalar &, const Scalar &)> &  dist_to_B,
Scalar &  l,
Scalar &  u 
)
47{
48 // e 3-long vector of opposite edge lengths
50 // Maximum edge length
51 Scalar e_max = 0;
52 for(int i=0;i<3;i++)
53 {
54 e(i) = (V.row((i+1)%3)-V.row((i+2)%3)).norm();
55 e_max = std::max(e_max,e(i));
56 }
57 // Semiperimeter
58 const Scalar s = (e(0)+e(1)+e(2))*0.5;
59 // Area
60 const Scalar A = sqrt(s*(s-e(0))*(s-e(1))*(s-e(2)));
61 // Circumradius
62 const Scalar R = e(0)*e(1)*e(2)/(4.*A);
63 // inradius
64 const Scalar r = A/s;
65 // Initialize lower bound to ∞
66 l = std::numeric_limits<Scalar>::infinity();
67 // d 3-long vector of distance from each corner to B
69 Scalar u1 = std::numeric_limits<Scalar>::infinity();
70 Scalar u2 = 0;
71 for(int i=0;i<3;i++)
72 {
73 d(i) = dist_to_B(V(i,0),V(i,1),V(i,2));
74 // Lower bound is simply the max over vertex distances
75 l = std::max(d(i),l);
76 // u1 is the minimum of corner distances + maximum adjacent edge
77 u1 = std::min(u1,d(i) + std::max(e((i+1)%3),e((i+2)%3)));
78 // u2 first takes the maximum over corner distances
79 u2 = std::max(u2,d(i));
80 }
81 // u2 is the distance from the circumcenter/midpoint of obtuse edge plus the
82 // largest corner distance
83 u2 += (s-r>2.*R ? R : 0.5*e_max);
84 u = std::min(u1,u2);
85}

References sqrt().

+ Here is the call graph for this function:

◆ hausdorff() [2/2]

template<typename DerivedVA , typename DerivedFA , typename DerivedVB , typename DerivedFB , typename Scalar >
IGL_INLINE void igl::hausdorff ( const Eigen::PlainObjectBase< DerivedVA > &  VA,
const Eigen::PlainObjectBase< DerivedFA > &  FA,
const Eigen::PlainObjectBase< DerivedVB > &  VB,
const Eigen::PlainObjectBase< DerivedFB > &  FB,
Scalar &  d 
)
23{
24 using namespace Eigen;
25 assert(VA.cols() == 3 && "VA should contain 3d points");
26 assert(FA.cols() == 3 && "FA should contain triangles");
27 assert(VB.cols() == 3 && "VB should contain 3d points");
28 assert(FB.cols() == 3 && "FB should contain triangles");
29 Matrix<Scalar,Dynamic,1> sqr_DBA,sqr_DAB;
32 point_mesh_squared_distance(VB,VA,FA,sqr_DBA,I,C);
33 point_mesh_squared_distance(VA,VB,FB,sqr_DAB,I,C);
34 const Scalar dba = sqr_DBA.maxCoeff();
35 const Scalar dab = sqr_DAB.maxCoeff();
36 d = sqrt(std::max(dba,dab));
37}

References Eigen::PlainObjectBase< Derived >::cols(), and sqrt().

Referenced by igl::copyleft::cgal::hausdorff().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hessian()

template<typename DerivedV , typename DerivedF , typename Scalar >
IGL_INLINE void igl::hessian ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::SparseMatrix< Scalar > &  H 
)
24{
25 typedef typename DerivedV::Scalar denseScalar;
27 typedef typename Eigen::SparseMatrix<Scalar> SparseMat;
28 typedef typename Eigen::DiagonalMatrix
29 <Scalar, Eigen::Dynamic, Eigen::Dynamic> DiagMat;
30
31 int dim = V.cols();
32 assert((dim==2 || dim==3) &&
33 "The dimension of the vertices should be 2 or 3");
34
35 //Construct the combined gradient matric
36 SparseMat G;
37 igl::grad(DerivedV(V),
38 DerivedF(F),
39 G, false);
40 SparseMat GG(F.rows(), dim*V.rows());
41 GG.reserve(G.nonZeros());
42 for(int i=0; i<dim; ++i)
43 GG.middleCols(i*G.cols(),G.cols()) = G.middleRows(i*F.rows(),F.rows());
44 SparseMat D;
45 igl::repdiag(GG,dim,D);
46
47 //Compute area matrix
48 VecXd areas;
49 igl::doublearea(V, F, areas);
50 DiagMat A = (0.5*areas).replicate(dim,1).asDiagonal();
51
52 //Compute FEM Hessian
53 H = D.transpose()*A*G;
54}
const int Dynamic
Definition Constants.h:21
IGL_INLINE void grad(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::SparseMatrix< typename DerivedV::Scalar > &G, bool uniform=false)
Definition grad.cpp:227

References doublearea(), Eigen::Dynamic, grad(), repdiag(), and Eigen::SparseMatrixBase< Derived >::transpose().

Referenced by hessian_energy().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hessian_energy()

template<typename DerivedV , typename DerivedF , typename Scalar >
IGL_INLINE void igl::hessian_energy ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::SparseMatrix< Scalar > &  Q 
)
22{
23 typedef typename DerivedV::Scalar denseScalar;
25 typedef typename Eigen::SparseMatrix<Scalar> SparseMat;
26 typedef typename Eigen::DiagonalMatrix
27 <Scalar, Eigen::Dynamic, Eigen::Dynamic> DiagMat;
28
29 int dim = V.cols();
30 assert((dim==2 || dim==3) &&
31 "The dimension of the vertices should be 2 or 3");
32
33 SparseMat M;
35
36 //Kill non-interior DOFs
37 VecXd Mint = M.diagonal();
38 std::vector<std::vector<int> > bdryLoop;
39 igl::boundary_loop(DerivedF(F),bdryLoop);
40 for(const std::vector<int>& loop : bdryLoop)
41 for(const int& bdryVert : loop)
42 Mint(bdryVert) = 0.;
43
44 //Invert Mint
45 for(int i=0; i<Mint.rows(); ++i)
46 if(Mint(i) > 0)
47 Mint(i) = 1./Mint(i);
48
49 //Repeat Mint to form diaginal matrix
50 DiagMat stackedMinv = Mint.replicate(dim*dim,1).asDiagonal();
51
52 //Compute squared Hessian
53 SparseMat H;
54 igl::hessian(V,F,H);
55 Q = H.transpose()*stackedMinv*H;
56
57}
IGL_INLINE void hessian(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::SparseMatrix< Scalar > &H)
Definition hessian.cpp:20
IGL_INLINE void loop(const int n_verts, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::SparseMatrix< SType > &S, Eigen::PlainObjectBase< DerivedNF > &NF)
Definition loop.cpp:21

References boundary_loop(), Eigen::Dynamic, hessian(), loop(), massmatrix(), MASSMATRIX_TYPE_VORONOI, and Eigen::SparseMatrixBase< Derived >::transpose().

+ Here is the call graph for this function:

◆ histc() [1/3]

template<typename DerivedX , typename DerivedE , typename DerivedB >
IGL_INLINE void igl::histc ( const Eigen::MatrixBase< DerivedX > &  X,
const Eigen::MatrixBase< DerivedE > &  E,
Eigen::PlainObjectBase< DerivedB > &  B 
)
41{
42 const int m = X.size();
43 using namespace std;
44 assert(
45 (E.bottomRightCorner(E.size()-1,1) -
46 E.topLeftCorner(E.size()-1,1)).maxCoeff() >= 0 &&
47 "E should be monotonically increasing");
48 B.resize(m,1);
49#pragma omp parallel for
50 for(int j = 0;j<m;j++)
51 {
52 const double x = X(j);
53 // Boring one-offs
54 if(x < E(0) || x > E(E.size()-1))
55 {
56 B(j) = -1;
57 continue;
58 }
59 // Find x in E
60 int l = 0;
61 int h = E.size()-1;
62 int k = l;
63 while((h-l)>1)
64 {
65 assert(x >= E(l));
66 assert(x <= E(h));
67 k = (h+l)/2;
68 if(x < E(k))
69 {
70 h = k;
71 }else
72 {
73 l = k;
74 }
75 }
76 if(x == E(h))
77 {
78 k = h;
79 }else
80 {
81 k = l;
82 }
83 B(j) = k;
84 }
85}

References Eigen::PlainObjectBase< Derived >::resize().

+ Here is the call graph for this function:

◆ histc() [2/3]

template<typename DerivedX , typename DerivedE , typename DerivedN , typename DerivedB >
IGL_INLINE void igl::histc ( const Eigen::MatrixBase< DerivedX > &  X,
const Eigen::MatrixBase< DerivedE > &  E,
Eigen::PlainObjectBase< DerivedN > &  N,
Eigen::PlainObjectBase< DerivedB > &  B 
)
18{
19 histc(X,E,B);
20 const int n = E.size();
21 const int m = X.size();
22 assert(m == B.size());
23 N.resize(n,1);
24 N.setConstant(0);
25#pragma omp parallel for
26 for(int j = 0;j<m;j++)
27 {
28 if(B(j) >= 0)
29 {
30#pragma omp atomic
31 N(B(j))++;
32 }
33 }
34}
IGL_INLINE void histc(const Eigen::MatrixBase< DerivedX > &X, const Eigen::MatrixBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedN > &N, Eigen::PlainObjectBase< DerivedB > &B)
Definition histc.cpp:13

References histc(), Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::setConstant().

Referenced by histc(), ramer_douglas_peucker(), and random_points_on_mesh().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ histc() [3/3]

template<typename DerivedE >
IGL_INLINE void igl::histc ( const typename DerivedE::Scalar &  x,
const Eigen::MatrixBase< DerivedE > &  E,
typename DerivedE::Index &  b 
)
92{
94 X(0) = x;
96 hist(X,E,B);
97 b = B(0);
98}

◆ hsv_to_rgb() [1/3]

template<typename DerivedH , typename DerivedR >
void igl::hsv_to_rgb ( const Eigen::PlainObjectBase< DerivedH > &  H,
Eigen::PlainObjectBase< DerivedR > &  R 
)
49{
50 assert(H.cols() == 3);
51 R.resizeLike(H);
52 for(typename DerivedH::Index r = 0;r<H.rows();r++)
53 {
54 typename DerivedH::Scalar hsv[3];
55 hsv[0] = H(r,0);
56 hsv[1] = H(r,1);
57 hsv[2] = H(r,2);
58 typename DerivedR::Scalar rgb[] = {0,0,0};
59 hsv_to_rgb(hsv,rgb);
60 R(r,0) = rgb[0];
61 R(r,1) = rgb[1];
62 R(r,2) = rgb[2];
63 }
64}

References Eigen::PlainObjectBase< Derived >::cols(), hsv_to_rgb(), Eigen::PlainObjectBase< Derived >::resizeLike(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ hsv_to_rgb() [2/3]

template<typename T >
IGL_INLINE void igl::hsv_to_rgb ( const T &  h,
const T &  s,
const T &  v,
T &  r,
T &  g,
T &  b 
)
24{
25 // From medit
26 double f,p,q,t,hh;
27 int i;
28 hh = ((int)h % 360) / 60.;
29 i = (int)std::floor(hh); /* largest int <= h */
30 f = hh - i; /* fractional part of h */
31 p = v * (1.0 - s);
32 q = v * (1.0 - (s * f));
33 t = v * (1.0 - (s * (1.0 - f)));
34
35 switch(i) {
36 case 0: r = v; g = t; b = p; break;
37 case 1: r = q; g = v; b = p; break;
38 case 2: r = p; g = v; b = t; break;
39 case 3: r = p; g = q; b = v; break;
40 case 4: r = t; g = p; b = v; break;
41 case 5: r = v; g = p; b = q; break;
42 }
43}

◆ hsv_to_rgb() [3/3]

template<typename T >
IGL_INLINE void igl::hsv_to_rgb ( const T *  hsv,
T *  rgb 
)
14{
16 hsv[0],hsv[1],hsv[2],
17 rgb[0],rgb[1],rgb[2]);
18}
IGL_INLINE void hsv_to_rgb(const T *hsv, T *rgb)
Definition hsv_to_rgb.cpp:13

References hsv_to_rgb().

Referenced by hsv_to_rgb(), and hsv_to_rgb().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ in_element() [1/2]

template<typename DerivedV , typename DerivedQ , int DIM, typename Scalar >
IGL_INLINE void igl::in_element ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::MatrixXi &  Ele,
const Eigen::PlainObjectBase< DerivedQ > &  Q,
const AABB< DerivedV, DIM > &  aabb,
Eigen::SparseMatrix< Scalar > &  I 
)
41{
42 using namespace std;
43 using namespace Eigen;
44 const int Qr = Q.rows();
45 std::vector<Triplet<Scalar> > IJV;
46 IJV.reserve(Qr);
47#pragma omp parallel for if (Qr>10000)
48 for(int e = 0;e<Qr;e++)
49 {
50 // find all
51 const auto R = aabb.find(V,Ele,Q.row(e).eval(),false);
52 for(const auto r : R)
53 {
54#pragma omp critical
55 IJV.push_back(Triplet<Scalar>(e,r,1));
56 }
57 }
58 I.resize(Qr,Ele.rows());
59 I.setFromTriplets(IJV.begin(),IJV.end());
60}
IGL_INLINE std::vector< int > find(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedEle > &Ele, const Eigen::MatrixBase< Derivedq > &q, const bool first=false) const
Definition AABB.cpp:206

References igl::AABB< DerivedV, DIM >::find(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::resize(), Eigen::PlainObjectBase< Derived >::rows(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets().

+ Here is the call graph for this function:

◆ in_element() [2/2]

template<typename DerivedV , typename DerivedQ , int DIM>
IGL_INLINE void igl::in_element ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::MatrixXi &  Ele,
const Eigen::PlainObjectBase< DerivedQ > &  Q,
const AABB< DerivedV, DIM > &  aabb,
Eigen::VectorXi &  I 
)
17{
18 using namespace std;
19 using namespace Eigen;
20 const int Qr = Q.rows();
21 I.setConstant(Qr,1,-1);
22#pragma omp parallel for if (Qr>10000)
23 for(int e = 0;e<Qr;e++)
24 {
25 // find all
26 const auto R = aabb.find(V,Ele,Q.row(e).eval(),true);
27 if(!R.empty())
28 {
29 I(e) = R[0];
30 }
31 }
32}

References igl::AABB< DerivedV, DIM >::find(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ infinite_cost_stopping_condition() [1/2]

IGL_INLINE std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int)> igl::infinite_cost_stopping_condition ( const std::function< void(const int, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> &  cost_and_placement)
89{
90 std::function<bool(
91 const Eigen::MatrixXd &,
92 const Eigen::MatrixXi &,
93 const Eigen::MatrixXi &,
94 const Eigen::VectorXi &,
95 const Eigen::MatrixXi &,
96 const Eigen::MatrixXi &,
97 const std::set<std::pair<double,int> > &,
98 const std::vector<std::set<std::pair<double,int> >::iterator > &,
99 const Eigen::MatrixXd &,
100 const int,
101 const int,
102 const int,
103 const int,
104 const int)> stopping_condition;
105 infinite_cost_stopping_condition(cost_and_placement,stopping_condition);
106 return stopping_condition;
107}
IGL_INLINE void infinite_cost_stopping_condition(const std::function< void(const int, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> &cost_and_placement, std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int)> &stopping_condition)
Definition infinite_cost_stopping_condition.cpp:10

References infinite_cost_stopping_condition().

+ Here is the call graph for this function:

◆ infinite_cost_stopping_condition() [2/2]

IGL_INLINE void igl::infinite_cost_stopping_condition ( const std::function< void(const int, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> &  cost_and_placement,
std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int)> &  stopping_condition 
)
36{
37 stopping_condition =
38 [&cost_and_placement]
39 (
40 const Eigen::MatrixXd & V,
41 const Eigen::MatrixXi & F,
42 const Eigen::MatrixXi & E,
43 const Eigen::VectorXi & EMAP,
44 const Eigen::MatrixXi & EF,
45 const Eigen::MatrixXi & EI,
46 const std::set<std::pair<double,int> > & Q,
47 const std::vector<std::set<std::pair<double,int> >::iterator > & Qit,
48 const Eigen::MatrixXd & C,
49 const int e,
50 const int /*e1*/,
51 const int /*e2*/,
52 const int /*f1*/,
53 const int /*f2*/)->bool
54 {
55 Eigen::RowVectorXd p;
56 double cost;
57 cost_and_placement(e,V,F,E,EMAP,EF,EI,cost,p);
58 return std::isinf(cost);
59 };
60}

Referenced by infinite_cost_stopping_condition(), and simplify_polyhedron().

+ Here is the caller graph for this function:

◆ inradius()

template<typename DerivedV , typename DerivedF , typename DerivedR >
IGL_INLINE void igl::inradius ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedR > &  R 
)
20{
23 igl::edge_lengths(V,F,l);
24 // If R is the circumradius,
25 // R*r = (abc)/(2*(a+b+c))
26 // R = abc/(4*area)
27 // r(abc/(4*area)) = (abc)/(2*(a+b+c))
28 // r/(4*area) = 1/(2*(a+b+c))
29 // r = (2*area)/(a+b+c)
30 DerivedR A;
31 igl::doublearea(l,0.,A);
32 r = A.array() /l.array().rowwise().sum();
33}

References doublearea(), and edge_lengths().

+ Here is the call graph for this function:

◆ internal_angles()

template<typename DerivedV , typename DerivedF , typename DerivedK >
IGL_INLINE void igl::internal_angles ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedK > &  K 
)
19{
20 using namespace Eigen;
21 using namespace std;
22 typedef typename DerivedV::Scalar Scalar;
23 if(F.cols() == 3)
24 {
25 // Edge lengths
26 Matrix<
27 Scalar,
28 DerivedF::RowsAtCompileTime,
29 DerivedF::ColsAtCompileTime> L_sq;
31
32 assert(F.cols() == 3 && "F should contain triangles");
34 }else
35 {
36 assert(V.cols() == 3 && "If F contains non-triangle facets, V must be 3D");
37 K.resizeLike(F);
38 auto corner = [](
39 const typename DerivedV::ConstRowXpr & x,
40 const typename DerivedV::ConstRowXpr & y,
41 const typename DerivedV::ConstRowXpr & z)
42 {
43 typedef Eigen::Matrix<Scalar,1,3> RowVector3S;
44 RowVector3S v1 = (x-y).normalized();
45 RowVector3S v2 = (z-y).normalized();
46 // http://stackoverflow.com/questions/10133957/signed-angle-between-two-vectors-without-a-reference-plane
47 Scalar s = v1.cross(v2).norm();
48 Scalar c = v1.dot(v2);
49 return atan2(s, c);
50 };
51 for(unsigned i=0; i<F.rows(); ++i)
52 {
53 for(unsigned j=0; j<F.cols(); ++j)
54 {
55 K(i,j) = corner(
56 V.row(F(i,int(j-1+F.cols())%F.cols())),
57 V.row(F(i,j)),
58 V.row(F(i,(j+1+F.cols())%F.cols()))
59 );
60 }
61 }
62 }
63}
IGL_INLINE void internal_angles_using_squared_edge_lengths(const Eigen::MatrixBase< DerivedL > &L_sq, Eigen::PlainObjectBase< DerivedK > &K)
Definition internal_angles.cpp:66

References internal_angles_using_squared_edge_lengths(), and squared_edge_lengths().

Referenced by gaussian_curvature(), and per_vertex_normals().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ internal_angles_using_edge_lengths()

template<typename DerivedL , typename DerivedK >
IGL_INLINE void igl::internal_angles_using_edge_lengths ( const Eigen::MatrixBase< DerivedL > &  L,
Eigen::PlainObjectBase< DerivedK > &  K 
)
93{
94 // Note:
95 // Usage of internal_angles_using_squared_edge_lengths() is preferred to internal_angles_using_squared_edge_lengths()
96 // This function is deprecated and probably will be removed in future versions
97 typedef typename DerivedL::Index Index;
98 assert(L.cols() == 3 && "Edge-lengths should come from triangles");
99 const Index m = L.rows();
100 K.resize(m,3);
102 m,
103 [&L,&K](const Index f)
104 {
105 for(size_t d = 0;d<3;d++)
106 {
107 const auto & s1 = L(f,d);
108 const auto & s2 = L(f,(d+1)%3);
109 const auto & s3 = L(f,(d+2)%3);
110 K(f,d) = acos((s3*s3 + s2*s2 - s1*s1)/(2.*s3*s2));
111 }
112 },
113 1000l);
114}

References acos(), L, and parallel_for().

+ Here is the call graph for this function:

◆ internal_angles_using_squared_edge_lengths()

template<typename DerivedL , typename DerivedK >
IGL_INLINE void igl::internal_angles_using_squared_edge_lengths ( const Eigen::MatrixBase< DerivedL > &  L_sq,
Eigen::PlainObjectBase< DerivedK > &  K 
)
69{
70 typedef typename DerivedL::Index Index;
71 assert(L_sq.cols() == 3 && "Edge-lengths should come from triangles");
72 const Index m = L_sq.rows();
73 K.resize(m,3);
75 m,
76 [&L_sq,&K](const Index f)
77 {
78 for(size_t d = 0;d<3;d++)
79 {
80 const auto & s1 = L_sq(f,d);
81 const auto & s2 = L_sq(f,(d+1)%3);
82 const auto & s3 = L_sq(f,(d+2)%3);
83 K(f,d) = acos((s3 + s2 - s1)/(2.*sqrt(s3*s2)));
84 }
85 },
86 1000l);
87}

References acos(), parallel_for(), and sqrt().

Referenced by internal_angles().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ intersect() [1/2]

template<class M >
IGL_INLINE M igl::intersect ( const M &  A,
const M &  B 
)
42{
43 M C;
44 intersect(A,B,C);
45 return C;
46}

References intersect().

+ Here is the call graph for this function:

◆ intersect() [2/2]

template<class M >
IGL_INLINE void igl::intersect ( const M &  A,
const M &  B,
M &  C 
)
11{
12 // Stupid O(size(A) * size(B)) to do it
13 // Alec: This should be implemented by using unique and sort like `setdiff`
14 M dyn_C(A.size() > B.size() ? A.size() : B.size(),1);
15 // count of intersects
16 int c = 0;
17 // Loop over A
18 for(int i = 0;i<A.size();i++)
19 {
20 // Loop over B
21 for(int j = 0;j<B.size();j++)
22 {
23 if(A(i) == B(j))
24 {
25 dyn_C(c) = A(i);
26 c++;
27 }
28 }
29 }
30
31 // resize output
32 C.resize(c,1);
33 // Loop over intersects
34 for(int i = 0;i<c;i++)
35 {
36 C(i) = dyn_C(i);
37 }
38}

Referenced by igl::opengl2::RotateWidget::down(), edge_collapse_is_valid(), intersect(), igl::copyleft::cgal::SelfIntersectMesh< Kernel, DerivedV, DerivedF, DerivedVV, DerivedFF, DerivedIF, DerivedJ, DerivedIM >::process_intersecting_boxes(), and igl::copyleft::cgal::SelfIntersectMesh< Kernel, DerivedV, DerivedF, DerivedVV, DerivedFF, DerivedIF, DerivedJ, DerivedIM >::single_shared_vertex().

+ Here is the caller graph for this function:

◆ invert_diag()

template<typename T >
IGL_INLINE void igl::invert_diag ( const Eigen::SparseMatrix< T > &  X,
Eigen::SparseMatrix< T > &  Y 
)
14{
15#ifndef NDEBUG
16 typename Eigen::SparseVector<T> dX = X.diagonal().sparseView();
17 // Check that there are no zeros along the diagonal
18 assert(dX.nonZeros() == dX.size());
19#endif
20 // http://www.alecjacobson.com/weblog/?p=2552
21 if(&Y != &X)
22 {
23 Y = X;
24 }
25 // Iterate over outside
26 for(int k=0; k<Y.outerSize(); ++k)
27 {
28 // Iterate over inside
29 for(typename Eigen::SparseMatrix<T>::InnerIterator it (Y,k); it; ++it)
30 {
31 if(it.col() == it.row())
32 {
33 T v = it.value();
34 assert(v != 0);
35 v = ((T)1.0)/v;
36 Y.coeffRef(it.row(),it.col()) = v;
37 }
38 }
39 }
40}
Index nonZeros() const
Definition SparseVector.h:140

References Eigen::SparseVector< _Scalar, _Options, _StorageIndex >::nonZeros(), and Eigen::SparseMatrixBase< Derived >::size().

Referenced by harmonic().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ is_border_vertex()

template<typename DerivedV , typename DerivedF >
IGL_INLINE std::vector< bool > igl::is_border_vertex ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F 
)
17{
18 DerivedF FF;
20 std::vector<bool> ret(V.rows());
21 for(unsigned i=0; i<ret.size();++i)
22 ret[i] = false;
23
24 for(unsigned i=0; i<F.rows();++i)
25 for(unsigned j=0;j<F.cols();++j)
26 if(FF(i,j) == -1)
27 {
28 ret[F(i,j)] = true;
29 ret[F(i,(j+1)%F.cols())] = true;
30 }
31 return ret;
32}

References Eigen::PlainObjectBase< Derived >::rows(), and triangle_triangle_adjacency().

Referenced by igl::MissMatchCalculator< DerivedV, DerivedF, DerivedM >::MissMatchCalculator(), igl::MissMatchCalculatorLine< DerivedV, DerivedF, DerivedO >::MissMatchCalculatorLine(), boundary_loop(), cut_mesh(), find_cross_field_singularities(), and is_irregular_vertex().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ is_boundary_edge() [1/2]

template<typename DerivedF , typename DerivedE , typename DerivedB >
void igl::is_boundary_edge ( const Eigen::PlainObjectBase< DerivedE > &  E,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedB > &  B 
)
20{
21 using namespace Eigen;
22 using namespace std;
23 // Should be triangles
24 assert(F.cols() == 3);
25 // Should be edges
26 assert(E.cols() == 2);
27 // number of faces
28 const int m = F.rows();
29 // Collect all directed edges after E
30 MatrixXi EallE(E.rows()+3*m,2);
31 EallE.block(0,0,E.rows(),E.cols()) = E;
32 for(int e = 0;e<3;e++)
33 {
34 for(int f = 0;f<m;f++)
35 {
36 for(int c = 0;c<2;c++)
37 {
38 // 12 20 01
39 EallE(E.rows()+m*e+f,c) = F(f,(c+1+e)%3);
40 }
41 }
42 }
43 // sort directed edges into undirected edges
44 MatrixXi sorted_EallE,_;
45 sort(EallE,2,true,sorted_EallE,_);
46 // Determine unique undirected edges E and map to directed edges EMAP
47 MatrixXi uE;
48 VectorXi EMAP;
49 unique_rows(sorted_EallE,uE,_,EMAP);
50 // Counts of occurrences
51 VectorXi N = VectorXi::Zero(uE.rows());
52 for(int e = 0;e<EMAP.rows();e++)
53 {
54 N(EMAP(e))++;
55 }
56 B.resize(E.rows());
57 // Look of occurrences of 2: one for original and another for boundary
58 for(int e = 0;e<E.rows();e++)
59 {
60 B(e) = (N(EMAP(e)) == 2);
61 }
62}

References _, Eigen::PlainObjectBase< Derived >::resize(), sort(), and unique_rows().

+ Here is the call graph for this function:

◆ is_boundary_edge() [2/2]

template<typename DerivedF , typename DerivedE , typename DerivedB , typename DerivedEMAP >
void igl::is_boundary_edge ( const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedB > &  B,
Eigen::PlainObjectBase< DerivedE > &  E,
Eigen::PlainObjectBase< DerivedEMAP > &  EMAP 
)
75{
76 using namespace Eigen;
77 using namespace std;
78 // Should be triangles
79 assert(F.cols() == 3);
80 // number of faces
81 const int m = F.rows();
82 // Collect all directed edges after E
83 MatrixXi allE(3*m,2);
84 for(int e = 0;e<3;e++)
85 {
86 for(int f = 0;f<m;f++)
87 {
88 for(int c = 0;c<2;c++)
89 {
90 // 12 20 01
91 allE(m*e+f,c) = F(f,(c+1+e)%3);
92 }
93 }
94 }
95 // sort directed edges into undirected edges
96 MatrixXi sorted_allE,_;
97 sort(allE,2,true,sorted_allE,_);
98 // Determine unique undirected edges E and map to directed edges EMAP
99 unique_rows(sorted_allE,E,_,EMAP);
100 // Counts of occurrences
101 VectorXi N = VectorXi::Zero(E.rows());
102 for(int e = 0;e<EMAP.rows();e++)
103 {
104 N(EMAP(e))++;
105 }
106 B.resize(E.rows());
107 // Look of occurrences of 1
108 for(int e = 0;e<E.rows();e++)
109 {
110 B(e) = N(e) == 1;
111 }
112}

References _, Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), sort(), and unique_rows().

+ Here is the call graph for this function:

◆ is_dir()

IGL_INLINE bool igl::is_dir ( const char *  filename)
21{
22 struct stat status;
23 if(stat(filename,&status)!=0)
24 {
25 // path does not exist
26 return false;
27 }
28 // Tests whether existing path is a directory
29 return S_ISDIR(status.st_mode);
30}
#define S_ISDIR(mode)
Definition is_dir.cpp:13

References S_ISDIR, and stat.

◆ is_edge_manifold() [1/2]

template<typename DerivedF >
IGL_INLINE bool igl::is_edge_manifold ( const Eigen::MatrixBase< DerivedF > &  F)
58{
59 // TODO: It's bothersome that this is not calling/reusing the code from the
60 // overload above. This could result in disagreement.
61
62 // List of edges (i,j,f,c) where edge i<j is associated with corner i of face
63 // f
64 std::vector<std::vector<int> > TTT;
65 for(int f=0;f<F.rows();++f)
66 for (int i=0;i<3;++i)
67 {
68 // v1 v2 f ei
69 int v1 = F(f,i);
70 int v2 = F(f,(i+1)%3);
71 if (v1 > v2) std::swap(v1,v2);
72 std::vector<int> r(4);
73 r[0] = v1; r[1] = v2;
74 r[2] = f; r[3] = i;
75 TTT.push_back(r);
76 }
77 // Sort lexicographically
78 std::sort(TTT.begin(),TTT.end());
79
80 for(int i=2;i<(int)TTT.size();++i)
81 {
82 // Check any edges occur 3 times
83 std::vector<int>& r1 = TTT[i-2];
84 std::vector<int>& r2 = TTT[i-1];
85 std::vector<int>& r3 = TTT[i];
86 if ( (r1[0] == r2[0] && r2[0] == r3[0])
87 &&
88 (r1[1] == r2[1] && r2[1] == r3[1]) )
89 {
90 return false;
91 }
92 }
93 return true;
94}

◆ is_edge_manifold() [2/2]

template<typename DerivedF , typename DerivedBF , typename DerivedE , typename DerivedEMAP , typename DerivedBE >
IGL_INLINE bool igl::is_edge_manifold ( const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedBF > &  BF,
Eigen::PlainObjectBase< DerivedE > &  E,
Eigen::PlainObjectBase< DerivedEMAP > &  EMAP,
Eigen::PlainObjectBase< DerivedBE > &  BE 
)
27{
28 using namespace Eigen;
29 typedef typename DerivedF::Index Index;
32 MatrixXF2 allE;
33 oriented_facets(F,allE);
34 // Find unique undirected edges and mapping
35 VectorXF _;
36 unique_simplices(allE,E,_,EMAP);
37 std::vector<typename DerivedF::Index> count(E.rows(),0);
38 for(Index e = 0;e<EMAP.rows();e++)
39 {
40 count[EMAP[e]]++;
41 }
42 const Index m = F.rows();
43 BF.resize(m,3);
44 BE.resize(E.rows(),1);
45 bool all = true;
46 for(Index e = 0;e<EMAP.rows();e++)
47 {
48 const bool manifold = count[EMAP[e]] <= 2;
49 all &= BF(e%m,e/m) = manifold;
50 BE(EMAP[e]) = manifold;
51 }
52 return all;
53}
IGL_INLINE void all(const Eigen::SparseMatrix< AType > &A, const int dim, Eigen::PlainObjectBase< DerivedB > &B)
Definition all.cpp:13

References _, all(), count(), oriented_facets(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), and unique_simplices().

Referenced by crouzeix_raviart_cotmatrix(), crouzeix_raviart_massmatrix(), decimate(), edge_topology(), and qslim().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ is_file()

IGL_INLINE bool igl::is_file ( const char *  filename)
17{
18 struct stat status;
19 if(stat(filename,&status)!=0)
20 {
21 // path does not exist
22 return false;
23 }
24 // Tests whether existing path is a regular file
25 return S_ISREG(status.st_mode);
26}
#define S_ISREG(mode)
Definition is_dir.cpp:17

References S_ISREG, and stat.

◆ is_irregular_vertex()

template<typename DerivedV , typename DerivedF >
IGL_INLINE std::vector< bool > igl::is_irregular_vertex ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F 
)
15{
16 Eigen::VectorXi count = Eigen::VectorXi::Zero(F.maxCoeff());
17
18 for(unsigned i=0; i<F.rows();++i)
19 {
20 for(unsigned j=0; j<F.cols();++j)
21 {
22 if (F(i,j) < F(i,(j+1)%F.cols())) // avoid duplicate edges
23 {
24 count(F(i,j )) += 1;
25 count(F(i,(j+1)%F.cols())) += 1;
26 }
27 }
28 }
29
30 std::vector<bool> border = is_border_vertex(V,F);
31
32 std::vector<bool> res(count.size());
33
34 for (unsigned i=0; i<res.size(); ++i)
35 res[i] = !border[i] && count[i] != (F.cols() == 3 ? 6 : 4 );
36
37 return res;
38}

References count(), and is_border_vertex().

+ Here is the call graph for this function:

◆ is_planar()

IGL_INLINE bool igl::is_planar ( const Eigen::MatrixXd &  V)
10{
11 if(V.size() == 0) return false;
12 if(V.cols() == 2) return true;
13 for(int i = 0;i<V.rows();i++)
14 {
15 if(V(i,2) != 0) return false;
16 }
17 return true;
18}

◆ is_readable()

IGL_INLINE bool igl::is_readable ( const char *  filename)
27{
28 // Check if file already exists
29 struct stat status;
30 if(stat(filename,&status)!=0)
31 {
32 return false;
33 }
34
35 // Get current users uid and gid
36 uid_t this_uid = getuid();
37 gid_t this_gid = getgid();
38
39 // Dealing with owner
40 if( this_uid == status.st_uid )
41 {
42 return S_IRUSR & status.st_mode;
43 }
44
45 // Dealing with group member
46 if( this_gid == status.st_gid )
47 {
48 return S_IRGRP & status.st_mode;
49 }
50
51 // Dealing with other
52 return S_IROTH & status.st_mode;
53
54}

References stat.

◆ is_sparse() [1/2]

template<typename DerivedA >
IGL_INLINE bool igl::is_sparse ( const Eigen::PlainObjectBase< DerivedA > &  A)
18{
19 return false;
20}

◆ is_sparse() [2/2]

template<typename T >
IGL_INLINE bool igl::is_sparse ( const Eigen::SparseMatrix< T > &  A)
12{
13 return true;
14}

Referenced by arap_dof_precomputation().

+ Here is the caller graph for this function:

◆ is_stl() [1/2]

IGL_INLINE bool igl::is_stl ( FILE *  stl_file)
61{
62 bool is_ascii;
63 return is_stl(stl_file,is_ascii);
64}
Definition stl.h:137

References is_stl().

+ Here is the call graph for this function:

◆ is_stl() [2/2]

IGL_INLINE bool igl::is_stl ( FILE *  stl_file,
bool &  is_ascii 
)
4{
5
6 // solid?
7 // YES NO
8 // / if .stl, definitely binary
9 // /
10 // perfect size?
11 // YES NO
12 //
13 const auto perfect_size = [](FILE * stl_file)->bool
14 {
15 //stl_file = freopen(NULL,"rb",stl_file);
16 // Read 80 header
17 char header[80];
18 if(fread(header,sizeof(char),80,stl_file)!=80)
19 {
20 return false;
21 }
22 // Read number of triangles
23 unsigned int num_tri;
24 if(fread(&num_tri,sizeof(unsigned int),1,stl_file)!=1)
25 {
26 return false;
27 }
28 fseek(stl_file,0,SEEK_END);
29 int file_size = ftell(stl_file);
30 fseek(stl_file,0,SEEK_SET);
31 //stl_file = freopen(NULL,"r",stl_file);
32 return (file_size == 80 + 4 + (4*12 + 2) * num_tri);
33 };
34 // Specifically 80 character header
35 char header[80];
36 char solid[80];
37 is_ascii = true;
38 bool f = true;
39 if(fread(header,1,80,stl_file) != 80)
40 {
41 f = false;
42 goto finish;
43 }
44
45 sscanf(header,"%s",solid);
46 if(std::string("solid") == solid)
47 {
48 f = true;
49 is_ascii = !perfect_size(stl_file);
50 }else
51 {
52 is_ascii = false;
53 f = perfect_size(stl_file);
54 }
55finish:
56 rewind(stl_file);
57 return f;
58}
#define SEEK_SET

References SEEK_SET.

Referenced by guess_extension(), and is_stl().

+ Here is the caller graph for this function:

◆ is_symmetric() [1/3]

template<typename DerivedA >
IGL_INLINE bool igl::is_symmetric ( const Eigen::PlainObjectBase< DerivedA > &  A)
31{
32 if(A.rows() != A.cols())
33 {
34 return false;
35 }
36 assert(A.size() != 0);
37 return (A-A.transpose()).eval().nonZeros() == 0;
38}

References Eigen::PlainObjectBase< Derived >::cols(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ is_symmetric() [2/3]

template<typename AT >
IGL_INLINE bool igl::is_symmetric ( const Eigen::SparseMatrix< AT > &  A)

Referenced by arap_dof_precomputation(), arap_dof_recomputation(), and min_quad_with_fixed_precompute().

+ Here is the caller graph for this function:

◆ is_symmetric() [3/3]

template<typename AT , typename epsilonT >
IGL_INLINE bool igl::is_symmetric ( const Eigen::SparseMatrix< AT > &  A,
const epsilonT  epsilon 
)

◆ is_vertex_manifold()

template<typename DerivedF , typename DerivedB >
IGL_INLINE bool igl::is_vertex_manifold ( const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedB > &  B 
)
22{
23 using namespace std;
24 using namespace Eigen;
25 assert(F.cols() == 3 && "F must contain triangles");
26 typedef typename DerivedF::Scalar Index;
27 typedef typename DerivedF::Index FIndex;
28 const FIndex m = F.rows();
29 const Index n = F.maxCoeff()+1;
30 vector<vector<vector<FIndex > > > TT;
31 vector<vector<vector<FIndex > > > TTi;
33
34 vector<vector<FIndex > > V2F,_1;
35 vertex_triangle_adjacency(n,F,V2F,_1);
36
37 const auto & check_vertex = [&](const Index v)->bool
38 {
39 vector<FIndex> uV2Fv;
40 {
41 vector<size_t> _1,_2;
42 unique(V2F[v],uV2Fv,_1,_2);
43 }
44 const FIndex one_ring_size = uV2Fv.size();
45 if(one_ring_size == 0)
46 {
47 return false;
48 }
49 const FIndex g = uV2Fv[0];
50 queue<Index> Q;
51 Q.push(g);
52 map<FIndex,bool> seen;
53 while(!Q.empty())
54 {
55 const FIndex f = Q.front();
56 Q.pop();
57 if(seen.count(f)==1)
58 {
59 continue;
60 }
61 seen[f] = true;
62 // Face f's neighbor lists opposite opposite each corner
63 for(const auto & c : TT[f])
64 {
65 // Each neighbor
66 for(const auto & n : c)
67 {
68 bool contains_v = false;
69 for(Index nc = 0;nc<F.cols();nc++)
70 {
71 if(F(n,nc) == v)
72 {
73 contains_v = true;
74 break;
75 }
76 }
77 if(seen.count(n)==0 && contains_v)
78 {
79 Q.push(n);
80 }
81 }
82 }
83 }
84 return one_ring_size == (FIndex) seen.size();
85 };
86
87 // Unreferenced vertices are considered non-manifold
88 B.setConstant(n,1,false);
89 // Loop over all vertices touched by F
90 bool all = true;
91 for(Index v = 0;v<n;v++)
92 {
93 all &= B(v) = check_vertex(v);
94 }
95 return all;
96}

References all(), Eigen::PlainObjectBase< Derived >::setConstant(), triangle_triangle_adjacency(), unique(), and vertex_triangle_adjacency().

+ Here is the call graph for this function:

◆ is_writable()

IGL_INLINE bool igl::is_writable ( const char *  filename)
31{
32 // Check if file already exists
33 struct stat status;
34 if(stat(filename,&status)!=0)
35 {
36 return false;
37 }
38
39 // Get current users uid and gid
40 uid_t this_uid = getuid();
41 gid_t this_gid = getgid();
42
43 // Dealing with owner
44 if( this_uid == status.st_uid )
45 {
46 return S_IWUSR & status.st_mode;
47 }
48
49 // Dealing with group member
50 if( this_gid == status.st_gid )
51 {
52 return S_IWGRP & status.st_mode;
53 }
54
55 // Dealing with other
56 return S_IWOTH & status.st_mode;
57}

References stat.

◆ isdiag()

template<typename Scalar >
IGL_INLINE bool igl::isdiag ( const Eigen::SparseMatrix< Scalar > &  A)
12{
13 // Iterate over outside of A
14 for(int k=0; k<A.outerSize(); ++k)
15 {
16 // Iterate over inside
17 for(typename Eigen::SparseMatrix<Scalar>::InnerIterator it (A,k); it; ++it)
18 {
19 if(it.row() != it.col() && it.value()!=0)
20 {
21 return false;
22 }
23 }
24 }
25 return true;
26}

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::outerSize().

Referenced by harmonic().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ismember()

template<typename DerivedA , typename DerivedB , typename DerivedIA , typename DerivedLOCB >
IGL_INLINE void igl::ismember ( const Eigen::MatrixBase< DerivedA > &  A,
const Eigen::MatrixBase< DerivedB > &  B,
Eigen::PlainObjectBase< DerivedIA > &  IA,
Eigen::PlainObjectBase< DerivedLOCB > &  LOCB 
)
27{
28 using namespace Eigen;
29 using namespace std;
30 IA.resizeLike(A);
31 IA.setConstant(false);
32 LOCB.resizeLike(A);
33 LOCB.setConstant(-1);
34 // boring base cases
35 if(A.size() == 0)
36 {
37 return;
38 }
39 if(B.size() == 0)
40 {
41 return;
42 }
43
44 // Get rid of any duplicates
47 const VectorA vA(Eigen::Map<const VectorA>(DerivedA(A).data(), A.cols()*A.rows(),1));
48 const VectorB vB(Eigen::Map<const VectorB>(DerivedB(B).data(), B.cols()*B.rows(),1));
49 VectorA uA;
50 VectorB uB;
52 unique(vA,uA,uIA,uIuA);
53 unique(vB,uB,uIB,uIuB);
54 // Sort both
55 VectorA sA;
56 VectorB sB;
58 sort(uA,1,true,sA,sIA);
59 sort(uB,1,true,sB,sIB);
60
65 Constant(sA.size(),1,-1);
66 {
67 int bi = 0;
68 // loop over sA
69 bool past = false;
70 for(int a = 0;a<sA.size();a++)
71 {
72 while(!past && sA(a)>sB(bi))
73 {
74 bi++;
75 past = bi>=sB.size();
76 }
77 if(!past && sA(a)==sB(bi))
78 {
79 uF(sIA(a)) = true;
80 uLOCB(sIA(a)) = uIB(sIB(bi));
81 }
82 }
83 }
84
86 vIA(IA.data(),IA.cols()*IA.rows(),1);
88 vLOCB(LOCB.data(),LOCB.cols()*LOCB.rows(),1);
89 for(int a = 0;a<A.size();a++)
90 {
91 vIA(a) = uF(uIuA(a));
92 vLOCB(a) = uLOCB(uIuA(a));
93 }
94}

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::data(), Eigen::PlainObjectBase< Derived >::resizeLike(), Eigen::PlainObjectBase< Derived >::rows(), Eigen::PlainObjectBase< Derived >::setConstant(), sort(), and unique().

+ Here is the call graph for this function:

◆ ismember_rows()

template<typename DerivedA , typename DerivedB , typename DerivedIA , typename DerivedLOCB >
IGL_INLINE void igl::ismember_rows ( const Eigen::MatrixBase< DerivedA > &  A,
const Eigen::MatrixBase< DerivedB > &  B,
Eigen::PlainObjectBase< DerivedIA > &  IA,
Eigen::PlainObjectBase< DerivedLOCB > &  LOCB 
)
106{
107 using namespace Eigen;
108 using namespace std;
109 assert(A.cols() == B.cols() && "number of columns must match");
110 IA.resize(A.rows(),1);
111 IA.setConstant(false);
112 LOCB.resize(A.rows(),1);
113 LOCB.setConstant(-1);
114 // boring base cases
115 if(A.size() == 0)
116 {
117 return;
118 }
119 if(B.size() == 0)
120 {
121 return;
122 }
123
124 // Get rid of any duplicates
125 DerivedA uA;
126 DerivedB uB;
128 unique_rows(A,uA,uIA,uIuA);
129 unique_rows(B,uB,uIB,uIuB);
130 // Sort both
131 DerivedA sA;
132 DerivedB sB;
134 sortrows(uA,true,sA,sIA);
135 sortrows(uB,true,sB,sIB);
136
141 Constant(sA.size(),1,-1);
142 const auto & row_greater_than = [&sA,&sB](const int a, const int b)
143 {
144 for(int c = 0;c<sA.cols();c++)
145 {
146 if(sA(a,c) > sB(b,c)) return true;
147 if(sA(a,c) < sB(b,c)) return false;
148 }
149 return false;
150 };
151 {
152 int bi = 0;
153 // loop over sA
154 bool past = false;
155 for(int a = 0;a<sA.rows();a++)
156 {
157 assert(bi < sB.rows());
158 while(!past && row_greater_than(a,bi))
159 {
160 bi++;
161 past = bi>=sB.rows();
162 }
163 if(!past && (sA.row(a).array()==sB.row(bi).array()).all() )
164 {
165 uF(sIA(a)) = true;
166 uLOCB(sIA(a)) = uIB(sIB(bi));
167 }
168 }
169 }
170
171 for(int a = 0;a<A.rows();a++)
172 {
173 IA(a) = uF(uIuA(a));
174 LOCB(a) = uLOCB(uIuA(a));
175 }
176}
IGL_INLINE void sortrows(const Eigen::DenseBase< DerivedX > &X, const bool ascending, Eigen::PlainObjectBase< DerivedX > &Y, Eigen::PlainObjectBase< DerivedI > &I)

References Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::setConstant(), sortrows(), and unique_rows().

Referenced by igl::copyleft::cgal::convex_hull(), edges_to_path(), and slice_tets().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ isolines()

template<typename DerivedV , typename DerivedF , typename DerivedZ , typename DerivedIsoV , typename DerivedIsoE >
IGL_INLINE void igl::isolines ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< DerivedZ > &  z,
const int  n,
Eigen::PlainObjectBase< DerivedIsoV > &  isoV,
Eigen::PlainObjectBase< DerivedIsoE > &  isoE 
)
31{
32 //Constants
33 const int dim = V.cols();
34 assert(dim==2 || dim==3);
35 const int nVerts = V.rows();
36 assert(z.rows() == nVerts &&
37 "There must be as many function entries as vertices");
38 const int nFaces = F.rows();
39 const int np1 = n+1;
40 const double min = z.minCoeff(), max = z.maxCoeff();
41
42
43 //Following http://www.alecjacobson.com/weblog/?p=2529
44 typedef typename DerivedZ::Scalar Scalar;
46 Vec iso(np1);
47 for(int i=0; i<np1; ++i)
48 iso(i) = Scalar(i)/Scalar(n)*(max-min) + min;
49
51 std::array<Matrix,3> t{{Matrix(nFaces, np1),
52 Matrix(nFaces, np1), Matrix(nFaces, np1)}};
53 for(int i=0; i<nFaces; ++i) {
54 for(int k=0; k<3; ++k) {
55 const Scalar z1=z(F(i,k)), z2=z(F(i,(k+1)%3));
56 for(int j=0; j<np1; ++j) {
57 t[k](i,j) = (iso(j)-z1) / (z2-z1);
58 if(t[k](i,j)<0 || t[k](i,j)>1)
59 t[k](i,j) = std::numeric_limits<Scalar>::quiet_NaN();
60 }
61 }
62 }
63
64 std::array<std::vector<int>,3> Fij, Iij;
65 for(int i=0; i<nFaces; ++i) {
66 for(int j=0; j<np1; ++j) {
67 for(int k=0; k<3; ++k) {
68 const int kp1=(k+1)%3, kp2=(k+2)%3;
69 if(std::isfinite(t[kp1](i,j)) && std::isfinite(t[kp2](i,j))) {
70 Fij[k].push_back(i);
71 Iij[k].push_back(j);
72 }
73 }
74 }
75 }
76
77 const int K = Fij[0].size()+Fij[1].size()+Fij[2].size();
78 isoV.resize(2*K, dim);
79 int b = 0;
80 for(int k=0; k<3; ++k) {
81 const int kp1=(k+1)%3, kp2=(k+2)%3;
82 for(int i=0; i<Fij[k].size(); ++i) {
83 isoV.row(b+i) = (1.-t[kp1](Fij[k][i],Iij[k][i]))*
84 V.row(F(Fij[k][i],kp1)) +
85 t[kp1](Fij[k][i],Iij[k][i])*V.row(F(Fij[k][i],kp2));
86 isoV.row(K+b+i) = (1.-t[kp2](Fij[k][i],Iij[k][i]))*
87 V.row(F(Fij[k][i],kp2)) +
88 t[kp2](Fij[k][i],Iij[k][i])*V.row(F(Fij[k][i],k));
89 }
90 b += Fij[k].size();
91 }
92
93 isoE.resize(K,2);
94 for(int i=0; i<K; ++i)
95 isoE.row(i) << i, K+i;
96
97
98 //Remove double entries
99 typedef typename DerivedIsoV::Scalar LScalar;
100 typedef typename DerivedIsoE::Scalar LInt;
104 LIVec dummy1, dummy2;
105 igl::remove_duplicate_vertices(LMat(isoV), LIMat(isoE),
106 2.2204e-15, isoV, dummy1, dummy2, isoE);
107
108}
EIGEN_DEVICE_FUNC internal::traits< Derived >::Scalar minCoeff() const
Definition Redux.h:426
EIGEN_DEVICE_FUNC internal::traits< Derived >::Scalar maxCoeff() const
Definition Redux.h:436
IGL_INLINE void remove_duplicate_vertices(const Eigen::MatrixBase< DerivedV > &V, const double epsilon, Eigen::PlainObjectBase< DerivedSV > &SV, Eigen::PlainObjectBase< DerivedSVI > &SVI, Eigen::PlainObjectBase< DerivedSVJ > &SVJ)
Definition remove_duplicate_vertices.cpp:20

References Eigen::DenseBase< Derived >::maxCoeff(), Eigen::DenseBase< Derived >::minCoeff(), remove_duplicate_vertices(), and Eigen::PlainObjectBase< Derived >::resize().

+ Here is the call graph for this function:

◆ jet() [1/4]

template<typename DerivedZ , typename DerivedC >
IGL_INLINE void igl::jet ( const Eigen::MatrixBase< DerivedZ > &  Z,
const bool  normalize,
Eigen::PlainObjectBase< DerivedC > &  C 
)
63{
65}

References COLOR_MAP_TYPE_JET, and colormap().

+ Here is the call graph for this function:

◆ jet() [2/4]

template<typename DerivedZ , typename DerivedC >
IGL_INLINE void igl::jet ( const Eigen::MatrixBase< DerivedZ > &  Z,
const double  min_Z,
const double  max_Z,
Eigen::PlainObjectBase< DerivedC > &  C 
)
73{
74 igl::colormap(igl::COLOR_MAP_TYPE_JET, Z, min_z, max_z, C);
75}

References COLOR_MAP_TYPE_JET, and colormap().

+ Here is the call graph for this function:

◆ jet() [3/4]

template<typename T >
IGL_INLINE void igl::jet ( const f,
T &  r,
T &  g,
T &  b 
)
19{
20 // Only important if the number of colors is small. In which case the rest is
21 // still wrong anyway
22 // x = linspace(0,1,jj)' * (1-1/jj) + 1/jj;
23 //
24 const double rone = 0.8;
25 const double gone = 1.0;
26 const double bone = 1.0;
27 T x = x_in;
28 x = (x_in<0 ? 0 : (x>1 ? 1 : x));
29
30 if (x<1. / 8.)
31 {
32 r = 0;
33 g = 0;
34 b = bone*(0.5 + (x) / (1. / 8.)*0.5);
35 } else if (x<3. / 8.)
36 {
37 r = 0;
38 g = gone*(x - 1. / 8.) / (3. / 8. - 1. / 8.);
39 b = bone;
40 } else if (x<5. / 8.)
41 {
42 r = rone*(x - 3. / 8.) / (5. / 8. - 3. / 8.);
43 g = gone;
44 b = (bone - (x - 3. / 8.) / (5. / 8. - 3. / 8.));
45 } else if (x<7. / 8.)
46 {
47 r = rone;
48 g = (gone - (x - 5. / 8.) / (7. / 8. - 5. / 8.));
49 b = 0;
50 } else
51 {
52 r = (rone - (x - 7. / 8.) / (1. - 7. / 8.)*0.5);
53 g = 0;
54 b = 0;
55 }
56}

◆ jet() [4/4]

template<typename T >
IGL_INLINE void igl::jet ( const f,
T *  rgb 
)
13{
15}

References COLOR_MAP_TYPE_JET, and colormap().

Referenced by colormap().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ knn()

template<typename DerivedP , typename KType , typename IndexType , typename DerivedCH , typename DerivedCN , typename DerivedW , typename DerivedI >
IGL_INLINE void igl::knn ( const Eigen::MatrixBase< DerivedP > &  P,
const KType &  k,
const std::vector< std::vector< IndexType > > &  point_indices,
const Eigen::MatrixBase< DerivedCH > &  CH,
const Eigen::MatrixBase< DerivedCN > &  CN,
const Eigen::MatrixBase< DerivedW > &  W,
Eigen::PlainObjectBase< DerivedI > &  I 
)
18 {
19 typedef typename DerivedCN::Scalar CentersType;
20 typedef typename DerivedW::Scalar WidthsType;
21
23
24 int n = P.rows();
25 const KType real_k = std::min(n,k);
26
27 auto distance_to_width_one_cube = [](RowVector3PType point){
28 return std::sqrt(std::pow(std::max(std::abs(point(0))-1,0.0),2)
29 + std::pow(std::max(std::abs(point(1))-1,0.0),2)
30 + std::pow(std::max(std::abs(point(2))-1,0.0),2));
31 };
32
33 auto distance_to_cube = [&distance_to_width_one_cube]
34 (RowVector3PType point,
36 WidthsType cube_width){
37 RowVector3PType transformed_point = (point-cube_center)/cube_width;
38 return cube_width*distance_to_width_one_cube(transformed_point);
39 };
40
41 I.resize(n,real_k);
42
43 igl::parallel_for(n,[&](int i)
44 {
45 int points_found = 0;
46 RowVector3PType point_of_interest = P.row(i);
47
48 //To make my priority queue take both points and octree cells,
49 //I use the indices 0 to n-1 for the n points,
50 // and the indices n to n+m-1 for the m octree cells
51
52 // Using lambda to compare elements.
53 auto cmp = [&point_of_interest, &P, &CN, &W,
54 &n, &distance_to_cube](int left, int right) {
55 double leftdistance, rightdistance;
56 if(left < n){ //left is a point index
57 leftdistance = (P.row(left) - point_of_interest).norm();
58 } else { //left is an octree cell
59 leftdistance = distance_to_cube(point_of_interest,
60 CN.row(left-n),
61 W(left-n));
62 }
63
64 if(right < n){ //left is a point index
65 rightdistance = (P.row(right) - point_of_interest).norm();
66 } else { //left is an octree cell
67 rightdistance = distance_to_cube(point_of_interest,
68 CN.row(right-n),
69 W(right-n));
70 }
71 return leftdistance >= rightdistance;
72 };
73
74 std::priority_queue<IndexType, std::vector<IndexType>,
75 decltype(cmp)> queue(cmp);
76
77 queue.push(n); //This is the 0th octree cell (ie the root)
78 while(points_found < real_k){
79 IndexType curr_cell_or_point = queue.top();
80 queue.pop();
81 if(curr_cell_or_point < n){ //current index is for is a point
82 I(i,points_found) = curr_cell_or_point;
83 points_found++;
84 } else {
85 IndexType curr_cell = curr_cell_or_point - n;
86 if(CH(curr_cell,0) == -1){ //In the case of a leaf
87 if(point_indices.at(curr_cell).size() > 0){
88 //Assumption: Leaves either have one point, or none
89 queue.push(point_indices.at(curr_cell).at(0));
90 }
91 } else { //Not a leaf
92 for(int j = 0; j < 8; j++){
93 //+n to adjust for the octree cells
94 queue.push(CH(curr_cell,j)+n);
95 }
96 }
97 }
98 }
99 },1000);
100 }

References parallel_for(), and Eigen::PlainObjectBase< Derived >::resize().

Referenced by igl::copyleft::cgal::fast_winding_number().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ launch_medit()

template<typename DerivedV , typename DerivedT , typename DerivedF >
IGL_INLINE int igl::launch_medit ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedT > &  T,
const Eigen::PlainObjectBase< DerivedF > &  F,
const bool  wait 
)
25{
26 using namespace std;
27 // Build medit command, end with & so command returns without waiting
28 stringstream command;
30 if(!wait)
31 {
32 command<<" &";
33 }
34 bool mesh_saved = writeMESH(TEMP_MESH_FILE,V,T,F);
35 if(!mesh_saved)
36 {
37 return -1;
38 }
39 // Write default medit options
40 const string default_medit_file_contents =
41 "BackgroundColor 1 1 1\n"
42 "LineColor 0 0 0\n"
43 "WindowSize 1024 800\n"
44 "RenderMode shading + lines\n";
45 FILE * fp = fopen(TEMP_MEDIT_FILE,"w");
46 if(fp == NULL)
47 {
48 cerr<<"^"<<__FUNCTION__<<": Could not write to "<<TEMP_MEDIT_FILE<<endl;
49 return -1;
50 }
51 fprintf(fp,"%s",default_medit_file_contents.c_str());
52 fclose(fp);
53
54 try
55 {
56 return system(command.str().c_str());
57 }catch(int e)
58 {
59 cerr<<"^"<<__FUNCTION__<<": Calling to medit crashed..."<<endl;
60 return -1;
61 }
62 // Could clean up and delete these files but not really worth it
63}
#define TEMP_MEDIT_FILE
Definition launch_medit.cpp:17
#define MEDIT_PATH
Definition launch_medit.cpp:15
#define TEMP_MESH_FILE
Definition launch_medit.cpp:16
Definition term.c:39

References MEDIT_PATH, TEMP_MEDIT_FILE, TEMP_MESH_FILE, and writeMESH().

+ Here is the call graph for this function:

◆ lbs_matrix()

IGL_INLINE void igl::lbs_matrix ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXd &  W,
Eigen::MatrixXd &  M 
)
14{
15 using namespace Eigen;
16 // Number of dimensions
17 const int dim = V.cols();
18 // Number of model points
19 const int n = V.rows();
20 // Number of skinning transformations/weights
21 const int m = W.cols();
22
23 // Assumes that first n rows of weights correspond to V
24 assert(W.rows() >= n);
25
26 M.resize(n,(dim+1)*m);
27 for(int j = 0;j<m;j++)
28 {
29 VectorXd Wj = W.block(0,j,V.rows(),1);
30 for(int i = 0;i<(dim+1);i++)
31 {
32 if(i<dim)
33 {
34 M.col(i + j*(dim+1)) =
35 Wj.cwiseProduct(V.col(i));
36 }else
37 {
38 M.col(i + j*(dim+1)).array() = W.block(0,j,V.rows(),1).array();
39 }
40 }
41 }
42}

◆ lbs_matrix_column() [1/4]

IGL_INLINE void igl::lbs_matrix_column ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXd &  W,
const Eigen::MatrixXi &  WI,
Eigen::MatrixXd &  M 
)
178{
179 // Cheapskate wrapper
180 using namespace Eigen;
182 lbs_matrix_column(V,W,WI,sM);
183 M = MatrixXd(sM);
184}
IGL_INLINE void lbs_matrix_column(const Eigen::MatrixXd &V, const Eigen::MatrixXd &W, Eigen::SparseMatrix< double > &M)
Definition lbs_matrix.cpp:44

References lbs_matrix_column().

+ Here is the call graph for this function:

◆ lbs_matrix_column() [2/4]

IGL_INLINE void igl::lbs_matrix_column ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXd &  W,
const Eigen::MatrixXi &  WI,
Eigen::SparseMatrix< double > &  M 
)
128{
129 // number of mesh vertices
130 int n = V.rows();
131 assert(n == W.rows());
132 assert(n == WI.rows());
133 // dimension of mesh
134 int dim = V.cols();
135 // number of handles
136 int m = WI.maxCoeff()+1;
137 // max number of influencing handles
138 int k = W.cols();
139 assert(k == WI.cols());
140
141 M.resize(n*dim,m*dim*(dim+1));
142
143 // loop over coordinates of mesh vertices
144 for(int x = 0; x < dim; x++)
145 {
146 // loop over mesh vertices
147 for(int j = 0; j < n; j++)
148 {
149 // loop over handles
150 for(int i = 0; i < k; i++)
151 {
152 // loop over cols of affine transformations
153 for(int c = 0; c < (dim+1); c++)
154 {
155 double value = W(j,i);
156 if(c<dim)
157 {
158 value *= V(j,c);
159 }
160 if(value != 0)
161 {
162 M.insert(x*n + j,x*m + c*m*dim + WI(j,i)) = value;
163 }
164 }
165 }
166 }
167 }
168
169 M.makeCompressed();
170}

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::insert(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::makeCompressed(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::resize().

+ Here is the call graph for this function:

◆ lbs_matrix_column() [3/4]

IGL_INLINE void igl::lbs_matrix_column ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXd &  W,
Eigen::MatrixXd &  M 
)
89{
90 // number of mesh vertices
91 int n = V.rows();
92 assert(n == W.rows());
93 // dimension of mesh
94 int dim = V.cols();
95 // number of handles
96 int m = W.cols();
97 M.resize(n*dim,m*dim*(dim+1));
98
99 // loop over coordinates of mesh vertices
100 for(int x = 0; x < dim; x++)
101 {
102 // loop over mesh vertices
103 for(int j = 0; j < n; j++)
104 {
105 // loop over handles
106 for(int i = 0; i < m; i++)
107 {
108 // loop over cols of affine transformations
109 for(int c = 0; c < (dim+1); c++)
110 {
111 double value = W(j,i);
112 if(c<dim)
113 {
114 value *= V(j,c);
115 }
116 M(x*n + j,x*m + c*m*dim + i) = value;
117 }
118 }
119 }
120 }
121}

◆ lbs_matrix_column() [4/4]

IGL_INLINE void igl::lbs_matrix_column ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXd &  W,
Eigen::SparseMatrix< double > &  M 
)
48{
49 // number of mesh vertices
50 int n = V.rows();
51 assert(n == W.rows());
52 // dimension of mesh
53 int dim = V.cols();
54 // number of handles
55 int m = W.cols();
56
57 M.resize(n*dim,m*dim*(dim+1));
58
59 // loop over coordinates of mesh vertices
60 for(int x = 0; x < dim; x++)
61 {
62 // loop over mesh vertices
63 for(int j = 0; j < n; j++)
64 {
65 // loop over handles
66 for(int i = 0; i < m; i++)
67 {
68 // loop over cols of affine transformations
69 for(int c = 0; c < (dim+1); c++)
70 {
71 double value = W(j,i);
72 if(c<dim)
73 {
74 value *= V(j,c);
75 }
76 M.insert(x*n + j,x*m + c*m*dim + i) = value;
77 }
78 }
79 }
80 }
81
83}

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::insert(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::makeCompressed(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::resize().

Referenced by lbs_matrix_column().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ lexicographic_triangulation()

template<typename DerivedP , typename Orient2D , typename DerivedF >
IGL_INLINE void igl::lexicographic_triangulation ( const Eigen::PlainObjectBase< DerivedP > &  P,
Orient2D  orient2D,
Eigen::PlainObjectBase< DerivedF > &  F 
)
25{
26 typedef typename DerivedP::Scalar Scalar;
27 const size_t num_pts = P.rows();
28 if (num_pts < 3) {
29 throw "At least 3 points are required for triangulation!";
30 }
31
32 // Sort points in lexicographic order.
33 DerivedP ordered_P;
34 Eigen::VectorXi order;
35 igl::sortrows(P, true, ordered_P, order);
36
37 std::vector<Eigen::Vector3i> faces;
38 std::list<int> boundary;
39 const Scalar p0[] = {ordered_P(0, 0), ordered_P(0, 1)};
40 const Scalar p1[] = {ordered_P(1, 0), ordered_P(1, 1)};
41 for (size_t i=2; i<num_pts; i++) {
42 const Scalar curr_p[] = {ordered_P(i, 0), ordered_P(i, 1)};
43 if (faces.size() == 0) {
44 // All points processed so far are collinear.
45 // Check if the current point is collinear with every points before it.
46 auto orientation = orient2D(p0, p1, curr_p);
47 if (orientation != 0) {
48 // Add a fan of triangles eminating from curr_p.
49 if (orientation > 0) {
50 for (size_t j=0; j<=i-2; j++) {
51 faces.push_back({order[j], order[j+1], order[i]});
52 }
53 } else if (orientation < 0) {
54 for (size_t j=0; j<=i-2; j++) {
55 faces.push_back({order[j+1], order[j], order[i]});
56 }
57 }
58 // Initialize current boundary.
59 boundary.insert(boundary.end(), order.data(), order.data()+i+1);
60 if (orientation < 0) {
61 boundary.reverse();
62 }
63 }
64 } else {
65 const size_t bd_size = boundary.size();
66 assert(bd_size >= 3);
67 std::vector<short> orientations;
68 for (auto itr=boundary.begin(); itr!=boundary.end(); itr++) {
69 auto next_itr = std::next(itr, 1);
70 if (next_itr == boundary.end()) {
71 next_itr = boundary.begin();
72 }
73 const Scalar bd_p0[] = {P(*itr, 0), P(*itr, 1)};
74 const Scalar bd_p1[] = {P(*next_itr, 0), P(*next_itr, 1)};
75 auto orientation = orient2D(bd_p0, bd_p1, curr_p);
76 if (orientation < 0) {
77 faces.push_back({*next_itr, *itr, order[i]});
78 }
79 orientations.push_back(orientation);
80 }
81
82 auto left_itr = boundary.begin();
83 auto right_itr = boundary.begin();
84 auto curr_itr = boundary.begin();
85 for (size_t j=0; j<bd_size; j++, curr_itr++) {
86 size_t prev = (j+bd_size-1) % bd_size;
87 if (orientations[j] >= 0 && orientations[prev] < 0) {
88 right_itr = curr_itr;
89 } else if (orientations[j] < 0 && orientations[prev] >= 0) {
90 left_itr = curr_itr;
91 }
92 }
93 assert(left_itr != right_itr);
94
95 for (auto itr=left_itr; itr!=right_itr; itr++) {
96 if (itr == boundary.end()) itr = boundary.begin();
97 if (itr == right_itr) break;
98 if (itr == left_itr || itr == right_itr) continue;
99 itr = boundary.erase(itr);
100 if (itr == boundary.begin()) {
101 itr = boundary.end();
102 } else {
103 itr--;
104 }
105 }
106
107 if (right_itr == boundary.begin()) {
108 assert(std::next(left_itr, 1) == boundary.end());
109 boundary.insert(boundary.end(), order[i]);
110 } else {
111 assert(std::next(left_itr, 1) == right_itr);
112 boundary.insert(right_itr, order[i]);
113 }
114 }
115 }
116
117 const size_t num_faces = faces.size();
118 if (num_faces == 0) {
119 // All input points are collinear.
120 // Do nothing here.
121 } else {
122 F.resize(num_faces, 3);
123 for (size_t i=0; i<num_faces; i++) {
124 F.row(i) = faces[i];
125 }
126 }
127}
IGL_INLINE short orient2D(const Scalar pa[2], const Scalar pb[2], const Scalar pc[2])
Definition orient2D.cpp:14

References Eigen::PlainObjectBase< Derived >::rows(), and sortrows().

Referenced by delaunay_triangulation(), and igl::copyleft::cgal::lexicographic_triangulation().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ limit_faces()

template<typename MatF , typename VecL >
IGL_INLINE void igl::limit_faces ( const MatF &  F,
const VecL &  L,
const bool  exclusive,
MatF &  LF 
)
19{
20 using namespace std;
21 using namespace Eigen;
22 vector<bool> in(F.rows(),false);
23 int num_in = 0;
24 // loop over faces
25 for(int i = 0;i<F.rows();i++)
26 {
27 bool all = true;
28 bool any = false;
29 for(int j = 0;j<F.cols();j++)
30 {
31 bool found = false;
32 // loop over L
33 for(int l = 0;l<L.size();l++)
34 {
35 if(F(i,j) == L(l))
36 {
37 found = true;
38 break;
39 }
40 }
41 any |= found;
42 all &= found;
43 }
44 in[i] = (exclusive?all:any);
45 num_in += (in[i]?1:0);
46 }
47
48 LF.resize(num_in,F.cols());
49 // loop over faces
50 int lfi = 0;
51 for(int i = 0;i<F.rows();i++)
52 {
53 if(in[i])
54 {
55 LF.row(lfi) = F.row(i);
56 lfi++;
57 }
58 }
59}
IGL_INLINE void any(const Eigen::SparseMatrix< AType > &A, const int dim, Eigen::PlainObjectBase< DerivedB > &B)
Definition any.cpp:13

References all(), any(), and L.

+ Here is the call graph for this function:

◆ line_field_missmatch()

template<typename DerivedV , typename DerivedF , typename DerivedO >
IGL_INLINE void igl::line_field_missmatch ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedV > &  PD1,
const bool  isCombed,
Eigen::PlainObjectBase< DerivedO > &  missmatch 
)
125{
126 DerivedV PD1_combed;
127 DerivedV PD2_combed;
128
129 if (!isCombed)
130 igl::comb_line_field(V,F,PD1,PD1_combed);
131 else
132 {
133 PD1_combed = PD1;
134 }
135 Eigen::MatrixXd B1,B2,B3;
136 igl::local_basis(V,F,B1,B2,B3);
137 PD2_combed = igl::rotate_vectors(PD1_combed, Eigen::VectorXd::Constant(1,igl::PI/2), B1, B2);
138 igl::MissMatchCalculatorLine<DerivedV, DerivedF, DerivedO> sf(V, F, PD1_combed, PD2_combed);
139 sf.calculateMissmatchLine(missmatch);
140}
Definition line_field_missmatch.cpp:28
IGL_INLINE Eigen::MatrixXd rotate_vectors(const Eigen::MatrixXd &V, const Eigen::VectorXd &A, const Eigen::MatrixXd &B1, const Eigen::MatrixXd &B2)
Definition rotate_vectors.cpp:10
IGL_INLINE void comb_line_field(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedV > &PD1in, Eigen::PlainObjectBase< DerivedV > &PD1out)
Definition comb_line_field.cpp:121

References igl::MissMatchCalculatorLine< DerivedV, DerivedF, DerivedO >::calculateMissmatchLine(), comb_line_field(), local_basis(), PI, and rotate_vectors().

+ Here is the call graph for this function:

◆ line_search()

IGL_INLINE double igl::line_search ( Eigen::MatrixXd &  x,
const Eigen::MatrixXd &  d,
double  i_step_size,
std::function< double(Eigen::MatrixXd &)>  energy,
double  cur_energy = -1 
)
16{
17 double old_energy;
18 if (cur_energy > 0)
19 {
20 old_energy = cur_energy;
21 }
22 else
23 {
24 old_energy = energy(x); // no energy was given -> need to compute the current energy
25 }
26 double new_energy = old_energy;
27 int cur_iter = 0; int MAX_STEP_SIZE_ITER = 12;
28
29 while (new_energy >= old_energy && cur_iter < MAX_STEP_SIZE_ITER)
30 {
31 Eigen::MatrixXd new_x = x + step_size * d;
32
33 double cur_e = energy(new_x);
34 if ( cur_e >= old_energy)
35 {
36 step_size /= 2;
37 }
38 else
39 {
40 x = new_x;
41 new_energy = cur_e;
42 }
43 cur_iter++;
44 }
45 return new_energy;
46}

Referenced by flip_avoiding_line_search().

+ Here is the caller graph for this function:

◆ line_segment_in_rectangle()

IGL_INLINE bool igl::line_segment_in_rectangle ( const Eigen::Vector2d &  s,
const Eigen::Vector2d &  d,
const Eigen::Vector2d &  A,
const Eigen::Vector2d &  B 
)
15{
16 using namespace std;
17 using namespace Eigen;
18 // http://stackoverflow.com/a/100165/148668
19 const auto SegmentIntersectRectangle = [](double a_rectangleMinX,
20 double a_rectangleMinY,
21 double a_rectangleMaxX,
22 double a_rectangleMaxY,
23 double a_p1x,
24 double a_p1y,
25 double a_p2x,
26 double a_p2y)->bool
27 {
28 // Find min and max X for the segment
29
30 double minX = a_p1x;
31 double maxX = a_p2x;
32
33 if(a_p1x > a_p2x)
34 {
35 minX = a_p2x;
36 maxX = a_p1x;
37 }
38
39 // Find the intersection of the segment's and rectangle's x-projections
40
41 if(maxX > a_rectangleMaxX)
42 {
43 maxX = a_rectangleMaxX;
44 }
45
46 if(minX < a_rectangleMinX)
47 {
48 minX = a_rectangleMinX;
49 }
50
51 if(minX > maxX) // If their projections do not intersect return false
52 {
53 return false;
54 }
55
56 // Find corresponding min and max Y for min and max X we found before
57
58 double minY = a_p1y;
59 double maxY = a_p2y;
60
61 double dx = a_p2x - a_p1x;
62
63 if(fabs(dx) > 0.0000001)
64 {
65 double a = (a_p2y - a_p1y) / dx;
66 double b = a_p1y - a * a_p1x;
67 minY = a * minX + b;
68 maxY = a * maxX + b;
69 }
70
71 if(minY > maxY)
72 {
73 double tmp = maxY;
74 maxY = minY;
75 minY = tmp;
76 }
77
78 // Find the intersection of the segment's and rectangle's y-projections
79
80 if(maxY > a_rectangleMaxY)
81 {
82 maxY = a_rectangleMaxY;
83 }
84
85 if(minY < a_rectangleMinY)
86 {
87 minY = a_rectangleMinY;
88 }
89
90 if(minY > maxY) // If Y-projections do not intersect return false
91 {
92 return false;
93 }
94
95 return true;
96 };
97 const double minX = std::min(A(0),B(0));
98 const double minY = std::min(A(1),B(1));
99 const double maxX = std::max(A(0),B(0));
100 const double maxY = std::max(A(1),B(1));
101 bool ret = SegmentIntersectRectangle(minX,minY,maxX,maxY,s(0),s(1),d(0),d(1));
102 return ret;
103}

Referenced by igl::opengl2::MouseController::set_selection_from_last_drag().

+ Here is the caller graph for this function:

◆ linprog() [1/2]

IGL_INLINE bool igl::linprog ( const Eigen::VectorXd &  c,
const Eigen::MatrixXd &  A,
const Eigen::VectorXd &  b,
const int  k,
Eigen::VectorXd &  f 
)
22{
23 // This is a very literal translation of
24 // http://www.mathworks.com/matlabcentral/fileexchange/2166-introduction-to-linear-algebra/content/strang/linprog.m
25 using namespace Eigen;
26 using namespace std;
27 bool success = true;
28 // number of constraints
29 const int m = _A.rows();
30 // number of original variables
31 const int n = _A.cols();
32 // number of iterations
33 int it = 0;
34 // maximum number of iterations
35 //const int MAXIT = 10*m;
36 const int MAXIT = 100*m;
37 // residual tolerance
38 const double tol = 1e-10;
39 const auto & sign = [](const Eigen::VectorXd & B) -> Eigen::VectorXd
40 {
41 Eigen::VectorXd Bsign(B.size());
42 for(int i = 0;i<B.size();i++)
43 {
44 Bsign(i) = B(i)>0?1:(B(i)<0?-1:0);
45 }
46 return Bsign;
47 };
48 // initial (inverse) basis matrix
49 VectorXd Dv = sign(sign(b).array()+0.5);
50 Dv.head(k).setConstant(1.);
51 MatrixXd D = Dv.asDiagonal();
52 // Incorporate slack variables
53 MatrixXd A(_A.rows(),_A.cols()+D.cols());
54 A<<_A,D;
55 // Initial basis
56 VectorXi B = igl::colon<int>(n,n+m-1);
57 // non-basis, may turn out that vector<> would be better here
58 VectorXi N = igl::colon<int>(0,n-1);
59 int j;
60 double bmin = b.minCoeff(&j);
61 int phase;
62 VectorXd xb;
63 VectorXd s;
64 VectorXi J;
65 if(k>0 && bmin<0)
66 {
67 phase = 1;
68 xb = VectorXd::Ones(m);
69 // super cost
70 s.resize(n+m+1);
71 s<<VectorXd::Zero(n+k),VectorXd::Ones(m-k+1);
72 N.resize(n+1);
73 N<<igl::colon<int>(0,n-1),B(j);
74 J.resize(B.size()-1);
75 // [0 1 2 3 4]
76 // ^
77 // [0 1]
78 // [3 4]
79 J.head(j) = B.head(j);
80 J.tail(B.size()-j-1) = B.tail(B.size()-j-1);
81 B(j) = n+m;
82 MatrixXd AJ;
83 igl::slice(A,J,2,AJ);
84 const VectorXd a = b - AJ.rowwise().sum();
85 {
86 MatrixXd old_A = A;
87 A.resize(A.rows(),A.cols()+a.cols());
88 A<<old_A,a;
89 }
90 D.col(j) = -a/a(j);
91 D(j,j) = 1./a(j);
92 }else if(k==m)
93 {
94 phase = 2;
95 xb = b;
96 s.resize(c.size()+m);
97 // cost function
98 s<<c,VectorXd::Zero(m);
99 }else //k = 0 or bmin >=0
100 {
101 phase = 1;
102 xb = b.array().abs();
103 s.resize(n+m);
104 // super cost
105 s<<VectorXd::Zero(n+k),VectorXd::Ones(m-k);
106 }
107 while(phase<3)
108 {
109 double df = -1;
110 int t = std::numeric_limits<int>::max();
111 // Lagrange mutipliers fro Ax=b
112 VectorXd yb = D.transpose() * igl::slice(s,B);
113 while(true)
114 {
115 if(MAXIT>0 && it>=MAXIT)
116 {
117#ifdef IGL_LINPROG_VERBOSE
118 cerr<<"linprog: warning! maximum iterations without convergence."<<endl;
119#endif
120 success = false;
121 break;
122 }
123 // no freedom for minimization
124 if(N.size() == 0)
125 {
126 break;
127 }
128 // reduced costs
129 VectorXd sN = igl::slice(s,N);
130 MatrixXd AN = igl::slice(A,N,2);
131 VectorXd r = sN - AN.transpose() * yb;
132 int q;
133 // determine new basic variable
134 double rmin = r.minCoeff(&q);
135 // optimal! infinity norm
136 if(rmin>=-tol*(sN.array().abs().maxCoeff()+1))
137 {
138 break;
139 }
140 // increment iteration count
141 it++;
142 // apply Bland's rule to avoid cycling
143 if(df>=0)
144 {
145 if(MAXIT == -1)
146 {
147#ifdef IGL_LINPROG_VERBOSE
148 cerr<<"linprog: warning! degenerate vertex"<<endl;
149#endif
150 success = false;
151 }
152 igl::find((r.array()<0).eval(),J);
153 double Nq = igl::slice(N,J).minCoeff();
154 // again seems like q is assumed to be a scalar though matlab code
155 // could produce a vector for multiple matches
156 (N.array()==Nq).cast<int>().maxCoeff(&q);
157 }
158 VectorXd d = D*A.col(N(q));
159 VectorXi I;
160 igl::find((d.array()>tol).eval(),I);
161 if(I.size() == 0)
162 {
163#ifdef IGL_LINPROG_VERBOSE
164 cerr<<"linprog: warning! solution is unbounded"<<endl;
165#endif
166 // This seems dubious:
167 it=-it;
168 success = false;
169 break;
170 }
171 VectorXd xbd = igl::slice(xb,I).array()/igl::slice(d,I).array();
172 // new use of r
173 int p;
174 {
175 double r;
176 r = xbd.minCoeff(&p);
177 p = I(p);
178 // apply Bland's rule to avoid cycling
179 if(df>=0)
180 {
181 igl::find((xbd.array()==r).eval(),J);
182 double Bp = igl::slice(B,igl::slice(I,J)).minCoeff();
183 // idiotic way of finding index in B of Bp
184 // code down the line seems to assume p is a scalar though the matlab
185 // code could find a vector of matches)
186 (B.array()==Bp).cast<int>().maxCoeff(&p);
187 }
188 // update x
189 xb -= r*d;
190 xb(p) = r;
191 // change in f
192 df = r*rmin;
193 }
194 // row vector
195 RowVectorXd v = D.row(p)/d(p);
196 yb += v.transpose() * (s(N(q)) - d.transpose()*igl::slice(s,B));
197 d(p)-=1;
198 // update inverse basis matrix
199 D = D - d*v;
200 t = B(p);
201 B(p) = N(q);
202 if(t>(n+k-1))
203 {
204 // remove qth entry from N
205 VectorXi old_N = N;
206 N.resize(N.size()-1);
207 N.head(q) = old_N.head(q);
208 N.head(q) = old_N.head(q);
209 N.tail(old_N.size()-q-1) = old_N.tail(old_N.size()-q-1);
210 }else
211 {
212 N(q) = t;
213 }
214 }
215 // iterative refinement
216 xb = (xb+D*(b-igl::slice(A,B,2)*xb)).eval();
217 // must be due to rounding
218 VectorXi I;
219 igl::find((xb.array()<0).eval(),I);
220 if(I.size()>0)
221 {
222 // so correct
223 VectorXd Z = VectorXd::Zero(I.size(),1);
224 igl::slice_into(Z,I,xb);
225 }
226 // B, xb,n,m,res=A(:,B)*xb-b
227 if(phase == 2 || it<0)
228 {
229 break;
230 }
231 if(xb.transpose()*igl::slice(s,B) > tol)
232 {
233 it = -it;
234#ifdef IGL_LINPROG_VERBOSE
235 cerr<<"linprog: warning, no feasible solution"<<endl;
236#endif
237 success = false;
238 break;
239 }
240 // re-initialize for Phase 2
241 phase = phase+1;
242 s*=1e6*c.array().abs().maxCoeff();
243 s.head(n) = c;
244 }
245 x.resize(std::max(B.maxCoeff()+1,n));
246 igl::slice_into(xb,B,x);
247 x = x.head(n).eval();
248 return success;
249}
IGL_INLINE void find(const Eigen::SparseMatrix< T > &X, Eigen::DenseBase< DerivedI > &I, Eigen::DenseBase< DerivedJ > &J, Eigen::DenseBase< DerivedV > &V)
Definition find.cpp:18

References find(), sign(), slice(), and slice_into().

Referenced by linprog().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ linprog() [2/2]

IGL_INLINE bool igl::linprog ( const Eigen::VectorXd &  f,
const Eigen::MatrixXd &  A,
const Eigen::VectorXd &  b,
const Eigen::MatrixXd &  B,
const Eigen::VectorXd &  c,
Eigen::VectorXd &  x 
)
258{
259 using namespace Eigen;
260 using namespace std;
261 const int m = A.rows();
262 const int n = A.cols();
263 const int p = B.rows();
264 MatrixXd Im = MatrixXd::Identity(m,m);
265 MatrixXd AS(m,n+m);
266 AS<<A,Im;
267 MatrixXd bS = b.array().abs();
268 for(int i = 0;i<m;i++)
269 {
270 const auto & sign = [](double x)->double
271 {
272 return (x<0?-1:(x>0?1:0));
273 };
274 AS.row(i) *= sign(b(i));
275 }
276 MatrixXd In = MatrixXd::Identity(n,n);
277 MatrixXd P(n+m,2*n+m);
278 P<< In, -In, MatrixXd::Zero(n,m),
279 MatrixXd::Zero(m,2*n), Im;
280 MatrixXd ASP = AS*P;
281 MatrixXd BSP(0,2*n+m);
282 if(p>0)
283 {
284 MatrixXd BS(p,2*n);
285 BS<<B,MatrixXd::Zero(p,n);
286 BSP = BS*P;
287 }
288
289 VectorXd fSP = VectorXd::Ones(2*n+m);
290 fSP.head(2*n) = P.block(0,0,n,2*n).transpose()*f;
291 const VectorXd & cc = fSP;
292
293 MatrixXd AA(m+p,2*n+m);
294 AA<<ASP,BSP;
295 VectorXd bb(m+p);
296 bb<<bS,c;
297
298 VectorXd xxs;
299 bool ret = linprog(cc,AA,bb,0,xxs);
300 x = P.block(0,0,n,2*n+m)*xxs;
301 return ret;
302}
IGL_INLINE bool linprog(const Eigen::VectorXd &c, const Eigen::MatrixXd &A, const Eigen::VectorXd &b, const int k, Eigen::VectorXd &f)
Definition linprog.cpp:16

References linprog(), and sign().

+ Here is the call graph for this function:

◆ LinSpaced()

template<typename Derived >
Derived igl::LinSpaced ( typename Derived::Index  size,
const typename Derived::Scalar &  low,
const typename Derived::Scalar &  high 
)
inline
48{
49 if(size == 0)
50 {
51 // Force empty vector with correct "RandomAccessLinSpacedReturnType" type.
52 return Derived::LinSpaced(0,0,1);
53 }else if(high < low)
54 {
55 return low-Derived::LinSpaced(size,low-low,low-high).array();
56 }else{
57 return Derived::LinSpaced(size,low,high);
58 }
59}

Referenced by igl::copyleft::cgal::remesh_intersections(), slice_tets(), and sort_angles().

+ Here is the caller graph for this function:

◆ list_to_matrix() [1/3]

template<typename T , typename Derived >
IGL_INLINE bool igl::list_to_matrix ( const std::vector< std::vector< T > > &  V,
const int  n,
const T &  padding,
Eigen::PlainObjectBase< Derived > &  M 
)
57{
58 const int m = V.size();
59 M.resize(m,n);
60 for(int i = 0;i<m;i++)
61 {
62 const auto & row = V[i];
63 if(row.size()>n)
64 {
65 return false;
66 }
67 int j = 0;
68 for(;j<row.size();j++)
69 {
70 M(i,j) = row[j];
71 }
72 for(;j<n;j++)
73 {
74 M(i,j) = padding;
75 }
76 }
77 return true;
78}

References Eigen::PlainObjectBase< Derived >::resize(), and row().

+ Here is the call graph for this function:

◆ list_to_matrix() [2/3]

template<typename T , typename Derived >
IGL_INLINE bool igl::list_to_matrix ( const std::vector< std::vector< T > > &  V,
Eigen::PlainObjectBase< Derived > &  M 
)
20{
21 // number of rows
22 int m = V.size();
23 if(m == 0)
24 {
25 M.resize(0,0);
26 return true;
27 }
28 // number of columns
29 int n = igl::min_size(V);
30 if(n != igl::max_size(V))
31 {
32 return false;
33 }
34 assert(n != -1);
35 // Resize output
36 M.resize(m,n);
37
38 // Loop over rows
39 for(int i = 0;i<m;i++)
40 {
41 // Loop over cols
42 for(int j = 0;j<n;j++)
43 {
44 M(i,j) = V[i][j];
45 }
46 }
47
48 return true;
49}
IGL_INLINE int max_size(const std::vector< T > &V)
Definition max_size.cpp:12
IGL_INLINE int min_size(const std::vector< T > &V)
Definition min_size.cpp:11

References max_size(), min_size(), and Eigen::PlainObjectBase< Derived >::resize().

Referenced by bfs(), boundary_facets(), circulation(), dfs(), edge_collapse_is_valid(), flipped_triangles(), igl::mosek::mosek_quadprog(), on_boundary(), igl::copyleft::cgal::projected_cdt(), read_triangle_mesh(), readBF(), readOBJ(), readOBJ(), readOFF(), readOFF(), readPLY(), readSTL(), readTGF(), remesh_along_isoline(), igl::matlab::MatlabWorkspace::save(), igl::matlab::MatlabWorkspace::save(), igl::matlab::MatlabWorkspace::save_index(), igl::matlab::MatlabWorkspace::save_index(), setdiff(), straighten_seams(), igl::copyleft::cgal::subdivide_segments(), igl::copyleft::tetgen::tetgenio_to_tetmesh(), igl::copyleft::tetgen::tetrahedralize(), igl::copyleft::tetgen::tetrahedralize(), triangle_fan(), igl::copyleft::cgal::trim_with_solid(), unique(), unique(), igl::copyleft::cgal::wire_mesh(), writeDMAT(), writeDMAT(), and writeMESH().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ list_to_matrix() [3/3]

template<typename T , typename Derived >
IGL_INLINE bool igl::list_to_matrix ( const std::vector< T > &  V,
Eigen::PlainObjectBase< Derived > &  M 
)
82{
83 // number of rows
84 int m = V.size();
85 if(m == 0)
86 {
87 //fprintf(stderr,"Error: list_to_matrix() list is empty()\n");
88 //return false;
89 if(Derived::ColsAtCompileTime == 1)
90 {
91 M.resize(0,1);
92 }else if(Derived::RowsAtCompileTime == 1)
93 {
94 M.resize(1,0);
95 }else
96 {
97 M.resize(0,0);
98 }
99 return true;
100 }
101 // Resize output
102 if(Derived::RowsAtCompileTime == 1)
103 {
104 M.resize(1,m);
105 }else
106 {
107 M.resize(m,1);
108 }
109
110 // Loop over rows
111 for(int i = 0;i<m;i++)
112 {
113 M(i) = V[i];
114 }
115
116 return true;
117}

References Eigen::PlainObjectBase< Derived >::resize().

+ Here is the call graph for this function:

◆ local_basis()

template<typename DerivedV , typename DerivedF >
IGL_INLINE void igl::local_basis ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedV > &  B1,
Eigen::PlainObjectBase< DerivedV > &  B2,
Eigen::PlainObjectBase< DerivedV > &  B3 
)
26{
27 using namespace Eigen;
28 using namespace std;
29 B1.resize(F.rows(),3);
30 B2.resize(F.rows(),3);
31 B3.resize(F.rows(),3);
32
33 for (unsigned i=0;i<F.rows();++i)
34 {
35 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v1 = (V.row(F(i,1)) - V.row(F(i,0))).normalized();
36 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> t = V.row(F(i,2)) - V.row(F(i,0));
37 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v3 = v1.cross(t).normalized();
38 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v2 = v1.cross(v3).normalized();
39
40 B1.row(i) = v1;
41 B2.row(i) = -v2;
42 B3.row(i) = v3;
43 }
44}

References Eigen::PlainObjectBase< Derived >::resize().

Referenced by igl::copyleft::comiso::MIQ_class< DerivedV, DerivedF, DerivedU >::MIQ_class(), comb_frame_field(), compute_frame_field_bisectors(), frame_to_cross_field(), line_field_missmatch(), and igl::slim::pre_calc().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ look_at()

template<typename Derivedeye , typename Derivedcenter , typename Derivedup , typename DerivedR >
IGL_INLINE void igl::look_at ( const Eigen::PlainObjectBase< Derivedeye > &  eye,
const Eigen::PlainObjectBase< Derivedcenter > &  center,
const Eigen::PlainObjectBase< Derivedup > &  up,
Eigen::PlainObjectBase< DerivedR > &  R 
)
20{
22 Vector3S f = (center - eye).normalized();
23 Vector3S s = f.cross(up).normalized();
24 Vector3S u = s.cross(f);
26 R(0,0) = s(0);
27 R(0,1) = s(1);
28 R(0,2) = s(2);
29 R(1,0) = u(0);
30 R(1,1) = u(1);
31 R(1,2) = u(2);
32 R(2,0) =-f(0);
33 R(2,1) =-f(1);
34 R(2,2) =-f(2);
35 R(0,3) =-s.transpose() * eye;
36 R(1,3) =-u.transpose() * eye;
37 R(2,3) = f.transpose() * eye;
38}

Referenced by igl::opengl::ViewerCore::draw().

+ Here is the caller graph for this function:

◆ loop() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedNV , typename DerivedNF >
IGL_INLINE void igl::loop ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedNV > &  NV,
Eigen::PlainObjectBase< DerivedNF > &  NF,
const int  number_of_subdivs = 1 
)
158{
159 NV = V;
160 NF = F;
161 for(int i=0; i<number_of_subdivs; ++i)
162 {
163 DerivedNF tempF = NF;
165 loop(NV.rows(), tempF, S, NF);
166 // This .eval is super important
167 NV = (S*NV).eval();
168 }
169}

References loop(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ loop() [2/2]

template<typename DerivedF , typename SType , typename DerivedNF >
IGL_INLINE void igl::loop ( const int  n_verts,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::SparseMatrix< SType > &  S,
Eigen::PlainObjectBase< DerivedNF > &  NF 
)
26{
27 typedef Eigen::SparseMatrix<SType> SparseMat;
28 typedef Eigen::Triplet<SType> Triplet_t;
29
30 //Ref. https://graphics.stanford.edu/~mdfisher/subdivision.html
31 //Heavily borrowing from igl::upsample
32
33 DerivedF FF, FFi;
35 std::vector<std::vector<typename DerivedF::Scalar>> adjacencyList;
36 adjacency_list(F, adjacencyList, true);
37
38 //Compute the number and positions of the vertices to insert (on edges)
39 Eigen::MatrixXi NI = Eigen::MatrixXi::Constant(FF.rows(), FF.cols(), -1);
40 Eigen::MatrixXi NIdoubles = Eigen::MatrixXi::Zero(FF.rows(), FF.cols());
41 Eigen::VectorXi vertIsOnBdry = Eigen::VectorXi::Zero(n_verts);
42 int counter = 0;
43 for(int i=0; i<FF.rows(); ++i)
44 {
45 for(int j=0; j<3; ++j)
46 {
47 if(NI(i,j) == -1)
48 {
49 NI(i,j) = counter;
50 NIdoubles(i,j) = 0;
51 if (FF(i,j) != -1)
52 {
53 //If it is not a boundary
54 NI(FF(i,j), FFi(i,j)) = counter;
55 NIdoubles(i,j) = 1;
56 } else
57 {
58 //Mark boundary vertices for later
59 vertIsOnBdry(F(i,j)) = 1;
60 vertIsOnBdry(F(i,(j+1)%3)) = 1;
61 }
62 ++counter;
63 }
64 }
65 }
66
67 const int& n_odd = n_verts;
68 const int& n_even = counter;
69 const int n_newverts = n_odd + n_even;
70
71 //Construct vertex positions
72 std::vector<Triplet_t> tripletList;
73 for(int i=0; i<n_odd; ++i)
74 {
75 //Old vertices
76 const std::vector<int>& localAdjList = adjacencyList[i];
77 if(vertIsOnBdry(i)==1)
78 {
79 //Boundary vertex
80 tripletList.emplace_back(i, localAdjList.front(), 1./8.);
81 tripletList.emplace_back(i, localAdjList.back(), 1./8.);
82 tripletList.emplace_back(i, i, 3./4.);
83 } else
84 {
85 const int n = localAdjList.size();
86 const SType dn = n;
87 SType beta;
88 if(n==3)
89 {
90 beta = 3./16.;
91 } else
92 {
93 beta = 3./8./dn;
94 }
95 for(int j=0; j<n; ++j)
96 {
97 tripletList.emplace_back(i, localAdjList[j], beta);
98 }
99 tripletList.emplace_back(i, i, 1.-dn*beta);
100 }
101 }
102 for(int i=0; i<FF.rows(); ++i)
103 {
104 //New vertices
105 for(int j=0; j<3; ++j)
106 {
107 if(NIdoubles(i,j)==0)
108 {
109 if(FF(i,j)==-1)
110 {
111 //Boundary vertex
112 tripletList.emplace_back(NI(i,j) + n_odd, F(i,j), 1./2.);
113 tripletList.emplace_back(NI(i,j) + n_odd, F(i, (j+1)%3), 1./2.);
114 } else
115 {
116 tripletList.emplace_back(NI(i,j) + n_odd, F(i,j), 3./8.);
117 tripletList.emplace_back(NI(i,j) + n_odd, F(i, (j+1)%3), 3./8.);
118 tripletList.emplace_back(NI(i,j) + n_odd, F(i, (j+2)%3), 1./8.);
119 tripletList.emplace_back(NI(i,j) + n_odd, F(FF(i,j), (FFi(i,j)+2)%3), 1./8.);
120 }
121 }
122 }
123 }
124 S.resize(n_newverts, n_verts);
125 S.setFromTriplets(tripletList.begin(), tripletList.end());
126
127 // Build the new topology (Every face is replaced by four)
128 NF.resize(F.rows()*4, 3);
129 for(int i=0; i<F.rows();++i)
130 {
131 Eigen::VectorXi VI(6);
132 VI << F(i,0), F(i,1), F(i,2), NI(i,0) + n_odd, NI(i,1) + n_odd, NI(i,2) + n_odd;
133
134 Eigen::VectorXi f0(3), f1(3), f2(3), f3(3);
135 f0 << VI(0), VI(3), VI(5);
136 f1 << VI(1), VI(4), VI(3);
137 f2 << VI(3), VI(4), VI(5);
138 f3 << VI(4), VI(2), VI(5);
139
140 NF.row((i*4)+0) = f0;
141 NF.row((i*4)+1) = f1;
142 NF.row((i*4)+2) = f2;
143 NF.row((i*4)+3) = f3;
144 }
145}
CGAL::SM_Vertex_index VI
Definition CutSurface.cpp:75

References adjacency_list(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::resize(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets(), and triangle_triangle_adjacency().

Referenced by hessian_energy(), igl::opengl::glfw::Viewer::launch_rendering(), loop(), and readSTL().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ lscm()

IGL_INLINE bool igl::lscm ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const Eigen::VectorXi &  b,
const Eigen::MatrixXd &  bc,
Eigen::MatrixXd &  V_uv 
)
22{
23 using namespace Eigen;
24 using namespace std;
25
26 // Assemble the area matrix (note that A is #Vx2 by #Vx2)
29
30 // Assemble the cotan laplacian matrix
32 igl::cotmatrix(V,F,L);
33
35 repdiag(L,2,L_flat);
36
37 VectorXi b_flat(b.size()*bc.cols(),1);
38 VectorXd bc_flat(bc.size(),1);
39 for(int c = 0;c<bc.cols();c++)
40 {
41 b_flat.block(c*b.size(),0,b.rows(),1) = c*V.rows() + b.array();
42 bc_flat.block(c*bc.rows(),0,bc.rows(),1) = bc.col(c);
43 }
44
45 // Minimize the LSCM energy
46 SparseMatrix<double> Q = -L_flat + 2.*A;
47 const VectorXd B_flat = VectorXd::Zero(V.rows()*2);
50 {
51 return false;
52 }
53
54 MatrixXd W_flat;
55 if(!min_quad_with_fixed_solve(data,B_flat,bc_flat,VectorXd(),W_flat))
56 {
57 return false;
58 }
59
60
61 assert(W_flat.rows() == V.rows()*2);
62 V_uv.resize(V.rows(),2);
63 for (unsigned i=0;i<V_uv.cols();++i)
64 {
65 V_uv.col(V_uv.cols()-i-1) = W_flat.block(V_uv.rows()*i,0,V_uv.rows(),1);
66 }
67 return true;
68}
IGL_INLINE void vector_area_matrix(const Eigen::PlainObjectBase< DerivedF > &F, Eigen::SparseMatrix< Scalar > &A)
Definition vector_area_matrix.cpp:19

References cotmatrix(), L, min_quad_with_fixed_precompute(), min_quad_with_fixed_solve(), repdiag(), and vector_area_matrix().

+ Here is the call graph for this function:

◆ map_vertices_to_circle()

IGL_INLINE void igl::map_vertices_to_circle ( const Eigen::MatrixXd &  V,
const Eigen::VectorXi &  bnd,
Eigen::MatrixXd &  UV 
)
16{
17 // Get sorted list of boundary vertices
18 std::vector<int> interior,map_ij;
19 map_ij.resize(V.rows());
20
21 std::vector<bool> isOnBnd(V.rows(),false);
22 for (int i = 0; i < bnd.size(); i++)
23 {
24 isOnBnd[bnd[i]] = true;
25 map_ij[bnd[i]] = i;
26 }
27
28 for (int i = 0; i < (int)isOnBnd.size(); i++)
29 {
30 if (!isOnBnd[i])
31 {
32 map_ij[i] = interior.size();
33 interior.push_back(i);
34 }
35 }
36
37 // Map boundary to unit circle
38 std::vector<double> len(bnd.size());
39 len[0] = 0.;
40
41 for (int i = 1; i < bnd.size(); i++)
42 {
43 len[i] = len[i-1] + (V.row(bnd[i-1]) - V.row(bnd[i])).norm();
44 }
45 double total_len = len[len.size()-1] + (V.row(bnd[0]) - V.row(bnd[bnd.size()-1])).norm();
46
47 UV.resize(bnd.size(),2);
48 for (int i = 0; i < bnd.size(); i++)
49 {
50 double frac = len[i] * 2. * igl::PI / total_len;
51 UV.row(map_ij[bnd[i]]) << cos(frac), sin(frac);
52 }
53
54}

References cos(), PI, and sin().

+ Here is the call graph for this function:

◆ massmatrix()

template<typename DerivedV , typename DerivedF , typename Scalar >
IGL_INLINE void igl::massmatrix ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const MassMatrixType  type,
Eigen::SparseMatrix< Scalar > &  M 
)
22{
23 using namespace Eigen;
24 using namespace std;
25
26 const int n = V.rows();
27 const int m = F.rows();
28 const int simplex_size = F.cols();
29
30 MassMatrixType eff_type = type;
31 // Use voronoi of for triangles by default, otherwise barycentric
32 if(type == MASSMATRIX_TYPE_DEFAULT)
33 {
34 eff_type = (simplex_size == 3?MASSMATRIX_TYPE_VORONOI:MASSMATRIX_TYPE_BARYCENTRIC);
35 }
36
37 // Not yet supported
38 assert(type!=MASSMATRIX_TYPE_FULL);
39
43 if(simplex_size == 3)
44 {
45 // Triangles
46 // edge lengths numbered same as opposite vertices
48 // loop over faces
49 for(int i = 0;i<m;i++)
50 {
51 l(i,0) = (V.row(F(i,1))-V.row(F(i,2))).norm();
52 l(i,1) = (V.row(F(i,2))-V.row(F(i,0))).norm();
53 l(i,2) = (V.row(F(i,0))-V.row(F(i,1))).norm();
54 }
56 doublearea(l,0.,dblA);
57
58 switch(eff_type)
59 {
61 // diagonal entries for each face corner
62 MI.resize(m*3,1); MJ.resize(m*3,1); MV.resize(m*3,1);
63 MI.block(0*m,0,m,1) = F.col(0);
64 MI.block(1*m,0,m,1) = F.col(1);
65 MI.block(2*m,0,m,1) = F.col(2);
66 MJ = MI;
67 repmat(dblA,3,1,MV);
68 MV.array() /= 6.0;
69 break;
71 {
72 // diagonal entries for each face corner
73 // http://www.alecjacobson.com/weblog/?p=874
74 MI.resize(m*3,1); MJ.resize(m*3,1); MV.resize(m*3,1);
75 MI.block(0*m,0,m,1) = F.col(0);
76 MI.block(1*m,0,m,1) = F.col(1);
77 MI.block(2*m,0,m,1) = F.col(2);
78 MJ = MI;
79
80 // Holy shit this needs to be cleaned up and optimized
81 Matrix<Scalar,Dynamic,3> cosines(m,3);
82 cosines.col(0) =
83 (l.col(2).array().pow(2)+l.col(1).array().pow(2)-l.col(0).array().pow(2))/(l.col(1).array()*l.col(2).array()*2.0);
84 cosines.col(1) =
85 (l.col(0).array().pow(2)+l.col(2).array().pow(2)-l.col(1).array().pow(2))/(l.col(2).array()*l.col(0).array()*2.0);
86 cosines.col(2) =
87 (l.col(1).array().pow(2)+l.col(0).array().pow(2)-l.col(2).array().pow(2))/(l.col(0).array()*l.col(1).array()*2.0);
88 Matrix<Scalar,Dynamic,3> barycentric = cosines.array() * l.array();
89 normalize_row_sums(barycentric,barycentric);
90 Matrix<Scalar,Dynamic,3> partial = barycentric;
91 partial.col(0).array() *= dblA.array() * 0.5;
92 partial.col(1).array() *= dblA.array() * 0.5;
93 partial.col(2).array() *= dblA.array() * 0.5;
94 Matrix<Scalar,Dynamic,3> quads(partial.rows(),partial.cols());
95 quads.col(0) = (partial.col(1)+partial.col(2))*0.5;
96 quads.col(1) = (partial.col(2)+partial.col(0))*0.5;
97 quads.col(2) = (partial.col(0)+partial.col(1))*0.5;
98
99 quads.col(0) = (cosines.col(0).array()<0).select( 0.25*dblA,quads.col(0));
100 quads.col(1) = (cosines.col(0).array()<0).select(0.125*dblA,quads.col(1));
101 quads.col(2) = (cosines.col(0).array()<0).select(0.125*dblA,quads.col(2));
102
103 quads.col(0) = (cosines.col(1).array()<0).select(0.125*dblA,quads.col(0));
104 quads.col(1) = (cosines.col(1).array()<0).select(0.25*dblA,quads.col(1));
105 quads.col(2) = (cosines.col(1).array()<0).select(0.125*dblA,quads.col(2));
106
107 quads.col(0) = (cosines.col(2).array()<0).select(0.125*dblA,quads.col(0));
108 quads.col(1) = (cosines.col(2).array()<0).select(0.125*dblA,quads.col(1));
109 quads.col(2) = (cosines.col(2).array()<0).select( 0.25*dblA,quads.col(2));
110
111 MV.block(0*m,0,m,1) = quads.col(0);
112 MV.block(1*m,0,m,1) = quads.col(1);
113 MV.block(2*m,0,m,1) = quads.col(2);
114
115 break;
116 }
118 assert(false && "Implementation incomplete");
119 break;
120 default:
121 assert(false && "Unknown Mass matrix eff_type");
122 }
123
124 }else if(simplex_size == 4)
125 {
126 assert(V.cols() == 3);
127 assert(eff_type == MASSMATRIX_TYPE_BARYCENTRIC);
128 MI.resize(m*4,1); MJ.resize(m*4,1); MV.resize(m*4,1);
129 MI.block(0*m,0,m,1) = F.col(0);
130 MI.block(1*m,0,m,1) = F.col(1);
131 MI.block(2*m,0,m,1) = F.col(2);
132 MI.block(3*m,0,m,1) = F.col(3);
133 MJ = MI;
134 // loop over tets
135 for(int i = 0;i<m;i++)
136 {
137 // http://en.wikipedia.org/wiki/Tetrahedron#Volume
138 Matrix<Scalar,3,1> v0m3,v1m3,v2m3;
139 v0m3.head(V.cols()) = V.row(F(i,0)) - V.row(F(i,3));
140 v1m3.head(V.cols()) = V.row(F(i,1)) - V.row(F(i,3));
141 v2m3.head(V.cols()) = V.row(F(i,2)) - V.row(F(i,3));
142 Scalar v = fabs(v0m3.dot(v1m3.cross(v2m3)))/6.0;
143 MV(i+0*m) = v/4.0;
144 MV(i+1*m) = v/4.0;
145 MV(i+2*m) = v/4.0;
146 MV(i+3*m) = v/4.0;
147 }
148 }else
149 {
150 // Unsupported simplex size
151 assert(false && "Unsupported simplex size");
152 }
153 sparse(MI,MJ,MV,n,n,M);
154}
IGL_INLINE void repmat(const Eigen::MatrixBase< DerivedA > &A, const int r, const int c, Eigen::PlainObjectBase< DerivedB > &B)
Definition repmat.cpp:11
IGL_INLINE void normalize_row_sums(const Eigen::MatrixBase< DerivedA > &A, Eigen::MatrixBase< DerivedB > &B)
Definition normalize_row_sums.cpp:11
MassMatrixType
Definition massmatrix.h:20
IGL_INLINE void sparse(const IndexVector &I, const IndexVector &J, const ValueVector &V, Eigen::SparseMatrix< T > &X)
Definition sparse.cpp:14

References Eigen::PlainObjectBase< Derived >::cols(), doublearea(), MASSMATRIX_TYPE_BARYCENTRIC, MASSMATRIX_TYPE_DEFAULT, MASSMATRIX_TYPE_FULL, MASSMATRIX_TYPE_VORONOI, normalize_row_sums(), repmat(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), and sparse().

Referenced by arap_dof_precomputation(), arap_precomputation(), biharmonic_coordinates(), igl::embree::bone_heat(), harmonic(), harmonic(), and hessian_energy().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mat3_to_quat()

template<typename Q_type >
IGL_INLINE void igl::mat3_to_quat ( const Q_type *  m,
Q_type *  q 
)
85{
86 Q_type trace;
87 Q_type s;
88 Q_type t;
89 int i;
90 int j;
91 int k;
92
93 static int next[3] = { 1, 2, 0 };
94
95 trace = mat[0 * 3 + 0] + mat[1 * 3 + 1] + mat[2 * 3 + 2];
96
97 if ( trace > 0.0f ) {
98
99 t = trace + 1.0f;
100 s = ReciprocalSqrt( t ) * 0.5f;
101
102 q[3] = s * t;
103 q[0] = ( mat[1 * 3 + 2] - mat[2 * 3 + 1] ) * s;
104 q[1] = ( mat[2 * 3 + 0] - mat[0 * 3 + 2] ) * s;
105 q[2] = ( mat[0 * 3 + 1] - mat[1 * 3 + 0] ) * s;
106
107 } else {
108
109 i = 0;
110 if ( mat[1 * 3 + 1] > mat[0 * 3 + 0] ) {
111 i = 1;
112 }
113 if ( mat[2 * 3 + 2] > mat[i * 3 + i] ) {
114 i = 2;
115 }
116 j = next[i];
117 k = next[j];
118
119 t = ( mat[i * 3 + i] - ( mat[j * 3 + j] + mat[k * 3 + k] ) ) + 1.0f;
120 s = ReciprocalSqrt( t ) * 0.5f;
121
122 q[i] = s * t;
123 q[3] = ( mat[j * 3 + k] - mat[k * 3 + j] ) * s;
124 q[j] = ( mat[i * 3 + j] + mat[j * 3 + i] ) * s;
125 q[k] = ( mat[i * 3 + k] + mat[k * 3 + i] ) * s;
126 }
127
129 //jq.t[0] = mat[0 * 4 + 3];
130 //jq.t[1] = mat[1 * 4 + 3];
131 //jq.t[2] = mat[2 * 4 + 3];
132}
static Q_type ReciprocalSqrt(const Q_type x)
Definition mat_to_quat.cpp:13

References ReciprocalSqrt().

+ Here is the call graph for this function:

◆ mat4_to_quat()

template<typename Q_type >
IGL_INLINE void igl::mat4_to_quat ( const Q_type *  m,
Q_type *  q 
)
34{
35 Q_type trace;
36 Q_type s;
37 Q_type t;
38 int i;
39 int j;
40 int k;
41
42 static int next[3] = { 1, 2, 0 };
43
44 trace = mat[0 * 4 + 0] + mat[1 * 4 + 1] + mat[2 * 4 + 2];
45
46 if ( trace > 0.0f ) {
47
48 t = trace + 1.0f;
49 s = ReciprocalSqrt( t ) * 0.5f;
50
51 q[3] = s * t;
52 q[0] = ( mat[1 * 4 + 2] - mat[2 * 4 + 1] ) * s;
53 q[1] = ( mat[2 * 4 + 0] - mat[0 * 4 + 2] ) * s;
54 q[2] = ( mat[0 * 4 + 1] - mat[1 * 4 + 0] ) * s;
55
56 } else {
57
58 i = 0;
59 if ( mat[1 * 4 + 1] > mat[0 * 4 + 0] ) {
60 i = 1;
61 }
62 if ( mat[2 * 4 + 2] > mat[i * 4 + i] ) {
63 i = 2;
64 }
65 j = next[i];
66 k = next[j];
67
68 t = ( mat[i * 4 + i] - ( mat[j * 4 + j] + mat[k * 4 + k] ) ) + 1.0f;
69 s = ReciprocalSqrt( t ) * 0.5f;
70
71 q[i] = s * t;
72 q[3] = ( mat[j * 4 + k] - mat[k * 4 + j] ) * s;
73 q[j] = ( mat[i * 4 + j] + mat[j * 4 + i] ) * s;
74 q[k] = ( mat[i * 4 + k] + mat[k * 4 + i] ) * s;
75 }
76
78 //jq.t[0] = mat[0 * 4 + 3];
79 //jq.t[1] = mat[1 * 4 + 3];
80 //jq.t[2] = mat[2 * 4 + 3];
81}

References ReciprocalSqrt().

Referenced by igl::opengl2::RotateWidget::drag().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mat_max()

template<typename DerivedX , typename DerivedY , typename DerivedI >
IGL_INLINE void igl::mat_max ( const Eigen::DenseBase< DerivedX > &  X,
const int  dim,
Eigen::PlainObjectBase< DerivedY > &  Y,
Eigen::PlainObjectBase< DerivedI > &  I 
)
16{
17 assert(dim==1||dim==2);
18
19 // output size
20 int n = (dim==1?X.cols():X.rows());
21 // resize output
22 Y.resize(n);
23 I.resize(n);
24
25 // loop over dimension opposite of dim
26 for(int j = 0;j<n;j++)
27 {
28 typename DerivedX::Index PHONY,i;
29 typename DerivedX::Scalar m;
30 if(dim==1)
31 {
32 m = X.col(j).maxCoeff(&i,&PHONY);
33 }else
34 {
35 m = X.row(j).maxCoeff(&PHONY,&i);
36 }
37 Y(j) = m;
38 I(j) = i;
39 }
40}

References Eigen::PlainObjectBase< Derived >::resize().

Referenced by bounding_box_diagonal().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mat_min()

template<typename DerivedX , typename DerivedY , typename DerivedI >
IGL_INLINE void igl::mat_min ( const Eigen::DenseBase< DerivedX > &  X,
const int  dim,
Eigen::PlainObjectBase< DerivedY > &  Y,
Eigen::PlainObjectBase< DerivedI > &  I 
)
16{
17 assert(dim==1||dim==2);
18
19 // output size
20 int n = (dim==1?X.cols():X.rows());
21 // resize output
22 Y.resize(n);
23 I.resize(n);
24
25 // loop over dimension opposite of dim
26 for(int j = 0;j<n;j++)
27 {
28 typename DerivedX::Index PHONY,i;
29 typename DerivedX::Scalar m;
30 if(dim==1)
31 {
32 m = X.col(j).minCoeff(&i,&PHONY);
33 }else
34 {
35 m = X.row(j).minCoeff(&PHONY,&i);
36 }
37 Y(j) = m;
38 I(j) = i;
39 }
40}

References Eigen::PlainObjectBase< Derived >::resize().

Referenced by igl::embree::bone_heat(), bounding_box_diagonal(), ears(), and partition().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ matlab_format() [1/5]

IGL_INLINE Eigen::IOFormat igl::matlab_format ( )
74{
75 // M = [1 2 3;4 5 6];
76 // M.format(matlab_format()) produces:
77 // [
78 // 1 2 3
79 // 4 5 6
80 // ];
81 return Eigen::IOFormat(
83 0,
84 " ",
85 "\n",
86 "",
87 "",
88 // This seems like a bit of a hack since I would expect the rows to align
89 // with out this extra spacing on the first line
90 "[\n ",
91 "\n];");
92}
@ FullPrecision
Definition IO.h:18
Stores a set of parameters controlling the way matrices are printed.
Definition IO.h:51

References Eigen::FullPrecision.

Referenced by igl::copyleft::comiso::VertexIndexing< DerivedV, DerivedF >::VertexIndexing().

+ Here is the caller graph for this function:

◆ matlab_format() [2/5]

IGL_INLINE const std::string igl::matlab_format ( const double  v,
const std::string  name = "" 
)
97{
98 using namespace std;
99 string prefix = "";
100 if(!name.empty())
101 {
102 prefix = name + " = ";
103 }
104 return STR(prefix<<v<<";");
105}
#define STR(X)
Definition STR.h:17

References STR.

◆ matlab_format() [3/5]

template<typename DerivedM >
IGL_INLINE const Eigen::WithFormat< DerivedM > igl::matlab_format ( const Eigen::DenseBase< DerivedM > &  M,
const std::string  name = "" 
)
16{
17 using namespace std;
18 string prefix = "";
19 if(!name.empty())
20 {
21 prefix = name + " = ";
22 }
23
24 return M.format(Eigen::IOFormat(
26 0,
27 " ",
28 "\n",
29 "",
30 "",
31 // This seems like a bit of a hack since I would expect the rows to align
32 // with out this extra spacing on the first line
33 prefix + "[\n ",
34 "\n];"));
35}
const WithFormat< Derived > format(const IOFormat &fmt) const
Definition DenseBase.h:473

References Eigen::DenseBase< Derived >::format(), and Eigen::FullPrecision.

Referenced by matlab_format().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ matlab_format() [4/5]

template<typename DerivedS >
IGL_INLINE const std::string igl::matlab_format ( const Eigen::SparseMatrix< DerivedS > &  S,
const std::string  name = "" 
)
42{
43 using namespace Eigen;
44 using namespace std;
47 find(S,I,J,V);
48 I.array() += 1;
49 J.array() += 1;
50 SIJV.resize(V.rows(),3);
51 SIJV << I,J,V;
52 string prefix = "";
53 string suffix = "";
54 if(!name.empty())
55 {
56 prefix = name + "IJV = ";
57 suffix = "\n"+name + " = sparse("+name+"IJV(:,1),"+name+"IJV(:,2),"+name+"IJV(:,3),"+std::to_string(S.rows())+","+std::to_string(S.cols())+" );";
58 }
59 return STR(""<<
60 SIJV.format(Eigen::IOFormat(
62 0,
63 " ",
64 "\n",
65 "",
66 "",
67 // This seems like a bit of a hack since I would expect the rows to align
68 // with out this extra spacing on the first line
69 prefix + "[\n ",
70 "\n];"))<<suffix);
71}

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), find(), Eigen::FullPrecision, Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows(), and STR.

+ Here is the call graph for this function:

◆ matlab_format() [5/5]

IGL_INLINE const std::string igl::matlab_format ( const float  v,
const std::string  name = "" 
)
110{
111 return matlab_format(double(v),name);
112}
IGL_INLINE const Eigen::WithFormat< DerivedM > matlab_format(const Eigen::DenseBase< DerivedM > &M, const std::string name="")
Definition matlab_format.cpp:13

References matlab_format().

+ Here is the call graph for this function:

◆ matrix_to_list() [1/3]

template<typename DerivedM >
IGL_INLINE std::vector< typename DerivedM::Scalar > igl::matrix_to_list ( const Eigen::DenseBase< DerivedM > &  M)
50{
51 std::vector<typename DerivedM::Scalar> V;
52 matrix_to_list(M,V);
53 return V;
54}

References matrix_to_list().

+ Here is the call graph for this function:

◆ matrix_to_list() [2/3]

template<typename DerivedM >
IGL_INLINE void igl::matrix_to_list ( const Eigen::DenseBase< DerivedM > &  M,
std::vector< std::vector< typename DerivedM::Scalar > > &  V 
)
16{
17 using namespace std;
18 V.resize(M.rows(),vector<typename DerivedM::Scalar >(M.cols()));
19 // loop over rows
20 for(int i = 0;i<M.rows();i++)
21 {
22 // loop over cols
23 for(int j = 0;j<M.cols();j++)
24 {
25 V[i][j] = M(i,j);
26 }
27 }
28}

Referenced by boundary_facets(), matrix_to_list(), median(), igl::copyleft::tetgen::mesh_to_tetgenio(), igl::mosek::mosek_quadprog(), on_boundary(), polygon_mesh_to_triangle_mesh(), readNODE(), igl::copyleft::tetgen::tetrahedralize(), igl::copyleft::tetgen::tetrahedralize(), unique(), unique(), and writeTGF().

+ Here is the caller graph for this function:

◆ matrix_to_list() [3/3]

template<typename DerivedM >
IGL_INLINE void igl::matrix_to_list ( const Eigen::DenseBase< DerivedM > &  M,
std::vector< typename DerivedM::Scalar > &  V 
)
34{
35 using namespace std;
36 V.resize(M.size());
37 // loop over cols then rows
38 for(int j = 0;j<M.cols();j++)
39 {
40 for(int i = 0;i<M.rows();i++)
41 {
42 V[i+j*M.rows()] = M(i,j);
43 }
44 }
45}

◆ max()

template<typename AType , typename DerivedB , typename DerivedI >
IGL_INLINE void igl::max ( const Eigen::SparseMatrix< AType > &  A,
const int  dim,
Eigen::PlainObjectBase< DerivedB > &  B,
Eigen::PlainObjectBase< DerivedI > &  I 
)
11{
12 const int n = A.cols();
13 const int m = A.rows();
14 B.resize(dim==1?n:m);
15 B.setConstant(std::numeric_limits<typename DerivedB::Scalar>::lowest());
16 I.resize(dim==1?n:m);
17 for_each(A,[&B,&I,&dim](int i, int j,const typename DerivedB::Scalar v)
18 {
19 if(dim == 2)
20 {
21 std::swap(i,j);
22 }
23 // Coded as if dim == 1, assuming swap for dim == 2
24 if(v > B(j))
25 {
26 B(j) = v;
27 I(j) = i;
28 }
29 });
30 Eigen::VectorXi Z;
31 find_zero(A,dim,Z);
32 for(int j = 0;j<I.size();j++)
33 {
34 if(Z(j) != (dim==1?m:n) && 0 > B(j))
35 {
36 B(j) = 0;
37 I(j) = Z(j);
38 }
39 }
40}
IGL_INLINE void find_zero(const Eigen::SparseMatrix< AType > &A, const int dim, Eigen::PlainObjectBase< DerivedI > &I)
Definition find_zero.cpp:6

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), find_zero(), for_each(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows(), and Eigen::PlainObjectBase< Derived >::setConstant().

Referenced by igl::Camera::dolly_zoom().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ max_faces_stopping_condition() [1/2]

IGL_INLINE void igl::max_faces_stopping_condition ( int &  m,
const int  orig_m,
const int  max_m,
std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int)> &  stopping_condition 
)
29{
30 stopping_condition =
31 [orig_m,max_m,&m](
32 const Eigen::MatrixXd &,
33 const Eigen::MatrixXi &,
34 const Eigen::MatrixXi &,
35 const Eigen::VectorXi &,
36 const Eigen::MatrixXi &,
37 const Eigen::MatrixXi &,
38 const std::set<std::pair<double,int> > &,
39 const std::vector<std::set<std::pair<double,int> >::iterator > &,
40 const Eigen::MatrixXd &,
41 const int,
42 const int,
43 const int,
44 const int f1,
45 const int f2)->bool
46 {
47 // Only subtract if we're collapsing a real face
48 if(f1 < orig_m) m-=1;
49 if(f2 < orig_m) m-=1;
50 return m<=(int)max_m;
51 };
52}

Referenced by decimate(), max_faces_stopping_condition(), igl::copyleft::progressive_hulls(), and qslim().

+ Here is the caller graph for this function:

◆ max_faces_stopping_condition() [2/2]

IGL_INLINE std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int)> igl::max_faces_stopping_condition ( int &  m,
const int  orign_m,
const int  max_m 
)
74{
75 std::function<bool(
76 const Eigen::MatrixXd &,
77 const Eigen::MatrixXi &,
78 const Eigen::MatrixXi &,
79 const Eigen::VectorXi &,
80 const Eigen::MatrixXi &,
81 const Eigen::MatrixXi &,
82 const std::set<std::pair<double,int> > &,
83 const std::vector<std::set<std::pair<double,int> >::iterator > &,
84 const Eigen::MatrixXd &,
85 const int,
86 const int,
87 const int,
88 const int,
89 const int)> stopping_condition;
91 m,orig_m,max_m,stopping_condition);
92 return stopping_condition;
93}
IGL_INLINE void max_faces_stopping_condition(int &m, const int orig_m, const int max_m, std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int)> &stopping_condition)
Definition max_faces_stopping_condition.cpp:10

References max_faces_stopping_condition().

+ Here is the call graph for this function:

◆ max_size()

template<typename T >
IGL_INLINE int igl::max_size ( const std::vector< T > &  V)
13{
14 int max_size = -1;
15 for(
16 typename std::vector<T>::const_iterator iter = V.begin();
17 iter != V.end();
18 iter++)
19 {
20 int size = (int)iter->size();
21 max_size = (max_size > size ? max_size : size);
22 }
23 return max_size;
24}

References max_size().

Referenced by list_to_matrix(), max_size(), readOBJ(), and rows_to_matrix().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ maxBlokErr()

template<typename SSCALAR >
static SSCALAR igl::maxBlokErr ( const Eigen::Matrix3f &  blok)
inlinestatic
315 {
316 SSCALAR mD;
317 SSCALAR value = blok(0,0);
318 SSCALAR diff1 = fabs(blok(1,1) - value);
319 SSCALAR diff2 = fabs(blok(2,2) - value);
320 if (diff1 > diff2) mD = diff1;
321 else mD = diff2;
322
323 for (int v=0; v<3; v++)
324 {
325 for (int w=0; w<3; w++)
326 {
327 if (v == w)
328 {
329 continue;
330 }
331 if (mD < fabs(blok(v, w)))
332 {
333 mD = fabs(blok(v, w));
334 }
335 }
336 }
337
338 return mD;
339 }

◆ MAYA_BLUE()

const Eigen::Vector4f igl::MAYA_BLUE ( 0./  255.,
73./  255.,
252./  255.,
1.   
)

Referenced by igl::opengl2::RotateWidget::draw().

+ Here is the caller graph for this function:

◆ MAYA_CYAN()

const Eigen::Vector4f igl::MAYA_CYAN ( 131./  255.,
219./  255.,
252./  255.,
1.   
)

Referenced by igl::opengl2::RotateWidget::draw().

+ Here is the caller graph for this function:

◆ MAYA_GREEN()

const Eigen::Vector4f igl::MAYA_GREEN ( 128./  255.,
242./  255.,
0./  255.,
1.   
)

Referenced by igl::opengl2::RotateWidget::draw().

+ Here is the caller graph for this function:

◆ MAYA_GREY()

const Eigen::Vector4f igl::MAYA_GREY ( 0.  5,
0.  5,
0.  5,
1.  0 
)

Referenced by igl::opengl2::RotateWidget::draw(), and igl::opengl2::TranslateWidget::draw().

+ Here is the caller graph for this function:

◆ MAYA_PURPLE()

const Eigen::Vector4f igl::MAYA_PURPLE ( 180./  255.,
73./  255.,
200./  255.,
1.   
)

◆ MAYA_RED()

const Eigen::Vector4f igl::MAYA_RED ( 234./  255.,
63./  255.,
52./  255.,
1.   
)

Referenced by igl::opengl2::RotateWidget::draw().

+ Here is the caller graph for this function:

◆ MAYA_SEA_GREEN()

const Eigen::Vector4f igl::MAYA_SEA_GREEN ( 70./  255.,
252./  255.,
167./  255.,
1.   
)

Referenced by igl::opengl2::draw_skeleton_3d(), igl::opengl2::draw_skeleton_3d(), and igl::opengl2::draw_skeleton_3d().

+ Here is the caller graph for this function:

◆ MAYA_VIOLET()

const Eigen::Vector4f igl::MAYA_VIOLET ( 31./  255.,
15./  255.,
66./  255.,
1.   
)

◆ MAYA_YELLOW()

const Eigen::Vector4f igl::MAYA_YELLOW ( 255./  255.,
247./  255.,
50./  255.,
1.   
)

Referenced by igl::opengl2::RotateWidget::draw(), and igl::opengl2::TranslateWidget::draw().

+ Here is the caller graph for this function:

◆ median()

template<typename DerivedV , typename mType >
IGL_INLINE bool igl::median ( const Eigen::MatrixBase< DerivedV > &  V,
mType &  m 
)
17{
18 using namespace std;
19 if(V.size() == 0)
20 {
21 return false;
22 }
23 vector<typename DerivedV::Scalar> vV;
24 matrix_to_list(V,vV);
25 // http://stackoverflow.com/a/1719155/148668
26 size_t n = vV.size()/2;
27 nth_element(vV.begin(),vV.begin()+n,vV.end());
28 if(vV.size()%2==0)
29 {
30 nth_element(vV.begin(),vV.begin()+n-1,vV.end());
31 m = 0.5*(vV[n]+vV[n-1]);
32 }else
33 {
34 m = vV[n];
35 }
36 return true;
37}

References matrix_to_list().

Referenced by igl::WindingNumberAABB< Point, DerivedV, DerivedF >::grow(), and igl::AABB< DerivedV, DIM >::init().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mergeColumns()

template<typename MatrixXS >
static void igl::mergeColumns ( const MatrixXS &  Lsep,
int  numBones,
int  dim,
int  dimp1,
MatrixXS &  L 
)
static
433 {
434 assert(L.cols() == 1);
435 assert(L.rows() == dim*(dimp1)*numBones);
436
437 assert(Lsep.rows() == (dimp1)*numBones && Lsep.cols() == dim);
438
439 for (int b=0; b<numBones; b++)
440 {
441 for (int coord=0; coord<dimp1; coord++)
442 {
443 for (int c=0; c<dim; c++)
444 {
445 L(coord*numBones*dim + c*numBones + b, 0) = Lsep(coord*numBones + b, c);
446 }
447 }
448 }
449 }

References L.

Referenced by arap_dof_update().

+ Here is the caller graph for this function:

◆ min()

template<typename AType , typename DerivedB , typename DerivedI >
IGL_INLINE void igl::min ( const Eigen::SparseMatrix< AType > &  A,
const int  dim,
Eigen::PlainObjectBase< DerivedB > &  B,
Eigen::PlainObjectBase< DerivedI > &  I 
)
11{
12 const int n = A.cols();
13 const int m = A.rows();
14 B.resize(dim==1?n:m);
15 B.setConstant(std::numeric_limits<typename DerivedB::Scalar>::max());
16 I.resize(dim==1?n:m);
17 for_each(A,[&B,&I,&dim](int i, int j,const typename DerivedB::Scalar v)
18 {
19 if(dim == 2)
20 {
21 std::swap(i,j);
22 }
23 // Coded as if dim == 1, assuming swap for dim == 2
24 if(v < B(j))
25 {
26 B(j) = v;
27 I(j) = i;
28 }
29 });
30 Eigen::VectorXi Z;
31 find_zero(A,dim,Z);
32 for(int j = 0;j<I.size();j++)
33 {
34 if(Z(j) != (dim==1?m:n) && 0 < B(j))
35 {
36 B(j) = 0;
37 I(j) = Z(j);
38 }
39 }
40}

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), find_zero(), for_each(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows(), and Eigen::PlainObjectBase< Derived >::setConstant().

Referenced by igl::geodesic::GeodesicAlgorithmExact::check_stop_conditions(), igl::Camera::dolly_zoom(), and igl::geodesic::GeodesicAlgorithmExact::propagate().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ min_quad_dense_precompute()

template<typename T >
IGL_INLINE void igl::min_quad_dense_precompute ( const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &  A,
const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &  Aeq,
const bool  use_lu_decomposition,
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &  S 
)
21{
23 // This threshold seems to matter a lot but I'm not sure how to
24 // set it
25 const T treshold = igl::FLOAT_EPS;
26 //const T treshold = igl::DOUBLE_EPS;
27
28 const int n = A.rows();
29 assert(A.cols() == n);
30 const int m = Aeq.rows();
31 assert(Aeq.cols() == n);
32
33 // Lagrange multipliers method:
35 LM.block(0, 0, n, n) = A;
36 LM.block(0, n, n, m) = Aeq.transpose();
37 LM.block(n, 0, m, n) = Aeq;
38 LM.block(n, n, m, m).setZero();
39
40 Mat LMpinv;
41 if(use_lu_decomposition)
42 {
43 // if LM is close to singular, use at your own risk :)
44 LMpinv = LM.inverse();
45 }else
46 {
47 // use SVD
49 Vec singValues;
52 const Mat& u = svd.matrixU();
53 const Mat& v = svd.matrixV();
54 const Vec& singVals = svd.singularValues();
55
56 Vec pi_singVals(n + m);
57 int zeroed = 0;
58 for (int i=0; i<n + m; i++)
59 {
60 T sv = singVals(i, 0);
61 assert(sv >= 0);
62 // printf("sv: %lg ? %lg\n",(double) sv,(double)treshold);
63 if (sv > treshold) pi_singVals(i, 0) = T(1) / sv;
64 else
65 {
66 pi_singVals(i, 0) = T(0);
67 zeroed++;
68 }
69 }
70
71 printf("min_quad_dense_precompute: %i singular values zeroed (threshold = %e)\n", zeroed, treshold);
73
74 LMpinv = v * pi_diag * u.transpose();
75 }
76 S = LMpinv.block(0, 0, n, n + m);
77
79 //mlinit(&g_pEngine);
80 //
81 //mlsetmatrix(&g_pEngine, "A", A);
82 //mlsetmatrix(&g_pEngine, "Aeq", Aeq);
83 //mlsetmatrix(&g_pEngine, "LM", LM);
84 //mlsetmatrix(&g_pEngine, "u", u);
85 //mlsetmatrix(&g_pEngine, "v", v);
86 //MatrixXd svMat = singVals;
87 //mlsetmatrix(&g_pEngine, "singVals", svMat);
88 //mlsetmatrix(&g_pEngine, "LMpinv", LMpinv);
89 //mlsetmatrix(&g_pEngine, "S", S);
90
91 //int hu = 1;
92}
JacobiSVD & compute(const MatrixType &matrix, unsigned int computationOptions)
Method performing the decomposition of given matrix using custom options.
Definition JacobiSVD.h:663
const SingularValuesType & singularValues() const
Definition SVDBase.h:111
const MatrixUType & matrixU() const
Definition SVDBase.h:83
const MatrixVType & matrixV() const
Definition SVDBase.h:99
const float FLOAT_EPS
Definition EPS.h:16

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::JacobiSVD< _MatrixType, QRPreconditioner >::compute(), Eigen::ComputeFullU, Eigen::ComputeFullV, FLOAT_EPS, Eigen::SVDBase< Derived >::matrixU(), Eigen::SVDBase< Derived >::matrixV(), Eigen::PlainObjectBase< Derived >::rows(), Eigen::PlainObjectBase< Derived >::setZero(), and Eigen::SVDBase< Derived >::singularValues().

Referenced by arap_dof_recomputation().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ min_quad_with_fixed()

template<typename T , typename Derivedknown , typename DerivedB , typename DerivedY , typename DerivedBeq , typename DerivedZ >
IGL_INLINE bool igl::min_quad_with_fixed ( const Eigen::SparseMatrix< T > &  A,
const Eigen::MatrixBase< DerivedB > &  B,
const Eigen::MatrixBase< Derivedknown > &  known,
const Eigen::MatrixBase< DerivedY > &  Y,
const Eigen::SparseMatrix< T > &  Aeq,
const Eigen::MatrixBase< DerivedBeq > &  Beq,
const bool  pd,
Eigen::PlainObjectBase< DerivedZ > &  Z 
)
574{
576 if(!min_quad_with_fixed_precompute(A,known,Aeq,pd,data))
577 {
578 return false;
579 }
580 return min_quad_with_fixed_solve(data,B,Y,Beq,Z);
581}

References min_quad_with_fixed_precompute(), and min_quad_with_fixed_solve().

Referenced by biharmonic_coordinates().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ min_quad_with_fixed_precompute()

template<typename T , typename Derivedknown >
IGL_INLINE bool igl::min_quad_with_fixed_precompute ( const Eigen::SparseMatrix< T > &  A,
const Eigen::MatrixBase< Derivedknown > &  known,
const Eigen::SparseMatrix< T > &  Aeq,
const bool  pd,
min_quad_with_fixed_data< T > &  data 
)
35{
36//#define MIN_QUAD_WITH_FIXED_CPP_DEBUG
37 using namespace Eigen;
38 using namespace std;
39 const Eigen::SparseMatrix<T> A = 0.5*A2;
40#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG
41 cout<<" pre"<<endl;
42#endif
43 // number of rows
44 int n = A.rows();
45 // cache problem size
46 data.n = n;
47
48 int neq = Aeq.rows();
49 // default is to have 0 linear equality constraints
50 if(Aeq.size() != 0)
51 {
52 assert(n == Aeq.cols() && "#Aeq.cols() should match A.rows()");
53 }
54
55 assert(A.rows() == n && "A should be square");
56 assert(A.cols() == n && "A should be square");
57
58 // number of known rows
59 int kr = known.size();
60
61 assert((kr == 0 || known.minCoeff() >= 0)&& "known indices should be in [0,n)");
62 assert((kr == 0 || known.maxCoeff() < n) && "known indices should be in [0,n)");
63 assert(neq <= n && "Number of equality constraints should be less than DOFs");
64
65
66 // cache known
67 data.known = known;
68 // get list of unknown indices
69 data.unknown.resize(n-kr);
70 std::vector<bool> unknown_mask;
71 unknown_mask.resize(n,true);
72 for(int i = 0;i<kr;i++)
73 {
74 unknown_mask[known(i)] = false;
75 }
76 int u = 0;
77 for(int i = 0;i<n;i++)
78 {
79 if(unknown_mask[i])
80 {
81 data.unknown(u) = i;
82 u++;
83 }
84 }
85 // get list of lagrange multiplier indices
86 data.lagrange.resize(neq);
87 for(int i = 0;i<neq;i++)
88 {
89 data.lagrange(i) = n + i;
90 }
91 // cache unknown followed by lagrange indices
92 data.unknown_lagrange.resize(data.unknown.size()+data.lagrange.size());
93 // Would like to do:
94 //data.unknown_lagrange << data.unknown, data.lagrange;
95 // but Eigen can't handle empty vectors in comma initialization
96 // https://forum.kde.org/viewtopic.php?f=74&t=107974&p=364947#p364947
97 if(data.unknown.size() > 0)
98 {
99 data.unknown_lagrange.head(data.unknown.size()) = data.unknown;
100 }
101 if(data.lagrange.size() > 0)
102 {
103 data.unknown_lagrange.tail(data.lagrange.size()) = data.lagrange;
104 }
105
106 SparseMatrix<T> Auu;
107 slice(A,data.unknown,data.unknown,Auu);
108 assert(Auu.size() != 0 && Auu.rows() > 0 && "There should be at least one unknown.");
109
110 // Positive definiteness is *not* determined, rather it is given as a
111 // parameter
112 data.Auu_pd = pd;
113 if(data.Auu_pd)
114 {
115 // PD implies symmetric
116 data.Auu_sym = true;
117 // This is an annoying assertion unless EPS can be chosen in a nicer way.
118 //assert(is_symmetric(Auu,EPS<double>()));
119 assert(is_symmetric(Auu,1.0) &&
120 "Auu should be symmetric if positive definite");
121 }else
122 {
123 // determine if A(unknown,unknown) is symmetric and/or positive definite
124 VectorXi AuuI,AuuJ;
125 MatrixXd AuuV;
126 find(Auu,AuuI,AuuJ,AuuV);
127 data.Auu_sym = is_symmetric(Auu,EPS<double>()*AuuV.maxCoeff());
128 }
129
130 // Determine number of linearly independent constraints
131 int nc = 0;
132 if(neq>0)
133 {
134#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG
135 cout<<" qr"<<endl;
136#endif
137 // QR decomposition to determine row rank in Aequ
138 slice(Aeq,data.unknown,2,data.Aequ);
139 assert(data.Aequ.rows() == neq &&
140 "#Rows in Aequ should match #constraints");
141 assert(data.Aequ.cols() == data.unknown.size() &&
142 "#cols in Aequ should match #unknowns");
143 data.AeqTQR.compute(data.Aequ.transpose().eval());
144#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG
145 cout<<endl<<matlab_format(SparseMatrix<T>(data.Aequ.transpose().eval()),"AeqT")<<endl<<endl;
146#endif
147 switch(data.AeqTQR.info())
148 {
149 case Eigen::Success:
150 break;
152 cerr<<"Error: Numerical issue."<<endl;
153 return false;
155 cerr<<"Error: Invalid input."<<endl;
156 return false;
157 default:
158 cerr<<"Error: Other."<<endl;
159 return false;
160 }
161 nc = data.AeqTQR.rank();
162 assert(nc<=neq &&
163 "Rank of reduced constraints should be <= #original constraints");
164 data.Aeq_li = nc == neq;
165 //cout<<"data.Aeq_li: "<<data.Aeq_li<<endl;
166 }else
167 {
168 data.Aeq_li = true;
169 }
170
171 if(data.Aeq_li)
172 {
173#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG
174 cout<<" Aeq_li=true"<<endl;
175#endif
176 // Append lagrange multiplier quadratic terms
177 SparseMatrix<T> new_A;
178 SparseMatrix<T> AeqT = Aeq.transpose();
179 SparseMatrix<T> Z(neq,neq);
180 // This is a bit slower. But why isn't cat fast?
181 new_A = cat(1, cat(2, A, AeqT ),
182 cat(2, Aeq, Z ));
183
184 // precompute RHS builders
185 if(kr > 0)
186 {
187 SparseMatrix<T> Aulk,Akul;
188 // Slow
189 slice(new_A,data.unknown_lagrange,data.known,Aulk);
191 //data.preY = Aulk + Akul.transpose();
192 // Slow
193 if(data.Auu_sym)
194 {
195 data.preY = Aulk*2;
196 }else
197 {
198 slice(new_A,data.known,data.unknown_lagrange,Akul);
199 SparseMatrix<T> AkulT = Akul.transpose();
200 data.preY = Aulk + AkulT;
201 }
202 }else
203 {
204 data.preY.resize(data.unknown_lagrange.size(),0);
205 }
206
207 // Positive definite and no equality constraints (Positive definiteness
208 // implies symmetric)
209#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG
210 cout<<" factorize"<<endl;
211#endif
212 if(data.Auu_pd && neq == 0)
213 {
214#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG
215 cout<<" llt"<<endl;
216#endif
217 data.llt.compute(Auu);
218 switch(data.llt.info())
219 {
220 case Eigen::Success:
221 break;
223 cerr<<"Error: Numerical issue."<<endl;
224 return false;
225 default:
226 cerr<<"Error: Other."<<endl;
227 return false;
228 }
229 data.solver_type = min_quad_with_fixed_data<T>::LLT;
230 }else
231 {
232#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG
233 cout<<" ldlt"<<endl;
234#endif
235 // Either not PD or there are equality constraints
237 slice(new_A,data.unknown_lagrange,data.unknown_lagrange,NA);
238 data.NA = NA;
239 // Ideally we'd use LDLT but Eigen doesn't support positive semi-definite
240 // matrices:
241 // http://forum.kde.org/viewtopic.php?f=74&t=106962&p=291990#p291990
242 if(data.Auu_sym && false)
243 {
244 data.ldlt.compute(NA);
245 switch(data.ldlt.info())
246 {
247 case Eigen::Success:
248 break;
250 cerr<<"Error: Numerical issue."<<endl;
251 return false;
252 default:
253 cerr<<"Error: Other."<<endl;
254 return false;
255 }
256 data.solver_type = min_quad_with_fixed_data<T>::LDLT;
257 }else
258 {
259#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG
260 cout<<" lu"<<endl;
261#endif
262 // Resort to LU
263 // Bottleneck >1/2
264 data.lu.compute(NA);
265 //std::cout<<"NA=["<<std::endl<<NA<<std::endl<<"];"<<std::endl;
266 switch(data.lu.info())
267 {
268 case Eigen::Success:
269 break;
271 cerr<<"Error: Numerical issue."<<endl;
272 return false;
274 cerr<<"Error: Invalid Input."<<endl;
275 return false;
276 default:
277 cerr<<"Error: Other."<<endl;
278 return false;
279 }
280 data.solver_type = min_quad_with_fixed_data<T>::LU;
281 }
282 }
283 }else
284 {
285#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG
286 cout<<" Aeq_li=false"<<endl;
287#endif
288 data.neq = neq;
289 const int nu = data.unknown.size();
290 //cout<<"nu: "<<nu<<endl;
291 //cout<<"neq: "<<neq<<endl;
292 //cout<<"nc: "<<nc<<endl;
293 //cout<<" matrixR"<<endl;
294 SparseMatrix<T> AeqTR,AeqTQ;
295 AeqTR = data.AeqTQR.matrixR();
296 // This shouldn't be necessary
297 AeqTR.prune(0.0);
298#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG
299 cout<<" matrixQ"<<endl;
300#endif
301 // THIS IS ESSENTIALLY DENSE AND THIS IS BY FAR THE BOTTLENECK
302 // http://forum.kde.org/viewtopic.php?f=74&t=117500
303 AeqTQ = data.AeqTQR.matrixQ();
304#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG
305 cout<<" prune"<<endl;
306 cout<<" nnz: "<<AeqTQ.nonZeros()<<endl;
307#endif
308 // This shouldn't be necessary
309 AeqTQ.prune(0.0);
310 //cout<<"AeqTQ: "<<AeqTQ.rows()<<" "<<AeqTQ.cols()<<endl;
311 //cout<<matlab_format(AeqTQ,"AeqTQ")<<endl;
312 //cout<<" perms"<<endl;
313#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG
314 cout<<" nnz: "<<AeqTQ.nonZeros()<<endl;
315 cout<<" perm"<<endl;
316#endif
317 SparseMatrix<double> I(neq,neq);
318 I.setIdentity();
319 data.AeqTE = data.AeqTQR.colsPermutation() * I;
320 data.AeqTET = data.AeqTQR.colsPermutation().transpose() * I;
321 assert(AeqTR.rows() == nu && "#rows in AeqTR should match #unknowns");
322 assert(AeqTR.cols() == neq && "#cols in AeqTR should match #constraints");
323 assert(AeqTQ.rows() == nu && "#rows in AeqTQ should match #unknowns");
324 assert(AeqTQ.cols() == nu && "#cols in AeqTQ should match #unknowns");
325 //cout<<" slice"<<endl;
326#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG
327 cout<<" slice"<<endl;
328#endif
329 data.AeqTQ1 = AeqTQ.topLeftCorner(nu,nc);
330 data.AeqTQ1T = data.AeqTQ1.transpose().eval();
331 // ALREADY TRIM (Not 100% sure about this)
332 data.AeqTR1 = AeqTR.topLeftCorner(nc,nc);
333 data.AeqTR1T = data.AeqTR1.transpose().eval();
334 //cout<<"AeqTR1T.size() "<<data.AeqTR1T.rows()<<" "<<data.AeqTR1T.cols()<<endl;
335 // Null space
336 data.AeqTQ2 = AeqTQ.bottomRightCorner(nu,nu-nc);
337 data.AeqTQ2T = data.AeqTQ2.transpose().eval();
338#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG
339 cout<<" proj"<<endl;
340#endif
341 // Projected hessian
342 SparseMatrix<T> QRAuu = data.AeqTQ2T * Auu * data.AeqTQ2;
343 {
344#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG
345 cout<<" factorize"<<endl;
346#endif
347 // QRAuu should always be PD
348 data.llt.compute(QRAuu);
349 switch(data.llt.info())
350 {
351 case Eigen::Success:
352 break;
354 cerr<<"Error: Numerical issue."<<endl;
355 return false;
356 default:
357 cerr<<"Error: Other."<<endl;
358 return false;
359 }
360 data.solver_type = min_quad_with_fixed_data<T>::QR_LLT;
361 }
362#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG
363 cout<<" smash"<<endl;
364#endif
365 // Known value multiplier
366 SparseMatrix<T> Auk;
367 slice(A,data.unknown,data.known,Auk);
368 SparseMatrix<T> Aku;
369 slice(A,data.known,data.unknown,Aku);
370 SparseMatrix<T> AkuT = Aku.transpose();
371 data.preY = Auk + AkuT;
372 // Needed during solve
373 data.Auu = Auu;
374 slice(Aeq,data.known,2,data.Aeqk);
375 assert(data.Aeqk.rows() == neq);
376 assert(data.Aeqk.cols() == data.known.size());
377 }
378 return true;
379}
void prune(const Scalar &reference, const RealScalar &epsilon=NumTraits< RealScalar >::dummy_precision())
Definition SparseMatrix.h:507
@ InvalidInput
Definition Constants.h:439

References cat(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), find(), Eigen::InvalidInput, is_symmetric(), Eigen::DenseBase< Derived >::maxCoeff(), Eigen::DenseBase< Derived >::minCoeff(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::nonZeros(), Eigen::NumericalIssue, Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::prune(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setIdentity(), Eigen::SparseMatrixBase< Derived >::size(), slice(), Eigen::Success, and Eigen::SparseMatrixBase< Derived >::transpose().

Referenced by active_set(), arap_precomputation(), bbw(), harmonic(), lscm(), min_quad_with_fixed(), and shapeup_precomputation().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ min_quad_with_fixed_solve() [1/2]

template<typename T , typename DerivedB , typename DerivedY , typename DerivedBeq , typename DerivedZ >
IGL_INLINE bool igl::min_quad_with_fixed_solve ( const min_quad_with_fixed_data< T > &  data,
const Eigen::MatrixBase< DerivedB > &  B,
const Eigen::MatrixBase< DerivedY > &  Y,
const Eigen::MatrixBase< DerivedBeq > &  Beq,
Eigen::PlainObjectBase< DerivedZ > &  Z 
)

References min_quad_with_fixed_solve().

+ Here is the call graph for this function:

◆ min_quad_with_fixed_solve() [2/2]

template<typename T , typename DerivedB , typename DerivedY , typename DerivedBeq , typename DerivedZ , typename Derivedsol >
IGL_INLINE bool igl::min_quad_with_fixed_solve ( const min_quad_with_fixed_data< T > &  data,
const Eigen::MatrixBase< DerivedB > &  B,
const Eigen::MatrixBase< DerivedY > &  Y,
const Eigen::MatrixBase< DerivedBeq > &  Beq,
Eigen::PlainObjectBase< DerivedZ > &  Z,
Eigen::PlainObjectBase< Derivedsol > &  sol 
)
396{
397 using namespace std;
398 using namespace Eigen;
399 typedef Matrix<T,Dynamic,1> VectorXT;
400 typedef Matrix<T,Dynamic,Dynamic> MatrixXT;
401 // number of known rows
402 int kr = data.known.size();
403 if(kr!=0)
404 {
405 assert(kr == Y.rows());
406 }
407 // number of columns to solve
408 int cols = Y.cols();
409 assert(B.cols() == 1 || B.cols() == cols);
410 assert(Beq.size() == 0 || Beq.cols() == 1 || Beq.cols() == cols);
411
412 // resize output
413 Z.resize(data.n,cols);
414 // Set known values
415 for(int i = 0;i < kr;i++)
416 {
417 for(int j = 0;j < cols;j++)
418 {
419 Z(data.known(i),j) = Y(i,j);
420 }
421 }
422
423 if(data.Aeq_li)
424 {
425 // number of lagrange multipliers aka linear equality constraints
426 int neq = data.lagrange.size();
427 // append lagrange multiplier rhs's
428 MatrixXT BBeq(B.rows() + Beq.rows(),cols);
429 if(B.size() > 0)
430 {
431 BBeq.topLeftCorner(B.rows(),cols) = B.replicate(1,B.cols()==cols?1:cols);
432 }
433 if(Beq.size() > 0)
434 {
435 BBeq.bottomLeftCorner(Beq.rows(),cols) = -2.0*Beq.replicate(1,Beq.cols()==cols?1:cols);
436 }
437
438 // Build right hand side
439 MatrixXT BBequlcols;
440 igl::slice(BBeq,data.unknown_lagrange,1,BBequlcols);
441 MatrixXT NB;
442 if(kr == 0)
443 {
444 NB = BBequlcols;
445 }else
446 {
447 NB = data.preY * Y + BBequlcols;
448 }
449
450 //std::cout<<"NB=["<<std::endl<<NB<<std::endl<<"];"<<std::endl;
451 //cout<<matlab_format(NB,"NB")<<endl;
452 switch(data.solver_type)
453 {
455 sol = data.llt.solve(NB);
456 break;
458 sol = data.ldlt.solve(NB);
459 break;
461 // Not a bottleneck
462 sol = data.lu.solve(NB);
463 break;
464 default:
465 cerr<<"Error: invalid solver type"<<endl;
466 return false;
467 }
468 //std::cout<<"sol=["<<std::endl<<sol<<std::endl<<"];"<<std::endl;
469 // Now sol contains sol/-0.5
470 sol *= -0.5;
471 // Now sol contains solution
472 // Place solution in Z
473 for(int i = 0;i<(sol.rows()-neq);i++)
474 {
475 for(int j = 0;j<sol.cols();j++)
476 {
477 Z(data.unknown_lagrange(i),j) = sol(i,j);
478 }
479 }
480 }else
481 {
482 assert(data.solver_type == min_quad_with_fixed_data<T>::QR_LLT);
483 MatrixXT eff_Beq;
484 // Adjust Aeq rhs to include known parts
485 eff_Beq =
486 //data.AeqTQR.colsPermutation().transpose() * (-data.Aeqk * Y + Beq);
487 data.AeqTET * (-data.Aeqk * Y + Beq.replicate(1,Beq.cols()==cols?1:cols));
488 // Where did this -0.5 come from? Probably the same place as above.
489 MatrixXT Bu;
490 slice(B,data.unknown,1,Bu);
491 MatrixXT NB;
492 NB = -0.5*(Bu.replicate(1,B.cols()==cols?1:cols) + data.preY * Y);
493 // Trim eff_Beq
494 const int nc = data.AeqTQR.rank();
495 const int neq = Beq.rows();
496 eff_Beq = eff_Beq.topLeftCorner(nc,cols).eval();
497 data.AeqTR1T.template triangularView<Lower>().solveInPlace(eff_Beq);
498 // Now eff_Beq = (data.AeqTR1T \ (data.AeqTET * (-data.Aeqk * Y + Beq)))
499 MatrixXT lambda_0;
500 lambda_0 = data.AeqTQ1 * eff_Beq;
501 //cout<<matlab_format(lambda_0,"lambda_0")<<endl;
502 MatrixXT QRB;
503 QRB = -data.AeqTQ2T * (data.Auu * lambda_0) + data.AeqTQ2T * NB;
504 Derivedsol lambda;
505 lambda = data.llt.solve(QRB);
506 // prepare output
507 Derivedsol solu;
508 solu = data.AeqTQ2 * lambda + lambda_0;
509 // http://www.math.uh.edu/~rohop/fall_06/Chapter3.pdf
510 Derivedsol solLambda;
511 {
512 Derivedsol temp1,temp2;
513 temp1 = (data.AeqTQ1T * NB - data.AeqTQ1T * data.Auu * solu);
514 data.AeqTR1.template triangularView<Upper>().solveInPlace(temp1);
515 //cout<<matlab_format(temp1,"temp1")<<endl;
516 temp2 = Derivedsol::Zero(neq,cols);
517 temp2.topLeftCorner(nc,cols) = temp1;
518 //solLambda = data.AeqTQR.colsPermutation() * temp2;
519 solLambda = data.AeqTE * temp2;
520 }
521 // sol is [Z(unknown);Lambda]
522 assert(data.unknown.size() == solu.rows());
523 assert(cols == solu.cols());
524 assert(data.neq == neq);
525 assert(data.neq == solLambda.rows());
526 assert(cols == solLambda.cols());
527 sol.resize(data.unknown.size()+data.neq,cols);
528 sol.block(0,0,solu.rows(),solu.cols()) = solu;
529 sol.block(solu.rows(),0,solLambda.rows(),solLambda.cols()) = solLambda;
530 for(int u = 0;u<data.unknown.size();u++)
531 {
532 for(int j = 0;j<Z.cols();j++)
533 {
534 Z(data.unknown(u),j) = solu(u,j);
535 }
536 }
537 }
538 return true;
539}
EIGEN_DEVICE_FUNC const Replicate< Derived, RowFactor, ColFactor > replicate() const
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EvalReturnType eval() const
Definition DenseBase.h:401

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::MatrixBase< Derived >::eval(), Eigen::DenseBase< Derived >::replicate(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), and slice().

Referenced by active_set(), arap_solve(), bbw(), harmonic(), lscm(), min_quad_with_fixed(), min_quad_with_fixed_solve(), and shapeup_solve().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ min_size()

template<typename T >
IGL_INLINE int igl::min_size ( const std::vector< T > &  V)
12{
13 int min_size = -1;
14 for(
15 typename std::vector<T>::const_iterator iter = V.begin();
16 iter != V.end();
17 iter++)
18 {
19 int size = (int)iter->size();
20 // have to handle base case
21 if(min_size == -1)
22 {
23 min_size = size;
24 }else{
25 min_size = (min_size < size ? min_size : size);
26 }
27 }
28 return min_size;
29}

References min_size().

Referenced by list_to_matrix(), min_size(), readOBJ(), and rows_to_matrix().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mod() [1/2]

template<typename DerivedA >
IGL_INLINE DerivedA igl::mod ( const Eigen::PlainObjectBase< DerivedA > &  A,
const int  base 
)
28{
29 DerivedA B;
30 mod(A,base,B);
31 return B;
32}
IGL_INLINE void mod(const Eigen::PlainObjectBase< DerivedA > &A, const int base, Eigen::PlainObjectBase< DerivedB > &B)
Definition mod.cpp:11

References mod().

+ Here is the call graph for this function:

◆ mod() [2/2]

template<typename DerivedA , typename DerivedB >
IGL_INLINE void igl::mod ( const Eigen::PlainObjectBase< DerivedA > &  A,
const int  base,
Eigen::PlainObjectBase< DerivedB > &  B 
)
15{
16 B.resizeLike(A);
17 for(int i = 0;i<A.rows();i++)
18 {
19 for(int j = 0;j<A.cols();j++)
20 {
21 B(i,j) = A(i,j)%base;
22 }
23 }
24}

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::resizeLike(), and Eigen::PlainObjectBase< Derived >::rows().

Referenced by mod().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mode()

template<typename T >
IGL_INLINE void igl::mode ( const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &  X,
const int  d,
Eigen::Matrix< T, Eigen::Dynamic, 1 > &  M 
)
18{
19 assert(d==1 || d==2);
20 using namespace std;
21 int m = X.rows();
22 int n = X.cols();
23 M.resize((d==1)?n:m,1);
24 for(int i = 0;i<((d==2)?m:n);i++)
25 {
26 vector<int> counts(((d==2)?n:m),0);
27 for(int j = 0;j<((d==2)?n:m);j++)
28 {
29 T v = (d==2)?X(i,j):X(j,i);
30 for(int k = 0;k<((d==2)?n:m);k++)
31 {
32 T u = (d==2)?X(i,k):X(k,i);
33 if(v == u)
34 {
35 counts[k]++;
36 }
37 }
38 }
39 assert(counts.size() > 0);
40 int max_count = -1;
41 int max_count_j = -1;
42 int j =0;
43 for(vector<int>::iterator it = counts.begin();it<counts.end();it++)
44 {
45 if(max_count < *it)
46 {
47 max_count = *it;
48 max_count_j = j;
49 }
50 j++;
51 }
52 M(i,0) = (d==2)?X(i,max_count_j):X(max_count_j,i);
53 }
54}

References Eigen::PlainObjectBase< Derived >::resize().

Referenced by igl::opengl::glfw::Viewer::launch_init(), serialize(), and igl::opengl2::MouseController::set_widget_mode().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mvc()

IGL_INLINE void igl::mvc ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXd &  C,
Eigen::MatrixXd &  W 
)
15{
16
17 // at least three control points
18 assert(C.rows()>2);
19
20 // dimension of points
21 assert(C.cols() == 3 || C.cols() == 2);
22 assert(V.cols() == 3 || V.cols() == 2);
23
24 // number of polygon points
25 int num = C.rows();
26
27 Eigen::MatrixXd V1,C1;
28 int i_prev, i_next;
29
30 // check if either are 3D but really all z's are 0
31 bool V_flat = (V.cols() == 3) && (std::sqrt( (V.col(3)).dot(V.col(3)) ) < 1e-10);
32 bool C_flat = (C.cols() == 3) && (std::sqrt( (C.col(3)).dot(C.col(3)) ) < 1e-10);
33
34 // if both are essentially 2D then ignore z-coords
35 if((C.cols() == 2 || C_flat) && (V.cols() == 2 || V_flat))
36 {
37 // ignore z coordinate
38 V1 = V.block(0,0,V.rows(),2);
39 C1 = C.block(0,0,C.rows(),2);
40 }
41 else
42 {
43 // give dummy z coordinate to either mesh or poly
44 if(V.rows() == 2)
45 {
46 V1 = Eigen::MatrixXd(V.rows(),3);
47 V1.block(0,0,V.rows(),2) = V;
48 }
49 else
50 V1 = V;
51
52 if(C.rows() == 2)
53 {
54 C1 = Eigen::MatrixXd(C.rows(),3);
55 C1.block(0,0,C.rows(),2) = C;
56 }
57 else
58 C1 = C;
59
60 // check that C is planar
61 // average normal around poly corners
62
63 Eigen::Vector3d n = Eigen::Vector3d::Zero();
64 // take centroid as point on plane
65 Eigen::Vector3d p = Eigen::Vector3d::Zero();
66 for (int i = 0; i<num; ++i)
67 {
68 i_prev = (i>0)?(i-1):(num-1);
69 i_next = (i<num-1)?(i+1):0;
70 Eigen::Vector3d vnext = (C1.row(i_next) - C1.row(i)).transpose();
71 Eigen::Vector3d vprev = (C1.row(i_prev) - C1.row(i)).transpose();
72 n += vnext.cross(vprev);
73 p += C1.row(i);
74 }
75 p/=num;
76 n/=num;
77 // normalize n
78 n /= std::sqrt(n.dot(n));
79
80 // check that poly is really coplanar
81#ifndef NDEBUG
82 for (int i = 0; i<num; ++i)
83 {
84 double dist_to_plane_C = std::abs((C1.row(i)-p.transpose()).dot(n));
85 assert(dist_to_plane_C<1e-10);
86 }
87#endif
88
89 // check that poly is really coplanar
90 for (int i = 0; i<V1.rows(); ++i)
91 {
92 double dist_to_plane_V = std::abs((V1.row(i)-p.transpose()).dot(n));
93 if(dist_to_plane_V>1e-10)
94 std::cerr<<"Distance from V to plane of C is large..."<<std::endl;
95 }
96
97 // change of basis
98 Eigen::Vector3d b1 = C1.row(1)-C1.row(0);
99 Eigen::Vector3d b2 = n.cross(b1);
100 // normalize basis rows
101 b1 /= std::sqrt(b1.dot(b1));
102 b2 /= std::sqrt(b2.dot(b2));
103 n /= std::sqrt(n.dot(n));
104
105 //transpose of the basis matrix in the m-file
106 Eigen::Matrix3d basis = Eigen::Matrix3d::Zero();
107 basis.col(0) = b1;
108 basis.col(1) = b2;
109 basis.col(2) = n;
110
111 // change basis of rows vectors by right multiplying with inverse of matrix
112 // with basis vectors as rows
113 Eigen::ColPivHouseholderQR<Eigen::Matrix3d> solver = basis.colPivHouseholderQr();
114 // Throw away coordinates in normal direction
115 V1 = solver.solve(V1.transpose()).transpose().block(0,0,V1.rows(),2);
116 C1 = solver.solve(C1.transpose()).transpose().block(0,0,C1.rows(),2);
117
118 }
119
120 // vectors from V to every C, where CmV(i,j,:) is the vector from domain
121 // vertex j to handle i
122 double EPS = 1e-10;
123 Eigen::MatrixXd WW = Eigen::MatrixXd(C1.rows(), V1.rows());
124 Eigen::MatrixXd dist_C_V (C1.rows(), V1.rows());
125 std::vector< std::pair<int,int> > on_corner(0);
126 std::vector< std::pair<int,int> > on_segment(0);
127 for (int i = 0; i<C1.rows(); ++i)
128 {
129 i_prev = (i>0)?(i-1):(num-1);
130 i_next = (i<num-1)?(i+1):0;
131 // distance from each corner in C to the next corner so that edge_length(i)
132 // is the distance from C(i,:) to C(i+1,:) defined cyclically
133 double edge_length = std::sqrt((C1.row(i) - C1.row(i_next)).dot(C1.row(i) - C1.row(i_next)));
134 for (int j = 0; j<V1.rows(); ++j)
135 {
136 Eigen::VectorXd v = C1.row(i) - V1.row(j);
137 Eigen::VectorXd vnext = C1.row(i_next) - V1.row(j);
138 Eigen::VectorXd vprev = C1.row(i_prev) - V1.row(j);
139 // distance from V to every C, where dist_C_V(i,j) is the distance from domain
140 // vertex j to handle i
141 dist_C_V(i,j) = std::sqrt(v.dot(v));
142 double dist_C_V_next = std::sqrt(vnext.dot(vnext));
143 double a_prev = std::atan2(vprev[1],vprev[0]) - std::atan2(v[1],v[0]);
144 double a_next = std::atan2(v[1],v[0]) - std::atan2(vnext[1],vnext[0]);
145 // mean value coordinates
146 WW(i,j) = (std::tan(a_prev/2.0) + std::tan(a_next/2.0)) / dist_C_V(i,j);
147
148 if (dist_C_V(i,j) < EPS)
149 on_corner.push_back(std::make_pair(j,i));
150 else
151 // only in case of no-corner (no need for checking for multiple segments afterwards --
152 // should only be on one segment (otherwise must be on a corner and we already
153 // handled that)
154 // domain vertex j is on the segment from i to i+1 if the distances from vj to
155 // pi and pi+1 are about
156 if(std::abs((dist_C_V(i,j) + dist_C_V_next) / edge_length - 1) < EPS)
157 on_segment.push_back(std::make_pair(j,i));
158
159 }
160 }
161
162 // handle degenerate cases
163 // snap vertices close to corners
164 for (unsigned i = 0; i<on_corner.size(); ++i)
165 {
166 int vi = on_corner[i].first;
167 int ci = on_corner[i].second;
168 for (int ii = 0; ii<C.rows(); ++ii)
169 WW(ii,vi) = (ii==ci)?1:0;
170 }
171
172 // snap vertices close to segments
173 for (unsigned i = 0; i<on_segment.size(); ++i)
174 {
175 int vi = on_segment[i].first;
176 int ci = on_segment[i].second;
177 int ci_next = (ci<num-1)?(ci+1):0;
178 for (int ii = 0; ii<C.rows(); ++ii)
179 if (ii == ci)
180 WW(ii,vi) = dist_C_V(ci_next,vi);
181 else
182 {
183 if ( ii == ci_next)
184 WW(ii,vi) = dist_C_V(ci,vi);
185 else
186 WW(ii,vi) = 0;
187 }
188 }
189
190 // normalize W
191 for (int i = 0; i<V.rows(); ++i)
192 WW.col(i) /= WW.col(i).sum();
193
194 // we've made W transpose
195 W = WW.transpose();
196}
Householder rank-revealing QR decomposition of a matrix with column-pivoting.
Definition ColPivHouseholderQR.h:49
const Solve< ColPivHouseholderQR, Rhs > solve(const MatrixBase< Rhs > &b) const
Definition ColPivHouseholderQR.h:175
IGL_INLINE S_type EPS()

References EPS(), and Eigen::ColPivHouseholderQR< _MatrixType >::solve().

+ Here is the call graph for this function:

◆ nchoosek() [1/2]

template<typename DerivedV , typename DerivedU >
IGL_INLINE void igl::nchoosek ( const Eigen::MatrixBase< DerivedV > &  V,
const int  k,
Eigen::PlainObjectBase< DerivedU > &  U 
)
36{
37 using namespace Eigen;
38 if(V.size() == 0)
39 {
40 U.resize(0,k);
41 return;
42 }
43 assert((V.cols() == 1 || V.rows() == 1) && "V must be a vector");
44 U.resize(nchoosek(V.size(),k),k);
45 int running_i = 0;
46 int running_j = 0;
48 int N = V.size();
49 const std::function<void(int,int)> doCombs =
50 [&running,&N,&doCombs,&running_i,&running_j,&U,&V](int offset, int k)
51 {
52 if(k==0)
53 {
54 U.row(running_i) = running;
55 running_i++;
56 return;
57 }
58 for (int i = offset; i <= N - k; ++i)
59 {
60 running(running_j) = V(i);
61 running_j++;
62 doCombs(i+1,k-1);
63 running_j--;
64 }
65 };
66 doCombs(0,k);
67}

References nchoosek(), Eigen::PlainObjectBase< Derived >::resize(), and void().

+ Here is the call graph for this function:

◆ nchoosek() [2/2]

IGL_INLINE double igl::nchoosek ( const int  n,
const int  k 
)
13{
14 if(k>n/2)
15 {
16 return nchoosek(n,n-k);
17 }else if(k==1)
18 {
19 return n;
20 }else
21 {
22 double c = 1;
23 for(int i = 1;i<=k;i++)
24 {
25 c *= (((double)n-k+i)/((double)i));
26 }
27 return std::round(c);
28 }
29}
IGL_INLINE double nchoosek(const int n, const int k)
Definition nchoosek.cpp:12

References nchoosek().

Referenced by nchoosek(), and nchoosek().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ next_filename()

bool igl::next_filename ( const std::string &  prefix,
const int  zeros,
const std::string &  suffix,
std::string &  next 
)
19{
20 using namespace std;
21 // O(n), for huge lists could at least find bounds with exponential search
22 // and then narrow with binary search O(log(n))
23 int i = 0;
24 while(true)
25 {
26 next = STR(prefix << setfill('0') << setw(zeros)<<i<<suffix);
27 if(!file_exists(next))
28 {
29 return true;
30 }
31 i++;
32 if(zeros > 0 && i >= pow(10,zeros))
33 {
34 return false;
35 }
36 }
37}
IGL_INLINE bool file_exists(const std::string filename)
Definition file_exists.cpp:12

References file_exists(), and STR.

+ Here is the call graph for this function:

◆ normal_derivative()

template<typename DerivedV , typename DerivedEle , typename Scalar >
IGL_INLINE void igl::normal_derivative ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedEle > &  Ele,
Eigen::SparseMatrix< Scalar > &  DD 
)
22{
23 using namespace Eigen;
24 using namespace std;
25 // Element simplex-size
26 const size_t ss = Ele.cols();
27 assert( ((ss==3) || (ss==4)) && "Only triangles or tets");
28 // cotangents
30 cotmatrix_entries(V,Ele,C);
31 vector<Triplet<Scalar> > IJV;
32 // Number of elements
33 const size_t m = Ele.rows();
34 // Number of vertices
35 const size_t n = V.rows();
36 switch(ss)
37 {
38 default:
39 assert(false);
40 return;
41 case 4:
42 {
43 const MatrixXi DDJ =
44 slice(
45 Ele,
46 (VectorXi(24)<<
47 1,0,2,0,3,0,2,1,3,1,0,1,3,2,0,2,1,2,0,3,1,3,2,3).finished(),
48 2);
49 MatrixXi DDI(m,24);
50 for(size_t f = 0;f<4;f++)
51 {
52 const auto & I = (igl::LinSpaced<VectorXi >(m,0,m-1).array()+f*m).eval();
53 for(size_t r = 0;r<6;r++)
54 {
55 DDI.col(f*6+r) = I;
56 }
57 }
59 (Matrix<Scalar,2,1>(1,-1).template replicate<12,1>()).asDiagonal();
61 slice(
62 C,
63 (VectorXi(24)<<
64 2,2,1,1,3,3,0,0,4,4,2,2,5,5,1,1,0,0,3,3,4,4,5,5).finished(),
65 2);
66 DDV *= S;
67
68 IJV.reserve(DDV.size());
69 for(size_t f = 0;f<6*4;f++)
70 {
71 for(size_t e = 0;e<m;e++)
72 {
73 IJV.push_back(Triplet<Scalar>(DDI(e,f),DDJ(e,f),DDV(e,f)));
74 }
75 }
76 DD.resize(m*4,n);
77 DD.setFromTriplets(IJV.begin(),IJV.end());
78 break;
79 }
80 case 3:
81 {
82 const MatrixXi DDJ =
83 slice(Ele,(VectorXi(12)<<2,0,1,0,0,1,2,1,1,2,0,2).finished(),2);
84 MatrixXi DDI(m,12);
85 for(size_t f = 0;f<3;f++)
86 {
87 const auto & I = (igl::LinSpaced<VectorXi >(m,0,m-1).array()+f*m).eval();
88 for(size_t r = 0;r<4;r++)
89 {
90 DDI.col(f*4+r) = I;
91 }
92 }
94 (Matrix<Scalar,2,1>(1,-1).template replicate<6,1>()).asDiagonal();
96 slice(C,(VectorXi(12)<<1,1,2,2,2,2,0,0,0,0,1,1).finished(),2);
97 DDV *= S;
98
99 IJV.reserve(DDV.size());
100 for(size_t f = 0;f<12;f++)
101 {
102 for(size_t e = 0;e<m;e++)
103 {
104 IJV.push_back(Triplet<Scalar>(DDI(e,f),DDJ(e,f),DDV(e,f)));
105 }
106 }
107 DD.resize(m*3,n);
108 DD.setFromTriplets(IJV.begin(),IJV.end());
109 break;
110 }
111 }
112
113}

References Eigen::PlainObjectBase< Derived >::cols(), cotmatrix_entries(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::resize(), Eigen::PlainObjectBase< Derived >::rows(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets(), and slice().

Referenced by biharmonic_coordinates().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ normalize_quat()

template<typename Q_type >
IGL_INLINE bool igl::normalize_quat ( const Q_type *  q,
Q_type *  out 
)
17{
18 // Get length
19 Q_type len = sqrt(
20 q[0]*q[0]+
21 q[1]*q[1]+
22 q[2]*q[2]+
23 q[3]*q[3]);
24
25 // Noramlize each coordinate
26 out[0] = q[0]/len;
27 out[1] = q[1]/len;
28 out[2] = q[2]/len;
29 out[3] = q[3]/len;
30
31 // Test whether length was below Epsilon
32 return (len > igl::EPS<Q_type>());
33}

References sqrt().

Referenced by snap_to_canonical_view_quat().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ normalize_row_lengths()

template<typename DerivedV >
IGL_INLINE void igl::normalize_row_lengths ( const Eigen::PlainObjectBase< DerivedV > &  A,
Eigen::PlainObjectBase< DerivedV > &  B 
)
14{
15 // Resize output
16 B.resizeLike(A);
17
18 // loop over rows
19 for(int i = 0; i < A.rows();i++)
20 {
21 B.row(i) = A.row(i).normalized();
22 }
24 //B = A;
25 //B.rowwise().normalize();
26}

References Eigen::PlainObjectBase< Derived >::resizeLike(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ normalize_row_sums()

template<typename DerivedA , typename DerivedB >
IGL_INLINE void igl::normalize_row_sums ( const Eigen::MatrixBase< DerivedA > &  A,
Eigen::MatrixBase< DerivedB > &  B 
)
14{
15#ifndef NDEBUG
16 // loop over rows
17 for(int i = 0; i < A.rows();i++)
18 {
19 typename DerivedB::Scalar sum = A.row(i).sum();
20 assert(sum != 0);
21 }
22#endif
23 B = (A.array().colwise() / A.rowwise().sum().array()).eval();
24}
EIGEN_DEVICE_FUNC Scalar sum() const
Definition Redux.h:449
EIGEN_DEVICE_FUNC ConstRowwiseReturnType rowwise() const
Definition DenseBase.h:504
EIGEN_DEVICE_FUNC const SumReturnType sum() const
Definition VectorwiseOp.h:398

References Eigen::MatrixBase< Derived >::array(), Eigen::DenseBase< Derived >::rowwise(), Eigen::DenseBase< Derived >::sum(), Eigen::VectorwiseOp< ExpressionType, Direction >::sum(), and sum().

Referenced by massmatrix().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ null()

template<typename DerivedA , typename DerivedN >
IGL_INLINE void igl::null ( const Eigen::PlainObjectBase< DerivedA > &  A,
Eigen::PlainObjectBase< DerivedN > &  N 
)
15{
16 using namespace Eigen;
17 typedef typename DerivedA::Scalar Scalar;
18 JacobiSVD<MatrixXd> svd(A, ComputeFullV);
19 svd.setThreshold(A.cols() * svd.singularValues().maxCoeff() * EPS<Scalar>());
20 N = svd.matrixV().rightCols(A.cols()-svd.rank());
21}

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::SVDBase< Derived >::matrixV(), Eigen::JacobiSVD< _MatrixType, QRPreconditioner >::rank(), Eigen::SVDBase< Derived >::setThreshold(), and Eigen::SVDBase< Derived >::singularValues().

+ Here is the call graph for this function:

◆ octree()

template<typename DerivedP , typename IndexType , typename DerivedCH , typename DerivedCN , typename DerivedW >
IGL_INLINE void igl::octree ( const Eigen::MatrixBase< DerivedP > &  P,
std::vector< std::vector< IndexType > > &  point_indices,
Eigen::PlainObjectBase< DerivedCH > &  CH,
Eigen::PlainObjectBase< DerivedCN > &  CN,
Eigen::PlainObjectBase< DerivedW > &  W 
)
13 {
14
15
16
17 const int MAX_DEPTH = 30000;
18
19 typedef typename DerivedCH::Scalar ChildrenType;
20 typedef typename DerivedCN::Scalar CentersType;
21 typedef typename DerivedW::Scalar WidthsType;
22 typedef Eigen::Matrix<ChildrenType,8,1> Vector8i;
24 typedef Eigen::Matrix<CentersType, 1, 3> RowVector3CentersType;
25
26 std::vector<Eigen::Matrix<ChildrenType,8,1>,
28 std::vector<Eigen::Matrix<CentersType,1,3>,
30 std::vector<WidthsType> widths;
31
32 auto get_octant = [](RowVector3PType location,
33 RowVector3CentersType center){
34 // We use a binary numbering of children. Treating the parent cell's
35 // center as the origin, we number the octants in the following manner:
36 // The first bit is 1 iff the octant's x coordinate is positive
37 // The second bit is 1 iff the octant's y coordinate is positive
38 // The third bit is 1 iff the octant's z coordinate is positive
39 //
40 // For example, the octant with negative x, positive y, positive z is:
41 // 110 binary = 6 decimal
42 IndexType index = 0;
43 if( location(0) >= center(0)){
44 index = index + 1;
45 }
46 if( location(1) >= center(1)){
47 index = index + 2;
48 }
49 if( location(2) >= center(2)){
50 index = index + 4;
51 }
52 return index;
53 };
54
55
56 std::function< RowVector3CentersType(const RowVector3CentersType,
57 const CentersType,
58 const ChildrenType) >
59 translate_center =
60 [](const RowVector3CentersType & parent_center,
61 const CentersType h,
62 const ChildrenType child_index){
63 RowVector3CentersType change_vector;
64 change_vector << -h,-h,-h;
65
66 //positive x chilren are 1,3,4,7
67 if(child_index % 2){
68 change_vector(0) = h;
69 }
70 //positive y children are 2,3,6,7
71 if(child_index == 2 || child_index == 3 ||
72 child_index == 6 || child_index == 7){
73 change_vector(1) = h;
74 }
75 //positive z children are 4,5,6,7
76 if(child_index > 3){
77 change_vector(2) = h;
78 }
79 RowVector3CentersType output = parent_center + change_vector;
80 return output;
81 };
82
83 // How many cells do we have so far?
84 IndexType m = 0;
85
86 // Useful list of number 0..7
87 const Vector8i zero_to_seven = (Vector8i()<<0,1,2,3,4,5,6,7).finished();
88 const Vector8i neg_ones = (Vector8i()<<-1,-1,-1,-1,-1,-1,-1,-1).finished();
89
90 std::function< void(const ChildrenType, const int) > helper;
91 helper = [&helper,&translate_center,&get_octant,&m,
92 &zero_to_seven,&neg_ones,&P,
93 &point_indices,&children,&centers,&widths]
94 (const ChildrenType index, const int depth)-> void
95 {
96 if(point_indices.at(index).size() > 1 && depth < MAX_DEPTH){
97 //give the parent access to the children
98 children.at(index) = zero_to_seven.array() + m;
99 //make the children's data in our arrays
100
101 //Add the children to the lists, as default children
102 CentersType h = widths.at(index)/2;
103 RowVector3CentersType curr_center = centers.at(index);
104
105
106 for(ChildrenType i = 0; i < 8; i++){
107 children.emplace_back(neg_ones);
108 point_indices.emplace_back(std::vector<IndexType>());
109 centers.emplace_back(translate_center(curr_center,h,i));
110 widths.emplace_back(h);
111 }
112
113
114 //Split up the points into the corresponding children
115 for(int j = 0; j < point_indices.at(index).size(); j++){
116 IndexType curr_point_index = point_indices.at(index).at(j);
117 IndexType cell_of_curr_point =
118 get_octant(P.row(curr_point_index),curr_center)+m;
119 point_indices.at(cell_of_curr_point).emplace_back(curr_point_index);
120 }
121
122 //Now increase m
123 m += 8;
124
125
126 // Look ma, I'm calling myself.
127 for(int i = 0; i < 8; i++){
128 helper(children.at(index)(i),depth+1);
129 }
130 }
131 };
132
133 {
134 std::vector<IndexType> all(P.rows());
135 for(IndexType i = 0;i<all.size();i++) all[i]=i;
136 point_indices.emplace_back(all);
137 }
138 children.emplace_back(neg_ones);
139
140 //Get the minimum AABB for the points
141 RowVector3PType backleftbottom(P.col(0).minCoeff(),
142 P.col(1).minCoeff(),
143 P.col(2).minCoeff());
144 RowVector3PType frontrighttop(P.col(0).maxCoeff(),
145 P.col(1).maxCoeff(),
146 P.col(2).maxCoeff());
147 RowVector3CentersType aabb_center = (backleftbottom+frontrighttop)/2.0;
148 WidthsType aabb_width = std::max(std::max(
149 frontrighttop(0) - backleftbottom(0),
150 frontrighttop(1) - backleftbottom(1)),
151 frontrighttop(2) - backleftbottom(2));
152 centers.emplace_back( aabb_center );
153
154 //Widths are the side length of the cube, (not half the side length):
155 widths.emplace_back( aabb_width );
156 m++;
157 // then you have to actually call the function
158 helper(0,0);
159
160 //Now convert from vectors to Eigen matricies:
161 CH.resize(children.size(),8);
162 CN.resize(centers.size(),3);
163 W.resize(widths.size(),1);
164
165 for(int i = 0; i < children.size(); i++){
166 CH.row(i) = children.at(i);
167 }
168 for(int i = 0; i < centers.size(); i++){
169 CN.row(i) = centers.at(i);
170 }
171 for(int i = 0; i < widths.size(); i++){
172 W(i) = widths.at(i);
173 }
174 }
STL compatible allocator to use with types requiring a non standrad alignment.
Definition Memory.h:722

References all(), Eigen::DenseBase< Derived >::maxCoeff(), Eigen::DenseBase< Derived >::minCoeff(), Eigen::PlainObjectBase< Derived >::resize(), and void().

Referenced by fast_winding_number(), and igl::copyleft::cgal::fast_winding_number().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ on_boundary() [1/2]

template<typename DerivedT , typename DerivedI , typename DerivedC >
IGL_INLINE void igl::on_boundary ( const Eigen::MatrixBase< DerivedT > &  T,
Eigen::PlainObjectBase< DerivedI > &  I,
Eigen::PlainObjectBase< DerivedC > &  C 
)
120{
121 assert(T.cols() == 0 || T.cols() == 4 || T.cols() == 3);
122 using namespace std;
123 using namespace Eigen;
124 // Cop out: use vector of vectors version
125 vector<vector<typename DerivedT::Scalar> > vT;
126 matrix_to_list(T,vT);
127 vector<bool> vI;
128 vector<vector<bool> > vC;
129 on_boundary(vT,vI,vC);
130 list_to_matrix(vI,I);
131 list_to_matrix(vC,C);
132}

References list_to_matrix(), matrix_to_list(), and on_boundary().

+ Here is the call graph for this function:

◆ on_boundary() [2/2]

template<typename IntegerT >
IGL_INLINE void igl::on_boundary ( const std::vector< std::vector< IntegerT > > &  T,
std::vector< bool > &  I,
std::vector< std::vector< bool > > &  C 
)
21{
22 using namespace std;
23 if(T.empty())
24 {
25 I.clear();
26 C.clear();
27 return;
28 }
29
30 switch(T[0].size())
31 {
32 case 3:
33 {
34 // Get a list of all faces
35 vector<vector<IntegerT> > F(T.size()*3,vector<IntegerT>(2));
36 // Gather faces, loop over tets
37 for(int i = 0; i< (int)T.size();i++)
38 {
39 assert(T[i].size() == 3);
40 // get face in correct order
41 F[i*3+0][0] = T[i][1];
42 F[i*3+0][1] = T[i][2];
43 F[i*3+1][0] = T[i][2];
44 F[i*3+1][1] = T[i][0];
45 F[i*3+2][0] = T[i][0];
46 F[i*3+2][1] = T[i][1];
47 }
48 // Counts
49 vector<int> FC;
50 face_occurrences(F,FC);
51 C.resize(T.size(),vector<bool>(3));
52 I.resize(T.size(),false);
53 for(int i = 0; i< (int)T.size();i++)
54 {
55 for(int j = 0;j<3;j++)
56 {
57 assert(FC[i*3+j] == 2 || FC[i*3+j] == 1);
58 C[i][j] = FC[i*3+j]==1;
59 // if any are on boundary set to true
60 I[i] = I[i] || C[i][j];
61 }
62 }
63 return;
64 }
65 case 4:
66 {
67 // Get a list of all faces
68 vector<vector<IntegerT> > F(T.size()*4,vector<IntegerT>(3));
69 // Gather faces, loop over tets
70 for(int i = 0; i< (int)T.size();i++)
71 {
72 assert(T[i].size() == 4);
73 // get face in correct order
74 F[i*4+0][0] = T[i][1];
75 F[i*4+0][1] = T[i][3];
76 F[i*4+0][2] = T[i][2];
77 // get face in correct order
78 F[i*4+1][0] = T[i][0];
79 F[i*4+1][1] = T[i][2];
80 F[i*4+1][2] = T[i][3];
81 // get face in correct order
82 F[i*4+2][0] = T[i][0];
83 F[i*4+2][1] = T[i][3];
84 F[i*4+2][2] = T[i][1];
85 // get face in correct order
86 F[i*4+3][0] = T[i][0];
87 F[i*4+3][1] = T[i][1];
88 F[i*4+3][2] = T[i][2];
89 }
90 // Counts
91 vector<int> FC;
92 face_occurrences(F,FC);
93 C.resize(T.size(),vector<bool>(4));
94 I.resize(T.size(),false);
95 for(int i = 0; i< (int)T.size();i++)
96 {
97 for(int j = 0;j<4;j++)
98 {
99 assert(FC[i*4+j] == 2 || FC[i*4+j] == 1);
100 C[i][j] = FC[i*4+j]==1;
101 // if any are on boundary set to true
102 I[i] = I[i] || C[i][j];
103 }
104 }
105 return;
106 }
107 }
108
109
110}

References face_occurrences().

Referenced by biharmonic_coordinates(), ears(), on_boundary(), and straighten_seams().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ operator+()

IGL_INLINE std::tuple< Eigen::MatrixXd, Eigen::RowVectorXd, double > igl::operator+ ( const std::tuple< Eigen::MatrixXd, Eigen::RowVectorXd, double > &  a,
const std::tuple< Eigen::MatrixXd, Eigen::RowVectorXd, double > &  b 
)
14{
15 std::tuple<
16 Eigen::MatrixXd,
17 Eigen::RowVectorXd,
18 double> c;
19 std::get<0>(c) = (std::get<0>(a) + std::get<0>(b)).eval();
20 std::get<1>(c) = (std::get<1>(a) + std::get<1>(b)).eval();
21 std::get<2>(c) = (std::get<2>(a) + std::get<2>(b));
22 return c;
23}

◆ orient_outward()

template<typename DerivedV , typename DerivedF , typename DerivedC , typename DerivedFF , typename DerivedI >
IGL_INLINE void igl::orient_outward ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedC > &  C,
Eigen::PlainObjectBase< DerivedFF > &  FF,
Eigen::PlainObjectBase< DerivedI > &  I 
)
26{
27 using namespace Eigen;
28 using namespace std;
29 assert(C.rows() == F.rows());
30 assert(F.cols() == 3);
31 assert(V.cols() == 3);
32
33 // number of faces
34 const int m = F.rows();
35 // number of patches
36 const int num_cc = C.maxCoeff()+1;
37 I.resize(num_cc);
38 if(&FF != &F)
39 {
40 FF = F;
41 }
42 DerivedV N,BC,BCmean;
44 VectorXd totA(num_cc), dot(num_cc);
46 per_face_normals(V,F,Z.normalized(),N);
47 barycenter(V,F,BC);
48 doublearea(V,F,A);
49 BCmean.setConstant(num_cc,3,0);
50 dot.setConstant(num_cc,1,0);
51 totA.setConstant(num_cc,1,0);
52 // loop over faces
53 for(int f = 0;f<m;f++)
54 {
55 BCmean.row(C(f)) += A(f)*BC.row(f);
56 totA(C(f))+=A(f);
57 }
58 // take area weighted average
59 for(int c = 0;c<num_cc;c++)
60 {
61 BCmean.row(c) /= (typename DerivedV::Scalar) totA(c);
62 }
63 // subtract bcmean
64 for(int f = 0;f<m;f++)
65 {
66 BC.row(f) -= BCmean.row(C(f));
67 dot(C(f)) += A(f)*N.row(f).dot(BC.row(f));
68 }
69 // take area weighted average
70 for(int c = 0;c<num_cc;c++)
71 {
72 dot(c) /= (typename DerivedV::Scalar) totA(c);
73 if(dot(c) < 0)
74 {
75 I(c) = true;
76 }else
77 {
78 I(c) = false;
79 }
80 }
81 // flip according to I
82 for(int f = 0;f<m;f++)
83 {
84 if(I(C(f)))
85 {
86 FF.row(f) = FF.row(f).reverse().eval();
87 }
88 }
89}
IGL_INLINE double dot(const double *a, const double *b)
Definition dot.cpp:11

References barycenter(), Eigen::PlainObjectBase< Derived >::cols(), dot(), doublearea(), per_face_normals(), Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ orientable_patches() [1/2]

template<typename DerivedF , typename DerivedC >
IGL_INLINE void igl::orientable_patches ( const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedC > &  C 
)

References orientable_patches().

+ Here is the call graph for this function:

◆ orientable_patches() [2/2]

template<typename DerivedF , typename DerivedC , typename AScalar >
IGL_INLINE void igl::orientable_patches ( const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedC > &  C,
Eigen::SparseMatrix< AScalar > &  A 
)
20{
21 using namespace Eigen;
22 using namespace std;
23
24 // simplex size
25 assert(F.cols() == 3);
26
27 // List of all "half"-edges: 3*#F by 2
29 allE.resize(F.rows()*3,2);
31 VectorXi IA,IC;
32 allE.block(0*F.rows(),0,F.rows(),1) = F.col(1);
33 allE.block(0*F.rows(),1,F.rows(),1) = F.col(2);
34 allE.block(1*F.rows(),0,F.rows(),1) = F.col(2);
35 allE.block(1*F.rows(),1,F.rows(),1) = F.col(0);
36 allE.block(2*F.rows(),0,F.rows(),1) = F.col(0);
37 allE.block(2*F.rows(),1,F.rows(),1) = F.col(1);
38 // Sort each row
39 sort(allE,2,true,sortallE,IX);
40 //IC(i) tells us where to find sortallE(i,:) in uE:
41 // so that sortallE(i,:) = uE(IC(i),:)
42 unique_rows(sortallE,uE,IA,IC);
43 // uE2FT(e,f) = 1 means face f is adjacent to unique edge e
44 vector<Triplet<AScalar> > uE2FTijv(IC.rows());
45 for(int e = 0;e<IC.rows();e++)
46 {
47 uE2FTijv[e] = Triplet<AScalar>(e%F.rows(),IC(e),1);
48 }
49 SparseMatrix<AScalar> uE2FT(F.rows(),uE.rows());
50 uE2FT.setFromTriplets(uE2FTijv.begin(),uE2FTijv.end());
51 // kill non-manifold edges
52 for(int j=0; j<(int)uE2FT.outerSize();j++)
53 {
54 int degree = 0;
55 for(typename SparseMatrix<AScalar>::InnerIterator it (uE2FT,j); it; ++it)
56 {
57 degree++;
58 }
59 // Iterate over inside
60 if(degree > 2)
61 {
62 for(typename SparseMatrix<AScalar>::InnerIterator it (uE2FT,j); it; ++it)
63 {
64 uE2FT.coeffRef(it.row(),it.col()) = 0;
65 }
66 }
67 }
68 // Face-face Adjacency matrix
70 uE2F = uE2FT.transpose().eval();
71 A = uE2FT*uE2F;
72 // All ones
73 for(int j=0; j<A.outerSize();j++)
74 {
75 // Iterate over inside
76 for(typename SparseMatrix<AScalar>::InnerIterator it (A,j); it; ++it)
77 {
78 if(it.value() > 1)
79 {
80 A.coeffRef(it.row(),it.col()) = 1;
81 }
82 }
83 }
84 //% Connected components are patches
85 //%C = components(A); % alternative to graphconncomp from matlab_bgl
86 //[~,C] = graphconncomp(A);
87 // graph connected components
88 components(A,C);
89
90}

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::coeffRef(), components(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::outerSize(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets(), sort(), Eigen::SparseMatrixBase< Derived >::transpose(), and unique_rows().

Referenced by bfs_orient(), and orientable_patches().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ oriented_facets()

template<typename DerivedF , typename DerivedE >
IGL_INLINE void igl::oriented_facets ( const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedE > &  E 
)
14{
15 E.resize(F.rows()*F.cols(),F.cols()-1);
16 typedef typename DerivedE::Scalar EScalar;
17 switch(F.cols())
18 {
19 case 4:
20 E.block(0*F.rows(),0,F.rows(),1) = F.col(1).template cast<EScalar>();
21 E.block(0*F.rows(),1,F.rows(),1) = F.col(3).template cast<EScalar>();
22 E.block(0*F.rows(),2,F.rows(),1) = F.col(2).template cast<EScalar>();
23
24 E.block(1*F.rows(),0,F.rows(),1) = F.col(0).template cast<EScalar>();
25 E.block(1*F.rows(),1,F.rows(),1) = F.col(2).template cast<EScalar>();
26 E.block(1*F.rows(),2,F.rows(),1) = F.col(3).template cast<EScalar>();
27
28 E.block(2*F.rows(),0,F.rows(),1) = F.col(0).template cast<EScalar>();
29 E.block(2*F.rows(),1,F.rows(),1) = F.col(3).template cast<EScalar>();
30 E.block(2*F.rows(),2,F.rows(),1) = F.col(1).template cast<EScalar>();
31
32 E.block(3*F.rows(),0,F.rows(),1) = F.col(0).template cast<EScalar>();
33 E.block(3*F.rows(),1,F.rows(),1) = F.col(1).template cast<EScalar>();
34 E.block(3*F.rows(),2,F.rows(),1) = F.col(2).template cast<EScalar>();
35 return;
36 case 3:
37 E.block(0*F.rows(),0,F.rows(),1) = F.col(1).template cast<EScalar>();
38 E.block(0*F.rows(),1,F.rows(),1) = F.col(2).template cast<EScalar>();
39 E.block(1*F.rows(),0,F.rows(),1) = F.col(2).template cast<EScalar>();
40 E.block(1*F.rows(),1,F.rows(),1) = F.col(0).template cast<EScalar>();
41 E.block(2*F.rows(),0,F.rows(),1) = F.col(0).template cast<EScalar>();
42 E.block(2*F.rows(),1,F.rows(),1) = F.col(1).template cast<EScalar>();
43 return;
44 }
45}

Referenced by all_edges(), crouzeix_raviart_cotmatrix(), crouzeix_raviart_massmatrix(), exterior_edges(), is_edge_manifold(), per_edge_normals(), and unique_edge_map().

+ Here is the caller graph for this function:

◆ orth()

IGL_INLINE void igl::orth ( const Eigen::MatrixXd &  A,
Eigen::MatrixXd &  Q 
)
12{
13
14 //perform svd on A = U*S*V' (V is not computed and only the thin U is computed)
16 Eigen::MatrixXd U = svd.matrixU();
17 const Eigen::VectorXd S = svd.singularValues();
18
19 //get rank of A
20 int m = A.rows();
21 int n = A.cols();
22 double tol = std::max(m,n) * S.maxCoeff() * 2.2204e-16;
23 int r = 0;
24 for (int i = 0; i < S.rows(); ++r,++i)
25 {
26 if (S[i] < tol)
27 break;
28 }
29
30 //keep r first columns of U
31 Q = U.block(0,0,U.rows(),r);
32}
@ ComputeThinU
Definition Constants.h:385

References Eigen::ComputeThinU, Eigen::SVDBase< Derived >::matrixU(), and Eigen::SVDBase< Derived >::singularValues().

+ Here is the call graph for this function:

◆ ortho()

template<typename DerivedP >
IGL_INLINE void igl::ortho ( const typename DerivedP::Scalar  left,
const typename DerivedP::Scalar  right,
const typename DerivedP::Scalar  bottom,
const typename DerivedP::Scalar  top,
const typename DerivedP::Scalar  nearVal,
const typename DerivedP::Scalar  farVal,
Eigen::PlainObjectBase< DerivedP > &  P 
)
19{
20 P.setIdentity();
21 P(0,0) = 2. / (right - left);
22 P(1,1) = 2. / (top - bottom);
23 P(2,2) = - 2./ (farVal - nearVal);
24 P(0,3) = - (right + left) / (right - left);
25 P(1,3) = - (top + bottom) / (top - bottom);
26 P(2,3) = - (farVal + nearVal) / (farVal - nearVal);
27}

Referenced by igl::opengl::ViewerCore::draw().

+ Here is the caller graph for this function:

◆ outer_edge()

template<typename DerivedV , typename DerivedF , typename DerivedI , typename IndexType , typename DerivedA >
IGL_INLINE void igl::outer_edge ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedI > &  I,
IndexType &  v1,
IndexType &  v2,
Eigen::PlainObjectBase< DerivedA > &  A 
)
94 {
95 // Algorithm:
96 // Find an outer vertex first.
97 // Find the incident edge with largest abs slope when projected onto XY plane.
98 // If there is a tie, check the signed slope and use the positive one.
99 // If there is still a tie, break it using the projected slope onto ZX plane.
100 // If there is still a tie, again check the signed slope and use the positive one.
101 // If there is still a tie, then there are multiple overlapping edges,
102 // which violates the precondition.
103 typedef typename DerivedV::Scalar Scalar;
104 typedef typename DerivedV::Index Index;
105 typedef typename Eigen::Matrix<Scalar, 3, 1> ScalarArray3;
106 typedef typename Eigen::Matrix<typename DerivedF::Scalar, 3, 1> IndexArray3;
107 const Index INVALID = std::numeric_limits<Index>::max();
108
109 Index outer_vid;
111 outer_vertex(V, F, I, outer_vid, candidate_faces);
112 const ScalarArray3& outer_v = V.row(outer_vid);
113 assert(candidate_faces.size() > 0);
114
115 auto get_vertex_index = [&](const IndexArray3& f, Index vid) -> Index
116 {
117 if (f[0] == vid) return 0;
118 if (f[1] == vid) return 1;
119 if (f[2] == vid) return 2;
120 assert(false);
121 return -1;
122 };
123
124 auto unsigned_value = [](Scalar v) -> Scalar {
125 if (v < 0) return v * -1;
126 else return v;
127 };
128
129 Scalar outer_slope_YX = 0;
130 Scalar outer_slope_ZX = 0;
131 Index outer_opp_vid = INVALID;
132 bool infinite_slope_detected = false;
133 std::vector<Index> incident_faces;
134 auto check_and_update_outer_edge = [&](Index opp_vid, Index fid) {
135 if (opp_vid == outer_opp_vid)
136 {
137 incident_faces.push_back(fid);
138 return;
139 }
140
141 const ScalarArray3 opp_v = V.row(opp_vid);
142 if (!infinite_slope_detected && outer_v[0] != opp_v[0])
143 {
144 // Finite slope
145 const ScalarArray3 diff = opp_v - outer_v;
146 const Scalar slope_YX = diff[1] / diff[0];
147 const Scalar slope_ZX = diff[2] / diff[0];
148 const Scalar u_slope_YX = unsigned_value(slope_YX);
149 const Scalar u_slope_ZX = unsigned_value(slope_ZX);
150 bool update = false;
151 if (outer_opp_vid == INVALID) {
152 update = true;
153 } else {
154 const Scalar u_outer_slope_YX = unsigned_value(outer_slope_YX);
155 if (u_slope_YX > u_outer_slope_YX) {
156 update = true;
157 } else if (u_slope_YX == u_outer_slope_YX &&
158 slope_YX > outer_slope_YX) {
159 update = true;
160 } else if (slope_YX == outer_slope_YX) {
161 const Scalar u_outer_slope_ZX =
162 unsigned_value(outer_slope_ZX);
163 if (u_slope_ZX > u_outer_slope_ZX) {
164 update = true;
165 } else if (u_slope_ZX == u_outer_slope_ZX &&
166 slope_ZX > outer_slope_ZX) {
167 update = true;
168 } else if (slope_ZX == u_outer_slope_ZX) {
169 assert(false);
170 }
171 }
172 }
173
174 if (update) {
175 outer_opp_vid = opp_vid;
176 outer_slope_YX = slope_YX;
177 outer_slope_ZX = slope_ZX;
178 incident_faces = {fid};
179 }
180 } else if (!infinite_slope_detected)
181 {
182 // Infinite slope
183 outer_opp_vid = opp_vid;
184 infinite_slope_detected = true;
185 incident_faces = {fid};
186 }
187 };
188
189 const size_t num_candidate_faces = candidate_faces.size();
190 for (size_t i=0; i<num_candidate_faces; i++)
191 {
192 const Index fid = candidate_faces(i);
193 const IndexArray3& f = F.row(fid);
194 size_t id = get_vertex_index(f, outer_vid);
195 Index next_vid = f((id+1)%3);
196 Index prev_vid = f((id+2)%3);
197 check_and_update_outer_edge(next_vid, fid);
198 check_and_update_outer_edge(prev_vid, fid);
199 }
200
201 v1 = outer_vid;
202 v2 = outer_opp_vid;
203 A.resize(incident_faces.size());
204 std::copy(incident_faces.begin(), incident_faces.end(), A.data());
205}

References Eigen::PlainObjectBase< Derived >::data(), and Eigen::PlainObjectBase< Derived >::resize().

+ Here is the call graph for this function:

◆ outer_facet()

template<typename DerivedV , typename DerivedF , typename DerivedN , typename DerivedI , typename IndexType >
IGL_INLINE void igl::outer_facet ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedN > &  N,
const Eigen::PlainObjectBase< DerivedI > &  I,
IndexType &  f,
bool &  flipped 
)
220 {
221 // Algorithm:
222 // Find an outer edge.
223 // Find the incident facet with the largest absolute X normal component.
224 // If there is a tie, keep the one with positive X component.
225 // If there is still a tie, pick the face with the larger signed index
226 // (flipped face has negative index).
227 typedef typename DerivedV::Scalar Scalar;
228 typedef typename DerivedV::Index Index;
229 const size_t INVALID = std::numeric_limits<size_t>::max();
230
231 Index v1,v2;
233 outer_edge(V, F, I, v1, v2, incident_faces);
234 assert(incident_faces.size() > 0);
235
236 auto generic_fabs = [&](const Scalar& val) -> const Scalar {
237 if (val >= 0) return val;
238 else return -val;
239 };
240
241 Scalar max_nx = 0;
242 size_t outer_fid = INVALID;
243 const size_t num_incident_faces = incident_faces.size();
244 for (size_t i=0; i<num_incident_faces; i++)
245 {
246 const auto& fid = incident_faces(i);
247 const Scalar nx = N(fid, 0);
248 if (outer_fid == INVALID) {
249 max_nx = nx;
250 outer_fid = fid;
251 } else {
252 if (generic_fabs(nx) > generic_fabs(max_nx)) {
253 max_nx = nx;
254 outer_fid = fid;
255 } else if (nx == -max_nx && nx > 0) {
256 max_nx = nx;
257 outer_fid = fid;
258 } else if (nx == max_nx) {
259 if ((max_nx >= 0 && outer_fid < fid) ||
260 (max_nx < 0 && outer_fid > fid)) {
261 max_nx = nx;
262 outer_fid = fid;
263 }
264 }
265 }
266 }
267
268 assert(outer_fid != INVALID);
269 f = outer_fid;
270 flipped = max_nx < 0;
271}

◆ outer_vertex()

template<typename DerivedV , typename DerivedF , typename DerivedI , typename IndexType , typename DerivedA >
IGL_INLINE void igl::outer_vertex ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedI > &  I,
IndexType &  v_index,
Eigen::PlainObjectBase< DerivedA > &  A 
)
25{
26 // Algorithm:
27 // Find an outer vertex (i.e. vertex reachable from infinity)
28 // Return the vertex with the largest X value.
29 // If there is a tie, pick the one with largest Y value.
30 // If there is still a tie, pick the one with the largest Z value.
31 // If there is still a tie, then there are duplicated vertices within the
32 // mesh, which violates the precondition.
33 typedef typename DerivedF::Scalar Index;
34 const Index INVALID = std::numeric_limits<Index>::max();
35 const size_t num_selected_faces = I.rows();
36 std::vector<size_t> candidate_faces;
37 Index outer_vid = INVALID;
38 typename DerivedV::Scalar outer_val = 0;
39 for (size_t i=0; i<num_selected_faces; i++)
40 {
41 size_t f = I(i);
42 for (size_t j=0; j<3; j++)
43 {
44 Index v = F(f, j);
45 auto vx = V(v, 0);
46 if (outer_vid == INVALID || vx > outer_val)
47 {
48 outer_val = vx;
49 outer_vid = v;
50 candidate_faces = {f};
51 } else if (v == outer_vid)
52 {
53 candidate_faces.push_back(f);
54 } else if (vx == outer_val)
55 {
56 // Break tie.
57 auto vy = V(v,1);
58 auto vz = V(v, 2);
59 auto outer_y = V(outer_vid, 1);
60 auto outer_z = V(outer_vid, 2);
61 assert(!(vy == outer_y && vz == outer_z));
62 bool replace = (vy > outer_y) ||
63 ((vy == outer_y) && (vz > outer_z));
64 if (replace)
65 {
66 outer_val = vx;
67 outer_vid = v;
68 candidate_faces = {f};
69 }
70 }
71 }
72 }
73
74 assert(outer_vid != INVALID);
75 assert(candidate_faces.size() > 0);
76 v_index = outer_vid;
77 A.resize(candidate_faces.size());
78 std::copy(candidate_faces.begin(), candidate_faces.end(), A.data());
79}

References Eigen::PlainObjectBase< Derived >::data(), Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ parallel_for() [1/2]

template<typename Index , typename FunctionType >
bool igl::parallel_for ( const Index  loop_size,
const FunctionType &  func,
const size_t  min_parallel = 0 
)
inline
103{
104 using namespace std;
105 // no op preparation/accumulation
106 const auto & no_op = [](const size_t /*n/t*/){};
107 // two-parameter wrapper ignoring thread id
108 const auto & wrapper = [&func](Index i,size_t /*t*/){ func(i); };
109 return parallel_for(loop_size,no_op,wrapper,no_op,min_parallel);
110}

References parallel_for().

Referenced by ambient_occlusion(), bbw(), doublearea(), fast_winding_number(), internal_angles_using_edge_lengths(), internal_angles_using_squared_edge_lengths(), knn(), parallel_for(), igl::copyleft::cgal::point_areas(), shape_diameter_function(), signed_distance(), sort3(), igl::AABB< DerivedV, DIM >::squared_distance(), squared_edge_lengths(), triangle_triangle_adjacency(), triangle_triangle_adjacency(), triangle_triangle_adjacency(), unique_simplices(), and winding_number().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parallel_for() [2/2]

template<typename Index , typename PrepFunctionType , typename FunctionType , typename AccumFunctionType >
bool igl::parallel_for ( const Index  loop_size,
const PrepFunctionType &  prep_func,
const FunctionType &  func,
const AccumFunctionType &  accum_func,
const size_t  min_parallel = 0 
)
inline

◆ parallel_transport_angles()

template<typename DerivedV , typename DerivedF , typename DerivedK >
IGL_INLINE void igl::parallel_transport_angles ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedV > &  FN,
const Eigen::MatrixXi &  E2F,
const Eigen::MatrixXi &  F2E,
Eigen::PlainObjectBase< DerivedK > &  K 
)
19{
20 int numE = E2F.rows();
21
22 Eigen::VectorXi isBorderEdge;
23 isBorderEdge.setZero(numE,1);
24 for(unsigned i=0; i<numE; ++i)
25 {
26 if ((E2F(i,0) == -1) || ((E2F(i,1) == -1)))
27 isBorderEdge[i] = 1;
28 }
29
30 K.setZero(numE);
31 // For every non-border edge
32 for (unsigned eid=0; eid<numE; ++eid)
33 {
34 if (!isBorderEdge[eid])
35 {
36 int fid0 = E2F(eid,0);
37 int fid1 = E2F(eid,1);
38
40// Eigen::Matrix<typename DerivedV::Scalar, 1, 3> N1 = FN.row(fid1);
41
42 // find common edge on triangle 0 and 1
43 int fid0_vc = -1;
44 int fid1_vc = -1;
45 for (unsigned i=0;i<3;++i)
46 {
47 if (F2E(fid0,i) == eid)
48 fid0_vc = i;
49 if (F2E(fid1,i) == eid)
50 fid1_vc = i;
51 }
52 assert(fid0_vc != -1);
53 assert(fid1_vc != -1);
54
55 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> common_edge = V.row(F(fid0,(fid0_vc+1)%3)) - V.row(F(fid0,fid0_vc));
56 common_edge.normalize();
57
58 // Map the two triangles in a new space where the common edge is the x axis and the N0 the z axis
61 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> tmp = -N0.cross(common_edge);
62 P << common_edge, tmp, N0;
63 // P.transposeInPlace();
64
65
67 V0.row(0) = V.row(F(fid0,0)) -o;
68 V0.row(1) = V.row(F(fid0,1)) -o;
69 V0.row(2) = V.row(F(fid0,2)) -o;
70
71 V0 = (P*V0.transpose()).transpose();
72
73 // assert(V0(0,2) < 1e-10);
74 // assert(V0(1,2) < 1e-10);
75 // assert(V0(2,2) < 1e-10);
76
78 V1.row(0) = V.row(F(fid1,0)) -o;
79 V1.row(1) = V.row(F(fid1,1)) -o;
80 V1.row(2) = V.row(F(fid1,2)) -o;
81 V1 = (P*V1.transpose()).transpose();
82
83 // assert(V1(fid1_vc,2) < 10e-10);
84 // assert(V1((fid1_vc+1)%3,2) < 10e-10);
85
86 // compute rotation R such that R * N1 = N0
87 // i.e. map both triangles to the same plane
88 double alpha = -atan2(V1((fid1_vc+2)%3,2),V1((fid1_vc+2)%3,1));
89
91 R << 1, 0, 0,
92 0, cos(alpha), -sin(alpha) ,
93 0, sin(alpha), cos(alpha);
94 V1 = (R*V1.transpose()).transpose();
95
96 // assert(V1(0,2) < 1e-10);
97 // assert(V1(1,2) < 1e-10);
98 // assert(V1(2,2) < 1e-10);
99
100 // measure the angle between the reference frames
101 // k_ij is the angle between the triangle on the left and the one on the right
102 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> ref0 = V0.row(1) - V0.row(0);
103 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> ref1 = V1.row(1) - V1.row(0);
104
105 ref0.normalize();
106 ref1.normalize();
107
108 double ktemp = atan2(ref1(1),ref1(0)) - atan2(ref0(1),ref0(0));
109
110 // just to be sure, rotate ref0 using angle ktemp...
112 R2 << cos(ktemp), -sin(ktemp), sin(ktemp), cos(ktemp);
113
114// Eigen::Matrix<typename DerivedV::Scalar, 1, 2> tmp1 = R2*(ref0.head(2)).transpose();
115
116 // assert(tmp1(0) - ref1(0) < 1e-10);
117 // assert(tmp1(1) - ref1(1) < 1e-10);
118
119 K[eid] = ktemp;
120 }
121 }
122
123}

References cos(), and sin().

+ Here is the call graph for this function:

◆ partition()

IGL_INLINE void igl::partition ( const Eigen::MatrixXd &  W,
const int  k,
Eigen::Matrix< int, Eigen::Dynamic, 1 > &  G,
Eigen::Matrix< int, Eigen::Dynamic, 1 > &  S,
Eigen::Matrix< double, Eigen::Dynamic, 1 > &  D 
)
17{
18 // number of mesh vertices
19 int n = W.rows();
20
21 // Resize output
22 G.resize(n);
23 S.resize(k);
24
25 // "Randomly" choose first seed
26 // Pick a vertex farthest from 0
27 int s;
28 (W.array().square().matrix()).rowwise().sum().maxCoeff(&s);
29
30 S(0) = s;
31 // Initialize distance to closest seed
32 D = ((W.rowwise() - W.row(s)).array().square()).matrix().rowwise().sum();
33 G.setZero();
34
35 // greedily choose the remaining k-1 seeds
36 for(int i = 1;i<k;i++)
37 {
38 // Find maximum in D
39 D.maxCoeff(&s);
40 S(i) = s;
41 // distance to this seed
43 ((W.rowwise() - W.row(s)).array().square()).matrix().rowwise().sum();
44 // Concatenation of D and Ds: DDs = [D Ds];
46 // Make space for two columns
47 DDs.resize(D.rows(),2);
48 DDs.col(0) = D;
49 DDs.col(1) = Ds;
50 // Update D
51 // get minimum of old D and distance to this seed, C == 1 if new distance
52 // was smaller
54 igl::mat_min(DDs,2,D,C);
55 G = (C.array() ==0).select(G,i);
56 }
57
58
59}

References mat_min(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), and Eigen::PlainObjectBase< Derived >::setZero().

Referenced by uniformly_sample_two_manifold_at_vertices().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parula() [1/4]

template<typename DerivedZ , typename DerivedC >
IGL_INLINE void igl::parula ( const Eigen::MatrixBase< DerivedZ > &  Z,
const bool  normalize,
Eigen::PlainObjectBase< DerivedC > &  C 
)
29{
31}

References COLOR_MAP_TYPE_PARULA, and colormap().

+ Here is the call graph for this function:

◆ parula() [2/4]

template<typename DerivedZ , typename DerivedC >
IGL_INLINE void igl::parula ( const Eigen::MatrixBase< DerivedZ > &  Z,
const double  min_Z,
const double  max_Z,
Eigen::PlainObjectBase< DerivedC > &  C 
)
38{
39 igl::colormap(igl::COLOR_MAP_TYPE_PARULA, Z, min_z, max_z, C);
40}

References COLOR_MAP_TYPE_PARULA, and colormap().

+ Here is the call graph for this function:

◆ parula() [3/4]

template<typename T >
IGL_INLINE void igl::parula ( const f,
T &  r,
T &  g,
T &  b 
)
19{
21}

References COLOR_MAP_TYPE_PARULA, and colormap().

+ Here is the call graph for this function:

◆ parula() [4/4]

template<typename T >
IGL_INLINE void igl::parula ( const f,
T *  rgb 
)

References COLOR_MAP_TYPE_PARULA, and colormap().

Referenced by igl::opengl::ViewerData::set_colors().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ path_to_executable()

IGL_INLINE std::string igl::path_to_executable ( )
17{
18 // http://pastebin.com/ffzzxPzi
19 using namespace std;
20 std::string path;
21 char buffer[1024];
22 uint32_t size = sizeof(buffer);
23#if defined (WIN32)
24 GetModuleFileName(nullptr,buffer,size);
25 path = buffer;
26#elif defined (__APPLE__)
27 if(_NSGetExecutablePath(buffer, &size) == 0)
28 {
29 path = buffer;
30 }
31#elif defined(UNIX)
32 if (readlink("/proc/self/exe", buffer, sizeof(buffer)) == -1)
33 {
34 path = buffer;
35 }
36#elif defined(__FreeBSD__)
37 int mib[4];
38 mib[0] = CTL_KERN;
39 mib[1] = KERN_PROC;
40 mib[2] = KERN_PROC_PATHNAME;
41 mib[3] = -1;
42 sysctl(mib, 4, buffer, sizeof(buffer), NULL, 0);
43 path = buffer;
44#elif defined(SUNOS)
45 path = getexecname();
46#endif
47 return path;
48}
unsigned __int32 uint32_t
Definition unistd.h:79

◆ pathinfo()

IGL_INLINE void igl::pathinfo ( const std::string &  path,
std::string &  dirname,
std::string &  basename,
std::string &  extension,
std::string &  filename 
)
22{
23 dirname = igl::dirname(path);
24 basename = igl::basename(path);
25 std::string::reverse_iterator last_dot =
26 std::find(
27 basename.rbegin(),
28 basename.rend(), '.');
29 // Was a dot found?
30 if(last_dot == basename.rend())
31 {
32 // filename is same as basename
33 filename = basename;
34 // no extension
35 extension = "";
36 }else
37 {
38 // extension is substring of basename
39 extension = std::string(last_dot.base(),basename.end());
40 // filename is substring of basename
41 filename = std::string(basename.begin(),last_dot.base()-1);
42 }
43}

References basename(), and dirname().

Referenced by igl::copyleft::tetgen::read_into_tetgenio(), read_triangle_mesh(), read_triangle_mesh(), igl::png::texture_from_file(), igl::xml::write_triangle_mesh(), and write_triangle_mesh().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ per_corner_normals() [1/3]

template<typename DerivedV , typename DerivedF , typename DerivedCN >
IGL_INLINE void igl::per_corner_normals ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const double  corner_threshold,
Eigen::PlainObjectBase< DerivedCN > &  CN 
)
20{
21 using namespace Eigen;
22 using namespace std;
24 per_face_normals(V,F,FN);
25 vector<vector<int> > VF,VFi;
26 vertex_triangle_adjacency(V,F,VF,VFi);
27 return per_corner_normals(V,F,FN,VF,corner_threshold,CN);
28}
IGL_INLINE void per_corner_normals(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const double corner_threshold, Eigen::PlainObjectBase< DerivedCN > &CN)
Definition per_corner_normals.cpp:15
IGL_INLINE void per_face_normals(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedZ > &Z, Eigen::PlainObjectBase< DerivedN > &N)
Definition per_face_normals.cpp:13

References per_corner_normals(), per_face_normals(), and vertex_triangle_adjacency().

Referenced by per_corner_normals(), per_corner_normals(), and igl::opengl::ViewerData::updateGL().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ per_corner_normals() [2/3]

template<typename DerivedV , typename DerivedF , typename DerivedFN , typename DerivedCN >
IGL_INLINE void igl::per_corner_normals ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedFN > &  FN,
const double  corner_threshold,
Eigen::PlainObjectBase< DerivedCN > &  CN 
)
41{
42 using namespace Eigen;
43 using namespace std;
44 vector<vector<int> > VF,VFi;
45 vertex_triangle_adjacency(V,F,VF,VFi);
46 return per_corner_normals(V,F,FN,VF,corner_threshold,CN);
47}

References per_corner_normals(), and vertex_triangle_adjacency().

+ Here is the call graph for this function:

◆ per_corner_normals() [3/3]

template<typename DerivedV , typename DerivedF , typename DerivedFN , typename IndexType , typename DerivedCN >
IGL_INLINE void igl::per_corner_normals ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedFN > &  FN,
const std::vector< std::vector< IndexType > > &  VF,
const double  corner_threshold,
Eigen::PlainObjectBase< DerivedCN > &  CN 
)
62{
63 using namespace Eigen;
64 using namespace std;
65
66 // number of faces
67 const int m = F.rows();
68 // valence of faces
69 const int n = F.cols();
70
71 // initialize output to ***zero***
72 CN.setZero(m*n,3);
73
74 // loop over faces
75 for(size_t i = 0;int(i)<m;i++)
76 {
77 // Normal of this face
79 // loop over corners
80 for(size_t j = 0;int(j)<n;j++)
81 {
82 const std::vector<IndexType> &incident_faces = VF[F(i,j)];
83 // loop over faces sharing vertex of this corner
84 for(int k = 0;k<(int)incident_faces.size();k++)
85 {
86 Eigen::Matrix<typename DerivedV::Scalar,3,1> ifn = FN.row(incident_faces[k]);
87 // dot product between face's normal and other face's normal
88 double dp = fn.dot(ifn);
89 // if difference in normal is slight then add to average
90 if(dp > cos(corner_threshold*PI/180))
91 {
92 // add to running sum
93 CN.row(i*n+j) += ifn;
94 // else ignore
95 }else
96 {
97 }
98 }
99 // normalize to take average
100 CN.row(i*n+j).normalize();
101 }
102 }
103}

References cos(), PI, and Eigen::PlainObjectBase< Derived >::setZero().

+ Here is the call graph for this function:

◆ per_edge_normals() [1/3]

template<typename DerivedV , typename DerivedF , typename DerivedFN , typename DerivedN , typename DerivedE , typename DerivedEMAP >
IGL_INLINE void igl::per_edge_normals ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const PerEdgeNormalsWeightingType  weight,
const Eigen::MatrixBase< DerivedFN > &  FN,
Eigen::PlainObjectBase< DerivedN > &  N,
Eigen::PlainObjectBase< DerivedE > &  E,
Eigen::PlainObjectBase< DerivedEMAP > &  EMAP 
)
32{
33 using namespace Eigen;
34 using namespace std;
35 assert(F.cols() == 3 && "Faces must be triangles");
36 // number of faces
37 const int m = F.rows();
38 // All occurrences of directed edges
39 MatrixXi allE;
40 oriented_facets(F,allE);
41 // Find unique undirected edges and mapping
42 VectorXi _;
43 unique_simplices(allE,E,_,EMAP);
44 // now sort(allE,2) == E(EMAP,:), that is, if EMAP(i) = j, then E.row(j) is
45 // the undirected edge corresponding to the directed edge allE.row(i).
46
47 Eigen::VectorXd W;
48 switch(weighting)
49 {
51 // Do nothing
52 break;
53 default:
54 assert(false && "Unknown weighting type");
57 {
58 doublearea(V,F,W);
59 break;
60 }
61 }
62
63 N.setZero(E.rows(),3);
64 for(int f = 0;f<m;f++)
65 {
66 for(int c = 0;c<3;c++)
67 {
68 if(weighting == PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM)
69 {
70 N.row(EMAP(f+c*m)) += FN.row(f);
71 }else
72 {
73 N.row(EMAP(f+c*m)) += W(f) * FN.row(f);
74 }
75 }
76 }
77}

References _, doublearea(), oriented_facets(), PER_EDGE_NORMALS_WEIGHTING_TYPE_AREA, PER_EDGE_NORMALS_WEIGHTING_TYPE_DEFAULT, PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM, Eigen::PlainObjectBase< Derived >::setZero(), and unique_simplices().

Referenced by per_edge_normals(), per_edge_normals(), signed_distance(), igl::copyleft::cgal::signed_distance_isosurface(), and swept_volume_signed_distance().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ per_edge_normals() [2/3]

template<typename DerivedV , typename DerivedF , typename DerivedN , typename DerivedE , typename DerivedEMAP >
IGL_INLINE void igl::per_edge_normals ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const PerEdgeNormalsWeightingType  weight,
Eigen::PlainObjectBase< DerivedN > &  N,
Eigen::PlainObjectBase< DerivedE > &  E,
Eigen::PlainObjectBase< DerivedEMAP > &  EMAP 
)
92{
94 per_face_normals(V,F,FN);
95 return per_edge_normals(V,F,weighting,FN,N,E,EMAP);
96}
IGL_INLINE void per_edge_normals(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const PerEdgeNormalsWeightingType weight, const Eigen::MatrixBase< DerivedFN > &FN, Eigen::PlainObjectBase< DerivedN > &N, Eigen::PlainObjectBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedEMAP > &EMAP)
Definition per_edge_normals.cpp:23

References per_edge_normals(), and per_face_normals().

+ Here is the call graph for this function:

◆ per_edge_normals() [3/3]

template<typename DerivedV , typename DerivedF , typename DerivedN , typename DerivedE , typename DerivedEMAP >
IGL_INLINE void igl::per_edge_normals ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedN > &  N,
Eigen::PlainObjectBase< DerivedE > &  E,
Eigen::PlainObjectBase< DerivedEMAP > &  EMAP 
)
110{
111 return
112 per_edge_normals(V,F,PER_EDGE_NORMALS_WEIGHTING_TYPE_DEFAULT,N,E,EMAP);
113}

References per_edge_normals(), and PER_EDGE_NORMALS_WEIGHTING_TYPE_DEFAULT.

+ Here is the call graph for this function:

◆ per_face_normals() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedZ , typename DerivedN >
IGL_INLINE void igl::per_face_normals ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< DerivedZ > &  Z,
Eigen::PlainObjectBase< DerivedN > &  N 
)
18{
19 N.resize(F.rows(),3);
20 // loop over faces
21 int Frows = F.rows();
22#pragma omp parallel for if (Frows>10000)
23 for(int i = 0; i < Frows;i++)
24 {
25 const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v1 = V.row(F(i,1)) - V.row(F(i,0));
26 const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v2 = V.row(F(i,2)) - V.row(F(i,0));
27 N.row(i) = v1.cross(v2);//.normalized();
28 typename DerivedV::Scalar r = N.row(i).norm();
29 if(r == 0)
30 {
31 N.row(i) = Z;
32 }else
33 {
34 N.row(i) /= r;
35 }
36 }
37}

References Eigen::PlainObjectBase< Derived >::resize().

Referenced by igl::Comb< DerivedV, DerivedF >::Comb(), igl::CombLine< DerivedV, DerivedF >::CombLine(), igl::copyleft::comiso::FrameInterpolator::FrameInterpolator(), igl::MissMatchCalculator< DerivedV, DerivedF, DerivedM >::MissMatchCalculator(), igl::MissMatchCalculatorLine< DerivedV, DerivedF, DerivedO >::MissMatchCalculatorLine(), igl::copyleft::comiso::NRosyField::NRosyField(), igl::opengl::ViewerData::compute_normals(), grad_tet(), CurvatureCalculator::init(), igl::WindingNumberAABB< Point, DerivedV, DerivedF >::max_simple_abs_winding_number(), orient_outward(), per_corner_normals(), per_edge_normals(), per_face_normals(), per_vertex_normals(), igl::embree::reorient_facets_raycast(), shape_diameter_function(), signed_distance(), igl::copyleft::cgal::signed_distance_isosurface(), simplify_polyhedron(), and swept_volume_signed_distance().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ per_face_normals() [2/2]

template<typename DerivedV , typename DerivedF , typename DerivedN >
IGL_INLINE void igl::per_face_normals ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedN > &  N 
)
44{
45 using namespace Eigen;
47 return per_face_normals(V,F,Z,N);
48}

References per_face_normals().

+ Here is the call graph for this function:

◆ per_face_normals_stable()

template<typename DerivedV , typename DerivedF , typename DerivedN >
IGL_INLINE void igl::per_face_normals_stable ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedN > &  N 
)
55{
56 using namespace Eigen;
57 typedef Matrix<typename DerivedV::Scalar,1,3> RowVectorV3;
58 typedef typename DerivedV::Scalar Scalar;
59
60 const size_t m = F.rows();
61
62 N.resize(F.rows(),3);
63 // Grad all points
64 for(size_t f = 0;f<m;f++)
65 {
66 const RowVectorV3 p0 = V.row(F(f,0));
67 const RowVectorV3 p1 = V.row(F(f,1));
68 const RowVectorV3 p2 = V.row(F(f,2));
69 const RowVectorV3 n0 = (p1 - p0).cross(p2 - p0);
70 const RowVectorV3 n1 = (p2 - p1).cross(p0 - p1);
71 const RowVectorV3 n2 = (p0 - p2).cross(p1 - p2);
72
73 // careful sum
74 for(int d = 0;d<3;d++)
75 {
76 // This is a little _silly_ in terms of complexity, but its recursive
77 // implementation is clean looking...
78 const std::function<Scalar(Scalar,Scalar,Scalar)> sum3 =
79 [&sum3](Scalar a, Scalar b, Scalar c)->Scalar
80 {
81 if(fabs(c)>fabs(a))
82 {
83 return sum3(c,b,a);
84 }
85 // c < a
86 if(fabs(c)>fabs(b))
87 {
88 return sum3(a,c,b);
89 }
90 // c < a, c < b
91 if(fabs(b)>fabs(a))
92 {
93 return sum3(b,a,c);
94 }
95 return (a+b)+c;
96 };
97
98 N(f,d) = sum3(n0(d),n1(d),n2(d));
99 }
100 // sum better not be sure, or else NaN
101 N.row(f) /= N.row(f).norm();
102 }
103
104}

References cross(), and Eigen::PlainObjectBase< Derived >::resize().

+ Here is the call graph for this function:

◆ per_vertex_attribute_smoothing()

template<typename DerivedV , typename DerivedF >
IGL_INLINE void igl::per_vertex_attribute_smoothing ( const Eigen::PlainObjectBase< DerivedV > &  Ain,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedV > &  Aout 
)
16{
17 std::vector<double> denominator(Ain.rows(), 0);
18 Aout = DerivedV::Zero(Ain.rows(), Ain.cols());
19 for (int i = 0; i < F.rows(); ++i) {
20 for (int j = 0; j < 3; ++j) {
21 int j1 = (j + 1) % 3;
22 int j2 = (j + 2) % 3;
23 Aout.row(F(i, j)) += Ain.row(F(i, j1)) + Ain.row(F(i, j2));
24 denominator[F(i, j)] += 2;
25 }
26 }
27 for (int i = 0; i < Ain.rows(); ++i)
28 Aout.row(i) /= denominator[i];
29}

References Eigen::PlainObjectBase< Derived >::cols(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ per_vertex_normals() [1/4]

template<typename DerivedV , typename DerivedF , typename DerivedFN , typename DerivedN >
IGL_INLINE void igl::per_vertex_normals ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< DerivedFN > &  FN,
Eigen::PlainObjectBase< DerivedN > &  N 
)
117{
118 return
119 per_vertex_normals(V,F,PER_VERTEX_NORMALS_WEIGHTING_TYPE_DEFAULT,FN,N);
120}
IGL_INLINE void per_vertex_normals(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const igl::PerVertexNormalsWeightingType weighting, Eigen::PlainObjectBase< DerivedN > &N)
Definition per_vertex_normals.cpp:20

References per_vertex_normals(), and PER_VERTEX_NORMALS_WEIGHTING_TYPE_DEFAULT.

+ Here is the call graph for this function:

◆ per_vertex_normals() [2/4]

template<typename DerivedV , typename DerivedF , typename DerivedN >
IGL_INLINE void igl::per_vertex_normals ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const igl::PerVertexNormalsWeightingType  weighting,
Eigen::PlainObjectBase< DerivedN > &  N 
)
25{
27 igl::per_face_normals(V,F,PFN);
28 return per_vertex_normals(V,F,weighting,PFN,N);
29}

References per_face_normals(), and per_vertex_normals().

Referenced by igl::opengl::ViewerData::compute_normals(), CurvatureCalculator::init(), per_vertex_normals(), per_vertex_normals(), per_vertex_normals(), shape_diameter_function(), signed_distance(), igl::copyleft::cgal::signed_distance_isosurface(), and swept_volume_signed_distance().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ per_vertex_normals() [3/4]

template<typename DerivedV , typename DerivedF , typename DerivedFN , typename DerivedN >
IGL_INLINE void igl::per_vertex_normals ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const PerVertexNormalsWeightingType  weighting,
const Eigen::MatrixBase< DerivedFN > &  FN,
Eigen::PlainObjectBase< DerivedN > &  N 
)
47{
48 using namespace std;
49 // Resize for output
50 N.setZero(V.rows(),3);
51
53 W(F.rows(),3);
54 switch(weighting)
55 {
57 W.setConstant(1.);
58 break;
59 default:
60 assert(false && "Unknown weighting type");
63 {
65 doublearea(V,F,A);
66 W = A.replicate(1,3);
67 break;
68 }
69 case PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE:
70 internal_angles(V,F,W);
71 break;
72 }
73
74 // loop over faces
75 for(int i = 0;i<F.rows();i++)
76 {
77 // throw normal at each corner
78 for(int j = 0; j < 3;j++)
79 {
80 N.row(F(i,j)) += W(i,j) * FN.row(i);
81 }
82 }
83
85 //std::mutex critical;
86 //std::vector<DerivedN> NN;
87 //parallel_for(
88 // F.rows(),
89 // [&NN,&N](const size_t n){ NN.resize(n,DerivedN::Zero(N.rows(),3));},
90 // [&F,&W,&FN,&NN,&critical](const int i, const size_t t)
91 // {
92 // // throw normal at each corner
93 // for(int j = 0; j < 3;j++)
94 // {
95 // // Q: Does this need to be critical?
96 // // A: Yes. Different (i,j)'s could produce the same F(i,j)
97 // NN[t].row(F(i,j)) += W(i,j) * FN.row(i);
98 // }
99 // },
100 // [&N,&NN](const size_t t){ N += NN[t]; },
101 // 1000l);
102
103 // take average via normalization
104 N.rowwise().normalize();
105}

References doublearea(), internal_angles(), PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE, PER_VERTEX_NORMALS_WEIGHTING_TYPE_AREA, PER_VERTEX_NORMALS_WEIGHTING_TYPE_DEFAULT, PER_VERTEX_NORMALS_WEIGHTING_TYPE_UNIFORM, Eigen::PlainObjectBase< Derived >::setConstant(), and Eigen::PlainObjectBase< Derived >::setZero().

+ Here is the call graph for this function:

◆ per_vertex_normals() [4/4]

template<typename DerivedV , typename DerivedF , typename DerivedN >
IGL_INLINE void igl::per_vertex_normals ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedN > &  N 
)
36{
37 return per_vertex_normals(V,F,PER_VERTEX_NORMALS_WEIGHTING_TYPE_DEFAULT,N);
38}

References per_vertex_normals(), and PER_VERTEX_NORMALS_WEIGHTING_TYPE_DEFAULT.

+ Here is the call graph for this function:

◆ per_vertex_point_to_plane_quadrics()

IGL_INLINE void igl::per_vertex_point_to_plane_quadrics ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const Eigen::MatrixXi &  EMAP,
const Eigen::MatrixXi &  EF,
const Eigen::MatrixXi &  EI,
std::vector< std::tuple< Eigen::MatrixXd, Eigen::RowVectorXd, double > > &  quadrics 
)
23{
24 using namespace std;
25 typedef std::tuple<Eigen::MatrixXd,Eigen::RowVectorXd,double> Quadric;
26 const int dim = V.cols();
28 //std::vector<Quadric> face_quadrics(F.rows());
29 // Initialize each vertex quadric to zeros
30 quadrics.resize(
31 V.rows(),
32 // gcc <=4.8 can't handle initializer lists correctly
33 Quadric{Eigen::MatrixXd::Zero(dim,dim),Eigen::RowVectorXd::Zero(dim),0});
34 Eigen::MatrixXd I = Eigen::MatrixXd::Identity(dim,dim);
35 // Rather initial with zeros, initial with a small amount of energy pull
36 // toward original vertex position
37 const double w = 1e-10;
38 for(int v = 0;v<V.rows();v++)
39 {
40 std::get<0>(quadrics[v]) = w*I;
41 Eigen::RowVectorXd Vv = V.row(v);
42 std::get<1>(quadrics[v]) = w*-Vv;
43 std::get<2>(quadrics[v]) = w*Vv.dot(Vv);
44 }
45 // Generic nD qslim from "Simplifying Surfaces with Color and Texture
46 // using Quadric Error Metric" (follow up to original QSlim)
47 for(int f = 0;f<F.rows();f++)
48 {
49 int infinite_corner = -1;
50 for(int c = 0;c<3;c++)
51 {
52 if(
53 std::isinf(V(F(f,c),0)) ||
54 std::isinf(V(F(f,c),1)) ||
55 std::isinf(V(F(f,c),2)))
56 {
57 assert(infinite_corner == -1 && "Should only be one infinite corner");
58 infinite_corner = c;
59 }
60 }
61 // Inputs:
62 // p 1 by n row point on the subspace
63 // S m by n matrix where rows coorespond to orthonormal spanning
64 // vectors of the subspace to which we're measuring distance (usually
65 // a plane, m=2)
66 // weight scalar weight
67 // Returns quadric triple {A,b,c} so that A-2*b+c measures the quadric
68 const auto subspace_quadric = [&I](
69 const Eigen::RowVectorXd & p,
70 const Eigen::MatrixXd & S,
71 const double weight)->Quadric
72 {
73 // Dimension of subspace
74 const int m = S.rows();
75 // Weight face's quadric (v'*A*v + 2*b'*v + c) by area
76 // e1 and e2 should be perpendicular
77 Eigen::MatrixXd A = I;
78 Eigen::RowVectorXd b = -p;
79 double c = p.dot(p);
80 for(int i = 0;i<m;i++)
81 {
82 Eigen::RowVectorXd ei = S.row(i);
83 for(int j = 0;j<i;j++) assert(std::abs(S.row(j).dot(ei)) < 1e-10);
84 A += -ei.transpose()*ei;
85 b += p.dot(ei)*ei;
86 c += -pow(p.dot(ei),2);
87 }
88 // gcc <=4.8 can't handle initializer lists correctly: needs explicit
89 // cast
90 return Quadric{ weight*A, weight*b, weight*c };
91 };
92 if(infinite_corner == -1)
93 {
94 // Finite (non-boundary) face
95 Eigen::RowVectorXd p = V.row(F(f,0));
96 Eigen::RowVectorXd q = V.row(F(f,1));
97 Eigen::RowVectorXd r = V.row(F(f,2));
98 Eigen::RowVectorXd pq = q-p;
99 Eigen::RowVectorXd pr = r-p;
100 // Gram Determinant = squared area of parallelogram
101 double area = sqrt(pq.squaredNorm()*pr.squaredNorm()-pow(pr.dot(pq),2));
102 Eigen::RowVectorXd e1 = pq.normalized();
103 Eigen::RowVectorXd e2 = (pr-e1.dot(pr)*e1).normalized();
104 Eigen::MatrixXd S(2,V.cols());
105 S<<e1,e2;
106 Quadric face_quadric = subspace_quadric(p,S,area);
107 // Throw at each corner
108 for(int c = 0;c<3;c++)
109 {
110 quadrics[F(f,c)] = quadrics[F(f,c)] + face_quadric;
111 }
112 }else
113 {
114 // cth corner is infinite --> edge opposite cth corner is boundary
115 // Boundary edge vector
116 const Eigen::RowVectorXd p = V.row(F(f,(infinite_corner+1)%3));
117 Eigen::RowVectorXd ev = V.row(F(f,(infinite_corner+2)%3)) - p;
118 const double length = ev.norm();
119 ev /= length;
120 // Face neighbor across boundary edge
121 int e = EMAP(f+F.rows()*infinite_corner);
122 int opp = EF(e,0) == f ? 1 : 0;
123 int n = EF(e,opp);
124 int nc = EI(e,opp);
125 assert(
126 ((F(f,(infinite_corner+1)%3) == F(n,(nc+1)%3) &&
127 F(f,(infinite_corner+2)%3) == F(n,(nc+2)%3)) ||
128 (F(f,(infinite_corner+1)%3) == F(n,(nc+2)%3)
129 && F(f,(infinite_corner+2)%3) == F(n,(nc+1)%3))) &&
130 "Edge flaps not agreeing on shared edge");
131 // Edge vector on opposite face
132 const Eigen::RowVectorXd eu = V.row(F(n,nc)) - p;
133 assert(!std::isinf(eu(0)));
134 // Matrix with vectors spanning plane as columns
135 Eigen::MatrixXd A(ev.size(),2);
136 A<<ev.transpose(),eu.transpose();
137 // Use QR decomposition to find basis for orthogonal space
139 const Eigen::MatrixXd Q = qr.householderQ();
140 const Eigen::MatrixXd N =
141 Q.topRightCorner(ev.size(),ev.size()-2).transpose();
142 assert(N.cols() == ev.size());
143 assert(N.rows() == ev.size()-2);
144 Eigen::MatrixXd S(N.rows()+1,ev.size());
145 S<<ev,N;
146 Quadric boundary_edge_quadric = subspace_quadric(p,S,length);
147 for(int c = 0;c<3;c++)
148 {
149 if(c != infinite_corner)
150 {
151 quadrics[F(f,c)] = quadrics[F(f,c)] + boundary_edge_quadric;
152 }
153 }
154 }
155 }
156}
Householder QR decomposition of a matrix.
Definition HouseholderQR.h:45
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half pow(const half &a, const half &b)
Definition Half.h:477
Unit area(const Cntr &poly, const PathTag &)
Definition geometry_traits.hpp:971

References Eigen::HouseholderQR< _MatrixType >::householderQ(), sqrt(), and Eigen::HouseholderSequence< VectorsType, CoeffsType, Side >::transpose().

Referenced by qslim().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ piecewise_constant_winding_number() [1/2]

template<typename DerivedF >
IGL_INLINE bool igl::piecewise_constant_winding_number ( const Eigen::MatrixBase< DerivedF > &  F)
65{
68 std::vector<std::vector<size_t> > uE2E;
69 unique_edge_map(F, E, uE, EMAP, uE2E);
70 return piecewise_constant_winding_number(F,uE,uE2E);
71}

References unique_edge_map().

+ Here is the call graph for this function:

◆ piecewise_constant_winding_number() [2/2]

template<typename DerivedF , typename DeriveduE , typename uE2EType >
IGL_INLINE bool igl::piecewise_constant_winding_number ( const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< DeriveduE > &  uE,
const std::vector< std::vector< uE2EType > > &  uE2E 
)
20{
21 const size_t num_faces = F.rows();
22 const size_t num_edges = uE.rows();
23 const auto edge_index_to_face_index = [&](size_t ei)
24 {
25 return ei % num_faces;
26 };
27 const auto is_consistent = [&](size_t fid, size_t s, size_t d)
28 {
29 if ((size_t)F(fid, 0) == s && (size_t)F(fid, 1) == d) return true;
30 if ((size_t)F(fid, 1) == s && (size_t)F(fid, 2) == d) return true;
31 if ((size_t)F(fid, 2) == s && (size_t)F(fid, 0) == d) return true;
32
33 if ((size_t)F(fid, 0) == d && (size_t)F(fid, 1) == s) return false;
34 if ((size_t)F(fid, 1) == d && (size_t)F(fid, 2) == s) return false;
35 if ((size_t)F(fid, 2) == d && (size_t)F(fid, 0) == s) return false;
36 throw "Invalid face!!";
37 };
38 for (size_t i=0; i<num_edges; i++)
39 {
40 const size_t s = uE(i,0);
41 const size_t d = uE(i,1);
42 int count=0;
43 for (const auto& ei : uE2E[i])
44 {
45 const size_t fid = edge_index_to_face_index(ei);
46 if (is_consistent(fid, s, d))
47 {
48 count++;
49 }
50 else
51 {
52 count--;
53 }
54 }
55 if (count != 0)
56 {
57 return false;
58 }
59 }
60 return true;
61}

References count().

Referenced by igl::copyleft::cgal::piecewise_constant_winding_number(), and igl::copyleft::cgal::propagate_winding_numbers().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pinv() [1/2]

template<typename DerivedA , typename DerivedX >
void igl::pinv ( const Eigen::MatrixBase< DerivedA > &  A,
Eigen::PlainObjectBase< DerivedX > &  X 
)
33{
34 return pinv(A,-1,X);
35}
void pinv(const Eigen::MatrixBase< DerivedA > &A, typename DerivedA::Scalar tol, Eigen::PlainObjectBase< DerivedX > &X)
Definition pinv.cpp:6

References pinv().

+ Here is the call graph for this function:

◆ pinv() [2/2]

template<typename DerivedA , typename DerivedX >
void igl::pinv ( const Eigen::MatrixBase< DerivedA > &  A,
typename DerivedA::Scalar  tol,
Eigen::PlainObjectBase< DerivedX > &  X 
)
10{
12 typedef typename DerivedA::Scalar Scalar;
15 const Eigen::Matrix<Scalar,Eigen::Dynamic,1> & S = svd.singularValues();
16 if(tol < 0)
17 {
18 const Scalar smax = S.array().abs().maxCoeff();
19 tol =
20 (Scalar)(std::max(A.rows(),A.cols())) *
21 (smax-std::nextafter(smax,std::numeric_limits<Scalar>::epsilon()));
22 }
23 const int rank = (S.array()>0).count();
24 X = (V.leftCols(rank).array().rowwise() *
25 (1.0/S.head(rank).array()).transpose()).matrix()*
26 U.leftCols(rank).transpose();
27}
float BLASFUNC() smax(int *, float *, int *)

References Eigen::ComputeFullU, Eigen::ComputeFullV, count(), Eigen::SVDBase< Derived >::matrixU(), Eigen::SVDBase< Derived >::matrixV(), Eigen::SVDBase< Derived >::singularValues(), and smax().

Referenced by pinv().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ planarize_quad_mesh()

template<typename DerivedV , typename DerivedF >
IGL_INLINE void igl::planarize_quad_mesh ( const Eigen::PlainObjectBase< DerivedV > &  Vin,
const Eigen::PlainObjectBase< DerivedF > &  F,
const int  maxIter,
const double &  threshold,
Eigen::PlainObjectBase< DerivedV > &  Vout 
)
237{
238 PlanarizerShapeUp<DerivedV, DerivedF> planarizer(Vin, Fin, maxIter, threshold);
239 planarizer.planarize(Vout);
240}
Definition planarize_quad_mesh.cpp:18

References igl::PlanarizerShapeUp< DerivedV, DerivedF >::planarize().

+ Here is the call graph for this function:

◆ point_in_circle()

IGL_INLINE bool igl::point_in_circle ( const double  qx,
const double  qy,
const double  cx,
const double  cy,
const double  r 
)
16{
17 return (qx-cx)*(qx-cx) + (qy-cy)*(qy-cy) - r*r < 0;
18}

◆ point_in_poly()

bool IGL_INLINE igl::point_in_poly ( const std::vector< std::vector< unsigned int > > &  poly,
const unsigned int  xt,
const unsigned int  yt 
)
13{
14 int npoints= poly.size();
15 unsigned int xnew,ynew;
16 unsigned int xold,yold;
17 unsigned int x1,y1;
18 unsigned int x2,y2;
19 int i;
20 int inside=0;
21
22 if (npoints < 3) {
23 return(0);
24 }
25 xold=poly[npoints-1][0];
26 yold=poly[npoints-1][1];
27 for (i=0 ; i < npoints ; i++) {
28 xnew=poly[i][0];
29 ynew=poly[i][1];
30 if (xnew > xold) {
31 x1=xold;
32 x2=xnew;
33 y1=yold;
34 y2=ynew;
35 }
36 else {
37 x1=xnew;
38 x2=xold;
39 y1=ynew;
40 y2=yold;
41 }
42 if ((xnew < xt) == (xt <= xold) /* edge "open" at one end */
43 && ((long)yt-(long)y1)*(long)(x2-x1)
44 < ((long)y2-(long)y1)*(long)(xt-x1)) {
46 }
47 xold=xnew;
48 yold=ynew;
49 }
50 return (inside != 0);
51}
bool inside(const Polygons &polygons, const Point &p)

◆ point_mesh_squared_distance()

template<typename DerivedP , typename DerivedV , typename DerivedsqrD , typename DerivedI , typename DerivedC >
IGL_INLINE void igl::point_mesh_squared_distance ( const Eigen::PlainObjectBase< DerivedP > &  P,
const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::MatrixXi &  Ele,
Eigen::PlainObjectBase< DerivedsqrD > &  sqrD,
Eigen::PlainObjectBase< DerivedI > &  I,
Eigen::PlainObjectBase< DerivedC > &  C 
)
25{
26 using namespace std;
27 const size_t dim = P.cols();
28 assert((dim == 2 || dim == 3) && "P.cols() should be 2 or 3");
29 assert(P.cols() == V.cols() && "P.cols() should equal V.cols()");
30 switch(dim)
31 {
32 default:
33 assert(false && "Unsupported dim");
34 // fall-through and pray
35 case 3:
36 {
38 tree.init(V,Ele);
39 return tree.squared_distance(V,Ele,P,sqrD,I,C);
40 }
41 case 2:
42 {
43 AABB<DerivedV,2> tree;
44 tree.init(V,Ele);
45 return tree.squared_distance(V,Ele,P,sqrD,I,C);
46 }
47 }
48}
Definition AABB.h:27
IGL_INLINE void init(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedEle > &Ele, const Eigen::MatrixBase< Derivedbb_mins > &bb_mins, const Eigen::MatrixBase< Derivedbb_maxs > &bb_maxs, const Eigen::MatrixBase< Derivedelements > &elements, const int i=0)
Definition AABB.cpp:29
IGL_INLINE Scalar squared_distance(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedEle > &Ele, const RowVectorDIMS &p, int &i, Eigen::PlainObjectBase< RowVectorDIMS > &c) const

References Eigen::PlainObjectBase< Derived >::cols(), igl::AABB< DerivedV, DIM >::init(), and igl::AABB< DerivedV, DIM >::squared_distance().

+ Here is the call graph for this function:

◆ point_simplex_squared_distance() [1/2]

template<int DIM, typename Derivedp , typename DerivedV , typename DerivedEle , typename Derivedsqr_d , typename Derivedc >
IGL_INLINE void igl::point_simplex_squared_distance ( const Eigen::MatrixBase< Derivedp > &  p,
const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedEle > &  Ele,
const typename DerivedEle::Index  i,
Derivedsqr_d &  sqr_d,
Eigen::MatrixBase< Derivedc > &  c 
)
151{
152 // Use Dynamic because we don't know Ele.cols() at compile time.
154 point_simplex_squared_distance<DIM>( p, V, Ele, primitive, sqr_d, c, b );
155}

◆ point_simplex_squared_distance() [2/2]

template<int DIM, typename Derivedp , typename DerivedV , typename DerivedEle , typename Derivedsqr_d , typename Derivedc , typename Derivedb >
IGL_INLINE void igl::point_simplex_squared_distance ( const Eigen::MatrixBase< Derivedp > &  p,
const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedEle > &  Ele,
const typename DerivedEle::Index  i,
Derivedsqr_d &  sqr_d,
Eigen::MatrixBase< Derivedc > &  c,
Eigen::PlainObjectBase< Derivedb > &  b 
)
33{
34 typedef typename Derivedp::Scalar Scalar;
35 typedef typename Eigen::Matrix<Scalar,1,DIM> Vector;
36 typedef Vector Point;
37 //typedef Derivedb BaryPoint;
39
40 const auto & Dot = [](const Point & a, const Point & b)->Scalar
41 {
42 return a.dot(b);
43 };
44 // Real-time collision detection, Ericson, Chapter 5
45 const auto & ClosestBaryPtPointTriangle =
46 [&Dot](const Point &p, const Point &a, const Point &b, const Point &c, BaryPoint& bary_out )->Point
47 {
48 // Check if P in vertex region outside A
49 Vector ab = b - a;
50 Vector ac = c - a;
51 Vector ap = p - a;
52 Scalar d1 = Dot(ab, ap);
53 Scalar d2 = Dot(ac, ap);
54 if (d1 <= 0.0 && d2 <= 0.0) {
55 // barycentric coordinates (1,0,0)
56 bary_out << 1, 0, 0;
57 return a;
58 }
59 // Check if P in vertex region outside B
60 Vector bp = p - b;
61 Scalar d3 = Dot(ab, bp);
62 Scalar d4 = Dot(ac, bp);
63 if (d3 >= 0.0 && d4 <= d3) {
64 // barycentric coordinates (0,1,0)
65 bary_out << 0, 1, 0;
66 return b;
67 }
68 // Check if P in edge region of AB, if so return projection of P onto AB
69 Scalar vc = d1*d4 - d3*d2;
70 if( a != b)
71 {
72 if (vc <= 0.0 && d1 >= 0.0 && d3 <= 0.0) {
73 Scalar v = d1 / (d1 - d3);
74 // barycentric coordinates (1-v,v,0)
75 bary_out << 1-v, v, 0;
76 return a + v * ab;
77 }
78 }
79 // Check if P in vertex region outside C
80 Vector cp = p - c;
81 Scalar d5 = Dot(ab, cp);
82 Scalar d6 = Dot(ac, cp);
83 if (d6 >= 0.0 && d5 <= d6) {
84 // barycentric coordinates (0,0,1)
85 bary_out << 0, 0, 1;
86 return c;
87 }
88 // Check if P in edge region of AC, if so return projection of P onto AC
89 Scalar vb = d5*d2 - d1*d6;
90 if (vb <= 0.0 && d2 >= 0.0 && d6 <= 0.0) {
91 Scalar w = d2 / (d2 - d6);
92 // barycentric coordinates (1-w,0,w)
93 bary_out << 1-w, 0, w;
94 return a + w * ac;
95 }
96 // Check if P in edge region of BC, if so return projection of P onto BC
97 Scalar va = d3*d6 - d5*d4;
98 if (va <= 0.0 && (d4 - d3) >= 0.0 && (d5 - d6) >= 0.0) {
99 Scalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
100 // barycentric coordinates (0,1-w,w)
101 bary_out << 0, 1-w, w;
102 return b + w * (c - b);
103 }
104 // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
105 Scalar denom = 1.0 / (va + vb + vc);
106 Scalar v = vb * denom;
107 Scalar w = vc * denom;
108 bary_out << 1.0-v-w, v, w;
109 return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = 1.0-v-w
110 };
111
112 assert(p.size() == DIM);
113 assert(V.cols() == DIM);
114 assert(Ele.cols() <= DIM+1);
115 assert(Ele.cols() <= 3 && "Only simplices up to triangles are considered");
116
117 assert((Derivedb::RowsAtCompileTime == 1 || Derivedb::ColsAtCompileTime == 1) && "bary must be Eigen Vector or Eigen RowVector");
118 assert(
119 ((Derivedb::RowsAtCompileTime == -1 || Derivedb::ColsAtCompileTime == -1) ||
120 (Derivedb::RowsAtCompileTime == Ele.cols() || Derivedb::ColsAtCompileTime == Ele.cols())
121 ) && "bary must be Dynamic or size of Ele.cols()");
122
123 BaryPoint tmp_bary;
124 c = (const Derivedc &)ClosestBaryPtPointTriangle(
125 p,
126 V.row(Ele(primitive,0)),
127 // modulo is a HACK to handle points, segments and triangles. Because of
128 // this, we need 3d buffer for bary
129 V.row(Ele(primitive,1%Ele.cols())),
130 V.row(Ele(primitive,2%Ele.cols())),
131 tmp_bary);
132 bary.resize( Derivedb::RowsAtCompileTime == 1 ? 1 : Ele.cols(), Derivedb::ColsAtCompileTime == 1 ? 1 : Ele.cols());
133 bary.head(Ele.cols()) = tmp_bary.head(Ele.cols());
134 sqr_d = (p-c).squaredNorm();
135}
Point Vector
Definition Point.hpp:24
#define Dot(u, v)
Definition normal.c:49
Kernel::Point_2 Point
Definition point_areas.cpp:20

References Dot, and Eigen::PlainObjectBase< Derived >::resize().

+ Here is the call graph for this function:

◆ point_simplex_squared_distance< 2 >() [1/3]

template<>
IGL_INLINE void igl::point_simplex_squared_distance< 2 > ( Eigen::MatrixBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > const ,
Eigen::MatrixBase< Eigen::Matrix< double, -1, 3, 0, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< int, -1, 3, 0, -1, 3 > > const ,
Eigen::Matrix< int, -1, 3, 0, -1, 3 >::Index  ,
double &  ,
Eigen::MatrixBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > &   
)
160{assert(false);};

◆ point_simplex_squared_distance< 2 >() [2/3]

template<>
IGL_INLINE void igl::point_simplex_squared_distance< 2 > ( Eigen::MatrixBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > const ,
Eigen::MatrixBase< Eigen::Matrix< double, -1, 3, 1, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< int, -1, 3, 1, -1, 3 > > const ,
Eigen::Matrix< int, -1, 3, 1, -1, 3 >::Index  ,
double &  ,
Eigen::MatrixBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > &   
)
161{assert(false);};

◆ point_simplex_squared_distance< 2 >() [3/3]

template<>
IGL_INLINE void igl::point_simplex_squared_distance< 2 > ( Eigen::MatrixBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > const ,
Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 0, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< int, -1, 3, 0, -1, 3 > > const ,
Eigen::Matrix< int, -1, 3, 0, -1, 3 >::Index  ,
float &  ,
Eigen::MatrixBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > &   
)
159{assert(false);};

◆ polar_dec() [1/2]

template<typename DerivedA , typename DerivedR , typename DerivedT >
IGL_INLINE void igl::polar_dec ( const Eigen::PlainObjectBase< DerivedA > &  A,
Eigen::PlainObjectBase< DerivedR > &  R,
Eigen::PlainObjectBase< DerivedT > &  T 
)
86{
87 DerivedA U;
88 DerivedA V;
90 return igl::polar_dec(A,R,T,U,S,V);
91}
IGL_INLINE void polar_dec(const Eigen::PlainObjectBase< DerivedA > &A, Eigen::PlainObjectBase< DerivedR > &R, Eigen::PlainObjectBase< DerivedT > &T, Eigen::PlainObjectBase< DerivedU > &U, Eigen::PlainObjectBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedV > &V)
Definition polar_dec.cpp:27

References polar_dec().

+ Here is the call graph for this function:

◆ polar_dec() [2/2]

template<typename DerivedA , typename DerivedR , typename DerivedT , typename DerivedU , typename DerivedS , typename DerivedV >
IGL_INLINE void igl::polar_dec ( const Eigen::PlainObjectBase< DerivedA > &  A,
Eigen::PlainObjectBase< DerivedR > &  R,
Eigen::PlainObjectBase< DerivedT > &  T,
Eigen::PlainObjectBase< DerivedU > &  U,
Eigen::PlainObjectBase< DerivedS > &  S,
Eigen::PlainObjectBase< DerivedV > &  V 
)
34{
35 using namespace std;
36 using namespace Eigen;
37 typedef typename DerivedA::Scalar Scalar;
38
39 const Scalar th = std::sqrt(Eigen::NumTraits<Scalar>::dummy_precision());
40
42 feclearexcept(FE_UNDERFLOW);
43 eig.computeDirect(A.transpose()*A);
44 if(fetestexcept(FE_UNDERFLOW) || eig.eigenvalues()(0)/eig.eigenvalues()(2)<th)
45 {
46 cout<<"resorting to svd 1..."<<endl;
47 return polar_svd(A,R,T,U,S,V);
48 }
49
50 S = eig.eigenvalues().cwiseSqrt();
51
52 V = eig.eigenvectors();
53 U = A * V;
54 R = U * S.asDiagonal().inverse() * V.transpose();
55 T = V * S.asDiagonal() * V.transpose();
56
57 S = S.reverse().eval();
58 V = V.rowwise().reverse().eval();
59 U = U.rowwise().reverse().eval() * S.asDiagonal().inverse();
60
61 if(R.determinant() < 0)
62 {
63 // Annoyingly the .eval() is necessary
64 auto W = V.eval();
65 const auto & SVT = S.asDiagonal() * V.adjoint();
66 W.col(V.cols()-1) *= -1.;
67 R = U*W.transpose();
68 T = W*SVT;
69 }
70
71 if(std::fabs(R.squaredNorm()-3.) > th)
72 {
73 cout<<"resorting to svd 2..."<<endl;
74 return polar_svd(A,R,T,U,S,V);
75 }
76}
EIGEN_DEVICE_FUNC SelfAdjointEigenSolver & computeDirect(const MatrixType &matrix, int options=ComputeEigenvectors)
Computes eigendecomposition of given matrix using a closed-form algorithm.
Definition SelfAdjointEigenSolver.h:799
EIGEN_DEVICE_FUNC const EigenvectorsType & eigenvectors() const
Returns the eigenvectors of given matrix.
Definition SelfAdjointEigenSolver.h:259
EIGEN_DEVICE_FUNC const RealVectorType & eigenvalues() const
Returns the eigenvalues of given matrix.
Definition SelfAdjointEigenSolver.h:282
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition NumTraits.h:151

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::SelfAdjointEigenSolver< _MatrixType >::computeDirect(), Eigen::SelfAdjointEigenSolver< _MatrixType >::eigenvalues(), Eigen::SelfAdjointEigenSolver< _MatrixType >::eigenvectors(), and polar_svd().

Referenced by polar_dec(), and procrustes().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ polar_svd() [1/2]

template<typename DerivedA , typename DerivedR , typename DerivedT >
IGL_INLINE void igl::polar_svd ( const Eigen::PlainObjectBase< DerivedA > &  A,
Eigen::PlainObjectBase< DerivedR > &  R,
Eigen::PlainObjectBase< DerivedT > &  T 
)
22{
23 DerivedA U;
24 DerivedA V;
26 return igl::polar_svd(A,R,T,U,S,V);
27}

References polar_svd().

+ Here is the call graph for this function:

◆ polar_svd() [2/2]

template<typename DerivedA , typename DerivedR , typename DerivedT , typename DerivedU , typename DerivedS , typename DerivedV >
IGL_INLINE void igl::polar_svd ( const Eigen::PlainObjectBase< DerivedA > &  A,
Eigen::PlainObjectBase< DerivedR > &  R,
Eigen::PlainObjectBase< DerivedT > &  T,
Eigen::PlainObjectBase< DerivedU > &  U,
Eigen::PlainObjectBase< DerivedS > &  S,
Eigen::PlainObjectBase< DerivedV > &  V 
)
43{
44 using namespace std;
47 U = svd.matrixU();
48 V = svd.matrixV();
49 S = svd.singularValues();
50 R = U*V.transpose();
51 const auto & SVT = S.asDiagonal() * V.adjoint();
52 // Check for reflection
53 if(R.determinant() < 0)
54 {
55 // Annoyingly the .eval() is necessary
56 auto W = V.eval();
57 W.col(V.cols()-1) *= -1.;
58 R = U*W.transpose();
59 T = W*SVT;
60 }else
61 {
62 T = V*SVT;
63 }
64}

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::JacobiSVD< _MatrixType, QRPreconditioner >::compute(), Eigen::ComputeFullU, Eigen::ComputeFullV, Eigen::SVDBase< Derived >::matrixU(), Eigen::SVDBase< Derived >::matrixV(), and Eigen::SVDBase< Derived >::singularValues().

Referenced by igl::slim::compute_energy_with_jacobians(), fit_rotations(), fit_rotations_planar(), polar_dec(), polar_svd(), procrustes(), and igl::slim::update_weights_and_closest_rotations().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ polar_svd3x3()

template<typename Mat >
IGL_INLINE void igl::polar_svd3x3 ( const Mat &  A,
Mat &  R 
)
19{
20 // should be caught at compile time, but just to be 150% sure:
21 assert(A.rows() == 3 && A.cols() == 3);
22
25 svd3x3(A, U, S, Vt);
26 R = U * Vt.transpose();
27}
IGL_INLINE void svd3x3(const Eigen::Matrix< T, 3, 3 > &A, Eigen::Matrix< T, 3, 3 > &U, Eigen::Matrix< T, 3, 1 > &S, Eigen::Matrix< T, 3, 3 > &V)
Definition svd3x3.cpp:22

References svd3x3().

Referenced by fit_rotations().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ polygon_mesh_to_triangle_mesh() [1/2]

template<typename DerivedP , typename DerivedF >
IGL_INLINE void igl::polygon_mesh_to_triangle_mesh ( const Eigen::PlainObjectBase< DerivedP > &  P,
Eigen::PlainObjectBase< DerivedF > &  F 
)
62{
63 std::vector<std::vector<typename DerivedP::Scalar> > vP;
64 matrix_to_list(P,vP);
66}
IGL_INLINE void polygon_mesh_to_triangle_mesh(const std::vector< std::vector< Index > > &vF, Eigen::PlainObjectBase< DerivedF > &F)
Definition polygon_mesh_to_triangle_mesh.cpp:12

References matrix_to_list(), and polygon_mesh_to_triangle_mesh().

+ Here is the call graph for this function:

◆ polygon_mesh_to_triangle_mesh() [2/2]

template<typename Index , typename DerivedF >
IGL_INLINE void igl::polygon_mesh_to_triangle_mesh ( const std::vector< std::vector< Index > > &  vF,
Eigen::PlainObjectBase< DerivedF > &  F 
)
15{
16 using namespace std;
17 using namespace Eigen;
18 int m = 0;
19 // estimate of size
20 for(typename vector<vector<Index > >::const_iterator fit = vF.begin();
21 fit!=vF.end();
22 fit++)
23 {
24 if(fit->size() >= 3)
25 {
26 m += fit->size() - 2;
27 }
28 }
29 // Resize output
30 F.resize(m,3);
31 {
32 int k = 0;
33 for(typename vector<vector<Index > >::const_iterator fit = vF.begin();
34 fit!=vF.end();
35 fit++)
36 {
37 if(fit->size() >= 3)
38 {
39 typename vector<Index >::const_iterator cit = fit->begin();
40 cit++;
41 typename vector<Index >::const_iterator pit = cit++;
42 for(;
43 cit!=fit->end();
44 cit++,pit++)
45 {
46 F(k,0) = *(fit->begin());
47 F(k,1) = *pit;
48 F(k,2) = *cit;
49 k++;
50 }
51 }
52 }
53 assert(k==m);
54 }
55
56}

Referenced by polygon_mesh_to_triangle_mesh(), and read_triangle_mesh().

+ Here is the caller graph for this function:

◆ principal_curvature()

template<typename DerivedV , typename DerivedF , typename DerivedPD1 , typename DerivedPD2 , typename DerivedPV1 , typename DerivedPV2 >
IGL_INLINE void igl::principal_curvature ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedPD1 > &  PD1,
Eigen::PlainObjectBase< DerivedPD2 > &  PD2,
Eigen::PlainObjectBase< DerivedPV1 > &  PV1,
Eigen::PlainObjectBase< DerivedPV2 > &  PV2,
unsigned  radius = 5,
bool  useKring = true 
)
792{
793 if (radius < 2)
794 {
795 radius = 2;
796 std::cout << "WARNING: igl::principal_curvature needs a radius >= 2, fixing it to 2." << std::endl;
797 }
798
799 // Preallocate memory
800 PD1.resize(V.rows(),3);
801 PD2.resize(V.rows(),3);
802
803 // Preallocate memory
804 PV1.resize(V.rows(),1);
805 PV2.resize(V.rows(),1);
806
807 // Precomputation
809 cc.init(V.template cast<double>(),F.template cast<int>());
810 cc.sphereRadius = radius;
811
812 if (useKring)
813 {
814 cc.kRing = radius;
815 cc.st = K_RING_SEARCH;
816 }
817
818 // Compute
819 cc.computeCurvature();
820
821 // Copy it back
822 for (unsigned i=0; i<V.rows(); ++i)
823 {
824 PD1.row(i) << cc.curvDir[i][0][0], cc.curvDir[i][0][1], cc.curvDir[i][0][2];
825 PD2.row(i) << cc.curvDir[i][1][0], cc.curvDir[i][1][1], cc.curvDir[i][1][2];
826 PD1.row(i).normalize();
827 PD2.row(i).normalize();
828
829 if (std::isnan(PD1(i,0)) || std::isnan(PD1(i,1)) || std::isnan(PD1(i,2)) || std::isnan(PD2(i,0)) || std::isnan(PD2(i,1)) || std::isnan(PD2(i,2)))
830 {
831 PD1.row(i) << 0,0,0;
832 PD2.row(i) << 0,0,0;
833 }
834
835 PV1(i) = cc.curv[i][0];
836 PV2(i) = cc.curv[i][1];
837
838 if (PD1.row(i) * PD2.row(i).transpose() > 10e-6)
839 {
840 std::cerr << "PRINCIPAL_CURVATURE: Something is wrong with vertex: " << i << std::endl;
841 PD1.row(i) *= 0;
842 PD2.row(i) *= 0;
843 }
844 }
845
846}
Definition principal_curvature.cpp:40
std::vector< std::vector< Eigen::Vector3d > > curvDir
Definition principal_curvature.cpp:49
double sphereRadius
Definition principal_curvature.cpp:156
IGL_INLINE void computeCurvature()
Definition principal_curvature.cpp:653
int kRing
Definition principal_curvature.cpp:157
IGL_INLINE void init(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F)
Definition principal_curvature.cpp:318
std::vector< std::vector< double > > curv
Definition principal_curvature.cpp:48
searchType st
Definition principal_curvature.cpp:164
@ K_RING_SEARCH
Definition principal_curvature.cpp:30

References CurvatureCalculator::computeCurvature(), CurvatureCalculator::curv, CurvatureCalculator::curvDir, CurvatureCalculator::init(), K_RING_SEARCH, CurvatureCalculator::kRing, Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), CurvatureCalculator::sphereRadius, and CurvatureCalculator::st.

+ Here is the call graph for this function:

◆ print_ijv()

template<typename T >
IGL_INLINE void igl::print_ijv ( const Eigen::SparseMatrix< T > &  X,
const int  offset = 0 
)
17{
21 igl::find(X,I,J,V);
22 // Concatenate I,J,V
24 IJV.col(0) = I.cast<T>();
25 IJV.col(1) = J.cast<T>();
26 IJV.col(2) = V;
27 // Offset
28 if(offset != 0)
29 {
30 IJV.col(0).array() += offset;
31 IJV.col(1).array() += offset;
32 }
33 std::cout<<IJV;
34}

References find().

Referenced by arap_dof_precomputation().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_vector() [1/3]

template<typename T >
IGL_INLINE void igl::print_vector ( std::vector< std::vector< std::vector< T > > > &  v)
38{
39 using namespace std;
40 for (int m=0; m<v.size(); ++m)
41 {
42 std::cerr << "Matrix " << m << std::endl;
43
44 for (int i=0; i<v[m].size(); ++i)
45 {
46 std::cerr << i << ": ";
47 for (int j=0; j<v[m][i].size(); ++j)
48 std::cerr << v[m][i][j] << " ";
49 std::cerr << std::endl;
50 }
51
52 std::cerr << "---- end " << m << std::endl;
53
54 }
55}

◆ print_vector() [2/3]

template<typename T >
IGL_INLINE void igl::print_vector ( std::vector< std::vector< T > > &  v)
24{
25 using namespace std;
26 for (int i=0; i<v.size(); ++i)
27 {
28 std::cerr << i << ": ";
29 for (int j=0; j<v[i].size(); ++j)
30 std::cerr << v[i][j] << " ";
31 std::cerr << std::endl;
32 }
33}

◆ print_vector() [3/3]

template<typename T >
IGL_INLINE void igl::print_vector ( std::vector< T > &  v)
15{
16 using namespace std;
17 for (int i=0; i<v.size(); ++i)
18 std::cerr << v[i] << " ";
19 std::cerr << std::endl;
20}

Referenced by igl::copyleft::quadprog().

+ Here is the caller graph for this function:

◆ procrustes() [1/5]

template<typename DerivedX , typename DerivedY , typename DerivedR , typename DerivedT >
IGL_INLINE void igl::procrustes ( const Eigen::PlainObjectBase< DerivedX > &  X,
const Eigen::PlainObjectBase< DerivedY > &  Y,
bool  includeScaling,
bool  includeReflections,
Eigen::PlainObjectBase< DerivedR > &  S,
Eigen::PlainObjectBase< DerivedT > &  t 
)
100{
101 double scale;
102 procrustes(X,Y,includeScaling,includeReflections,scale,S,t);
103 S *= scale;
104}
int scale(const int val)
Definition WipeTowerDialog.cpp:14
IGL_INLINE void procrustes(const Eigen::PlainObjectBase< DerivedX > &X, const Eigen::PlainObjectBase< DerivedY > &Y, bool includeScaling, bool includeReflections, Scalar &scale, Eigen::PlainObjectBase< DerivedR > &R, Eigen::PlainObjectBase< DerivedT > &t)
Definition procrustes.cpp:18

References procrustes(), and scale().

+ Here is the call graph for this function:

◆ procrustes() [2/5]

template<typename DerivedX , typename DerivedY , typename Scalar , int DIM, int TType>
IGL_INLINE void igl::procrustes ( const Eigen::PlainObjectBase< DerivedX > &  X,
const Eigen::PlainObjectBase< DerivedY > &  Y,
bool  includeScaling,
bool  includeReflections,
Eigen::Transform< Scalar, DIM, TType > &  T 
)
77{
78 using namespace Eigen;
79 double scale;
80 MatrixXd R;
81 VectorXd t;
82 procrustes(X,Y,includeScaling,includeReflections,scale,R,t);
83
84 // Combine
86}
Represents a generic uniform scaling transformation.
Represents a translation transformation.
Definition Translation.h:31

References procrustes(), and scale().

+ Here is the call graph for this function:

◆ procrustes() [3/5]

template<typename DerivedX , typename DerivedY , typename Scalar , typename DerivedR , typename DerivedT >
IGL_INLINE void igl::procrustes ( const Eigen::PlainObjectBase< DerivedX > &  X,
const Eigen::PlainObjectBase< DerivedY > &  Y,
bool  includeScaling,
bool  includeReflections,
Scalar &  scale,
Eigen::PlainObjectBase< DerivedR > &  R,
Eigen::PlainObjectBase< DerivedT > &  t 
)
26{
27 using namespace Eigen;
28 assert (X.rows() == Y.rows() && "Same number of points");
29 assert(X.cols() == Y.cols() && "Points have same dimensions");
30
31 // Center data
32 const VectorXd Xmean = X.colwise().mean();
33 const VectorXd Ymean = Y.colwise().mean();
34 MatrixXd XC = X.rowwise() - Xmean.transpose();
35 MatrixXd YC = Y.rowwise() - Ymean.transpose();
36
37 // Scale
38 scale = 1.;
39 if (includeScaling)
40 {
41 double scaleX = XC.norm() / XC.rows();
42 double scaleY = YC.norm() / YC.rows();
43 scale = scaleY/scaleX;
44 XC *= scale;
45 assert (std::abs(XC.norm() / XC.rows() - scaleY) < 1e-8);
46 }
47
48 // Rotation
49 MatrixXd S = XC.transpose() * YC;
50 MatrixXd T;
51 if (includeReflections)
52 {
53 polar_dec(S,R,T);
54 }else
55 {
56 polar_svd(S,R,T);
57 }
58// R.transposeInPlace();
59
60 // Translation
61 t = Ymean - scale*R.transpose()*Xmean;
62}

References polar_dec(), polar_svd(), and scale().

Referenced by procrustes(), procrustes(), procrustes(), and procrustes().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ procrustes() [4/5]

template<typename DerivedX , typename DerivedY , typename DerivedR , typename DerivedT >
IGL_INLINE void igl::procrustes ( const Eigen::PlainObjectBase< DerivedX > &  X,
const Eigen::PlainObjectBase< DerivedY > &  Y,
Eigen::PlainObjectBase< DerivedR > &  R,
Eigen::PlainObjectBase< DerivedT > &  t 
)
116{
117 procrustes(X,Y,false,false,R,t);
118}

References procrustes().

+ Here is the call graph for this function:

◆ procrustes() [5/5]

template<typename DerivedX , typename DerivedY , typename Scalar , typename DerivedT >
IGL_INLINE void igl::procrustes ( const Eigen::PlainObjectBase< DerivedX > &  X,
const Eigen::PlainObjectBase< DerivedY > &  Y,
Eigen::Rotation2D< Scalar > &  R,
Eigen::PlainObjectBase< DerivedT > &  t 
)
130{
131 using namespace Eigen;
132 assert (X.cols() == 2 && Y.cols() == 2 && "Points must have dimension 2");
133 Matrix2d Rmat;
134 procrustes(X,Y,false,false,Rmat,t);
135 R.fromRotationMatrix(Rmat);
136}
EIGEN_DEVICE_FUNC Rotation2D & fromRotationMatrix(const MatrixBase< Derived > &m)

References Eigen::Rotation2D< _Scalar >::fromRotationMatrix(), and procrustes().

+ Here is the call graph for this function:

◆ project() [1/2]

template<typename Scalar >
IGL_INLINE Eigen::Matrix< Scalar, 3, 1 > igl::project ( const Eigen::Matrix< Scalar, 3, 1 > &  obj,
const Eigen::Matrix< Scalar, 4, 4 > &  model,
const Eigen::Matrix< Scalar, 4, 4 > &  proj,
const Eigen::Matrix< Scalar, 4, 1 > &  viewport 
)

Referenced by igl::opengl::glfw::imgui::ImGuiMenu::draw_text(), igl::opengl::glfw::Viewer::mouse_down(), and Slic3r::GUI::CameraUtils::project().

+ Here is the caller graph for this function:

◆ project() [2/2]

template<typename DerivedV , typename DerivedM , typename DerivedN , typename DerivedO , typename DerivedP >
IGL_INLINE void igl::project ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedM > &  model,
const Eigen::MatrixBase< DerivedN > &  proj,
const Eigen::MatrixBase< DerivedO > &  viewport,
Eigen::PlainObjectBase< DerivedP > &  P 
)
39{
40 typedef typename DerivedP::Scalar PScalar;
42 HV.leftCols(3) = V.template cast<PScalar>();
43 HV.col(3).setConstant(1);
44 HV = (HV*model.template cast<PScalar>().transpose()*
45 proj.template cast<PScalar>().transpose()).eval();
46 HV = (HV.array().colwise()/HV.col(3).array()).eval();
47 HV = (HV.array() * 0.5 + 0.5).eval();
48 HV.col(0) = (HV.array().col(0) * viewport(2) + viewport(0)).eval();
49 HV.col(1) = (HV.array().col(1) * viewport(3) + viewport(1)).eval();
50 P = HV.leftCols(3);
51}
EIGEN_DEVICE_FUNC TransposeReturnType transpose()
Definition Transpose.h:172

References Eigen::PlainObjectBase< Derived >::rows(), Eigen::PlainObjectBase< Derived >::setConstant(), and Eigen::DenseBase< Derived >::transpose().

+ Here is the call graph for this function:

◆ project_isometrically_to_plane()

template<typename DerivedV , typename DerivedF , typename DerivedU , typename DerivedUF , typename Scalar >
IGL_INLINE void igl::project_isometrically_to_plane ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedU > &  U,
Eigen::PlainObjectBase< DerivedUF > &  UF,
Eigen::SparseMatrix< Scalar > &  I 
)
23{
24 using namespace std;
25 using namespace Eigen;
26 assert(F.cols() == 3 && "F should contain triangles");
27 typedef DerivedV MatrixX;
28 MatrixX l;
29 edge_lengths(V,F,l);
30 // Number of faces
31 const int m = F.rows();
32
33 // First corner at origin
34 U = DerivedU::Zero(m*3,2);
35 // Second corner along x-axis
36 U.block(m,0,m,1) = l.col(2);
37 // Third corner rotated onto plane
38 U.block(m*2,0,m,1) =
39 (-l.col(0).array().square() +
40 l.col(1).array().square() +
41 l.col(2).array().square())/(2.*l.col(2).array());
42 U.block(m*2,1,m,1) =
43 (l.col(1).array().square()-U.block(m*2,0,m,1).array().square()).sqrt();
44
45 typedef Triplet<Scalar> IJV;
46 vector<IJV > ijv;
47 ijv.reserve(3*m);
48 UF.resize(m,3);
49 for(int f = 0;f<m;f++)
50 {
51 for(int c = 0;c<3;c++)
52 {
53 UF(f,c) = c*m+f;
54 ijv.push_back(IJV(F(f,c),c*m+f,1));
55 }
56 }
57 I.resize(V.rows(),m*3);
58 I.setFromTriplets(ijv.begin(),ijv.end());
59}

References edge_lengths(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::resize(), Eigen::PlainObjectBase< Derived >::rows(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets(), and sqrt().

Referenced by arap_precomputation().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ project_to_line() [1/3]

template<typename DerivedP , typename DerivedS , typename DerivedD , typename Derivedt , typename DerivedsqrD >
IGL_INLINE void igl::project_to_line ( const Eigen::MatrixBase< DerivedP > &  P,
const Eigen::MatrixBase< DerivedS > &  S,
const Eigen::MatrixBase< DerivedD > &  D,
Eigen::PlainObjectBase< Derivedt > &  t,
Eigen::PlainObjectBase< DerivedsqrD > &  sqrD 
)
24{
25 // http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
26
27 // number of dimensions
28#ifndef NDEBUG
29 int dim = P.cols();
30 assert(dim == S.size());
31 assert(dim == D.size());
32#endif
33 // number of points
34 int np = P.rows();
35 // vector from source to destination
36 DerivedD DmS = D-S;
37 double v_sqrlen = (double)(DmS.squaredNorm());
38 assert(v_sqrlen != 0);
39 // resize output
40 t.resize(np,1);
41 sqrD.resize(np,1);
42 // loop over points
43#pragma omp parallel for if (np>10000)
44 for(int i = 0;i<np;i++)
45 {
46 const typename DerivedP::ConstRowXpr Pi = P.row(i);
47 // vector from point i to source
48 const DerivedD SmPi = S-Pi;
49 t(i) = -(DmS.array()*SmPi.array()).sum() / v_sqrlen;
50 // P projected onto line
51 const DerivedD projP = (1-t(i))*S + t(i)*D;
52 sqrD(i) = (Pi-projP).squaredNorm();
53 }
54}

References Eigen::PlainObjectBase< Derived >::resize(), and sum().

Referenced by igl::embree::bone_visible(), boundary_conditions(), project_to_line(), project_to_line_segment(), and ramer_douglas_peucker().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ project_to_line() [2/3]

template<typename Scalar >
IGL_INLINE void igl::project_to_line ( const Scalar  px,
const Scalar  py,
const Scalar  pz,
const Scalar  sx,
const Scalar  sy,
const Scalar  sz,
const Scalar  dx,
const Scalar  dy,
const Scalar  dz,
Scalar &  projpx,
Scalar &  projpy,
Scalar &  projpz,
Scalar &  t,
Scalar &  sqrd 
)
72{
73 // vector from source to destination
74 Scalar dms[3];
75 dms[0] = dx-sx;
76 dms[1] = dy-sy;
77 dms[2] = dz-sz;
78 Scalar v_sqrlen = dms[0]*dms[0] + dms[1]*dms[1] + dms[2]*dms[2];
79 // line should have some length
80 assert(v_sqrlen != 0);
81 // vector from point to source
82 Scalar smp[3];
83 smp[0] = sx-px;
84 smp[1] = sy-py;
85 smp[2] = sz-pz;
86 t = -(dms[0]*smp[0]+dms[1]*smp[1]+dms[2]*smp[2])/v_sqrlen;
87 // P projectred onto line
88 projpx = (1.0-t)*sx + t*dx;
89 projpy = (1.0-t)*sy + t*dy;
90 projpz = (1.0-t)*sz + t*dz;
91 // vector from projected point to p
92 Scalar pmprojp[3];
93 pmprojp[0] = px-projpx;
94 pmprojp[1] = py-projpy;
95 pmprojp[2] = pz-projpz;
96 sqrd = pmprojp[0]*pmprojp[0] + pmprojp[1]*pmprojp[1] + pmprojp[2]*pmprojp[2];
97}

◆ project_to_line() [3/3]

template<typename Scalar >
IGL_INLINE void igl::project_to_line ( const Scalar  px,
const Scalar  py,
const Scalar  pz,
const Scalar  sx,
const Scalar  sy,
const Scalar  sz,
const Scalar  dx,
const Scalar  dy,
const Scalar  dz,
Scalar &  t,
Scalar &  sqrd 
)
112{
113 Scalar projpx;
114 Scalar projpy;
115 Scalar projpz;
117 px, py, pz, sx, sy, sz, dx, dy, dz,
118 projpx, projpy, projpz, t, sqrd);
119}

References project_to_line().

+ Here is the call graph for this function:

◆ project_to_line_segment()

template<typename DerivedP , typename DerivedS , typename DerivedD , typename Derivedt , typename DerivedsqrD >
IGL_INLINE void igl::project_to_line_segment ( const Eigen::MatrixBase< DerivedP > &  P,
const Eigen::MatrixBase< DerivedS > &  S,
const Eigen::MatrixBase< DerivedD > &  D,
Eigen::PlainObjectBase< Derivedt > &  t,
Eigen::PlainObjectBase< DerivedsqrD > &  sqrD 
)
24{
25 project_to_line(P,S,D,t,sqrD);
26 const int np = P.rows();
27 // loop over points and fix those that projected beyond endpoints
28#pragma omp parallel for if (np>10000)
29 for(int p = 0;p<np;p++)
30 {
31 const DerivedP Pp = P.row(p);
32 if(t(p)<0)
33 {
34 sqrD(p) = (Pp-S).squaredNorm();
35 t(p) = 0;
36 }else if(t(p)>1)
37 {
38 sqrD(p) = (Pp-D).squaredNorm();
39 t(p) = 1;
40 }
41 }
42}

References project_to_line().

Referenced by igl::embree::bone_heat(), and pseudonormal_test().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pseudonormal_test() [1/7]

template<typename DerivedV , typename DerivedF , typename DerivedEN , typename DerivedVN , typename Derivedq , typename Derivedc , typename Scalar , typename Derivedn >
IGL_INLINE void igl::pseudonormal_test ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  E,
const Eigen::MatrixBase< DerivedEN > &  EN,
const Eigen::MatrixBase< DerivedVN > &  VN,
const Eigen::MatrixBase< Derivedq > &  q,
const int  e,
Eigen::PlainObjectBase< Derivedc > &  c,
Scalar &  s,
Eigen::PlainObjectBase< Derivedn > &  n 
)
151{
152 using namespace Eigen;
153 const auto & qc = q-c;
154 const double len = (V.row(E(e,1))-V.row(E(e,0))).norm();
155 // barycentric coordinates
156 // this .head() nonsense is for "ridiculus" templates instantiations that AABB
157 // needs to compile
159 b((c-V.row(E(e,1))).norm()/len,(c-V.row(E(e,0))).norm()/len);
160 //b((c-V.row(E(e,1)).head(c.size())).norm()/len,(c-V.row(E(e,0)).head(c.size())).norm()/len);
161 // Determine which normal to use
162 const double epsilon = 1e-12;
163 const int type = (b.array()<=epsilon).template cast<int>().sum();
164 switch(type)
165 {
166 case 1:
167 // Find vertex
168 for(int x = 0;x<2;x++)
169 {
170 if(b(x)>epsilon)
171 {
172 n = VN.row(E(e,x)).head(2);
173 break;
174 }
175 }
176 break;
177 default:
178 assert(false && "all barycentric coords zero.");
179 case 0:
180 n = EN.row(e).head(2);
181 break;
182 }
183 s = (qc.dot(n) >= 0 ? 1. : -1.);
184}
EIGEN_DEVICE_FUNC SegmentReturnType head(Index n)
This is the const version of head(Index).
Definition BlockMethods.h:919

References head().

+ Here is the call graph for this function:

◆ pseudonormal_test() [2/7]

template<typename DerivedV , typename DerivedF , typename DerivedFN , typename DerivedVN , typename DerivedEN , typename DerivedEMAP , typename Derivedq , typename Derivedc , typename Scalar , typename Derivedn >
IGL_INLINE void igl::pseudonormal_test ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< DerivedFN > &  FN,
const Eigen::MatrixBase< DerivedVN > &  VN,
const Eigen::MatrixBase< DerivedEN > &  EN,
const Eigen::MatrixBase< DerivedEMAP > &  EMAP,
const Eigen::MatrixBase< Derivedq > &  q,
const int  f,
Eigen::PlainObjectBase< Derivedc > &  c,
Scalar &  s,
Eigen::PlainObjectBase< Derivedn > &  n 
)
36{
37 using namespace Eigen;
38 const auto & qc = q-c;
39 typedef Eigen::Matrix<Scalar,1,3> RowVector3S;
40 RowVector3S b;
41 // Using barycentric coorindates to determine whether close to a vertex/edge
42 // seems prone to error when dealing with nearly degenerate triangles: Even
43 // the barycenter (1/3,1/3,1/3) can be made arbitrarily close to an
44 // edge/vertex
45 //
46 const RowVector3S A = V.row(F(f,0));
47 const RowVector3S B = V.row(F(f,1));
48 const RowVector3S C = V.row(F(f,2));
49
50 const double area = [&A,&B,&C]()
51 {
53 doublearea(A,B,C,area);
54 return area(0);
55 }();
56 // These were chosen arbitrarily. In a floating point scenario, I'm not sure
57 // the best way to determine if c is on a vertex/edge or in the middle of the
58 // face: specifically, I'm worrying about degenerate triangles where
59 // barycentric coordinates are error-prone.
60 const double MIN_DOUBLE_AREA = 1e-4;
61 const double epsilon = 1e-12;
62 if(area>MIN_DOUBLE_AREA)
63 {
64 barycentric_coordinates( c,A,B,C,b);
65 // Determine which normal to use
66 const int type = (b.array()<=epsilon).template cast<int>().sum();
67 switch(type)
68 {
69 case 2:
70 // Find vertex
71 for(int x = 0;x<3;x++)
72 {
73 if(b(x)>epsilon)
74 {
75 n = VN.row(F(f,x));
76 break;
77 }
78 }
79 break;
80 case 1:
81 // Find edge
82 for(int x = 0;x<3;x++)
83 {
84 if(b(x)<=epsilon)
85 {
86 n = EN.row(EMAP(F.rows()*x+f));
87 break;
88 }
89 }
90 break;
91 default:
92 assert(false && "all barycentric coords zero.");
93 case 0:
94 n = FN.row(f);
95 break;
96 }
97 }else
98 {
99 // Check each vertex
100 bool found = false;
101 for(int v = 0;v<3 && !found;v++)
102 {
103 if( (c-V.row(F(f,v))).norm() < epsilon)
104 {
105 found = true;
106 n = VN.row(F(f,v));
107 }
108 }
109 // Check each edge
110 for(int e = 0;e<3 && !found;e++)
111 {
112 const RowVector3S s = V.row(F(f,(e+1)%3));
113 const RowVector3S d = V.row(F(f,(e+2)%3));
114 Matrix<double,1,1> sqr_d_j_x(1,1);
115 Matrix<double,1,1> t(1,1);
116 project_to_line_segment(c,s,d,t,sqr_d_j_x);
117 if(sqrt(sqr_d_j_x(0)) < epsilon)
118 {
119 n = EN.row(EMAP(F.rows()*e+f));
120 found = true;
121 }
122 }
123 // Finally just use face
124 if(!found)
125 {
126 n = FN.row(f);
127 }
128 }
129 s = (qc.dot(n) >= 0 ? 1. : -1.);
130}
constexpr double epsilon()
Definition DoubleSlider.hpp:28
IGL_INLINE void project_to_line_segment(const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedS > &S, const Eigen::MatrixBase< DerivedD > &D, Eigen::PlainObjectBase< Derivedt > &t, Eigen::PlainObjectBase< DerivedsqrD > &sqrD)
Definition project_to_line_segment.cpp:18

References barycentric_coordinates(), doublearea(), project_to_line_segment(), and sqrt().

+ Here is the call graph for this function:

◆ pseudonormal_test() [3/7]

template<>
IGL_INLINE void igl::pseudonormal_test ( Eigen::MatrixBase< Eigen::Matrix< double, -1, 3, 1, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< int, -1, 2, 0, -1, 2 > > const ,
Eigen::MatrixBase< Eigen::Matrix< double, -1, 3, 0, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< double, -1, 3, 0, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > const ,
int  ,
Eigen::PlainObjectBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > &  ,
double &  ,
Eigen::PlainObjectBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > &   
)
195{assert(false);};

◆ pseudonormal_test() [4/7]

template<>
IGL_INLINE void igl::pseudonormal_test ( Eigen::MatrixBase< Eigen::Matrix< double, -1, 3, 1, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< int, -1, 3, 1, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< double, -1, 3, 0, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< double, -1, 3, 0, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > const ,
int  ,
Eigen::PlainObjectBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > &  ,
double &  ,
Eigen::PlainObjectBase< Eigen::Matrix< double, 1, 2, 1, 1, 2 > > &   
)
194{assert(false);};

◆ pseudonormal_test() [5/7]

template<>
IGL_INLINE void igl::pseudonormal_test ( Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 0, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< int, -1, 2, 0, -1, 2 > > const ,
Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 0, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 0, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > const ,
int  ,
Eigen::PlainObjectBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > &  ,
float &  ,
Eigen::PlainObjectBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > &   
)
196{assert(false);};

◆ pseudonormal_test() [6/7]

template<>
IGL_INLINE void igl::pseudonormal_test ( Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 1, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< int, -1, 2, 0, -1, 2 > > const ,
Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 0, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 0, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > const ,
int  ,
Eigen::PlainObjectBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > &  ,
float &  ,
Eigen::PlainObjectBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > &   
)
193{assert(false);};

◆ pseudonormal_test() [7/7]

template<>
IGL_INLINE void igl::pseudonormal_test ( Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 1, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< int, -1, 3, 1, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 0, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 0, -1, 3 > > const ,
Eigen::MatrixBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > const ,
int  ,
Eigen::PlainObjectBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > &  ,
float &  ,
Eigen::PlainObjectBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > &   
)
192{assert(false);};

Referenced by signed_distance(), signed_distance_pseudonormal(), signed_distance_pseudonormal(), and swept_volume_signed_distance().

+ Here is the caller graph for this function:

◆ pso() [1/2]

template<typename Scalar , typename DerivedX , typename DerivedLB , typename DerivedUB , typename DerivedP >
IGL_INLINE Scalar igl::pso ( const std::function< Scalar(DerivedX &) >  f,
const Eigen::MatrixBase< DerivedLB > &  LB,
const Eigen::MatrixBase< DerivedUB > &  UB,
const Eigen::DenseBase< DerivedP > &  P,
const int  max_iters,
const int  population,
DerivedX &  X 
)
39{
40 const int dim = LB.size();
41 assert(UB.size() == dim && "UB should match LB size");
42 assert(P.size() == dim && "P should match LB size");
43 typedef std::vector<DerivedX,Eigen::aligned_allocator<DerivedX> > VectorList;
44 VectorList position(population);
45 VectorList best_position(population);
46 VectorList velocity(population);
48 // https://en.wikipedia.org/wiki/Particle_swarm_optimization#Algorithm
49 //
50 // g → X
51 // p_i → best[i]
52 // v_i → velocity[i]
53 // x_i → position[i]
54 Scalar min_f = std::numeric_limits<Scalar>::max();
55 for(int p=0;p<population;p++)
56 {
57 {
58 const DerivedX R = DerivedX::Random(dim).array()*0.5+0.5;
59 position[p] = LB.array() + R.array()*(UB-LB).array();
60 }
61 best_f[p] = f(position[p]);
62 best_position[p] = position[p];
63 if(best_f[p] < min_f)
64 {
65 min_f = best_f[p];
66 X = best_position[p];
67 }
68 {
69 const DerivedX R = DerivedX::Random(dim);
70 velocity[p] = (UB-LB).array() * R.array();
71 }
72 }
73
74 int iter = 0;
75 Scalar omega = 0.98;
76 Scalar phi_p = 0.01;
77 Scalar phi_g = 0.01;
78 while(true)
79 {
80 //if(iter % 10 == 0)
81 //{
82 // std::cout<<iter<<":"<<std::endl;
83 // for(int p=0;p<population;p++)
84 // {
85 // std::cout<<" "<<best_f[p]<<", "<<best_position[p]<<std::endl;
86 // }
87 // std::cout<<std::endl;
88 //}
89
90 for(int p=0;p<population;p++)
91 {
92 const DerivedX R_p = DerivedX::Random(dim).array()*0.5+0.5;
93 const DerivedX R_g = DerivedX::Random(dim).array()*0.5+0.5;
94 velocity[p] =
95 omega * velocity[p].array() +
96 phi_p * R_p.array() *(best_position[p] - position[p]).array() +
97 phi_g * R_g.array() *( X - position[p]).array();
98 position[p] += velocity[p];
99 // Clamp to bounds
100 for(int d = 0;d<dim;d++)
101 {
102//#define IGL_PSO_REFLECTION
103#ifdef IGL_PSO_REFLECTION
104 assert(!P(d));
105 // Reflect velocities if exceeding bounds
106 if(position[p](d) < LB(d))
107 {
108 position[p](d) = LB(d);
109 if(velocity[p](d) < 0.0) velocity[p](d) *= -1.0;
110 }
111 if(position[p](d) > UB(d))
112 {
113 position[p](d) = UB(d);
114 if(velocity[p](d) > 0.0) velocity[p](d) *= -1.0;
115 }
116#else
117//#warning "trying no bounds on periodic"
118// // TODO: I'm not sure this is the right thing to do/enough. The
119// // velocities could be weird. Suppose the current "best" value is ε and
120// // the value is -ε and the "periodic bounds" [0,2π]. Moding will send
121// // the value to 2π-ε but the "velocity" term will now be huge pointing
122// // all the way from 2π-ε to ε.
123// //
124// // Q: Would it be enough to try (all combinations) of ±(UB-LB) before
125// // computing velocities to "best"s? In the example above, instead of
126// //
127// // v += best - p = ε - (2π-ε) = -2π+2ε
128// //
129// // you'd use
130// //
131// // v += / argmin |b - p| \ - p = (ε+2π)-(2π-ε) = 2ε
132// // | |
133// // \ b∈{best, best+2π, best-2π} /
134// //
135// // Though, for multivariate b,p,v this would seem to explode
136// // combinatorially.
137// //
138// // Maybe periodic things just shouldn't be bounded and we hope that the
139// // forces toward the current minima "regularize" them away from insane
140// // values.
141// if(P(d))
142// {
143// position[p](d) = std::fmod(position[p](d)-LB(d),UB(d)-LB(d))+LB(d);
144// }else
145// {
146// position[p](d) = std::max(LB(d),std::min(UB(d),position[p](d)));
147// }
148 position[p](d) = std::max(LB(d),std::min(UB(d),position[p](d)));
149#endif
150 }
151 const Scalar fp = f(position[p]);
152 if(fp<best_f[p])
153 {
154 best_f[p] = fp;
155 best_position[p] = position[p];
156 if(best_f[p] < min_f)
157 {
158 min_f = best_f[p];
159 X = best_position[p];
160 }
161 }
162 }
163 iter++;
164 if(iter>=max_iters)
165 {
166 break;
167 }
168 }
169 return min_f;
170}

References Eigen::MatrixBase< Derived >::array().

+ Here is the call graph for this function:

◆ pso() [2/2]

template<typename Scalar , typename DerivedX , typename DerivedLB , typename DerivedUB >
IGL_INLINE Scalar igl::pso ( const std::function< Scalar(DerivedX &) >  f,
const Eigen::MatrixBase< DerivedLB > &  LB,
const Eigen::MatrixBase< DerivedUB > &  UB,
const int  max_iters,
const int  population,
DerivedX &  X 
)
19{
22 return igl::pso(f,LB,UB,P,max_iters,population,X);
23}
IGL_INLINE Scalar pso(const std::function< Scalar(DerivedX &) > f, const Eigen::MatrixBase< DerivedLB > &LB, const Eigen::MatrixBase< DerivedUB > &UB, const int max_iters, const int population, DerivedX &X)
Definition pso.cpp:12

References pso().

Referenced by pso().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ qslim()

IGL_INLINE bool igl::qslim ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const size_t  max_m,
Eigen::MatrixXd &  U,
Eigen::MatrixXi &  G,
Eigen::VectorXi &  J,
Eigen::VectorXi &  I 
)
31{
32 using namespace igl;
33
34 // Original number of faces
35 const int orig_m = F.rows();
36 // Tracking number of faces
37 int m = F.rows();
38 typedef Eigen::MatrixXd DerivedV;
39 typedef Eigen::MatrixXi DerivedF;
40 DerivedV VO;
41 DerivedF FO;
43 // decimate will not work correctly on non-edge-manifold meshes. By extension
44 // this includes meshes with non-manifold vertices on the boundary since these
45 // will create a non-manifold edge when connected to infinity.
46 if(!is_edge_manifold(FO))
47 {
48 return false;
49 }
50 Eigen::VectorXi EMAP;
51 Eigen::MatrixXi E,EF,EI;
52 edge_flaps(FO,E,EMAP,EF,EI);
53 // Quadrics per vertex
54 typedef std::tuple<Eigen::MatrixXd,Eigen::RowVectorXd,double> Quadric;
55 std::vector<Quadric> quadrics;
56 per_vertex_point_to_plane_quadrics(VO,FO,EMAP,EF,EI,quadrics);
57 // State variables keeping track of edge we just collapsed
58 int v1 = -1;
59 int v2 = -1;
60 // Callbacks for computing and updating metric
61 std::function<void(
62 const int e,
63 const Eigen::MatrixXd &,
64 const Eigen::MatrixXi &,
65 const Eigen::MatrixXi &,
66 const Eigen::VectorXi &,
67 const Eigen::MatrixXi &,
68 const Eigen::MatrixXi &,
69 double &,
70 Eigen::RowVectorXd &)> cost_and_placement;
71 std::function<bool(
72 const Eigen::MatrixXd & ,/*V*/
73 const Eigen::MatrixXi & ,/*F*/
74 const Eigen::MatrixXi & ,/*E*/
75 const Eigen::VectorXi & ,/*EMAP*/
76 const Eigen::MatrixXi & ,/*EF*/
77 const Eigen::MatrixXi & ,/*EI*/
78 const std::set<std::pair<double,int> > & ,/*Q*/
79 const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
80 const Eigen::MatrixXd & ,/*C*/
81 const int /*e*/
82 )> pre_collapse;
83 std::function<void(
84 const Eigen::MatrixXd & , /*V*/
85 const Eigen::MatrixXi & , /*F*/
86 const Eigen::MatrixXi & , /*E*/
87 const Eigen::VectorXi & ,/*EMAP*/
88 const Eigen::MatrixXi & , /*EF*/
89 const Eigen::MatrixXi & , /*EI*/
90 const std::set<std::pair<double,int> > & , /*Q*/
91 const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
92 const Eigen::MatrixXd & , /*C*/
93 const int , /*e*/
94 const int , /*e1*/
95 const int , /*e2*/
96 const int , /*f1*/
97 const int , /*f2*/
98 const bool /*collapsed*/
99 )> post_collapse;
100 qslim_optimal_collapse_edge_callbacks(
101 E,quadrics,v1,v2, cost_and_placement, pre_collapse,post_collapse);
102 // Call to greedy decimator
103 bool ret = decimate(
104 VO, FO,
105 cost_and_placement,
106 max_faces_stopping_condition(m,orig_m,max_m),
107 pre_collapse,
108 post_collapse,
109 E, EMAP, EF, EI,
110 U, G, J, I);
111 // Remove phony boundary faces and clean up
112 const Eigen::Array<bool,Eigen::Dynamic,1> keep = (J.array()<orig_m);
113 igl::slice_mask(Eigen::MatrixXi(G),keep,1,G);
114 igl::slice_mask(Eigen::VectorXi(J),keep,1,J);
115 Eigen::VectorXi _1,I2;
116 igl::remove_unreferenced(Eigen::MatrixXd(U),Eigen::MatrixXi(G),U,G,_1,I2);
117 igl::slice(Eigen::VectorXi(I),I2,1,I);
118
119 return ret;
120}
Definition AABB.cpp:1014

References connect_boundary_to_infinity(), decimate(), edge_flaps(), is_edge_manifold(), max_faces_stopping_condition(), per_vertex_point_to_plane_quadrics(), qslim_optimal_collapse_edge_callbacks(), remove_unreferenced(), slice(), slice_mask(), and void().

+ Here is the call graph for this function:

◆ qslim_optimal_collapse_edge_callbacks()

IGL_INLINE void igl::qslim_optimal_collapse_edge_callbacks ( Eigen::MatrixXi &  E,
std::vector< std::tuple< Eigen::MatrixXd, Eigen::RowVectorXd, double > > &  quadrics,
int &  v1,
int &  v2,
std::function< void(const int e, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> &  cost_and_placement,
std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int)> &  pre_collapse,
std::function< void(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int, const bool)> &  post_collapse 
)
57{
58 typedef std::tuple<Eigen::MatrixXd,Eigen::RowVectorXd,double> Quadric;
59 cost_and_placement = [&quadrics,&v1,&v2](
60 const int e,
61 const Eigen::MatrixXd & V,
62 const Eigen::MatrixXi & /*F*/,
63 const Eigen::MatrixXi & E,
64 const Eigen::VectorXi & /*EMAP*/,
65 const Eigen::MatrixXi & /*EF*/,
66 const Eigen::MatrixXi & /*EI*/,
67 double & cost,
68 Eigen::RowVectorXd & p)
69 {
70 // Combined quadric
71 Quadric quadric_p;
72 quadric_p = quadrics[E(e,0)] + quadrics[E(e,1)];
73 // Quadric: p'Ap + 2b'p + c
74 // optimal point: Ap = -b, or rather because we have row vectors: pA=-b
75 const auto & A = std::get<0>(quadric_p);
76 const auto & b = std::get<1>(quadric_p);
77 const auto & c = std::get<2>(quadric_p);
78 p = -b*A.inverse();
79 cost = p.dot(p*A) + 2*p.dot(b) + c;
80 // Force infs and nans to infinity
81 if(std::isinf(cost) || cost!=cost)
82 {
83 cost = std::numeric_limits<double>::infinity();
84 // Prevent NaNs. Actually NaNs might be useful for debugging.
85 p.setConstant(0);
86 }
87 };
88 // Remember endpoints
89 pre_collapse = [&v1,&v2](
90 const Eigen::MatrixXd & ,/*V*/
91 const Eigen::MatrixXi & ,/*F*/
92 const Eigen::MatrixXi & E,
93 const Eigen::VectorXi & ,/*EMAP*/
94 const Eigen::MatrixXi & ,/*EF*/
95 const Eigen::MatrixXi & ,/*EI*/
96 const std::set<std::pair<double,int> > & ,/*Q*/
97 const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
98 const Eigen::MatrixXd & ,/*C*/
99 const int e)->bool
100 {
101 v1 = E(e,0);
102 v2 = E(e,1);
103 return true;
104 };
105 // update quadric
106 post_collapse = [&v1,&v2,&quadrics](
107 const Eigen::MatrixXd & , /*V*/
108 const Eigen::MatrixXi & , /*F*/
109 const Eigen::MatrixXi & , /*E*/
110 const Eigen::VectorXi & ,/*EMAP*/
111 const Eigen::MatrixXi & , /*EF*/
112 const Eigen::MatrixXi & , /*EI*/
113 const std::set<std::pair<double,int> > & , /*Q*/
114 const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
115 const Eigen::MatrixXd & , /*C*/
116 const int , /*e*/
117 const int , /*e1*/
118 const int , /*e2*/
119 const int , /*f1*/
120 const int , /*f2*/
121 const bool collapsed
122 )->void
123 {
124 if(collapsed)
125 {
126 quadrics[v1<v2?v1:v2] = quadrics[v1] + quadrics[v2];
127 }
128 };
129}

Referenced by qslim().

+ Here is the caller graph for this function:

◆ quad_planarity()

template<typename DerivedV , typename DerivedF , typename DerivedP >
IGL_INLINE void igl::quad_planarity ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedP > &  P 
)
16{
17 int nf = F.rows();
18 P.setZero(nf,1);
19 for (int i =0; i<nf; ++i)
20 {
21 const Eigen::Matrix<typename DerivedV::Scalar,1,3> &v1 = V.row(F(i,0));
22 const Eigen::Matrix<typename DerivedV::Scalar,1,3> &v2 = V.row(F(i,1));
23 const Eigen::Matrix<typename DerivedV::Scalar,1,3> &v3 = V.row(F(i,2));
24 const Eigen::Matrix<typename DerivedV::Scalar,1,3> &v4 = V.row(F(i,3));
26 typename DerivedV::Scalar denom =
27 diagCross.norm()*(((v3-v1).norm()+(v4-v2).norm())/2);
28 if (fabs(denom)<1e-8)
29 //degenerate quad is still planar
30 P[i] = 0;
31 else
32 P[i] = (diagCross.dot(v2-v1)/denom);
33 }
34}

References cross(), and Eigen::PlainObjectBase< Derived >::setZero().

Referenced by igl::PlanarizerShapeUp< DerivedV, DerivedF >::planarize().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ quat_conjugate()

template<typename Q_type >
IGL_INLINE void igl::quat_conjugate ( const Q_type *  q1,
Q_type *  out 
)
14{
15 out[0] = -q1[0];
16 out[1] = -q1[1];
17 out[2] = -q1[2];
18 out[3] = q1[3];
19}

◆ quat_mult()

template<typename Q_type >
IGL_INLINE void igl::quat_mult ( const Q_type *  q1,
const Q_type *  q2,
Q_type *  out 
)
17{
18 // output can't be either of the inputs
19 assert(q1 != out);
20 assert(q2 != out);
21
22 out[0] = q1[3]*q2[0] + q1[0]*q2[3] + q1[1]*q2[2] - q1[2]*q2[1];
23 out[1] = q1[3]*q2[1] + q1[1]*q2[3] + q1[2]*q2[0] - q1[0]*q2[2];
24 out[2] = q1[3]*q2[2] + q1[2]*q2[3] + q1[0]*q2[1] - q1[1]*q2[0];
25 out[3] = q1[3]*q2[3] - (q1[0]*q2[0] + q1[1]*q2[1] + q1[2]*q2[2]);
26}

◆ quat_to_axis_angle()

template<typename Q_type >
IGL_INLINE void igl::quat_to_axis_angle ( const Q_type *  q,
Q_type *  axis,
Q_type &  angle 
)
20{
21 if( fabs(q[3])>(1.0 + igl::EPS<Q_type>()) )
22 {
23 //axis[0] = axis[1] = axis[2] = 0; // no, keep the previous value
24 angle = 0;
25 }
26 else
27 {
28 double a;
29 if( q[3]>=1.0f )
30 a = 0; // and keep V
31 else if( q[3]<=-1.0f )
32 a = PI; // and keep V
33 else if( fabs(q[0]*q[0]+q[1]*q[1]+q[2]*q[2]+q[3]*q[3])<igl::EPS_SQ<Q_type>())
34 {
35 a = 0;
36 }else
37 {
38 a = acos(q[3]);
39 if( a*angle<0 ) // Preserve the sign of angle
40 a = -a;
41 double f = 1.0f / sin(a);
42 axis[0] = q[0] * f;
43 axis[1] = q[1] * f;
44 axis[2] = q[2] * f;
45 }
46 angle = 2.0*a;
47 }
48
49 // if( angle>FLOAT_PI )
50 // angle -= 2.0f*FLOAT_PI;
51 // else if( angle<-FLOAT_PI )
52 // angle += 2.0f*FLOAT_PI;
53 //angle = RadToDeg(angle);
54
55 if( fabs(angle)<igl::EPS<Q_type>()&& fabs(axis[0]*axis[0]+axis[1]*axis[1]+axis[2]*axis[2])<igl::EPS_SQ<Q_type>())
56 {
57 axis[0] = 1.0e-7; // all components cannot be null
58 }
59}
double angle(const Eigen::MatrixBase< Derived > &v1, const Eigen::MatrixBase< Derived2 > &v2)
Definition Point.hpp:112

References acos(), PI, and sin().

Referenced by quat_to_axis_angle_deg().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ quat_to_axis_angle_deg()

template<typename Q_type >
IGL_INLINE void igl::quat_to_axis_angle_deg ( const Q_type *  q,
Q_type *  axis,
Q_type &  angle 
)
66{
67 igl::quat_to_axis_angle(q,axis,angle);
68 angle = angle*(180.0/PI);
69}
IGL_INLINE void quat_to_axis_angle(const Q_type *q, Q_type *axis, Q_type &angle)
Definition quat_to_axis_angle.cpp:16

References PI, and quat_to_axis_angle().

+ Here is the call graph for this function:

◆ quat_to_mat()

template<typename Q_type >
IGL_INLINE void igl::quat_to_mat ( const Q_type *  quat,
Q_type *  mat 
)
12{
13 Q_type yy2 = 2.0f * quat[1] * quat[1];
14 Q_type xy2 = 2.0f * quat[0] * quat[1];
15 Q_type xz2 = 2.0f * quat[0] * quat[2];
16 Q_type yz2 = 2.0f * quat[1] * quat[2];
17 Q_type zz2 = 2.0f * quat[2] * quat[2];
18 Q_type wz2 = 2.0f * quat[3] * quat[2];
19 Q_type wy2 = 2.0f * quat[3] * quat[1];
20 Q_type wx2 = 2.0f * quat[3] * quat[0];
21 Q_type xx2 = 2.0f * quat[0] * quat[0];
22 mat[0*4+0] = - yy2 - zz2 + 1.0f;
23 mat[0*4+1] = xy2 + wz2;
24 mat[0*4+2] = xz2 - wy2;
25 mat[0*4+3] = 0;
26 mat[1*4+0] = xy2 - wz2;
27 mat[1*4+1] = - xx2 - zz2 + 1.0f;
28 mat[1*4+2] = yz2 + wx2;
29 mat[1*4+3] = 0;
30 mat[2*4+0] = xz2 + wy2;
31 mat[2*4+1] = yz2 - wx2;
32 mat[2*4+2] = - xx2 - yy2 + 1.0f;
33 mat[2*4+3] = 0;
34 mat[3*4+0] = mat[3*4+1] = mat[3*4+2] = 0;
35 mat[3*4+3] = 1;
36}

◆ quats_to_column() [1/2]

IGL_INLINE Eigen::VectorXd igl::quats_to_column ( const std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > >  vQ)
29{
30 Eigen::VectorXd Q;
31 quats_to_column(vQ,Q);
32 return Q;
33}
IGL_INLINE void quats_to_column(const std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > vQ, Eigen::VectorXd &Q)
Definition quats_to_column.cpp:10

References quats_to_column().

+ Here is the call graph for this function:

◆ quats_to_column() [2/2]

IGL_INLINE void igl::quats_to_column ( const std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > >  vQ,
Eigen::VectorXd &  Q 
)
14{
15 Q.resize(vQ.size()*4);
16 for(int q = 0;q<(int)vQ.size();q++)
17 {
18 auto & xyzw = vQ[q].coeffs();
19 for(int c = 0;c<4;c++)
20 {
21 Q(q*4+c) = xyzw(c);
22 }
23 }
24}

Referenced by quats_to_column().

+ Here is the caller graph for this function:

◆ ramer_douglas_peucker() [1/2]

template<typename DerivedP , typename DerivedS , typename DerivedJ >
IGL_INLINE void igl::ramer_douglas_peucker ( const Eigen::MatrixBase< DerivedP > &  P,
const typename DerivedP::Scalar  tol,
Eigen::PlainObjectBase< DerivedS > &  S,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
18{
19 typedef typename DerivedP::Scalar Scalar;
20 // number of vertices
21 const int n = P.rows();
22 // Trivial base case
23 if(n <= 1)
24 {
25 J = DerivedJ::Zero(n);
26 S = P;
27 return;
28 }
29 // number of dimensions
30 const int m = P.cols();
33 const auto stol = tol*tol;
34 std::function<void(const int,const int)> simplify;
35 simplify = [&I,&P,&stol,&simplify](const int ixs, const int ixe)->void
36 {
37 assert(ixe>ixs);
38 Scalar sdmax = 0;
40 if((ixe-ixs)>1)
41 {
42 Scalar sdes = (P.row(ixe)-P.row(ixs)).squaredNorm();
44 const auto & Pblock = P.block(ixs+1,0,((ixe+1)-ixs)-2,P.cols());
45 if(sdes<=EPS<Scalar>())
46 {
47 sD = (Pblock.rowwise()-P.row(ixs)).rowwise().squaredNorm();
48 }else
49 {
51 project_to_line(Pblock,P.row(ixs).eval(),P.row(ixe).eval(),T,sD);
52 }
53 sdmax = sD.maxCoeff(&ixc);
54 // Index full P
55 ixc = ixc+(ixs+1);
56 }
57 if(sdmax <= stol)
58 {
59 if(ixs != ixe-1)
60 {
61 I.block(ixs+1,0,((ixe+1)-ixs)-2,1).setConstant(false);
62 }
63 }else
64 {
65 simplify(ixs,ixc);
66 simplify(ixc,ixe);
67 }
68 };
69 simplify(0,n-1);
70 slice_mask(P,I,1,S);
71 find(I,J);
72}
void simplify(Polygon &thiss, const int64_t smallest_line_segment_squared, const int64_t allowed_error_distance_squared)
Definition WallToolPaths.cpp:59

References Eigen::MatrixBase< Derived >::eval(), find(), project_to_line(), slice_mask(), and void().

Referenced by ramer_douglas_peucker(), and straighten_seams().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ramer_douglas_peucker() [2/2]

template<typename DerivedP , typename DerivedS , typename DerivedJ , typename DerivedQ >
IGL_INLINE void igl::ramer_douglas_peucker ( const Eigen::MatrixBase< DerivedP > &  P,
const typename DerivedP::Scalar  tol,
Eigen::PlainObjectBase< DerivedS > &  S,
Eigen::PlainObjectBase< DerivedJ > &  J,
Eigen::PlainObjectBase< DerivedQ > &  Q 
)
85{
86 typedef typename DerivedP::Scalar Scalar;
87 ramer_douglas_peucker(P,tol,S,J);
88 const int n = P.rows();
89 assert(n>=2 && "Curve should be at least 2 points");
91 // distance traveled along high-res curve
92 VectorXS L(n);
93 L(0) = 0;
94 L.block(1,0,n-1,1) = (P.bottomRows(n-1)-P.topRows(n-1)).rowwise().norm();
95 // Give extra on end
96 VectorXS T;
97 cumsum(L,1,T);
98 T.conservativeResize(T.size()+1);
99 T(T.size()-1) = T(T.size()-2);
100 // index of coarse point before each fine vertex
101 Eigen::VectorXi B;
102 {
103 Eigen::VectorXi N;
104 histc(igl::LinSpaced<Eigen::VectorXi >(n,0,n-1),J,N,B);
105 }
106 // Add extra point at end
107 J.conservativeResize(J.size()+1);
108 J(J.size()-1) = J(J.size()-2);
109 Eigen::VectorXi s,d;
110 // Find index in original list of "start" vertices
111 slice(J,B,s);
112 // Find index in original list of "destination" vertices
113 slice(J,(B.array()+1).eval(),d);
114 // Parameter between start and destination is linear in arc-length
115 VectorXS Ts,Td;
116 slice(T,s,Ts);
117 slice(T,d,Td);
118 T = ((T.head(T.size()-1)-Ts).array()/(Td-Ts).array()).eval();
119 for(int t =0;t<T.size();t++)
120 {
121 if(!std::isfinite(T(t)) || T(t)!=T(t))
122 {
123 T(t) = 0;
124 }
125 }
126 DerivedS SB;
127 slice(S,B,1,SB);
128 Eigen::VectorXi MB = B.array()+1;
129 for(int b = 0;b<MB.size();b++)
130 {
131 if(MB(b) >= S.rows())
132 {
133 MB(b) = S.rows()-1;
134 }
135 }
136 DerivedS SMB;
137 slice(S,MB,1,SMB);
138 Q = SB.array() + ((SMB.array()-SB.array()).colwise()*T.array());
139
140 // Remove extra point at end
141 J.conservativeResize(J.size()-1);
142}
IGL_INLINE void ramer_douglas_peucker(const Eigen::MatrixBase< DerivedP > &P, const typename DerivedP::Scalar tol, Eigen::PlainObjectBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedJ > &J)
Definition ramer_douglas_peucker.cpp:13
IGL_INLINE void cumsum(const Eigen::MatrixBase< DerivedX > &X, const int dim, Eigen::PlainObjectBase< DerivedY > &Y)
Definition cumsum.cpp:13

References Eigen::PlainObjectBase< Derived >::conservativeResize(), cumsum(), histc(), L, ramer_douglas_peucker(), Eigen::PlainObjectBase< Derived >::rows(), and slice().

+ Here is the call graph for this function:

◆ random_dir()

IGL_INLINE Eigen::Vector3d igl::random_dir ( )
13{
14 using namespace Eigen;
15 double z = (double)rand() / (double)RAND_MAX*2.0 - 1.0;
16 double t = (double)rand() / (double)RAND_MAX*2.0*PI;
17 // http://www.altdevblogaday.com/2012/05/03/generating-uniformly-distributed-points-on-sphere/
18 double r = sqrt(1.0-z*z);
19 double x = r * cos(t);
20 double y = r * sin(t);
21 return Vector3d(x,y,z);
22}

References cos(), PI, sin(), and sqrt().

Referenced by random_dir_stratified(), and igl::embree::reorient_facets_raycast().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ random_dir_stratified()

IGL_INLINE Eigen::MatrixXd igl::random_dir_stratified ( const int  n)
25{
26 using namespace Eigen;
27 using namespace std;
28 const double m = std::floor(sqrt(double(n)));
29 MatrixXd N(n,3);
30 int row = 0;
31 for(int i = 0;i<m;i++)
32 {
33 const double x = double(i)*1./m;
34 for(int j = 0;j<m;j++)
35 {
36 const double y = double(j)*1./m;
37 double z = (x+(1./m)*(double)rand() / (double)RAND_MAX)*2.0 - 1.0;
38 double t = (y+(1./m)*(double)rand() / (double)RAND_MAX)*2.0*PI;
39 double r = sqrt(1.0-z*z);
40 N(row,0) = r * cos(t);
41 N(row,1) = r * sin(t);
42 N(row,2) = z;
43 row++;
44 }
45 }
46 // Finish off with uniform random directions
47 for(;row<n;row++)
48 {
49 N.row(row) = random_dir();
50 }
51 return N;
52}
IGL_INLINE Eigen::Vector3d random_dir()
Definition random_dir.cpp:12

References cos(), PI, random_dir(), row(), sin(), and sqrt().

Referenced by ambient_occlusion(), and shape_diameter_function().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ random_points_on_mesh() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedB , typename DerivedFI >
IGL_INLINE void igl::random_points_on_mesh ( const int  n,
const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedB > &  B,
Eigen::PlainObjectBase< DerivedFI > &  FI 
)
22{
23 using namespace Eigen;
24 using namespace std;
25 typedef typename DerivedV::Scalar Scalar;
26 typedef Matrix<Scalar,Dynamic,1> VectorXs;
27 VectorXs A;
28 doublearea(V,F,A);
29 A /= A.array().sum();
30 // Should be traingle mesh. Although Turk's method 1 generalizes...
31 assert(F.cols() == 3);
32 VectorXs C;
33 VectorXs A0(A.size()+1);
34 A0(0) = 0;
35 A0.bottomRightCorner(A.size(),1) = A;
36 // Even faster would be to use the "Alias Table Method"
37 cumsum(A0,1,C);
38 const VectorXs R = (VectorXs::Random(n,1).array() + 1.)/2.;
39 assert(R.minCoeff() >= 0);
40 assert(R.maxCoeff() <= 1);
41 histc(R,C,FI);
42 const VectorXs S = (VectorXs::Random(n,1).array() + 1.)/2.;
43 const VectorXs T = (VectorXs::Random(n,1).array() + 1.)/2.;
44 B.resize(n,3);
45 B.col(0) = 1.-T.array().sqrt();
46 B.col(1) = (1.-S.array()) * T.array().sqrt();
47 B.col(2) = S.array() * T.array().sqrt();
48}

References cumsum(), doublearea(), histc(), and Eigen::PlainObjectBase< Derived >::resize().

Referenced by random_points_on_mesh(), and Slic3r::branchingtree::sample_mesh().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ random_points_on_mesh() [2/2]

template<typename DerivedV , typename DerivedF , typename ScalarB , typename DerivedFI >
IGL_INLINE void igl::random_points_on_mesh ( const int  n,
const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::SparseMatrix< ScalarB > &  B,
Eigen::PlainObjectBase< DerivedFI > &  FI 
)
57{
58 using namespace Eigen;
59 using namespace std;
61 random_points_on_mesh(n,V,F,BC,FI);
62 vector<Triplet<ScalarB> > BIJV;
63 BIJV.reserve(n*3);
64 for(int s = 0;s<n;s++)
65 {
66 for(int c = 0;c<3;c++)
67 {
68 assert(FI(s) < F.rows());
69 assert(FI(s) >= 0);
70 const int v = F(FI(s),c);
71 BIJV.push_back(Triplet<ScalarB>(s,v,BC(s,c)));
72 }
73 }
74 B.resize(n,V.rows());
75 B.reserve(n*3);
76 B.setFromTriplets(BIJV.begin(),BIJV.end());
77}
IGL_INLINE void random_points_on_mesh(const int n, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedB > &B, Eigen::PlainObjectBase< DerivedFI > &FI)
Definition random_points_on_mesh.cpp:16

References random_points_on_mesh(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::reserve(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::resize(), Eigen::PlainObjectBase< Derived >::rows(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets().

+ Here is the call graph for this function:

◆ random_quaternion()

template<typename Scalar >
IGL_INLINE Eigen::Quaternion< Scalar > igl::random_quaternion ( )
13{
14 const auto & unit_rand = []()->Scalar
15 {
16 return ((Scalar)rand() / (Scalar)RAND_MAX);
17 };
18#ifdef false
19 // http://mathproofs.blogspot.com/2005/05/uniformly-distributed-random-unit.html
20 const Scalar t0 = 2.*igl::PI*unit_rand();
21 const Scalar t1 = acos(1.-2.*unit_rand());
22 const Scalar t2 = 0.5*(igl::PI*unit_rand() + acos(unit_rand()));
24 1.*sin(t0)*sin(t1)*sin(t2),
25 1.*cos(t0)*sin(t1)*sin(t2),
26 1.*cos(t1)*sin(t2),
27 1.*cos(t2));
28#elif false
29 // "Uniform Random Rotations" [Shoemake 1992] method 1
30 const auto & uurand = [&unit_rand]()->Scalar
31 {
32 return unit_rand()*2.-1.;
33 };
34 Scalar x = uurand();
35 Scalar y = uurand();
36 Scalar z = uurand();
37 Scalar w = uurand();
38 const auto & hype = [&uurand](Scalar & x, Scalar & y)->Scalar
39 {
40 Scalar s1;
41 while((s1 = x*x + y*y) > 1.0)
42 {
43 x = uurand();
44 y = uurand();
45 }
46 return s1;
47 };
48 Scalar s1 = hype(x,y);
49 Scalar s2 = hype(z,w);
50 Scalar num1 = -2.*log(s1);
51 Scalar num2 = -2.*log(s2);
52 Scalar r = num1 + num2;
53 Scalar root1 = sqrt((num1/s1)/r);
54 Scalar root2 = sqrt((num2/s2)/r);
56 x*root1,
57 y*root1,
58 z*root2,
59 w*root2);
60#else
61 // Shoemake method 2
62 const Scalar x0 = unit_rand();
63 const Scalar x1 = unit_rand();
64 const Scalar x2 = unit_rand();
65 const Scalar r1 = sqrt(1.0 - x0);
66 const Scalar r2 = sqrt(x0);
67 const Scalar t1 = 2.*igl::PI*x1;
68 const Scalar t2 = 2.*igl::PI*x2;
69 const Scalar c1 = cos(t1);
70 const Scalar s1 = sin(t1);
71 const Scalar c2 = cos(t2);
72 const Scalar s2 = sin(t2);
74 s1*r1,
75 c1*r1,
76 s2*r2,
77 c2*r2);
78#endif
79}
EIGEN_DEVICE_FUNC const LogReturnType log() const
Definition ArrayCwiseUnaryOps.h:105

References acos(), cos(), log(), PI, sin(), and sqrt().

+ Here is the call graph for this function:

◆ random_search()

template<typename Scalar , typename DerivedX , typename DerivedLB , typename DerivedUB >
IGL_INLINE Scalar igl::random_search ( const std::function< Scalar(DerivedX &) >  f,
const Eigen::MatrixBase< DerivedLB > &  LB,
const Eigen::MatrixBase< DerivedUB > &  UB,
const int  iters,
DerivedX &  X 
)
16{
17 Scalar min_f = std::numeric_limits<Scalar>::max();
18 const int dim = LB.size();
19 assert(UB.size() == dim && "UB should match LB size");
20 for(int iter = 0;iter<iters;iter++)
21 {
22 const DerivedX R = DerivedX::Random(dim).array()*0.5+0.5;
23 DerivedX Xr = LB.array() + R.array()*(UB-LB).array();
24 const Scalar fr = f(Xr);
25 if(fr<min_f)
26 {
27 min_f = fr;
28 X = Xr;
29 }
30 }
31 return min_f;
32}

References Eigen::MatrixBase< Derived >::array().

+ Here is the call graph for this function:

◆ randperm()

template<typename DerivedI >
IGL_INLINE void igl::randperm ( const int  n,
Eigen::PlainObjectBase< DerivedI > &  I 
)
16{
17 Eigen::VectorXi II;
18 igl::colon(0,1,n-1,II);
19 I = II;
20 std::random_shuffle(I.data(),I.data()+n);
21}

References colon(), and Eigen::PlainObjectBase< Derived >::data().

+ Here is the call graph for this function:

◆ ray_box_intersect()

template<typename Derivedsource , typename Deriveddir , typename Scalar >
IGL_INLINE bool igl::ray_box_intersect ( const Eigen::MatrixBase< Derivedsource > &  source,
const Eigen::MatrixBase< Deriveddir > &  dir,
const Eigen::AlignedBox< Scalar, 3 > &  box,
const Scalar &  t0,
const Scalar &  t1,
Scalar &  tmin,
Scalar &  tmax 
)
23{
24#ifdef false
25 // https://github.com/RMonica/basic_next_best_view/blob/master/src/RayTracer.cpp
26 const auto & intersectRayBox = [](
27 const Eigen::Vector3f& rayo,
28 const Eigen::Vector3f& rayd,
29 const Eigen::Vector3f& bmin,
30 const Eigen::Vector3f& bmax,
31 float & tnear,
32 float & tfar
33 )->bool
34 {
35 Eigen::Vector3f bnear;
36 Eigen::Vector3f bfar;
37 // Checks for intersection testing on each direction coordinate
38 // Computes
39 float t1, t2;
40 tnear = -1e+6f, tfar = 1e+6f; //, tCube;
41 bool intersectFlag = true;
42 for (int i = 0; i < 3; ++i) {
43 // std::cout << "coordinate " << i << ": bmin " << bmin(i) << ", bmax " << bmax(i) << std::endl;
44 assert(bmin(i) <= bmax(i));
45 if (::fabs(rayd(i)) < 1e-6) { // Ray parallel to axis i-th
46 if (rayo(i) < bmin(i) || rayo(i) > bmax(i)) {
47 intersectFlag = false;
48 }
49 }
50 else {
51 // Finds the nearest and the farthest vertices of the box from the ray origin
52 if (::fabs(bmin(i) - rayo(i)) < ::fabs(bmax(i) - rayo(i))) {
53 bnear(i) = bmin(i);
54 bfar(i) = bmax(i);
55 }
56 else {
57 bnear(i) = bmax(i);
58 bfar(i) = bmin(i);
59 }
60 // std::cout << " bnear " << bnear(i) << ", bfar " << bfar(i) << std::endl;
61 // Finds the distance parameters t1 and t2 of the two ray-box intersections:
62 // t1 must be the closest to the ray origin rayo.
63 t1 = (bnear(i) - rayo(i)) / rayd(i);
64 t2 = (bfar(i) - rayo(i)) / rayd(i);
65 if (t1 > t2) {
66 std::swap(t1,t2);
67 }
68 // The two intersection values are used to saturate tnear and tfar
69 if (t1 > tnear) {
70 tnear = t1;
71 }
72 if (t2 < tfar) {
73 tfar = t2;
74 }
75 // std::cout << " t1 " << t1 << ", t2 " << t2 << ", tnear " << tnear << ", tfar " << tfar
76 // << " tnear > tfar? " << (tnear > tfar) << ", tfar < 0? " << (tfar < 0) << std::endl;
77 if(tnear > tfar) {
78 intersectFlag = false;
79 }
80 if(tfar < 0) {
81 intersectFlag = false;
82 }
83 }
84 }
85 // Checks whether intersection occurs or not
86 return intersectFlag;
87 };
88 float tmin_f, tmax_f;
89 bool ret = intersectRayBox(
90 origin. template cast<float>(),
91 dir. template cast<float>(),
92 box.min().template cast<float>(),
93 box.max().template cast<float>(),
94 tmin_f,
95 tmax_f);
96 tmin = tmin_f;
97 tmax = tmax_f;
98 return ret;
99#else
100 using namespace Eigen;
101 // This should be precomputed and provided as input
102 typedef Matrix<Scalar,1,3> RowVector3S;
103 const RowVector3S inv_dir( 1./dir(0),1./dir(1),1./dir(2));
104 const std::array<bool, 3> sign = { inv_dir(0)<0, inv_dir(1)<0, inv_dir(2)<0};
105 // http://people.csail.mit.edu/amy/papers/box-jgt.pdf
106 // "An Efficient and Robust Ray–Box Intersection Algorithm"
107 Scalar tymin, tymax, tzmin, tzmax;
108 std::array<RowVector3S, 2> bounds = {box.min(),box.max()};
109 tmin = ( bounds[sign[0]](0) - origin(0)) * inv_dir(0);
110 tmax = ( bounds[1-sign[0]](0) - origin(0)) * inv_dir(0);
111 tymin = (bounds[sign[1]](1) - origin(1)) * inv_dir(1);
112 tymax = (bounds[1-sign[1]](1) - origin(1)) * inv_dir(1);
113 if ( (tmin > tymax) || (tymin > tmax) )
114 {
115 return false;
116 }
117 if (tymin > tmin)
118 {
119 tmin = tymin;
120 }
121 if (tymax < tmax)
122 {
123 tmax = tymax;
124 }
125 tzmin = (bounds[sign[2]](2) - origin(2)) * inv_dir(2);
126 tzmax = (bounds[1-sign[2]](2) - origin(2)) * inv_dir(2);
127 if ( (tmin > tzmax) || (tzmin > tmax) )
128 {
129 return false;
130 }
131 if (tzmin > tmin)
132 {
133 tmin = tzmin;
134 }
135 if (tzmax < tmax)
136 {
137 tmax = tzmax;
138 }
139 if(!( (tmin < t1) && (tmax > t0) ))
140 {
141 return false;
142 }
143 return true;
144#endif
145}
EIGEN_DEVICE_FUNC const VectorType &() min() const
Definition AlignedBox.h:106
EIGEN_DEVICE_FUNC const VectorType &() max() const
Definition AlignedBox.h:110
Bounds< N > bounds(const Bound(&b)[N])
Definition Optimizer.hpp:192

References Eigen::AlignedBox< _Scalar, _AmbientDim >::max(), Eigen::AlignedBox< _Scalar, _AmbientDim >::min(), and sign().

Referenced by igl::AABB< DerivedV, DIM >::intersect_ray(), igl::AABB< DerivedV, DIM >::intersect_ray(), and igl::AABB< DerivedV, DIM >::intersect_ray().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ray_mesh_intersect() [1/2]

template<typename Derivedsource , typename Deriveddir , typename DerivedV , typename DerivedF >
IGL_INLINE bool igl::ray_mesh_intersect ( const Eigen::MatrixBase< Derivedsource > &  source,
const Eigen::MatrixBase< Deriveddir > &  dir,
const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
igl::Hit hit 
)
70{
71 std::vector<igl::Hit> hits;
72 ray_mesh_intersect(source,dir,V,F,hits);
73 if(hits.size() > 0)
74 {
75 hit = hits.front();
76 return true;
77 }else
78 {
79 return false;
80 }
81}

References ray_mesh_intersect().

+ Here is the call graph for this function:

◆ ray_mesh_intersect() [2/2]

template<typename Derivedsource , typename Deriveddir , typename DerivedV , typename DerivedF >
IGL_INLINE bool igl::ray_mesh_intersect ( const Eigen::MatrixBase< Derivedsource > &  source,
const Eigen::MatrixBase< Deriveddir > &  dir,
const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
std::vector< igl::Hit > &  hits 
)
26{
27 using namespace Eigen;
28 using namespace std;
29 // Should be but can't be const
30 Vector3d s_d = s.template cast<double>();
31 Vector3d dir_d = dir.template cast<double>();
32 hits.clear();
33 hits.reserve(F.rows());
34
35 // loop over all triangles
36 for(int f = 0;f<F.rows();f++)
37 {
38 // Should be but can't be const
39 RowVector3d v0 = V.row(F(f,0)).template cast<double>();
40 RowVector3d v1 = V.row(F(f,1)).template cast<double>();
41 RowVector3d v2 = V.row(F(f,2)).template cast<double>();
42 // shoot ray, record hit
43 double t,u,v;
45 s_d.data(), dir_d.data(), v0.data(), v1.data(), v2.data(), &t, &u, &v) &&
46 t>0)
47 {
48 hits.push_back({(int)f,(int)-1,(float)u,(float)v,(float)t});
49 }
50 }
51 // Sort hits based on distance
52 std::sort(
53 hits.begin(),
54 hits.end(),
55 [](const Hit & a, const Hit & b)->bool{ return a.t < b.t;});
56 return hits.size() > 0;
57}
int intersect_triangle1(double orig[3], double dir[3], double vert0[3], double vert1[3], double vert2[3], double *t, double *u, double *v)
Definition raytri.c:76

References intersect_triangle1().

Referenced by ambient_occlusion(), igl::AABB< DerivedV, DIM >::intersect_ray(), igl::AABB< DerivedV, DIM >::intersect_ray(), igl::AABB< DerivedV, DIM >::intersect_ray(), ray_mesh_intersect(), shape_diameter_function(), unproject_in_mesh(), and unproject_onto_mesh().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ray_sphere_intersect()

template<typename Derivedo , typename Derivedd , typename Derivedc , typename r_type , typename t_type >
IGL_INLINE int igl::ray_sphere_intersect ( const Eigen::PlainObjectBase< Derivedo > &  o,
const Eigen::PlainObjectBase< Derivedd > &  d,
const Eigen::PlainObjectBase< Derivedc > &  c,
r_type  r,
t_type &  t0,
t_type &  t1 
)
23{
24 Eigen::Vector3d o = ao-ac;
25 // http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
26 //Compute A, B and C coefficients
27 double a = d.dot(d);
28 double b = 2 * d.dot(o);
29 double c = o.dot(o) - (r * r);
30
31 //Find discriminant
32 double disc = b * b - 4 * a * c;
33
34 // if discriminant is negative there are no real roots, so return
35 // false as ray misses sphere
36 if (disc < 0)
37 {
38 return 0;
39 }
40
41 // compute q as described above
42 double distSqrt = sqrt(disc);
43 double q;
44 if (b < 0)
45 {
46 q = (-b - distSqrt)/2.0;
47 } else
48 {
49 q = (-b + distSqrt)/2.0;
50 }
51
52 // compute t0 and t1
53 t0 = q / a;
54 double _t1 = c/q;
55 if(_t1 == t0)
56 {
57 return 1;
58 }
59 t1 = _t1;
60 // make sure t0 is smaller than t1
61 if (t0 > t1)
62 {
63 // if t0 is bigger than t1 swap them around
64 double temp = t0;
65 t0 = t1;
66 t1 = temp;
67 }
68 return 2;
69}

References sqrt().

Referenced by igl::opengl2::RotateWidget::intersect().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ read_triangle_mesh() [1/4]

template<typename DerivedV , typename DerivedF >
IGL_INLINE bool igl::read_triangle_mesh ( const std::string &  ext,
FILE *  fp,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F 
)
97{
98 using namespace std;
99 using namespace Eigen;
100 vector<vector<double > > vV,vN,vTC,vC;
101 vector<vector<int > > vF,vFTC,vFN;
102 if(ext == "mesh")
103 {
104 // Convert extension to lower case
105 MatrixXi T;
106 if(!readMESH(fp,V,T,F))
107 {
108 return 1;
109 }
110 //if(F.size() > T.size() || F.size() == 0)
111 {
112 boundary_facets(T,F);
113 }
114 }else if(ext == "obj")
115 {
116 if(!readOBJ(fp,vV,vTC,vN,vF,vFTC,vFN))
117 {
118 return false;
119 }
120 // Annoyingly obj can store 4 coordinates, truncate to xyz for this generic
121 // read_triangle_mesh
122 for(auto & v : vV)
123 {
124 v.resize(std::min(v.size(),(size_t)3));
125 }
126 }else if(ext == "off")
127 {
128 if(!readOFF(fp,vV,vF,vN,vC))
129 {
130 return false;
131 }
132 }else if(ext == "ply")
133 {
134 if(!readPLY(fp,vV,vF,vN,vTC))
135 {
136 return false;
137 }
138 }else if(ext == "stl")
139 {
140 if(!readSTL(fp,vV,vF,vN))
141 {
142 return false;
143 }
144 }else if(ext == "wrl")
145 {
146 if(!readWRL(fp,vV,vF))
147 {
148 return false;
149 }
150 }else
151 {
152 cerr<<"Error: unknown extension: "<<ext<<endl;
153 return false;
154 }
155 if(vV.size() > 0)
156 {
157 if(!list_to_matrix(vV,V))
158 {
159 return false;
160 }
162 }
163 return true;
164}
IGL_INLINE bool readOFF(const std::string off_file_name, std::vector< std::vector< Scalar > > &V, std::vector< std::vector< Index > > &F, std::vector< std::vector< Scalar > > &N, std::vector< std::vector< Scalar > > &C)
Definition readOFF.cpp:12
IGL_INLINE bool readMESH(const std::string mesh_file_name, std::vector< std::vector< Scalar > > &V, std::vector< std::vector< Index > > &T, std::vector< std::vector< Index > > &F)
Definition readMESH.cpp:11
IGL_INLINE bool readSTL(const std::string &filename, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedN > &N)
Definition readSTL.cpp:13
IGL_INLINE bool readPLY(const std::string filename, std::vector< std::vector< Vtype > > &V, std::vector< std::vector< Ftype > > &F, std::vector< std::vector< Ntype > > &N, std::vector< std::vector< UVtype > > &UV)
Definition readPLY.cpp:18
IGL_INLINE bool readWRL(const std::string wrl_file_name, std::vector< std::vector< Scalar > > &V, std::vector< std::vector< Index > > &F)
Definition readWRL.cpp:12
IGL_INLINE bool readOBJ(const std::string obj_file_name, std::vector< std::vector< Scalar > > &V, std::vector< std::vector< Scalar > > &TC, std::vector< std::vector< Scalar > > &N, std::vector< std::vector< Index > > &F, std::vector< std::vector< Index > > &FTC, std::vector< std::vector< Index > > &FN)
Definition readOBJ.cpp:21

References boundary_facets(), list_to_matrix(), polygon_mesh_to_triangle_mesh(), readMESH(), readOBJ(), readOFF(), readPLY(), readSTL(), and readWRL().

+ Here is the call graph for this function:

◆ read_triangle_mesh() [2/4]

template<typename DerivedV , typename DerivedF >
IGL_INLINE bool igl::read_triangle_mesh ( const std::string  str,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F 
)
65{
66 std::string _1,_2,_3,_4;
67 return read_triangle_mesh(str,V,F,_1,_2,_3,_4);
68}

◆ read_triangle_mesh() [3/4]

template<typename DerivedV , typename DerivedF >
IGL_INLINE bool igl::read_triangle_mesh ( const std::string  str,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F,
std::string &  dir,
std::string &  base,
std::string &  ext,
std::string &  name 
)
79{
80 using namespace std;
81 using namespace Eigen;
82
83 // dirname, basename, extension and filename
84 pathinfo(filename,dir,base,ext,name);
85 // Convert extension to lower case
86 transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
87 FILE * fp = fopen(filename.c_str(),"rb");
88 return read_triangle_mesh(ext,fp,V,F);
89}
IGL_INLINE void pathinfo(const std::string &path, std::string &dirname, std::string &basename, std::string &extension, std::string &filename)
Definition pathinfo.cpp:16

References pathinfo().

+ Here is the call graph for this function:

◆ read_triangle_mesh() [4/4]

template<typename Scalar , typename Index >
IGL_INLINE bool igl::read_triangle_mesh ( const std::string  str,
std::vector< std::vector< Scalar > > &  V,
std::vector< std::vector< Index > > &  F 
)
30{
31 using namespace std;
32 // dirname, basename, extension and filename
33 string d,b,e,f;
34 pathinfo(str,d,b,e,f);
35 // Convert extension to lower case
36 std::transform(e.begin(), e.end(), e.begin(), ::tolower);
37 vector<vector<Scalar> > TC, N, C;
38 vector<vector<Index> > FTC, FN;
39 if(e == "obj")
40 {
41 // Annoyingly obj can store 4 coordinates, truncate to xyz for this generic
42 // read_triangle_mesh
43 bool success = readOBJ(str,V,TC,N,F,FTC,FN);
44 for(auto & v : V)
45 {
46 v.resize(std::min(v.size(),(size_t)3));
47 }
48 return success;
49 }else if(e == "off")
50 {
51 return readOFF(str,V,F,N,C);
52 }
53 cerr<<"Error: "<<__FUNCTION__<<": "<<
54 str<<" is not a recognized mesh file format."<<endl;
55 return false;
56}

References pathinfo(), readOBJ(), and readOFF().

Referenced by igl::copyleft::cgal::read_triangle_mesh().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ readBF() [1/2]

template<typename DerivedWI , typename DerivedbfP , typename DerivedO , typename DerivedC , typename DerivedBE , typename DerivedP >
IGL_INLINE bool igl::readBF ( const std::string &  filename,
Eigen::PlainObjectBase< DerivedWI > &  WI,
Eigen::PlainObjectBase< DerivedbfP > &  bfP,
Eigen::PlainObjectBase< DerivedO > &  O,
Eigen::PlainObjectBase< DerivedC > &  C,
Eigen::PlainObjectBase< DerivedBE > &  BE,
Eigen::PlainObjectBase< DerivedP > &  P 
)
68{
69 using namespace Eigen;
70 using namespace std;
71 if(!readBF(filename,WI,bfP,offsets))
72 {
73 return false;
74 }
75
76 C.resize(WI.rows(),3);
77 vector<bool> computed(C.rows(),false);
78 // better not be cycles in bfP
79 std::function<Eigen::RowVector3d(const int)> locate_tip;
80 locate_tip =
81 [&offsets,&computed,&bfP,&locate_tip,&C](const int w)->Eigen::RowVector3d
82 {
83 if(w<0) return Eigen::RowVector3d(0,0,0);
84 if(computed[w]) return C.row(w);
85 computed[w] = true;
86 return C.row(w) = locate_tip(bfP(w)) + offsets.row(w);
87 };
88 int num_roots = (bfP.array() == -1).count();
89 BE.resize(WI.rows()-num_roots,2);
90 P.resize(BE.rows());
91 for(int c = 0;c<C.rows();c++)
92 {
93 locate_tip(c);
94 assert(c>=0);
95 // weight associated with this bone
96 const int wi = WI(c);
97 if(wi >= 0)
98 {
99 // index into C
100 const int p = bfP(c);
101 assert(p >= 0 && "No weights for roots allowed");
102 // index into BE
103 const int pwi = WI(p);
104 P(wi) = pwi;
105 BE(wi,0) = p;
106 BE(wi,1) = c;
107 }
108 }
109 return true;
110}
IGL_INLINE bool readBF(const std::string &filename, Eigen::PlainObjectBase< DerivedWI > &WI, Eigen::PlainObjectBase< DerivedP > &P, Eigen::PlainObjectBase< DerivedO > &O)
Definition readBF.cpp:19

References count(), readBF(), Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ readBF() [2/2]

template<typename DerivedWI , typename DerivedP , typename DerivedO >
IGL_INLINE bool igl::readBF ( const std::string &  filename,
Eigen::PlainObjectBase< DerivedWI > &  WI,
Eigen::PlainObjectBase< DerivedP > &  P,
Eigen::PlainObjectBase< DerivedO > &  O 
)
24{
25 using namespace std;
26 ifstream is(filename);
27 if(!is.is_open())
28 {
29 return false;
30 }
31 string line;
32 std::vector<typename DerivedWI::Scalar> vWI;
33 std::vector<typename DerivedP::Scalar> vP;
34 std::vector<std::vector<typename DerivedO::Scalar> > vO;
35 while(getline(is, line))
36 {
37 int wi,p;
38 double cx,cy,cz;
39 if(sscanf(line.c_str(), "%d %d %lg %lg %lg",&wi,&p,&cx,&cy,&cz) != 5)
40 {
41 return false;
42 }
43 vWI.push_back(wi);
44 vP.push_back(p);
45 vO.push_back({cx,cy,cz});
46 }
47 list_to_matrix(vWI,WI);
48 list_to_matrix(vP,P);
49 list_to_matrix(vO,O);
50 return true;
51}

References list_to_matrix().

Referenced by readBF().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ readCSV()

template<typename Scalar >
IGL_INLINE bool igl::readCSV ( const std::string  str,
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > &  M 
)
21{
22 using namespace std;
23
24 std::vector<std::vector<Scalar> > Mt;
25
26 std::ifstream infile(str.c_str());
27 std::string line;
28 while (std::getline(infile, line))
29 {
30 std::istringstream iss(line);
31 vector<Scalar> temp;
32 Scalar a;
33 while (iss >> a)
34 temp.push_back(a);
35
36 if (temp.size() != 0) // skip empty lines
37 Mt.push_back(temp);
38 }
39
40 if (Mt.size() != 0)
41 {
42 // Verify that it is indeed a matrix
43 for (unsigned i = 0; i<Mt.size(); ++i)
44 {
45 if (Mt[i].size() != Mt[0].size())
46 {
47 infile.close();
48 return false;
49 }
50 }
51
52 M.resize(Mt.size(),Mt[0].size());
53 for (unsigned i = 0; i<Mt.size(); ++i)
54 for (unsigned j = 0; j<Mt[i].size(); ++j)
55 M(i,j) = Mt[i][j];
56
57// cerr << "TRUE!" << endl;
58 return true;
59 }
60
61 infile.close();
62 return false;
63}
const char * infile
Definition config.c:55

References infile, and Eigen::PlainObjectBase< Derived >::resize().

+ Here is the call graph for this function:

◆ readDMAT() [1/2]

template<typename DerivedW >
IGL_INLINE bool igl::readDMAT ( const std::string  file_name,
Eigen::PlainObjectBase< DerivedW > &  W 
)
62{
63 FILE * fp = fopen(file_name.c_str(),"rb");
64 if(fp == NULL)
65 {
66 fprintf(stderr,"IOError: readDMAT() could not open %s...\n",file_name.c_str());
67 return false;
68 }
69 int num_rows,num_cols;
70 int head_success = readDMAT_read_header(fp,num_rows,num_cols);
71 if(head_success != 0)
72 {
73 if(head_success == 1)
74 {
75 fprintf(stderr,
76 "IOError: readDMAT() first row should be [num cols] [num rows]...\n");
77 }
78 fclose(fp);
79 return false;
80 }
81
82 // Resize output to fit matrix, only if non-empty since this will trigger an
83 // error on fixed size matrices before reaching binary data.
84 bool empty = num_rows == 0 || num_cols == 0;
85 if(!empty)
86 {
87 W.resize(num_rows,num_cols);
88 }
89
90 // Loop over columns slowly
91 for(int j = 0;j < num_cols;j++)
92 {
93 // loop over rows (down columns) quickly
94 for(int i = 0;i < num_rows;i++)
95 {
96 double d;
97 if(fscanf(fp," %lg",&d) != 1)
98 {
99 fclose(fp);
100 fprintf(
101 stderr,
102 "IOError: readDMAT() bad format after reading %d entries\n",
103 j*num_rows + i);
104 return false;
105 }
106 W(i,j) = d;
107 }
108 }
109
110 // Try to read header for binary part
111 head_success = readDMAT_read_header(fp,num_rows,num_cols);
112 if(head_success == 0)
113 {
114 assert(W.size() == 0);
115 // Resize for output
116 W.resize(num_rows,num_cols);
117 double * Wraw = new double[num_rows*num_cols];
118 fread(Wraw, sizeof(double), num_cols*num_rows, fp);
119 // Loop over columns slowly
120 for(int j = 0;j < num_cols;j++)
121 {
122 // loop over rows (down columns) quickly
123 for(int i = 0;i < num_rows;i++)
124 {
125 W(i,j) = Wraw[j*num_rows+i];
126 }
127 }
128 }else
129 {
130 // we skipped resizing before in case there was binary data
131 if(empty)
132 {
133 // This could trigger an error if using fixed size matrices.
134 W.resize(num_rows,num_cols);
135 }
136 }
137
138 fclose(fp);
139 return true;
140}
bool empty(const BoundingBoxBase< PointType, PointsType > &bb)
Definition BoundingBox.hpp:229
static int readDMAT_read_header(FILE *fp, int &num_rows, int &num_cols)
Definition readDMAT.cpp:27

References readDMAT_read_header(), and Eigen::PlainObjectBase< Derived >::resize().

+ Here is the call graph for this function:

◆ readDMAT() [2/2]

template<typename Scalar >
IGL_INLINE bool igl::readDMAT ( const std::string  file_name,
std::vector< std::vector< Scalar > > &  W 
)
147{
148 FILE * fp = fopen(file_name.c_str(),"r");
149 if(fp == NULL)
150 {
151 fprintf(stderr,"IOError: readDMAT() could not open %s...\n",file_name.c_str());
152 return false;
153 }
154 int num_rows,num_cols;
155 bool head_success = readDMAT_read_header(fp,num_rows,num_cols);
156 if(head_success != 0)
157 {
158 if(head_success == 1)
159 {
160 fprintf(stderr,
161 "IOError: readDMAT() first row should be [num cols] [num rows]...\n");
162 }
163 fclose(fp);
164 return false;
165 }
166
167 // Resize for output
168 W.resize(num_rows,typename std::vector<Scalar>(num_cols));
169
170 // Loop over columns slowly
171 for(int j = 0;j < num_cols;j++)
172 {
173 // loop over rows (down columns) quickly
174 for(int i = 0;i < num_rows;i++)
175 {
176 double d;
177 if(fscanf(fp," %lg",&d) != 1)
178 {
179 fclose(fp);
180 fprintf(
181 stderr,
182 "IOError: readDMAT() bad format after reading %d entries\n",
183 j*num_rows + i);
184 return false;
185 }
186 W[i][j] = (Scalar)d;
187 }
188 }
189
190 // Try to read header for binary part
191 head_success = readDMAT_read_header(fp,num_rows,num_cols);
192 if(head_success == 0)
193 {
194 assert(W.size() == 0);
195 // Resize for output
196 W.resize(num_rows,typename std::vector<Scalar>(num_cols));
197 double * Wraw = new double[num_rows*num_cols];
198 fread(Wraw, sizeof(double), num_cols*num_rows, fp);
199 // Loop over columns slowly
200 for(int j = 0;j < num_cols;j++)
201 {
202 // loop over rows (down columns) quickly
203 for(int i = 0;i < num_rows;i++)
204 {
205 W[i][j] = Wraw[j*num_rows+i];
206 }
207 }
208 }
209
210 fclose(fp);
211 return true;
212}

References readDMAT_read_header().

+ Here is the call graph for this function:

◆ readMESH() [1/4]

template<typename DerivedV , typename DerivedF , typename DerivedT >
IGL_INLINE bool igl::readMESH ( const std::string  mesh_file_name,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedT > &  T,
Eigen::PlainObjectBase< DerivedF > &  F 
)
246{
247 using namespace std;
248 FILE * mesh_file = fopen(mesh_file_name.c_str(),"r");
249 if(NULL==mesh_file)
250 {
251 fprintf(stderr,"IOError: %s could not be opened...",mesh_file_name.c_str());
252 return false;
253 }
254 return readMESH(mesh_file,V,T,F);
255}

References readMESH().

+ Here is the call graph for this function:

◆ readMESH() [2/4]

template<typename Scalar , typename Index >
IGL_INLINE bool igl::readMESH ( const std::string  mesh_file_name,
std::vector< std::vector< Scalar > > &  V,
std::vector< std::vector< Index > > &  T,
std::vector< std::vector< Index > > &  F 
)
16{
17 using namespace std;
18 FILE * mesh_file = fopen(mesh_file_name.c_str(),"r");
19 if(NULL==mesh_file)
20 {
21 fprintf(stderr,"IOError: %s could not be opened...",mesh_file_name.c_str());
22 return false;
23 }
24 return igl::readMESH(mesh_file,V,T,F);
25}

References readMESH().

Referenced by read_triangle_mesh(), readMESH(), and readMESH().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ readMESH() [3/4]

template<typename DerivedV , typename DerivedF , typename DerivedT >
IGL_INLINE bool igl::readMESH ( FILE *  mesh_file,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedT > &  T,
Eigen::PlainObjectBase< DerivedF > &  F 
)
263{
264 using namespace std;
265#ifndef LINE_MAX
266# define LINE_MAX 2048
267#endif
268 char line[LINE_MAX];
269 bool still_comments;
270
271 // eat comments at beginning of file
272 still_comments= true;
273 while(still_comments)
274 {
275 fgets(line,LINE_MAX,mesh_file);
276 still_comments = (line[0] == '#' || line[0] == '\n');
277 }
278
279 char str[LINE_MAX];
280 sscanf(line," %s",str);
281 // check that first word is MeshVersionFormatted
282 if(0!=strcmp(str,"MeshVersionFormatted"))
283 {
284 fprintf(stderr,
285 "Error: first word should be MeshVersionFormatted not %s\n",str);
286 fclose(mesh_file);
287 return false;
288 }
289 int one = -1;
290 if(2 != sscanf(line,"%s %d",str,&one))
291 {
292 // 1 appears on next line?
293 fscanf(mesh_file," %d",&one);
294 }
295 if(one != 1)
296 {
297 fprintf(stderr,"Error: second word should be 1 not %d\n",one);
298 fclose(mesh_file);
299 return false;
300 }
301
302 // eat comments
303 still_comments= true;
304 while(still_comments)
305 {
306 fgets(line,LINE_MAX,mesh_file);
307 still_comments = (line[0] == '#' || line[0] == '\n');
308 }
309
310 sscanf(line," %s",str);
311 // check that third word is Dimension
312 if(0!=strcmp(str,"Dimension"))
313 {
314 fprintf(stderr,"Error: third word should be Dimension not %s\n",str);
315 fclose(mesh_file);
316 return false;
317 }
318 int three = -1;
319 if(2 != sscanf(line,"%s %d",str,&three))
320 {
321 // 1 appears on next line?
322 fscanf(mesh_file," %d",&three);
323 }
324 if(three != 3)
325 {
326 fprintf(stderr,"Error: only Dimension 3 supported not %d\n",three);
327 fclose(mesh_file);
328 return false;
329 }
330
331 // eat comments
332 still_comments= true;
333 while(still_comments)
334 {
335 fgets(line,LINE_MAX,mesh_file);
336 still_comments = (line[0] == '#' || line[0] == '\n');
337 }
338
339 sscanf(line," %s",str);
340 // check that fifth word is Vertices
341 if(0!=strcmp(str,"Vertices"))
342 {
343 fprintf(stderr,"Error: fifth word should be Vertices not %s\n",str);
344 fclose(mesh_file);
345 return false;
346 }
347
348 //fgets(line,LINE_MAX,mesh_file);
349
350 int number_of_vertices;
351 if(1 != fscanf(mesh_file," %d",&number_of_vertices) || number_of_vertices > 1000000000)
352 {
353 fprintf(stderr,"Error: expecting number of vertices less than 10^9...\n");
354 fclose(mesh_file);
355 return false;
356 }
357 // allocate space for vertices
358 V.resize(number_of_vertices,3);
359 int extra;
360 for(int i = 0;i<number_of_vertices;i++)
361 {
362 double x,y,z;
363 if(4 != fscanf(mesh_file," %lg %lg %lg %d",&x,&y,&z,&extra))
364 {
365 fprintf(stderr,"Error: expecting vertex position...\n");
366 fclose(mesh_file);
367 return false;
368 }
369 V(i,0) = x;
370 V(i,1) = y;
371 V(i,2) = z;
372 }
373
374 // eat comments
375 still_comments= true;
376 while(still_comments)
377 {
378 fgets(line,LINE_MAX,mesh_file);
379 still_comments = (line[0] == '#' || line[0] == '\n');
380 }
381
382 sscanf(line," %s",str);
383 // check that sixth word is Triangles
384 if(0!=strcmp(str,"Triangles"))
385 {
386 fprintf(stderr,"Error: sixth word should be Triangles not %s\n",str);
387 fclose(mesh_file);
388 return false;
389 }
390 int number_of_triangles;
391 if(1 != fscanf(mesh_file," %d",&number_of_triangles))
392 {
393 fprintf(stderr,"Error: expecting number of triangles...\n");
394 fclose(mesh_file);
395 return false;
396 }
397 // allocate space for triangles
398 F.resize(number_of_triangles,3);
399 // triangle indices
400 int tri[3];
401 for(int i = 0;i<number_of_triangles;i++)
402 {
403 if(4 != fscanf(mesh_file," %d %d %d %d",&tri[0],&tri[1],&tri[2],&extra))
404 {
405 printf("Error: expecting triangle indices...\n");
406 return false;
407 }
408 for(int j = 0;j<3;j++)
409 {
410 F(i,j) = tri[j]-1;
411 }
412 }
413
414 // eat comments
415 still_comments= true;
416 while(still_comments)
417 {
418 fgets(line,LINE_MAX,mesh_file);
419 still_comments = (line[0] == '#' || line[0] == '\n');
420 }
421
422 sscanf(line," %s",str);
423 // check that sixth word is Triangles
424 if(0!=strcmp(str,"Tetrahedra"))
425 {
426 fprintf(stderr,"Error: seventh word should be Tetrahedra not %s\n",str);
427 fclose(mesh_file);
428 return false;
429 }
430 int number_of_tetrahedra;
431 if(1 != fscanf(mesh_file," %d",&number_of_tetrahedra))
432 {
433 fprintf(stderr,"Error: expecting number of tetrahedra...\n");
434 fclose(mesh_file);
435 return false;
436 }
437 // allocate space for tetrahedra
438 T.resize(number_of_tetrahedra,4);
439 // tet indices
440 int a,b,c,d;
441 for(int i = 0;i<number_of_tetrahedra;i++)
442 {
443 if(5 != fscanf(mesh_file," %d %d %d %d %d",&a,&b,&c,&d,&extra))
444 {
445 fprintf(stderr,"Error: expecting tetrahedra indices...\n");
446 fclose(mesh_file);
447 return false;
448 }
449 T(i,0) = a-1;
450 T(i,1) = b-1;
451 T(i,2) = c-1;
452 T(i,3) = d-1;
453 }
454 fclose(mesh_file);
455 return true;
456}
#define LINE_MAX

References LINE_MAX, and Eigen::PlainObjectBase< Derived >::resize().

+ Here is the call graph for this function:

◆ readMESH() [4/4]

template<typename Scalar , typename Index >
IGL_INLINE bool igl::readMESH ( FILE *  mesh_file,
std::vector< std::vector< Scalar > > &  V,
std::vector< std::vector< Index > > &  T,
std::vector< std::vector< Index > > &  F 
)
33{
34 using namespace std;
35#ifndef LINE_MAX
36# define LINE_MAX 2048
37#endif
38 char line[LINE_MAX];
39 bool still_comments;
40 V.clear();
41 T.clear();
42 F.clear();
43
44 // eat comments at beginning of file
45 still_comments= true;
46 while(still_comments)
47 {
48 if(fgets(line,LINE_MAX,mesh_file) == NULL)
49 {
50 fprintf(stderr, "Error: couldn't find start of .mesh file");
51 fclose(mesh_file);
52 return false;
53 }
54 still_comments = (line[0] == '#' || line[0] == '\n');
55 }
56 char str[LINE_MAX];
57 sscanf(line," %s",str);
58 // check that first word is MeshVersionFormatted
59 if(0!=strcmp(str,"MeshVersionFormatted"))
60 {
61 fprintf(stderr,
62 "Error: first word should be MeshVersionFormatted not %s\n",str);
63 fclose(mesh_file);
64 return false;
65 }
66
67 int one = -1;
68 if(2 != sscanf(line,"%s %d",str,&one))
69 {
70 // 1 appears on next line?
71 fscanf(mesh_file," %d",&one);
72 }
73 if(one != 1)
74 {
75 fprintf(stderr,"Error: second word should be 1 not %d\n",one);
76 fclose(mesh_file);
77 return false;
78 }
79
80 // eat comments
81 still_comments= true;
82 while(still_comments)
83 {
84 fgets(line,LINE_MAX,mesh_file);
85 still_comments = (line[0] == '#' || line[0] == '\n');
86 }
87
88 sscanf(line," %s",str);
89 // check that third word is Dimension
90 if(0!=strcmp(str,"Dimension"))
91 {
92 fprintf(stderr,"Error: third word should be Dimension not %s\n",str);
93 fclose(mesh_file);
94 return false;
95 }
96 int three = -1;
97 if(2 != sscanf(line,"%s %d",str,&three))
98 {
99 // 1 appears on next line?
100 fscanf(mesh_file," %d",&three);
101 }
102 if(three != 3)
103 {
104 fprintf(stderr,"Error: only Dimension 3 supported not %d\n",three);
105 fclose(mesh_file);
106 return false;
107 }
108
109 // eat comments
110 still_comments= true;
111 while(still_comments)
112 {
113 fgets(line,LINE_MAX,mesh_file);
114 still_comments = (line[0] == '#' || line[0] == '\n');
115 }
116
117 sscanf(line," %s",str);
118 // check that fifth word is Vertices
119 if(0!=strcmp(str,"Vertices"))
120 {
121 fprintf(stderr,"Error: fifth word should be Vertices not %s\n",str);
122 fclose(mesh_file);
123 return false;
124 }
125
126 //fgets(line,LINE_MAX,mesh_file);
127
128 int number_of_vertices;
129 if(1 != fscanf(mesh_file," %d",&number_of_vertices) || number_of_vertices > 1000000000)
130 {
131 fprintf(stderr,"Error: expecting number of vertices less than 10^9...\n");
132 fclose(mesh_file);
133 return false;
134 }
135 // allocate space for vertices
136 V.resize(number_of_vertices,vector<Scalar>(3,0));
137 int extra;
138 for(int i = 0;i<number_of_vertices;i++)
139 {
140 double x,y,z;
141 if(4 != fscanf(mesh_file," %lg %lg %lg %d",&x,&y,&z,&extra))
142 {
143 fprintf(stderr,"Error: expecting vertex position...\n");
144 fclose(mesh_file);
145 return false;
146 }
147 V[i][0] = x;
148 V[i][1] = y;
149 V[i][2] = z;
150 }
151
152 // eat comments
153 still_comments= true;
154 while(still_comments)
155 {
156 fgets(line,LINE_MAX,mesh_file);
157 still_comments = (line[0] == '#' || line[0] == '\n');
158 }
159
160 sscanf(line," %s",str);
161 // check that sixth word is Triangles
162 if(0!=strcmp(str,"Triangles"))
163 {
164 fprintf(stderr,"Error: sixth word should be Triangles not %s\n",str);
165 fclose(mesh_file);
166 return false;
167 }
168 int number_of_triangles;
169 if(1 != fscanf(mesh_file," %d",&number_of_triangles))
170 {
171 fprintf(stderr,"Error: expecting number of triangles...\n");
172 fclose(mesh_file);
173 return false;
174 }
175 // allocate space for triangles
176 F.resize(number_of_triangles,vector<Index>(3));
177 // triangle indices
178 int tri[3];
179 for(int i = 0;i<number_of_triangles;i++)
180 {
181 if(4 != fscanf(mesh_file," %d %d %d %d",&tri[0],&tri[1],&tri[2],&extra))
182 {
183 printf("Error: expecting triangle indices...\n");
184 return false;
185 }
186 for(int j = 0;j<3;j++)
187 {
188 F[i][j] = tri[j]-1;
189 }
190 }
191
192 // eat comments
193 still_comments= true;
194 while(still_comments)
195 {
196 fgets(line,LINE_MAX,mesh_file);
197 still_comments = (line[0] == '#' || line[0] == '\n');
198 }
199
200 sscanf(line," %s",str);
201 // check that sixth word is Triangles
202 if(0!=strcmp(str,"Tetrahedra"))
203 {
204 fprintf(stderr,"Error: seventh word should be Tetrahedra not %s\n",str);
205 fclose(mesh_file);
206 return false;
207 }
208 int number_of_tetrahedra;
209 if(1 != fscanf(mesh_file," %d",&number_of_tetrahedra))
210 {
211 fprintf(stderr,"Error: expecting number of tetrahedra...\n");
212 fclose(mesh_file);
213 return false;
214 }
215 // allocate space for tetrahedra
216 T.resize(number_of_tetrahedra,vector<Index>(4));
217 // tet indices
218 int a,b,c,d;
219 for(int i = 0;i<number_of_tetrahedra;i++)
220 {
221 if(5 != fscanf(mesh_file," %d %d %d %d %d",&a,&b,&c,&d,&extra))
222 {
223 fprintf(stderr,"Error: expecting tetrahedra indices...\n");
224 fclose(mesh_file);
225 return false;
226 }
227 T[i][0] = a-1;
228 T[i][1] = b-1;
229 T[i][2] = c-1;
230 T[i][3] = d-1;
231 }
232 fclose(mesh_file);
233 return true;
234}

References LINE_MAX.

◆ readMSH()

template<typename DerivedV , typename DerivedT >
IGL_INLINE bool igl::readMSH ( const std::string &  filename,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedT > &  T 
)
24{
25 // https://github.com/Yixin-Hu/TetWild/blob/master/pymesh/MshSaver.cpp
26 // Original copyright: /* This file is part of PyMesh. Copyright (c) 2015 by Qingnan Zhou */
27 typedef typename DerivedV::Scalar Float;
30 typedef std::map<std::string, VectorF> FieldMap;
31 typedef std::vector<std::string> FieldNames;
32 VectorF m_nodes;
33 VectorI m_elements;
34 FieldMap m_node_fields;
35 FieldMap m_element_fields;
36
37 bool m_binary;
38 size_t m_data_size;
39 size_t m_nodes_per_element;
40 size_t m_element_type;
41 std::ifstream fin(filename.c_str(), std::ios::in | std::ios::binary);
42 if (!fin.is_open())
43 {
44 std::stringstream err_msg;
45 err_msg << "failed to open file \"" << filename << "\"";
46 return false;
47 }
48 // Parse header
49 std::string buf;
50 double version;
51 int type;
52 fin >> buf;
53 const auto invalid_format = []()->bool
54 {
55 assert(false && "Invalid format");
56 return false;
57 };
58 const auto not_implemented = []()->bool
59 {
60 assert(false && "Not implemented");
61 return false;
62 };
63 if (buf != "$MeshFormat") { return invalid_format(); }
64
65 fin >> version >> type >> m_data_size;
66 m_binary = (type == 1);
67
68 // Some sanity check.
69 if (m_data_size != 8) {
70 std::cerr << "Error: data size must be 8 bytes." << std::endl;
71 return not_implemented();
72 }
73 if (sizeof(int) != 4) {
74 std::cerr << "Error: code must be compiled with int size 4 bytes." << std::endl;
75 return not_implemented();
76 }
77 const auto eat_white_space = [](std::ifstream& fin)
78 {
79 char next = fin.peek();
80 while (next == '\n' || next == ' ' || next == '\t' || next == '\r')
81 {
82 fin.get();
83 next = fin.peek();
84 }
85 };
86
87 // Read in extra info from binary header.
88 if (m_binary) {
89 int one;
90 eat_white_space(fin);
91 fin.read(reinterpret_cast<char*>(&one), sizeof(int));
92 if (one != 1) {
93 std::cerr << "Warning: binary msh file " << filename
94 << " is saved with different endianness than this machine."
95 << std::endl;
96 return not_implemented();
97 }
98 }
99
100 fin >> buf;
101 if (buf != "$EndMeshFormat") { return not_implemented(); }
102
103 const auto num_nodes_per_elem_type = [](int elem_type)->int
104 {
105 size_t nodes_per_element = 0;
106 switch (elem_type) {
107 case 2:
108 nodes_per_element = 3; // Triangle
109 break;
110 case 3:
111 nodes_per_element = 4; // Quad
112 break;
113 case 4:
114 nodes_per_element = 4; // Tet
115 break;
116 case 5:
117 nodes_per_element = 8; // hexahedron
118 break;
119 default:
120 assert(false && "not implemented");
121 nodes_per_element = -1;
122 break;
123 }
124 return nodes_per_element;
125 };
126
127 const auto parse_nodes = [&](std::ifstream& fin)
128 {
129 size_t num_nodes;
130 fin >> num_nodes;
131 m_nodes.resize(num_nodes*3);
132
133 if (m_binary) {
134 size_t num_bytes = (4+3*m_data_size) * num_nodes;
135 char* data = new char[num_bytes];
136 eat_white_space(fin);
137 fin.read(data, num_bytes);
138
139 for (size_t i=0; i<num_nodes; i++) {
140 int node_idx = *reinterpret_cast<int*> (&data[i*(4+3*m_data_size)]) - 1;
141 m_nodes[node_idx*3] = *reinterpret_cast<Float*>(&data[i*(4+3*m_data_size) + 4]);
142 m_nodes[node_idx*3+1] = *reinterpret_cast<Float*>(&data[i*(4+3*m_data_size) + 4 + m_data_size]);
143 m_nodes[node_idx*3+2] = *reinterpret_cast<Float*>(&data[i*(4+3*m_data_size) + 4 + 2*m_data_size]);
144 }
145
146 delete [] data;
147 } else {
148 int node_idx;
149 for (size_t i=0; i<num_nodes; i++) {
150 fin >> node_idx;
151 node_idx -= 1;
152 fin >> m_nodes[node_idx*3]
153 >> m_nodes[node_idx*3+1]
154 >> m_nodes[node_idx*3+2];
155 }
156 }
157 };
158
159 const auto parse_elements = [&](std::ifstream& fin)
160 {
161 size_t num_elements;
162 fin >> num_elements;
163
164 // Tmp storage of elements;
165 std::vector<int> triangle_element_idx;
166 std::vector<int> triangle_elements;
167 std::vector<int> quad_element_idx;
168 std::vector<int> quad_elements;
169 std::vector<int> tet_element_idx;
170 std::vector<int> tet_elements;
171 std::vector<int> hex_element_idx;
172 std::vector<int> hex_elements;
173
174 auto get_element_storage = [&](int elem_type) -> std::vector<int>* {
175 switch (elem_type) {
176 default:
177 assert(false && "Unsupported element type encountered");
178 case 2:
179 return &triangle_elements;
180 case 3:
181 return &quad_elements;
182 case 4:
183 return &tet_elements;
184 case 5:
185 return &hex_elements;
186 };
187 };
188
189 auto get_element_idx_storage = [&](int elem_type) -> std::vector<int>* {
190 switch (elem_type) {
191 default:
192 assert(false && "Unsupported element type encountered");
193 case 2:
194 return &triangle_element_idx;
195 case 3:
196 return &quad_element_idx;
197 case 4:
198 return &tet_element_idx;
199 case 5:
200 return &hex_element_idx;
201 };
202 };
203
204 size_t nodes_per_element;
205 int glob_elem_type = -1;
206
207
208 if (m_binary)
209 {
210 eat_white_space(fin);
211 int elem_read = 0;
212 while (elem_read < num_elements) {
213 // Parse element header.
214 int elem_type, num_elems, num_tags;
215 fin.read((char*)&elem_type, sizeof(int));
216 fin.read((char*)&num_elems, sizeof(int));
217 fin.read((char*)&num_tags, sizeof(int));
218 nodes_per_element = num_nodes_per_elem_type(elem_type);
219 std::vector<int>& elements = *get_element_storage(elem_type);
220 std::vector<int>& element_idx = *get_element_idx_storage(elem_type);
221
222 for (size_t i=0; i<num_elems; i++) {
223 int elem_idx;
224 fin.read((char*)&elem_idx, sizeof(int));
225 elem_idx -= 1;
226 element_idx.push_back(elem_idx);
227
228 // Eat up tags.
229 for (size_t j=0; j<num_tags; j++) {
230 int tag;
231 fin.read((char*)&tag, sizeof(int));
232 }
233
234 // Element values.
235 for (size_t j=0; j<nodes_per_element; j++) {
236 int idx;
237 fin.read((char*)&idx, sizeof(int));
238 elements.push_back(idx-1);
239 }
240 }
241
242 elem_read += num_elems;
243 }
244 } else
245 {
246 for (size_t i=0; i<num_elements; i++) {
247 // Parse per element header
248 int elem_num, elem_type, num_tags;
249 fin >> elem_num >> elem_type >> num_tags;
250 for (size_t j=0; j<num_tags; j++) {
251 int tag;
252 fin >> tag;
253 }
254 nodes_per_element = num_nodes_per_elem_type(elem_type);
255 std::vector<int>& elements = *get_element_storage(elem_type);
256 std::vector<int>& element_idx = *get_element_idx_storage(elem_type);
257
258 elem_num -= 1;
259 element_idx.push_back(elem_num);
260
261 // Parse node idx.
262 for (size_t j=0; j<nodes_per_element; j++) {
263 int idx;
264 fin >> idx;
265 elements.push_back(idx-1); // msh index starts from 1.
266 }
267 }
268 }
269
270 auto copy_to_array = [&](
271 const std::vector<int>& elements,
272 const int nodes_per_element) {
273 const size_t num_elements = elements.size() / nodes_per_element;
274 if (elements.size() % nodes_per_element != 0) {
275 assert(false && "parsing element failed");
276 return;
277 }
278 m_elements.resize(elements.size());
279 std::copy(elements.begin(), elements.end(), m_elements.data());
280 m_nodes_per_element = nodes_per_element;
281 };
282
283 if (!tet_elements.empty()) {
284 copy_to_array(tet_elements, 4);
285 m_element_type = 4;
286 } else if (!hex_elements.empty()) {
287 copy_to_array(hex_elements, 8);
288 m_element_type = 5;
289 } else if (!triangle_elements.empty()) {
290 copy_to_array(triangle_elements, 3);
291 m_element_type = 2;
292 } else if (!quad_elements.empty()) {
293 copy_to_array(quad_elements, 4);
294 m_element_type = 3;
295 } else {
296 // 0 elements, use triangle by default.
297 m_element_type = 2;
298 }
299 };
300 const auto parse_element_field = [&](std::ifstream& fin)
301 {
302 size_t num_string_tags;
303 size_t num_real_tags;
304 size_t num_int_tags;
305
306 fin >> num_string_tags;
307 std::string* str_tags = new std::string[num_string_tags];
308 for (size_t i=0; i<num_string_tags; i++) {
309 eat_white_space(fin);
310 if (fin.peek() == '\"') {
311 // Handle field name between quoates.
312 char buf[128];
313 fin.get(); // remove the quote at the beginning.
314 fin.getline(buf, 128, '\"');
315 str_tags[i] = std::string(buf);
316 } else {
317 fin >> str_tags[i];
318 }
319 }
320
321 fin >> num_real_tags;
322 Float* real_tags = new Float[num_real_tags];
323 for (size_t i=0; i<num_real_tags; i++)
324 fin >> real_tags[i];
325
326 fin >> num_int_tags;
327 int* int_tags = new int[num_int_tags];
328 for (size_t i=0; i<num_int_tags; i++)
329 fin >> int_tags[i];
330
331 if (num_string_tags <= 0 || num_int_tags <= 2) { assert(false && "invalid format"); return; }
332 std::string fieldname = str_tags[0];
333 int num_components = int_tags[1];
334 int num_entries = int_tags[2];
335 VectorF field(num_entries * num_components);
336
337 delete [] str_tags;
338 delete [] real_tags;
339 delete [] int_tags;
340
341 if (m_binary) {
342 size_t num_bytes = (num_components * m_data_size + 4) * num_entries;
343 char* data = new char[num_bytes];
344 eat_white_space(fin);
345 fin.read(data, num_bytes);
346 for (size_t i=0; i<num_entries; i++) {
347 int elem_idx = *reinterpret_cast<int*>(&data[i*(4+num_components*m_data_size)]);
348 elem_idx -= 1;
349 size_t base_idx = i*(4+num_components*m_data_size) + 4;
350 for (size_t j=0; j<num_components; j++) {
351 field[elem_idx * num_components + j] = *reinterpret_cast<Float*>(&data[base_idx+j*m_data_size]);
352 }
353 }
354 delete [] data;
355 } else {
356 int elem_idx;
357 for (size_t i=0; i<num_entries; i++) {
358 fin >> elem_idx;
359 elem_idx -= 1;
360 for (size_t j=0; j<num_components; j++) {
361 fin >> field[elem_idx * num_components + j];
362 }
363 }
364 }
365
366 m_element_fields[fieldname] = field;
367 };
368
369 const auto parse_node_field = [&](std::ifstream& fin)
370 {
371 size_t num_string_tags;
372 size_t num_real_tags;
373 size_t num_int_tags;
374
375 fin >> num_string_tags;
376 std::string* str_tags = new std::string[num_string_tags];
377 for (size_t i=0; i<num_string_tags; i++) {
378 eat_white_space(fin);
379 if (fin.peek() == '\"') {
380 // Handle field name between quoates.
381 char buf[128];
382 fin.get(); // remove the quote at the beginning.
383 fin.getline(buf, 128, '\"');
384 str_tags[i] = std::string(buf);
385 } else {
386 fin >> str_tags[i];
387 }
388 }
389
390 fin >> num_real_tags;
391 Float* real_tags = new Float[num_real_tags];
392 for (size_t i=0; i<num_real_tags; i++)
393 fin >> real_tags[i];
394
395 fin >> num_int_tags;
396 int* int_tags = new int[num_int_tags];
397 for (size_t i=0; i<num_int_tags; i++)
398 fin >> int_tags[i];
399
400 if (num_string_tags <= 0 || num_int_tags <= 2) { assert(false && "invalid format"); return; }
401 std::string fieldname = str_tags[0];
402 int num_components = int_tags[1];
403 int num_entries = int_tags[2];
404 VectorF field(num_entries * num_components);
405
406 delete [] str_tags;
407 delete [] real_tags;
408 delete [] int_tags;
409
410 if (m_binary) {
411 size_t num_bytes = (num_components * m_data_size + 4) * num_entries;
412 char* data = new char[num_bytes];
413 eat_white_space(fin);
414 fin.read(data, num_bytes);
415 for (size_t i=0; i<num_entries; i++) {
416 int node_idx = *reinterpret_cast<int*>(&data[i*(4+num_components*m_data_size)]);
417 node_idx -= 1;
418 size_t base_idx = i*(4+num_components*m_data_size) + 4;
419 for (size_t j=0; j<num_components; j++) {
420 field[node_idx * num_components + j] = *reinterpret_cast<Float*>(&data[base_idx+j*m_data_size]);
421 }
422 }
423 delete [] data;
424 } else {
425 int node_idx;
426 for (size_t i=0; i<num_entries; i++) {
427 fin >> node_idx;
428 node_idx -= 1;
429 for (size_t j=0; j<num_components; j++) {
430 fin >> field[node_idx * num_components + j];
431 }
432 }
433 }
434
435 m_node_fields[fieldname] = field;
436 };
437 const auto parse_unknown_field = [](std::ifstream& fin,
438 const std::string& fieldname)
439 {
440 std::cerr << "Warning: \"" << fieldname << "\" not supported yet. Ignored." << std::endl;
441 std::string endmark = fieldname.substr(0,1) + "End"
442 + fieldname.substr(1,fieldname.size()-1);
443
444 std::string buf("");
445 while (buf != endmark && !fin.eof()) {
446 fin >> buf;
447 }
448 };
449
450
451 while (!fin.eof()) {
452 buf.clear();
453 fin >> buf;
454 if (buf == "$Nodes") {
455 parse_nodes(fin);
456 fin >> buf;
457 if (buf != "$EndNodes") { return invalid_format(); }
458 } else if (buf == "$Elements") {
459 parse_elements(fin);
460 fin >> buf;
461 if (buf != "$EndElements") { return invalid_format(); }
462 } else if (buf == "$NodeData") {
463 parse_node_field(fin);
464 fin >> buf;
465 if (buf != "$EndNodeData") { return invalid_format(); }
466 } else if (buf == "$ElementData") {
467 parse_element_field(fin);
468 fin >> buf;
469 if (buf != "$EndElementData") { return invalid_format(); }
470 } else if (fin.eof()) {
471 break;
472 } else {
473 parse_unknown_field(fin, buf);
474 }
475 }
476 fin.close();
477 V.resize(m_nodes.rows()/3,3);
478 for (int i = 0; i < m_nodes.rows() / 3; i++)
479 {
480 for (int j = 0; j < 3; j++)
481 {
482 V(i,j) = m_nodes(i * 3 + j);
483 }
484 }
485 int ss = num_nodes_per_elem_type(m_element_type);
486 T.resize(m_elements.rows()/ss,ss);
487 for (int i = 0; i < m_elements.rows() / ss; i++)
488 {
489 for (int j = 0; j < ss; j++)
490 {
491 T(i, j) = m_elements(i * ss + j);
492 }
493 }
494 return true;
495}
char * version
Definition main.c:59

References Eigen::PlainObjectBase< Derived >::resize(), and version.

+ Here is the call graph for this function:

◆ readNODE() [1/2]

template<typename DerivedV , typename DerivedI >
IGL_INLINE bool igl::readNODE ( const std::string  node_file_name,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedI > &  I 
)
37{
38 using namespace std;
39 FILE * node_file = fopen(node_file_name.c_str(),"r");
40 if(NULL==node_file)
41 {
42 fprintf(stderr,"readNODE: IOError: %s could not be opened...\n",
43 node_file_name.c_str());
44 return false;
45 }
46#ifndef LINE_MAX
47# define LINE_MAX 2048
48#endif
49 char line[LINE_MAX];
50 bool still_comments;
51
52 // eat comments at beginning of file
53 still_comments= true;
54 while(still_comments)
55 {
56 fgets(line,LINE_MAX,node_file);
57 still_comments = (line[0] == '#' || line[0] == '\n');
58 }
59
60 // Read header
61 // n number of points
62 // dim dimension
63 // num_attr number of attributes
64 // num_bm number of boundary markers
65 int n,dim,num_attr,num_bm;
66 int head_count = sscanf(line,"%d %d %d %d", &n, &dim, &num_attr, &num_bm);
67 if(head_count!=4)
68 {
69 fprintf(stderr,"readNODE: Error: incorrect header in %s...\n",
70 node_file_name.c_str());
71 fclose(node_file);
72 return false;
73 }
74 if(num_attr)
75 {
76 fprintf(stderr,"readNODE: Error: %d attributes found in %s. "
77 "Attributes are not supported...\n",
78 num_attr,
79 node_file_name.c_str());
80 fclose(node_file);
81 return false;
82 }
83 // Just quietly ignore boundary markers
84 //if(num_bm)
85 //{
86 // fprintf(stderr,"readNODE: Warning: %d boundary markers found in %s. "
87 // "Boundary markers are ignored...\n",
88 // num_bm,
89 // node_file_name.c_str());
90 //}
91
92 // resize output
93 V.resize(n,dim);
94 I.resize(n,1);
95
96 int line_no = 0;
97 int p = 0;
98 while (fgets(line, LINE_MAX, node_file) != NULL)
99 {
100 line_no++;
101 // Skip comments and blank lines
102 if(line[0] == '#' || line[0] == '\n')
103 {
104 continue;
105 }
106 char * l = line;
107 int offset;
108
109 if(sscanf(l,"%d%n",&I(p),&offset) != 1)
110 {
111 fprintf(stderr,"readNODE Error: bad index (%d) in %s...\n",
112 line_no,
113 node_file_name.c_str());
114 fclose(node_file);
115 return false;
116 }
117 // adjust offset
118 l += offset;
119
120 // Read coordinates
121 for(int d = 0;d<dim;d++)
122 {
123 if(sscanf(l,"%lf%n",&V(p,d),&offset) != 1)
124 {
125 fprintf(stderr,"readNODE Error: bad coordinates (%d) in %s...\n",
126 line_no,
127 node_file_name.c_str());
128 fclose(node_file);
129 return false;
130 }
131 // adjust offset
132 l += offset;
133 }
134 // Read boundary markers
135 for(int b = 0;b<num_bm;b++)
136 {
137 int dummy;
138 if(sscanf(l,"%d%n",&dummy,&offset) != 1)
139 {
140 fprintf(stderr,"readNODE Error: bad boundary markers (%d) in %s...\n",
141 line_no,
142 node_file_name.c_str());
143 fclose(node_file);
144 return false;
145 }
146 // adjust offset
147 l += offset;
148 }
149 p++;
150 }
151
152 assert(p == V.rows());
153
154 fclose(node_file);
155 return true;
156}
void offset(Slic3r::ExPolygon &sh, coord_t distance, const PolygonTag &)
Definition geometries.hpp:132

References LINE_MAX, Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ readNODE() [2/2]

template<typename Scalar , typename Index >
IGL_INLINE bool igl::readNODE ( const std::string  node_file_name,
std::vector< std::vector< Scalar > > &  V,
std::vector< std::vector< Index > > &  I 
)
17{
18 // TODO: should be templated
19 Eigen::MatrixXd mV;
20 Eigen::MatrixXi mI;
21 if(igl::readNODE(node_file_name,mV,mI))
22 {
23 matrix_to_list(mV,V);
24 matrix_to_list(mI,I);
25 return true;
26 }else
27 {
28 return false;
29 }
30}
IGL_INLINE bool readNODE(const std::string node_file_name, std::vector< std::vector< Scalar > > &V, std::vector< std::vector< Index > > &I)
Definition readNODE.cpp:13

References matrix_to_list(), and readNODE().

Referenced by readNODE().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ readOBJ() [1/5]

template<typename Scalar , typename Index >
IGL_INLINE bool igl::readOBJ ( const std::string  obj_file_name,
std::vector< std::vector< Scalar > > &  V,
std::vector< std::vector< Index > > &  F 
)
237{
238 std::vector<std::vector<Scalar > > TC,N;
239 std::vector<std::vector<Index > > FTC,FN;
240 return readOBJ(obj_file_name,V,TC,N,F,FTC,FN);
241}

References readOBJ().

+ Here is the call graph for this function:

◆ readOBJ() [2/5]

template<typename Scalar , typename Index >
IGL_INLINE bool igl::readOBJ ( const std::string  obj_file_name,
std::vector< std::vector< Scalar > > &  V,
std::vector< std::vector< Scalar > > &  TC,
std::vector< std::vector< Scalar > > &  N,
std::vector< std::vector< Index > > &  F,
std::vector< std::vector< Index > > &  FTC,
std::vector< std::vector< Index > > &  FN 
)
29{
30 // Open file, and check for error
31 FILE * obj_file = fopen(obj_file_name.c_str(),"r");
32 if(NULL==obj_file)
33 {
34 fprintf(stderr,"IOError: %s could not be opened...\n",
35 obj_file_name.c_str());
36 return false;
37 }
38 return igl::readOBJ(obj_file,V,TC,N,F,FTC,FN);
39}

References readOBJ().

Referenced by igl::opengl::glfw::Viewer::load_mesh_from_file(), igl::copyleft::tetgen::read_into_tetgenio(), read_triangle_mesh(), read_triangle_mesh(), readOBJ(), readOBJ(), readOBJ(), and readOBJ().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ readOBJ() [3/5]

template<typename DerivedV , typename DerivedF >
IGL_INLINE bool igl::readOBJ ( const std::string  str,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F 
)
329{
330 std::vector<std::vector<double> > vV,vTC,vN;
331 std::vector<std::vector<int> > vF,vFTC,vFN;
332 bool success = igl::readOBJ(str,vV,vTC,vN,vF,vFTC,vFN);
333 if(!success)
334 {
335 // readOBJ(str,vV,vTC,vN,vF,vFTC,vFN) should have already printed an error
336 // message to stderr
337 return false;
338 }
339 bool V_rect = igl::list_to_matrix(vV,V);
340 if(!V_rect)
341 {
342 // igl::list_to_matrix(vV,V) already printed error message to std err
343 return false;
344 }
345 bool F_rect = igl::list_to_matrix(vF,F);
346 if(!F_rect)
347 {
348 // igl::list_to_matrix(vF,F) already printed error message to std err
349 return false;
350 }
351 return true;
352}

References list_to_matrix(), and readOBJ().

+ Here is the call graph for this function:

◆ readOBJ() [4/5]

template<typename DerivedV , typename DerivedTC , typename DerivedCN , typename DerivedF , typename DerivedFTC , typename DerivedFN >
IGL_INLINE bool igl::readOBJ ( const std::string  str,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedTC > &  TC,
Eigen::PlainObjectBase< DerivedCN > &  CN,
Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedFTC > &  FTC,
Eigen::PlainObjectBase< DerivedFN > &  FN 
)
258{
259 std::vector<std::vector<double> > vV,vTC,vN;
260 std::vector<std::vector<int> > vF,vFTC,vFN;
261 bool success = igl::readOBJ(str,vV,vTC,vN,vF,vFTC,vFN);
262 if(!success)
263 {
264 // readOBJ(str,vV,vTC,vN,vF,vFTC,vFN) should have already printed an error
265 // message to stderr
266 return false;
267 }
268 bool V_rect = igl::list_to_matrix(vV,V);
269 const char * format = "Failed to cast %s to matrix: min (%d) != max (%d)\n";
270 if(!V_rect)
271 {
272 printf(format,"V",igl::min_size(vV),igl::max_size(vV));
273 return false;
274 }
275 bool F_rect = igl::list_to_matrix(vF,F);
276 if(!F_rect)
277 {
278 printf(format,"F",igl::min_size(vF),igl::max_size(vF));
279 return false;
280 }
281 if(!vN.empty())
282 {
283 bool VN_rect = igl::list_to_matrix(vN,CN);
284 if(!VN_rect)
285 {
286 printf(format,"CN",igl::min_size(vN),igl::max_size(vN));
287 return false;
288 }
289 }
290
291 if(!vFN.empty() && !vFN[0].empty())
292 {
293 bool FN_rect = igl::list_to_matrix(vFN,FN);
294 if(!FN_rect)
295 {
296 printf(format,"FN",igl::min_size(vFN),igl::max_size(vFN));
297 return false;
298 }
299 }
300
301 if(!vTC.empty())
302 {
303
304 bool T_rect = igl::list_to_matrix(vTC,TC);
305 if(!T_rect)
306 {
307 printf(format,"TC",igl::min_size(vTC),igl::max_size(vTC));
308 return false;
309 }
310 }
311 if(!vFTC.empty()&& !vFTC[0].empty())
312 {
313
314 bool FTC_rect = igl::list_to_matrix(vFTC,FTC);
315 if(!FTC_rect)
316 {
317 printf(format,"FTC",igl::min_size(vFTC),igl::max_size(vFTC));
318 return false;
319 }
320 }
321 return true;
322}

References list_to_matrix(), max_size(), min_size(), and readOBJ().

+ Here is the call graph for this function:

◆ readOBJ() [5/5]

template<typename Scalar , typename Index >
IGL_INLINE bool igl::readOBJ ( FILE *  obj_file,
std::vector< std::vector< Scalar > > &  V,
std::vector< std::vector< Scalar > > &  TC,
std::vector< std::vector< Scalar > > &  N,
std::vector< std::vector< Index > > &  F,
std::vector< std::vector< Index > > &  FTC,
std::vector< std::vector< Index > > &  FN 
)
50{
51 // File open was successful so clear outputs
52 V.clear();
53 TC.clear();
54 N.clear();
55 F.clear();
56 FTC.clear();
57 FN.clear();
58
59 // variables and constants to assist parsing the .obj file
60 // Constant strings to compare against
61 std::string v("v");
62 std::string vn("vn");
63 std::string vt("vt");
64 std::string f("f");
65 std::string tic_tac_toe("#");
66#ifndef IGL_LINE_MAX
67# define IGL_LINE_MAX 2048
68#endif
69
70 char line[IGL_LINE_MAX];
71 int line_no = 1;
72 while (fgets(line, IGL_LINE_MAX, obj_file) != NULL)
73 {
74 char type[IGL_LINE_MAX];
75 // Read first word containing type
76 if(sscanf(line, "%s",type) == 1)
77 {
78 // Get pointer to rest of line right after type
79 char * l = &line[strlen(type)];
80 if(type == v)
81 {
82 std::istringstream ls(&line[1]);
83 std::vector<Scalar > vertex{ std::istream_iterator<Scalar >(ls), std::istream_iterator<Scalar >() };
84
85 if (vertex.size() < 3)
86 {
87 fprintf(stderr,
88 "Error: readOBJ() vertex on line %d should have at least 3 coordinates",
89 line_no);
90 fclose(obj_file);
91 return false;
92 }
93
94 V.push_back(vertex);
95 }else if(type == vn)
96 {
97 double x[3];
98 int count =
99 sscanf(l,"%lf %lf %lf\n",&x[0],&x[1],&x[2]);
100 if(count != 3)
101 {
102 fprintf(stderr,
103 "Error: readOBJ() normal on line %d should have 3 coordinates",
104 line_no);
105 fclose(obj_file);
106 return false;
107 }
108 std::vector<Scalar > normal(count);
109 for(int i = 0;i<count;i++)
110 {
111 normal[i] = x[i];
112 }
113 N.push_back(normal);
114 }else if(type == vt)
115 {
116 double x[3];
117 int count =
118 sscanf(l,"%lf %lf %lf\n",&x[0],&x[1],&x[2]);
119 if(count != 2 && count != 3)
120 {
121 fprintf(stderr,
122 "Error: readOBJ() texture coords on line %d should have 2 "
123 "or 3 coordinates (%d)",
124 line_no,count);
125 fclose(obj_file);
126 return false;
127 }
128 std::vector<Scalar > tex(count);
129 for(int i = 0;i<count;i++)
130 {
131 tex[i] = x[i];
132 }
133 TC.push_back(tex);
134 }else if(type == f)
135 {
136 const auto & shift = [&V](const int i)->int
137 {
138 return i<0 ? i+V.size() : i-1;
139 };
140 const auto & shift_t = [&TC](const int i)->int
141 {
142 return i<0 ? i+TC.size() : i-1;
143 };
144 const auto & shift_n = [&N](const int i)->int
145 {
146 return i<0 ? i+N.size() : i-1;
147 };
148 std::vector<Index > f;
149 std::vector<Index > ftc;
150 std::vector<Index > fn;
151 // Read each "word" after type
152 char word[IGL_LINE_MAX];
153 int offset;
154 while(sscanf(l,"%s%n",word,&offset) == 1)
155 {
156 // adjust offset
157 l += offset;
158 // Process word
159 long int i,it,in;
160 if(sscanf(word,"%ld/%ld/%ld",&i,&it,&in) == 3)
161 {
162 f.push_back(shift(i));
163 ftc.push_back(shift_t(it));
164 fn.push_back(shift_n(in));
165 }else if(sscanf(word,"%ld/%ld",&i,&it) == 2)
166 {
167 f.push_back(shift(i));
168 ftc.push_back(shift_t(it));
169 }else if(sscanf(word,"%ld//%ld",&i,&in) == 2)
170 {
171 f.push_back(shift(i));
172 fn.push_back(shift_n(in));
173 }else if(sscanf(word,"%ld",&i) == 1)
174 {
175 f.push_back(shift(i));
176 }else
177 {
178 fprintf(stderr,
179 "Error: readOBJ() face on line %d has invalid element format\n",
180 line_no);
181 fclose(obj_file);
182 return false;
183 }
184 }
185 if(
186 (f.size()>0 && fn.size() == 0 && ftc.size() == 0) ||
187 (f.size()>0 && fn.size() == f.size() && ftc.size() == 0) ||
188 (f.size()>0 && fn.size() == 0 && ftc.size() == f.size()) ||
189 (f.size()>0 && fn.size() == f.size() && ftc.size() == f.size()))
190 {
191 // No matter what add each type to lists so that lists are the
192 // correct lengths
193 F.push_back(f);
194 FTC.push_back(ftc);
195 FN.push_back(fn);
196 }else
197 {
198 fprintf(stderr,
199 "Error: readOBJ() face on line %d has invalid format\n", line_no);
200 fclose(obj_file);
201 return false;
202 }
203 }else if(strlen(type) >= 1 && (type[0] == '#' ||
204 type[0] == 'g' ||
205 type[0] == 's' ||
206 strcmp("usemtl",type)==0 ||
207 strcmp("mtllib",type)==0))
208 {
209 //ignore comments or other shit
210 }else
211 {
212 //ignore any other lines
213 fprintf(stderr,
214 "Warning: readOBJ() ignored non-comment line %d:\n %s",
215 line_no,
216 line);
217 }
218 }else
219 {
220 // ignore empty line
221 }
222 line_no++;
223 }
224 fclose(obj_file);
225
226 assert(F.size() == FN.size());
227 assert(F.size() == FTC.size());
228
229 return true;
230}
Vec< 3, T > normal(const std::array< Vec< 3, T >, 3 > &tri)
Definition Rotfinder.cpp:43
#define IGL_LINE_MAX

References count(), and IGL_LINE_MAX.

+ Here is the call graph for this function:

◆ readOFF() [1/4]

template<typename Scalar , typename Index >
IGL_INLINE bool igl::readOFF ( const std::string  off_file_name,
std::vector< std::vector< Scalar > > &  V,
std::vector< std::vector< Index > > &  F,
std::vector< std::vector< Scalar > > &  N,
std::vector< std::vector< Scalar > > &  C 
)
18{
19 using namespace std;
20 FILE * off_file = fopen(off_file_name.c_str(),"r");
21 if(NULL==off_file)
22 {
23 printf("IOError: %s could not be opened...\n",off_file_name.c_str());
24 return false;
25 }
26 return readOFF(off_file,V,F,N,C);
27}

References readOFF().

Referenced by igl::opengl::glfw::Viewer::load_mesh_from_file(), read_triangle_mesh(), read_triangle_mesh(), readOFF(), readOFF(), and readOFF().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ readOFF() [2/4]

template<typename DerivedV , typename DerivedF >
IGL_INLINE bool igl::readOFF ( const std::string  str,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F 
)
172{
173 std::vector<std::vector<double> > vV;
174 std::vector<std::vector<double> > vN;
175 std::vector<std::vector<int> > vF;
176 std::vector<std::vector<double> > vC;
177 bool success = igl::readOFF(str,vV,vF,vN,vC);
178 if(!success)
179 {
180 // readOFF(str,vV,vF,vN,vC) should have already printed an error
181 // message to stderr
182 return false;
183 }
184 bool V_rect = igl::list_to_matrix(vV,V);
185 if(!V_rect)
186 {
187 // igl::list_to_matrix(vV,V) already printed error message to std err
188 return false;
189 }
190 bool F_rect = igl::list_to_matrix(vF,F);
191 if(!F_rect)
192 {
193 // igl::list_to_matrix(vF,F) already printed error message to std err
194 return false;
195 }
196 return true;
197}

References list_to_matrix(), and readOFF().

+ Here is the call graph for this function:

◆ readOFF() [3/4]

template<typename DerivedV , typename DerivedF >
IGL_INLINE bool igl::readOFF ( const std::string  str,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedV > &  N 
)
206{
207 std::vector<std::vector<double> > vV;
208 std::vector<std::vector<double> > vN;
209 std::vector<std::vector<int> > vF;
210 std::vector<std::vector<double> > vC;
211 bool success = igl::readOFF(str,vV,vF,vN,vC);
212 if(!success)
213 {
214 // readOFF(str,vV,vF,vC) should have already printed an error
215 // message to stderr
216 return false;
217 }
218 bool V_rect = igl::list_to_matrix(vV,V);
219 if(!V_rect)
220 {
221 // igl::list_to_matrix(vV,V) already printed error message to std err
222 return false;
223 }
224 bool F_rect = igl::list_to_matrix(vF,F);
225 if(!F_rect)
226 {
227 // igl::list_to_matrix(vF,F) already printed error message to std err
228 return false;
229 }
230
231 if (vN.size())
232 {
233 bool N_rect = igl::list_to_matrix(vN,N);
234 if(!N_rect)
235 {
236 // igl::list_to_matrix(vN,N) already printed error message to std err
237 return false;
238 }
239 }
240
241 //Warning: RGB colors will be returned in the N matrix
242 if (vC.size())
243 {
244 bool C_rect = igl::list_to_matrix(vC,N);
245 if(!C_rect)
246 {
247 // igl::list_to_matrix(vC,N) already printed error message to std err
248 return false;
249 }
250 }
251
252 return true;
253}

References list_to_matrix(), and readOFF().

+ Here is the call graph for this function:

◆ readOFF() [4/4]

template<typename Scalar , typename Index >
IGL_INLINE bool igl::readOFF ( FILE *  off_file,
std::vector< std::vector< Scalar > > &  V,
std::vector< std::vector< Index > > &  F,
std::vector< std::vector< Scalar > > &  N,
std::vector< std::vector< Scalar > > &  C 
)
36{
37 using namespace std;
38 V.clear();
39 F.clear();
40 N.clear();
41 C.clear();
42
43 // First line is always OFF
44 char header[1000];
45 const std::string OFF("OFF");
46 const std::string NOFF("NOFF");
47 const std::string COFF("COFF");
48 if(fscanf(off_file,"%s\n",header)!=1
49 || !(
50 string(header).compare(0, OFF.length(), OFF)==0 ||
51 string(header).compare(0, COFF.length(), COFF)==0 ||
52 string(header).compare(0,NOFF.length(),NOFF)==0))
53 {
54 printf("Error: readOFF() first line should be OFF or NOFF or COFF, not %s...",header);
55 fclose(off_file);
56 return false;
57 }
58 bool has_normals = string(header).compare(0,NOFF.length(),NOFF)==0;
59 bool has_vertexColors = string(header).compare(0,COFF.length(),COFF)==0;
60 // Second line is #vertices #faces #edges
61 int number_of_vertices;
62 int number_of_faces;
63 int number_of_edges;
64 char tic_tac_toe;
65 char line[1000];
66 bool still_comments = true;
67 while(still_comments)
68 {
69 fgets(line,1000,off_file);
70 still_comments = (line[0] == '#' || line[0] == '\n');
71 }
72 sscanf(line,"%d %d %d",&number_of_vertices,&number_of_faces,&number_of_edges);
73 V.resize(number_of_vertices);
74 if (has_normals)
75 N.resize(number_of_vertices);
76 if (has_vertexColors)
77 C.resize(number_of_vertices);
78 F.resize(number_of_faces);
79 //printf("%s %d %d %d\n",(has_normals ? "NOFF" : "OFF"),number_of_vertices,number_of_faces,number_of_edges);
80 // Read vertices
81 for(int i = 0;i<number_of_vertices;)
82 {
83 fgets(line, 1000, off_file);
84 double x,y,z,nx,ny,nz;
85 if(sscanf(line, "%lg %lg %lg %lg %lg %lg",&x,&y,&z,&nx,&ny,&nz)>= 3)
86 {
87 std::vector<Scalar > vertex;
88 vertex.resize(3);
89 vertex[0] = x;
90 vertex[1] = y;
91 vertex[2] = z;
92 V[i] = vertex;
93
94 if (has_normals)
95 {
96 std::vector<Scalar > normal;
97 normal.resize(3);
98 normal[0] = nx;
99 normal[1] = ny;
100 normal[2] = nz;
101 N[i] = normal;
102 }
103
104 if (has_vertexColors)
105 {
106 C[i].resize(3);
107 C[i][0] = nx / 255.0;
108 C[i][1] = ny / 255.0;
109 C[i][2] = nz / 255.0;
110 }
111 i++;
112 }else if(
113 fscanf(off_file,"%[#]",&tic_tac_toe)==1)
114 {
115 char comment[1000];
116 fscanf(off_file,"%[^\n]",comment);
117 }else
118 {
119 printf("Error: bad line (%d)\n",i);
120 if(feof(off_file))
121 {
122 fclose(off_file);
123 return false;
124 }
125 }
126 }
127 // Read faces
128 for(int i = 0;i<number_of_faces;)
129 {
130 std::vector<Index > face;
131 int valence;
132 if(fscanf(off_file,"%d",&valence)==1)
133 {
134 face.resize(valence);
135 for(int j = 0;j<valence;j++)
136 {
137 int index;
138 if(j<valence-1)
139 {
140 fscanf(off_file,"%d",&index);
141 }else{
142 fscanf(off_file,"%d%*[^\n]",&index);
143 }
144
145 face[j] = index;
146 }
147 F[i] = face;
148 i++;
149 }else if(
150 fscanf(off_file,"%[#]",&tic_tac_toe)==1)
151 {
152 char comment[1000];
153 fscanf(off_file,"%[^\n]",comment);
154 }else
155 {
156 printf("Error: bad line\n");
157 fclose(off_file);
158 return false;
159 }
160 }
161 fclose(off_file);
162 return true;
163}
TOKEN * string(char *text)
Definition config.c:233
#define comment
Definition lexer.c:1004
TPoint< S > & vertex(S &sh, unsigned long idx, const PolygonTag &)
Definition geometry_traits.hpp:1180

References comment, OFF, and string().

+ Here is the call graph for this function:

◆ readPLY() [1/4]

template<typename DerivedV , typename DerivedF >
IGL_INLINE bool igl::readPLY ( const std::string  filename,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F 
)
211{
212 Eigen::MatrixXd N,UV;
213 return readPLY(filename,V,F,N,UV);
214}

References readPLY().

+ Here is the call graph for this function:

◆ readPLY() [2/4]

template<typename DerivedV , typename DerivedF , typename DerivedN , typename DerivedUV >
IGL_INLINE bool igl::readPLY ( const std::string  filename,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedN > &  N,
Eigen::PlainObjectBase< DerivedUV > &  UV 
)
188{
189 std::vector<std::vector<typename DerivedV::Scalar> > vV;
190 std::vector<std::vector<typename DerivedF::Scalar> > vF;
191 std::vector<std::vector<typename DerivedN::Scalar> > vN;
192 std::vector<std::vector<typename DerivedUV::Scalar> > vUV;
193 if(!readPLY(filename,vV,vF,vN,vUV))
194 {
195 return false;
196 }
197 return
198 list_to_matrix(vV,V) &&
199 list_to_matrix(vF,F) &&
200 list_to_matrix(vN,N) &&
201 list_to_matrix(vUV,UV);
202}

References list_to_matrix(), and readPLY().

+ Here is the call graph for this function:

◆ readPLY() [3/4]

template<typename Vtype , typename Ftype , typename Ntype , typename UVtype >
IGL_INLINE bool igl::readPLY ( const std::string  filename,
std::vector< std::vector< Vtype > > &  V,
std::vector< std::vector< Ftype > > &  F,
std::vector< std::vector< Ntype > > &  N,
std::vector< std::vector< UVtype > > &  UV 
)
24{
25 using namespace std;
26 // Largely follows ply2iv.c
27 FILE * ply_file = fopen(filename.c_str(),"r");
28 if(ply_file == NULL)
29 {
30 return false;
31 }
32 return readPLY(ply_file,V,F,N,UV);
33}

References readPLY().

Referenced by read_triangle_mesh(), readPLY(), readPLY(), and readPLY().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ readPLY() [4/4]

template<typename Vtype , typename Ftype , typename Ntype , typename UVtype >
IGL_INLINE bool igl::readPLY ( FILE *  ply_file,
std::vector< std::vector< Vtype > > &  V,
std::vector< std::vector< Ftype > > &  F,
std::vector< std::vector< Ntype > > &  N,
std::vector< std::vector< UVtype > > &  UV 
)
46{
47 using namespace std;
48 typedef struct Vertex {
49 double x,y,z; /* position */
50 double nx,ny,nz; /* surface normal */
51 double s,t; /* texture coordinates */
52 void *other_props; /* other properties */
53 } Vertex;
54
55 typedef struct Face {
56 unsigned char nverts; /* number of vertex indices in list */
57 int *verts; /* vertex index list */
58 void *other_props; /* other properties */
59 } Face;
60
61 igl::ply::PlyProperty vert_props[] = { /* list of property information for a vertex */
62 {"x", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,x), 0, 0, 0, 0},
63 {"y", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,y), 0, 0, 0, 0},
64 {"z", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,z), 0, 0, 0, 0},
65 {"nx", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,nx), 0, 0, 0, 0},
66 {"ny", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,ny), 0, 0, 0, 0},
67 {"nz", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,nz), 0, 0, 0, 0},
68 {"s", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,s), 0, 0, 0, 0},
69 {"t", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,t), 0, 0, 0, 0},
70 };
71
72 igl::ply::PlyProperty face_props[] = { /* list of property information for a face */
73 {"vertex_indices", PLY_INT, PLY_INT, offsetof(Face,verts),
74 1, PLY_UCHAR, PLY_UCHAR, offsetof(Face,nverts)},
75 };
76
77 int nelems;
78 char ** elem_names;
79 igl::ply::PlyFile * in_ply = igl::ply::ply_read(ply_file,&nelems,&elem_names);
80 if(in_ply==NULL)
81 {
82 return false;
83 }
84
85 bool has_normals = false;
86 bool has_texture_coords = false;
88 int nprops;
89 int elem_count;
90 plist = ply_get_element_description (in_ply,"vertex", &elem_count, &nprops);
91 int native_binary_type = igl::ply::get_native_binary_type2();
92 if (plist != NULL)
93 {
94 /* set up for getting vertex elements */
95 ply_get_property (in_ply,"vertex",&vert_props[0]);
96 ply_get_property (in_ply,"vertex",&vert_props[1]);
97 ply_get_property (in_ply,"vertex",&vert_props[2]);
98 for (int j = 0; j < nprops; j++)
99 {
100 igl::ply::PlyProperty * prop = plist[j];
101 if (igl::ply::equal_strings ("nx", prop->name)
102 || igl::ply::equal_strings ("ny", prop->name)
103 || igl::ply::equal_strings ("nz", prop->name))
104 {
105 ply_get_property (in_ply,"vertex",&vert_props[3]);
106 ply_get_property (in_ply,"vertex",&vert_props[4]);
107 ply_get_property (in_ply,"vertex",&vert_props[5]);
108 has_normals = true;
109 }
110 if (igl::ply::equal_strings ("s", prop->name) ||
111 igl::ply::equal_strings ("t", prop->name))
112 {
113 ply_get_property(in_ply,"vertex",&vert_props[6]);
114 ply_get_property(in_ply,"vertex",&vert_props[7]);
115 has_texture_coords = true;
116 }
117 }
118 // Is this call necessary?
119 ply_get_other_properties(in_ply,"vertex",
120 offsetof(Vertex,other_props));
121 V.resize(elem_count,std::vector<Vtype>(3));
122 if(has_normals)
123 {
124 N.resize(elem_count,std::vector<Ntype>(3));
125 }else
126 {
127 N.resize(0);
128 }
129 if(has_texture_coords)
130 {
131 UV.resize(elem_count,std::vector<UVtype>(2));
132 }else
133 {
134 UV.resize(0);
135 }
136
137 for(int j = 0;j<elem_count;j++)
138 {
139 Vertex v;
140 ply_get_element_setup(in_ply,"vertex",3,vert_props);
141 ply_get_element(in_ply,(void*)&v, &native_binary_type);
142 V[j][0] = v.x;
143 V[j][1] = v.y;
144 V[j][2] = v.z;
145 if(has_normals)
146 {
147 N[j][0] = v.nx;
148 N[j][1] = v.ny;
149 N[j][2] = v.nz;
150 }
151 if(has_texture_coords)
152 {
153 UV[j][0] = v.s;
154 UV[j][1] = v.t;
155 }
156 }
157 }
158 plist = ply_get_element_description (in_ply,"face", &elem_count, &nprops);
159 if (plist != NULL)
160 {
161 F.resize(elem_count);
162 ply_get_property(in_ply,"face",&face_props[0]);
163 for (int j = 0; j < elem_count; j++)
164 {
165 Face f;
166 ply_get_element(in_ply, (void *) &f, &native_binary_type);
167 for(size_t c = 0;c<f.nverts;c++)
168 {
169 F[j].push_back(f.verts[c]);
170 }
171 }
172 }
173 ply_close(in_ply);
174 return true;
175}
const char * name
Definition ply.h:114
void ply_get_element(PlyFile *, void *, int *)
Definition ply.h:1346
void ply_close(PlyFile *)
Definition ply.h:1733
int equal_strings(const char *, const char *)
Definition ply.h:1769
PlyProperty ** ply_get_element_description(PlyFile *, const char *, int *, int *)
Definition ply.h:1209
int get_native_binary_type2()
Definition ply.h:2161
void ply_get_element_setup(PlyFile *, const char *, int, PlyProperty *)
Definition ply.h:1253
void ply_get_property(PlyFile *, const char *, PlyProperty *)
Definition ply.h:1304
PlyOtherProp * ply_get_other_properties(PlyFile *, const char *, int)
Definition ply.h:1477
Definition ply.h:112
#define PLY_INT
Definition ply.h:98
#define PLY_DOUBLE
Definition ply.h:103
#define PLY_UCHAR
Definition ply.h:99

References igl::ply::equal_strings(), igl::ply::get_native_binary_type2(), igl::ply::PlyProperty::name, PLY_DOUBLE, PLY_INT, igl::ply::ply_read(), and PLY_UCHAR.

+ Here is the call graph for this function:

◆ readSTL() [1/3]

template<typename DerivedV , typename DerivedF , typename DerivedN >
IGL_INLINE bool igl::readSTL ( const std::string &  filename,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedN > &  N 
)
18{
19 using namespace std;
20 vector<vector<typename DerivedV::Scalar> > vV;
21 vector<vector<typename DerivedN::Scalar> > vN;
22 vector<vector<typename DerivedF::Scalar> > vF;
23 if(!readSTL(filename,vV,vF,vN))
24 {
25 return false;
26 }
27
28 if(!list_to_matrix(vV,V))
29 {
30 return false;
31 }
32
33 if(!list_to_matrix(vF,F))
34 {
35 return false;
36 }
37
38 if(!list_to_matrix(vN,N))
39 {
40 return false;
41 }
42 return true;
43}

References list_to_matrix(), and readSTL().

Referenced by read_triangle_mesh(), readSTL(), and readSTL().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ readSTL() [2/3]

template<typename TypeV , typename TypeF , typename TypeN >
IGL_INLINE bool igl::readSTL ( const std::string &  filename,
std::vector< std::vector< TypeV > > &  V,
std::vector< std::vector< TypeF > > &  F,
std::vector< std::vector< TypeN > > &  N 
)
51{
52 using namespace std;
53 // Should test for ascii
54
55 // Open file, and check for error
56 FILE * stl_file = fopen(filename.c_str(),"rb");
57 if(NULL==stl_file)
58 {
59 fprintf(stderr,"IOError: %s could not be opened...\n",
60 filename.c_str());
61 return false;
62 }
63 return readSTL(stl_file,V,F,N);
64}

References readSTL().

+ Here is the call graph for this function:

◆ readSTL() [3/3]

template<typename TypeV , typename TypeF , typename TypeN >
IGL_INLINE bool igl::readSTL ( FILE *  stl_file,
std::vector< std::vector< TypeV > > &  V,
std::vector< std::vector< TypeF > > &  F,
std::vector< std::vector< TypeN > > &  N 
)
72{
73 using namespace std;
74 //stl_file = freopen(NULL,"rb",stl_file);
75 if(NULL==stl_file)
76 {
77 fprintf(stderr,"IOError: stl file could not be reopened as binary (1) ...\n");
78 return false;
79 }
80
81 V.clear();
82 F.clear();
83 N.clear();
84
85
86 // Specifically 80 character header
87 char header[80];
88 char solid[80];
89 bool is_ascii = true;
90 if(fread(header,1,80,stl_file) != 80)
91 {
92 cerr<<"IOError: too short (1)."<<endl;
93 goto close_false;
94 }
95 sscanf(header,"%s",solid);
96 if(string("solid") != solid)
97 {
98 // definitely **not** ascii
99 is_ascii = false;
100 }else
101 {
102 // might still be binary
103 char buf[4];
104 if(fread(buf,1,4,stl_file) != 4)
105 {
106 cerr<<"IOError: too short (3)."<<endl;
107 goto close_false;
108 }
109 size_t num_faces = *reinterpret_cast<unsigned int*>(buf);
110 fseek(stl_file,0,SEEK_END);
111 int file_size = ftell(stl_file);
112 if(file_size == 80 + 4 + (4*12 + 2) * num_faces)
113 {
114 is_ascii = false;
115 }else
116 {
117 is_ascii = true;
118 }
119 }
120
121 if(is_ascii)
122 {
123 // Rewind to end of header
124 //stl_file = fopen(filename.c_str(),"r");
125 //stl_file = freopen(NULL,"r",stl_file);
126 fseek(stl_file, 0, SEEK_SET);
127 if(NULL==stl_file)
128 {
129 fprintf(stderr,"IOError: stl file could not be reopened as ascii ...\n");
130 return false;
131 }
132 // Read 80 header
133 // Eat file name
134#ifndef IGL_LINE_MAX
135# define IGL_LINE_MAX 2048
136#endif
137 char name[IGL_LINE_MAX];
138 if(NULL==fgets(name,IGL_LINE_MAX,stl_file))
139 {
140 cerr<<"IOError: ascii too short (2)."<<endl;
141 goto close_false;
142 }
143 // ascii
144 while(true)
145 {
146 int ret;
147 char facet[IGL_LINE_MAX],normal[IGL_LINE_MAX];
148 vector<TypeN > n(3);
149 double nd[3];
150 ret = fscanf(stl_file,"%s %s %lg %lg %lg",facet,normal,nd,nd+1,nd+2);
151 if(string("endsolid") == facet)
152 {
153 break;
154 }
155 if(ret != 5 ||
156 !(string("facet") == facet ||
157 string("faced") == facet) ||
158 string("normal") != normal)
159 {
160 cout<<"facet: "<<facet<<endl;
161 cout<<"normal: "<<normal<<endl;
162 cerr<<"IOError: bad format (1)."<<endl;
163 goto close_false;
164 }
165 // copy casts to Type
166 n[0] = nd[0]; n[1] = nd[1]; n[2] = nd[2];
167 N.push_back(n);
168 char outer[IGL_LINE_MAX], loop[IGL_LINE_MAX];
169 ret = fscanf(stl_file,"%s %s",outer,loop);
170 if(ret != 2 || string("outer") != outer || string("loop") != loop)
171 {
172 cerr<<"IOError: bad format (2)."<<endl;
173 goto close_false;
174 }
175 vector<TypeF> f;
176 while(true)
177 {
178 char word[IGL_LINE_MAX];
179 int ret = fscanf(stl_file,"%s",word);
180 if(ret == 1 && string("endloop") == word)
181 {
182 break;
183 }else if(ret == 1 && string("vertex") == word)
184 {
185 vector<TypeV> v(3);
186 double vd[3];
187 int ret = fscanf(stl_file,"%lg %lg %lg",vd,vd+1,vd+2);
188 if(ret != 3)
189 {
190 cerr<<"IOError: bad format (3)."<<endl;
191 goto close_false;
192 }
193 f.push_back(V.size());
194 // copy casts to Type
195 v[0] = vd[0]; v[1] = vd[1]; v[2] = vd[2];
196 V.push_back(v);
197 }else
198 {
199 cerr<<"IOError: bad format (4)."<<endl;
200 goto close_false;
201 }
202 }
203 F.push_back(f);
204 char endfacet[IGL_LINE_MAX];
205 ret = fscanf(stl_file,"%s",endfacet);
206 if(ret != 1 || string("endfacet") != endfacet)
207 {
208 cerr<<"IOError: bad format (5)."<<endl;
209 goto close_false;
210 }
211 }
212 // read endfacet
213 goto close_true;
214 }else
215 {
216 // Binary
217 //stl_file = freopen(NULL,"rb",stl_file);
218 fseek(stl_file, 0, SEEK_SET);
219 // Read 80 header
220 char header[80];
221 if(fread(header,sizeof(char),80,stl_file)!=80)
222 {
223 cerr<<"IOError: bad format (6)."<<endl;
224 goto close_false;
225 }
226 // Read number of triangles
227 unsigned int num_tri;
228 if(fread(&num_tri,sizeof(unsigned int),1,stl_file)!=1)
229 {
230 cerr<<"IOError: bad format (7)."<<endl;
231 goto close_false;
232 }
233 V.resize(num_tri*3,vector<TypeV >(3,0));
234 N.resize(num_tri,vector<TypeN >(3,0));
235 F.resize(num_tri,vector<TypeF >(3,0));
236 for(int t = 0;t<(int)num_tri;t++)
237 {
238 // Read normal
239 float n[3];
240 if(fread(n,sizeof(float),3,stl_file)!=3)
241 {
242 cerr<<"IOError: bad format (8)."<<endl;
243 goto close_false;
244 }
245 // Read each vertex
246 for(int c = 0;c<3;c++)
247 {
248 F[t][c] = 3*t+c;
249 N[t][c] = n[c];
250 float v[3];
251 if(fread(v,sizeof(float),3,stl_file)!=3)
252 {
253 cerr<<"IOError: bad format (9)."<<endl;
254 goto close_false;
255 }
256 V[3*t+c][0] = v[0];
257 V[3*t+c][1] = v[1];
258 V[3*t+c][2] = v[2];
259 }
260 // Read attribute size
261 unsigned short att_count;
262 if(fread(&att_count,sizeof(unsigned short),1,stl_file)!=1)
263 {
264 cerr<<"IOError: bad format (10)."<<endl;
265 goto close_false;
266 }
267 }
268 goto close_true;
269 }
270close_false:
271 fclose(stl_file);
272 return false;
273close_true:
274 fclose(stl_file);
275 return true;
276}

References IGL_LINE_MAX, loop(), and SEEK_SET.

+ Here is the call graph for this function:

◆ readTGF() [1/3]

IGL_INLINE bool igl::readTGF ( const std::string  tgf_filename,
Eigen::MatrixXd &  C,
Eigen::MatrixXi &  E 
)
195{
196 Eigen::VectorXi P;
197 Eigen::MatrixXi BE,CE,PE;
198 return readTGF(tgf_filename,C,E,P,BE,CE,PE);
199}
IGL_INLINE bool readTGF(const std::string tgf_filename, std::vector< std::vector< double > > &C, std::vector< std::vector< int > > &E, std::vector< int > &P, std::vector< std::vector< int > > &BE, std::vector< std::vector< int > > &CE, std::vector< std::vector< int > > &PE)
Definition readTGF.cpp:12

References readTGF().

+ Here is the call graph for this function:

◆ readTGF() [2/3]

IGL_INLINE bool igl::readTGF ( const std::string  tgf_filename,
Eigen::MatrixXd &  C,
Eigen::MatrixXi &  E,
Eigen::VectorXi &  P,
Eigen::MatrixXi &  BE,
Eigen::MatrixXi &  CE,
Eigen::MatrixXi &  PE 
)
150{
151 std::vector<std::vector<double> > vC;
152 std::vector<std::vector<int> > vE;
153 std::vector<int> vP;
154 std::vector<std::vector<int> > vBE;
155 std::vector<std::vector<int> > vCE;
156 std::vector<std::vector<int> > vPE;
157 bool success = readTGF(tgf_filename,vC,vE,vP,vBE,vCE,vPE);
158 if(!success)
159 {
160 return false;
161 }
162
163 if(!list_to_matrix(vC,C))
164 {
165 return false;
166 }
167 if(!list_to_matrix(vE,E))
168 {
169 return false;
170 }
171 if(!list_to_matrix(vP,P))
172 {
173 return false;
174 }
175 if(!list_to_matrix(vBE,BE))
176 {
177 return false;
178 }
179 if(!list_to_matrix(vCE,CE))
180 {
181 return false;
182 }
183 if(!list_to_matrix(vPE,PE))
184 {
185 return false;
186 }
187
188 return true;
189}

References list_to_matrix(), and readTGF().

+ Here is the call graph for this function:

◆ readTGF() [3/3]

IGL_INLINE bool igl::readTGF ( const std::string  tgf_filename,
std::vector< std::vector< double > > &  C,
std::vector< std::vector< int > > &  E,
std::vector< int > &  P,
std::vector< std::vector< int > > &  BE,
std::vector< std::vector< int > > &  CE,
std::vector< std::vector< int > > &  PE 
)
20{
21 using namespace std;
22 // clear output
23 C.clear();
24 E.clear();
25 P.clear();
26 BE.clear();
27 CE.clear();
28 PE.clear();
29
30 FILE * tgf_file = fopen(tgf_filename.c_str(),"r");
31 if(NULL==tgf_file)
32 {
33 printf("IOError: %s could not be opened\n",tgf_filename.c_str());
34 return false;
35 }
36
37 bool reading_vertices = true;
38 bool reading_edges = true;
39 const int MAX_LINE_LENGTH = 500;
40 char line[MAX_LINE_LENGTH];
41 // read until seeing end of file
42 while(fgets(line,MAX_LINE_LENGTH,tgf_file)!=NULL)
43 {
44 // comment signifies end of vertices, next line is start of edges
45 if(line[0] == '#')
46 {
47 if(reading_vertices)
48 {
49 reading_vertices = false;
50 reading_edges = true;
51 }else if(reading_edges)
52 {
53 reading_edges = false;
54 }
55 // process vertex line
56 }else if(reading_vertices)
57 {
58 int index;
59 vector<double> position(3);
60 int count =
61 sscanf(line,"%d %lg %lg %lg",
62 &index,
63 &position[0],
64 &position[1],
65 &position[2]);
66 if(count != 4)
67 {
68 fprintf(stderr,"Error: readTGF.h: bad format in vertex line\n");
69 fclose(tgf_file);
70 return false;
71 }
72 // index is ignored since vertices must already be in order
73 C.push_back(position);
74 }else if(reading_edges)
75 {
76 vector<int> edge(2);
77 int is_BE = 0;
78 int is_PE = 0;
79 int is_CE = 0;
80 int count = sscanf(line,"%d %d %d %d %d\n",
81 &edge[0],
82 &edge[1],
83 &is_BE,
84 &is_PE,
85 &is_CE);
86 if(count<2)
87 {
88 fprintf(stderr,"Error: readTGF.h: bad format in edge line\n");
89 fclose(tgf_file);
90 return false;
91 }
92 // .tgf is one indexed
93 edge[0]--;
94 edge[1]--;
95 E.push_back(edge);
96 if(is_BE == 1)
97 {
98 BE.push_back(edge);
99 }
100 if(is_PE == 1)
101 {
102 // PE should index P
103 fprintf(stderr,
104 "Warning: readTGF.h found pseudo edges but does not support "
105 "them\n");
106 }
107 if(is_CE == 1)
108 {
109 // CE should index P
110 fprintf(stderr,
111 "Warning: readTGF.h found cage edges but does not support them\n");
112 }
113 }else
114 {
115 // ignore faces
116 }
117 }
118 fclose(tgf_file);
119 // Construct P, indices not in BE
120 for(int i = 0;i<(int)C.size();i++)
121 {
122 bool in_edge = false;
123 for(int j = 0;j<(int)BE.size();j++)
124 {
125 if(i == BE[j][0] || i == BE[j][1])
126 {
127 in_edge = true;
128 break;
129 }
130 }
131 if(!in_edge)
132 {
133 P.push_back(i);
134 }
135 }
136 return true;
137}

References count().

Referenced by readTGF(), and readTGF().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ readWRL() [1/2]

template<typename Scalar , typename Index >
IGL_INLINE bool igl::readWRL ( const std::string  wrl_file_name,
std::vector< std::vector< Scalar > > &  V,
std::vector< std::vector< Index > > &  F 
)
16{
17 using namespace std;
18 FILE * wrl_file = fopen(wrl_file_name.c_str(),"r");
19 if(NULL==wrl_file)
20 {
21 printf("IOError: %s could not be opened...",wrl_file_name.c_str());
22 return false;
23 }
24 return readWRL(wrl_file,V,F);
25}

References readWRL().

Referenced by read_triangle_mesh(), and readWRL().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ readWRL() [2/2]

template<typename Scalar , typename Index >
IGL_INLINE bool igl::readWRL ( FILE *  wrl_file,
std::vector< std::vector< Scalar > > &  V,
std::vector< std::vector< Index > > &  F 
)
32{
33 using namespace std;
34
35 char line[1000];
36 // Read lines until seeing "point ["
37 // treat other lines in file as "comments"
38 bool still_comments = true;
39 string needle("point [");
40 string haystack;
41 while(still_comments)
42 {
43 if(fgets(line,1000,wrl_file) == NULL)
44 {
45 std::cerr<<"readWRL, reached EOF without finding \"point [\""<<std::endl;
46 fclose(wrl_file);
47 return false;
48 }
49 haystack = string(line);
50 still_comments = string::npos == haystack.find(needle);
51 }
52
53 // read points in sets of 3
54 int floats_read = 3;
55 double x,y,z;
56 while(floats_read == 3)
57 {
58 floats_read = fscanf(wrl_file," %lf %lf %lf,",&x,&y,&z);
59 if(floats_read == 3)
60 {
61 vector<Scalar > point;
62 point.resize(3);
63 point[0] = x;
64 point[1] = y;
65 point[2] = z;
66 V.push_back(point);
67 //printf("(%g, %g, %g)\n",x,y,z);
68 }else if(floats_read != 0)
69 {
70 printf("ERROR: unrecognized format...\n");
71 return false;
72 }
73 }
74 // Read lines until seeing "coordIndex ["
75 // treat other lines in file as "comments"
76 still_comments = true;
77 needle = string("coordIndex [");
78 while(still_comments)
79 {
80 fgets(line,1000,wrl_file);
81 haystack = string(line);
82 still_comments = string::npos == haystack.find(needle);
83 }
84 // read F
85 int ints_read = 1;
86 while(ints_read > 0)
87 {
88 // read new face indices (until hit -1)
89 vector<Index > face;
90 while(true)
91 {
92 // indices are 0-indexed
93 int i;
94 ints_read = fscanf(wrl_file," %d,",&i);
95 if(ints_read > 0)
96 {
97 if(i>=0)
98 {
99 face.push_back(i);
100 }else
101 {
102 F.push_back(face);
103 break;
104 }
105 }else
106 {
107 break;
108 }
109 }
110 }
111
112
113
114 fclose(wrl_file);
115 return true;
116}

References string().

+ Here is the call graph for this function:

◆ redux()

template<typename AType , typename Func , typename DerivedB >
void igl::redux ( const Eigen::SparseMatrix< AType > &  A,
const int  dim,
const Func &  func,
Eigen::PlainObjectBase< DerivedB > &  B 
)
inline
46{
47 assert((dim == 1 || dim == 2) && "dim must be 2 or 1");
48 // Get size of input
49 int m = A.rows();
50 int n = A.cols();
51 // resize output
52 B = DerivedB::Zero(dim==1?n:m);
53 const auto func_wrap = [&func,&B,&dim](const int i, const int j, const int v)
54 {
55 if(dim == 1)
56 {
57 B(j) = i == 0? v : func(B(j),v);
58 }else
59 {
60 B(i) = j == 0? v : func(B(i),v);
61 }
62 };
63 for_each(A,func_wrap);
64}

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), for_each(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows().

Referenced by all(), any(), and sum().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remesh_along_isoline() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedS , typename DerivedU , typename DerivedG , typename DerivedJ , typename BCtype , typename DerivedSU , typename DerivedL >
IGL_INLINE void igl::remesh_along_isoline ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< DerivedS > &  S,
const typename DerivedS::Scalar  val,
Eigen::PlainObjectBase< DerivedU > &  U,
Eigen::PlainObjectBase< DerivedG > &  G,
Eigen::PlainObjectBase< DerivedSU > &  SU,
Eigen::PlainObjectBase< DerivedJ > &  J,
Eigen::SparseMatrix< BCtype > &  BC,
Eigen::PlainObjectBase< DerivedL > &  L 
)
32{
33 igl::remesh_along_isoline(V.rows(),F,S,val,G,SU,J,BC,L);
34 U = BC * V;
35}
IGL_INLINE void remesh_along_isoline(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedS > &S, const typename DerivedS::Scalar val, Eigen::PlainObjectBase< DerivedU > &U, Eigen::PlainObjectBase< DerivedG > &G, Eigen::PlainObjectBase< DerivedSU > &SU, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::SparseMatrix< BCtype > &BC, Eigen::PlainObjectBase< DerivedL > &L)
Definition remesh_along_isoline.cpp:21

References L, and remesh_along_isoline().

Referenced by remesh_along_isoline().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remesh_along_isoline() [2/2]

template<typename DerivedF , typename DerivedS , typename DerivedG , typename DerivedJ , typename BCtype , typename DerivedSU , typename DerivedL >
IGL_INLINE void igl::remesh_along_isoline ( const int  n,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< DerivedS > &  S,
const typename DerivedS::Scalar  val,
Eigen::PlainObjectBase< DerivedG > &  G,
Eigen::PlainObjectBase< DerivedSU > &  SU,
Eigen::PlainObjectBase< DerivedJ > &  J,
Eigen::SparseMatrix< BCtype > &  BC,
Eigen::PlainObjectBase< DerivedL > &  L 
)
55{
56 // Lazy implementation using vectors
57
58 //assert(val.size() == 1);
59 const int isoval_i = 0;
60 //auto isoval = val(isoval_i);
61 auto isoval = val;
62 std::vector<std::vector<typename DerivedG::Scalar> > vG;
63 std::vector<typename DerivedJ::Scalar> vJ;
64 std::vector<typename DerivedL::Scalar> vL;
65 std::vector<Eigen::Triplet<BCtype> > vBC;
66 int Ucount = 0;
67 for(int i = 0;i<num_vertices;i++)
68 {
69 vBC.emplace_back(Ucount,i,1.0);
70 Ucount++;
71 }
72
73 // Loop over each face
74 for(int f = 0;f<F.rows();f++)
75 {
76 bool Psign[2];
77 int P[2];
78 int count = 0;
79 for(int p = 0;p<3;p++)
80 {
81 const bool psign = S(F(f,p)) > isoval;
82 // Find crossings
83 const int n = (p+1)%3;
84 const bool nsign = S(F(f,n)) > isoval;
85 if(psign != nsign)
86 {
87 P[count] = p;
88 Psign[count] = psign;
89 // record crossing
90 count++;
91 }
92 }
93
94 assert(count == 0 || count == 2);
95 switch(count)
96 {
97 case 0:
98 {
99 // Easy case
100 std::vector<typename DerivedG::Scalar> row = {F(f,0),F(f,1),F(f,2)};
101 vG.push_back(row);
102 vJ.push_back(f);
103 vL.push_back( S(F(f,0))>isoval ? isoval_i+1 : isoval_i );
104 break;
105 }
106 case 2:
107 {
108 // Cut case
109 // flip so that P[1] is the one-off vertex
110 if(P[0] == 0 && P[1] == 2)
111 {
112 std::swap(P[0],P[1]);
113 std::swap(Psign[0],Psign[1]);
114 }
115 assert(Psign[0] != Psign[1]);
116 // Create two new vertices
117 for(int i = 0;i<2;i++)
118 {
119 const double bci = (isoval - S(F(f,(P[i]+1)%3)))/
120 (S(F(f,P[i]))-S(F(f,(P[i]+1)%3)));
121 vBC.emplace_back(Ucount,F(f,P[i]),bci);
122 vBC.emplace_back(Ucount,F(f,(P[i]+1)%3),1.0-bci);
123 Ucount++;
124 }
125 const int v0 = F(f,P[0]);
126 const int v01 = Ucount-2;
127 assert(((P[0]+1)%3) == P[1]);
128 const int v1 = F(f,P[1]);
129 const int v12 = Ucount-1;
130 const int v2 = F(f,(P[1]+1)%3);
131 // v0
132 // | \
133 // | \
134 // | \
135 // v01 \
136 // | \
137 // | \
138 // | \
139 // v1--v12---v2
140 typedef std::vector<typename DerivedG::Scalar> Row;
141 {Row row = {v01,v1,v12}; vG.push_back(row);vJ.push_back(f);vL.push_back(Psign[0]?isoval_i:isoval_i+1);}
142 {Row row = {v12,v2,v01}; vG.push_back(row);vJ.push_back(f);vL.push_back(Psign[1]?isoval_i:isoval_i+1);}
143 {Row row = {v2,v0,v01}; vG.push_back(row) ;vJ.push_back(f);vL.push_back(Psign[1]?isoval_i:isoval_i+1);}
144 break;
145 }
146 default: assert(false);
147 }
148 }
152 BC.resize(Ucount,num_vertices);
153 BC.setFromTriplets(vBC.begin(),vBC.end());
154 SU = BC * S;
155}
TRasterValue< T > isoval(const T &rst, const Coord &crd)
Definition MarchingSquares.hpp:65

References count(), L, list_to_matrix(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::resize(), row(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets().

+ Here is the call graph for this function:

◆ remove_duplicate_vertices() [1/2]

template<typename DerivedV , typename DerivedSV , typename DerivedSVI , typename DerivedSVJ >
IGL_INLINE void igl::remove_duplicate_vertices ( const Eigen::MatrixBase< DerivedV > &  V,
const double  epsilon,
Eigen::PlainObjectBase< DerivedSV > &  SV,
Eigen::PlainObjectBase< DerivedSVI > &  SVI,
Eigen::PlainObjectBase< DerivedSVJ > &  SVJ 
)
26{
27 if(epsilon > 0)
28 {
29 DerivedV rV,rSV;
30 round((V/(10.0*epsilon)).eval(),rV);
31 unique_rows(rV,rSV,SVI,SVJ);
32 slice(V,SVI,colon<int>(0,V.cols()-1),SV);
33 }else
34 {
35 unique_rows(V,SV,SVI,SVJ);
36 }
37}

References round(), slice(), and unique_rows().

Referenced by igl::triangle::cdt(), isolines(), remove_duplicate_vertices(), and igl::WindingNumberTree< Point, DerivedV, DerivedF >::set_mesh().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remove_duplicate_vertices() [2/2]

template<typename DerivedV , typename DerivedF , typename DerivedSV , typename DerivedSVI , typename DerivedSVJ , typename DerivedSF >
IGL_INLINE void igl::remove_duplicate_vertices ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const double  epsilon,
Eigen::PlainObjectBase< DerivedSV > &  SV,
Eigen::PlainObjectBase< DerivedSVI > &  SVI,
Eigen::PlainObjectBase< DerivedSVJ > &  SVJ,
Eigen::PlainObjectBase< DerivedSF > &  SF 
)
54{
55 using namespace Eigen;
56 using namespace std;
57 remove_duplicate_vertices(V,epsilon,SV,SVI,SVJ);
58 SF.resizeLike(F);
59 for(int f = 0;f<F.rows();f++)
60 {
61 for(int c = 0;c<F.cols();c++)
62 {
63 SF(f,c) = SVJ(F(f,c));
64 }
65 }
66}

References remove_duplicate_vertices(), and Eigen::PlainObjectBase< Derived >::resizeLike().

+ Here is the call graph for this function:

◆ remove_duplicates()

template<typename DerivedV , typename DerivedF >
IGL_INLINE void igl::remove_duplicates ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedV > &  NV,
Eigen::PlainObjectBase< DerivedF > &  NF,
Eigen::Matrix< typename DerivedF::Scalar, Eigen::Dynamic, 1 > &  I,
const double  epsilon = 2.2204e-15 
)
27{
28 using namespace std;
30 int n = V.rows();
31
33 I[0] = 0;
34
35 bool *VISITED = new bool[n];
36 for (int i =0; i <n; ++i)
37 VISITED[i] = false;
38
39 NV.resize(n,V.cols());
40 int count = 0;
41 Eigen::VectorXd d(n);
42 for (int i =0; i <n; ++i)
43 {
44 if(!VISITED[i])
45 {
46 NV.row(count) = V.row(i);
47 I[i] = count;
48 VISITED[i] = true;
49 for (int j = i+1; j <n; ++j)
50 {
51 if((V.row(j) - V.row(i)).norm() < epsilon)
52 {
53 VISITED[j] = true;
54 I[j] = count;
55 }
56 }
57 count ++;
58 }
59 }
60
62
63 count = 0;
64 std::vector<typename DerivedF::Scalar> face;
65 NF.resizeLike(F);
66 for (int i =0; i <F.rows(); ++i)
67 {
68 face.clear();
69 for (int j = 0; j< F.cols(); ++j)
70 if(std::find(face.begin(), face.end(), I[F(i,j)]) == face.end())
71 face.push_back(I[F(i,j)]);
72 if (face.size() == size_t(F.cols()))
73 {
74 for (unsigned j = 0; j< F.cols(); ++j)
75 NF(count,j) = face[j];
76 count ++;
77 }
78 }
80
81 delete [] VISITED;
82}

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::conservativeResize(), count(), Eigen::NoChange, Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::resizeLike(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ remove_unreferenced() [1/3]

template<typename DerivedV , typename DerivedF , typename DerivedNV , typename DerivedNF , typename DerivedI >
IGL_INLINE void igl::remove_unreferenced ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedNV > &  NV,
Eigen::PlainObjectBase< DerivedNF > &  NF,
Eigen::PlainObjectBase< DerivedI > &  I 
)

References remove_unreferenced().

Referenced by igl::triangle::cdt(), igl::copyleft::cgal::complex_to_mesh(), decimate(), decimate(), igl::copyleft::cgal::mesh_boolean(), igl::copyleft::cgal::outer_hull(), qslim(), remove_unreferenced(), remove_unreferenced(), igl::copyleft::cgal::snap_rounding(), and igl::copyleft::cgal::trim_with_solid().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remove_unreferenced() [2/3]

template<typename DerivedV , typename DerivedF , typename DerivedNV , typename DerivedNF , typename DerivedI , typename DerivedJ >
IGL_INLINE void igl::remove_unreferenced ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedNV > &  NV,
Eigen::PlainObjectBase< DerivedNF > &  NF,
Eigen::PlainObjectBase< DerivedI > &  I,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
43{
44 using namespace std;
45 const size_t n = V.rows();
46 remove_unreferenced(n,F,I,J);
47 NF = F;
48 std::for_each(NF.data(),NF.data()+NF.size(),
49 [&I](typename DerivedNF::Scalar & a){a=I(a);});
50 slice(V,J,1,NV);
51}

References Eigen::PlainObjectBase< Derived >::data(), remove_unreferenced(), and slice().

+ Here is the call graph for this function:

◆ remove_unreferenced() [3/3]

template<typename DerivedF , typename DerivedI , typename DerivedJ >
IGL_INLINE void igl::remove_unreferenced ( const size_t  n,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedI > &  I,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
62{
63 // Mark referenced vertices
65 MatrixXb mark = MatrixXb::Zero(n,1);
66 for(int i=0; i<F.rows(); ++i)
67 {
68 for(int j=0; j<F.cols(); ++j)
69 {
70 if (F(i,j) != -1)
71 {
72 mark(F(i,j)) = 1;
73 }
74 }
75 }
76
77 // Sum the occupied cells
78 int newsize = mark.count();
79
80 I.resize(n,1);
81 J.resize(newsize,1);
82
83 // Do a pass on the marked vector and remove the unreferenced vertices
84 int count = 0;
85 for(int i=0;i<mark.rows();++i)
86 {
87 if (mark(i) == 1)
88 {
89 I(i) = count;
90 J(count) = i;
91 count++;
92 }
93 else
94 {
95 I(i) = -1;
96 }
97 }
98}

References count(), and Eigen::PlainObjectBase< Derived >::resize().

+ Here is the call graph for this function:

◆ reorder()

template<class T >
IGL_INLINE void igl::reorder ( const std::vector< T > &  unordered,
std::vector< size_t > const index_map,
std::vector< T > &  ordered 
)
20{
21 // copy for the reorder according to index_map, because unsorted may also be
22 // sorted
23 std::vector<T> copy = unordered;
24 ordered.resize(index_map.size());
25 for(int i = 0; i<(int)index_map.size();i++)
26 {
27 ordered[i] = copy[index_map[i]];
28 }
29}

Referenced by sort().

+ Here is the caller graph for this function:

◆ repdiag() [1/3]

template<typename T >
IGL_INLINE void igl::repdiag ( const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &  A,
const int  d,
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &  B 
)
71{
72 int m = A.rows();
73 int n = A.cols();
74 B.resize(m*d,n*d);
75 B.array() *= 0;
76 for(int i = 0;i<d;i++)
77 {
78 B.block(i*m,i*n,m,n) = A;
79 }
80}

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ repdiag() [2/3]

template<typename T >
IGL_INLINE void igl::repdiag ( const Eigen::SparseMatrix< T > &  A,
const int  d,
Eigen::SparseMatrix< T > &  B 
)
16{
17 using namespace std;
18 using namespace Eigen;
19 int m = A.rows();
20 int n = A.cols();
21#if false
22 vector<Triplet<T> > IJV;
23 IJV.reserve(A.nonZeros()*d);
24 // Loop outer level
25 for (int k=0; k<A.outerSize(); ++k)
26 {
27 // loop inner level
28 for (typename Eigen::SparseMatrix<T>::InnerIterator it(A,k); it; ++it)
29 {
30 for(int i = 0;i<d;i++)
31 {
32 IJV.push_back(Triplet<T>(i*m+it.row(),i*n+it.col(),it.value()));
33 }
34 }
35 }
36 B.resize(m*d,n*d);
37 B.setFromTriplets(IJV.begin(),IJV.end());
38#else
39 // This will not work for RowMajor
40 B.resize(m*d,n*d);
41 Eigen::VectorXi per_col = Eigen::VectorXi::Zero(n*d);
42 for (int k=0; k<A.outerSize(); ++k)
43 {
44 for (typename Eigen::SparseMatrix<T>::InnerIterator it(A,k); it; ++it)
45 {
46 for(int r = 0;r<d;r++) per_col(n*r + k)++;
47 }
48 }
49 B.reserve(per_col);
50 for(int r = 0;r<d;r++)
51 {
52 const int mr = m*r;
53 const int nr = n*r;
54 for (int k=0; k<A.outerSize(); ++k)
55 {
56 for (typename Eigen::SparseMatrix<T>::InnerIterator it(A,k); it; ++it)
57 {
58 B.insert(it.row()+mr,k+nr) = it.value();
59 }
60 }
61 }
63#endif
64}

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::insert(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::makeCompressed(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::nonZeros(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::outerSize(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::reserve(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::resize(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets().

Referenced by arap_dof_precomputation(), arap_precomputation(), arap_rhs(), hessian(), lscm(), and repdiag().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ repdiag() [3/3]

template<class Mat >
IGL_INLINE Mat igl::repdiag ( const Mat &  A,
const int  d 
)
85{
86 Mat B;
87 repdiag(A,d,B);
88 return B;
89}

References repdiag().

+ Here is the call graph for this function:

◆ repmat() [1/2]

template<typename DerivedA , typename DerivedB >
IGL_INLINE void igl::repmat ( const Eigen::MatrixBase< DerivedA > &  A,
const int  r,
const int  c,
Eigen::PlainObjectBase< DerivedB > &  B 
)
16{
17 assert(r>0);
18 assert(c>0);
19 // Make room for output
20 B.resize(r*A.rows(),c*A.cols());
21
22 // copy tiled blocks
23 for(int i = 0;i<r;i++)
24 {
25 for(int j = 0;j<c;j++)
26 {
27 B.block(i*A.rows(),j*A.cols(),A.rows(),A.cols()) = A;
28 }
29 }
30}

References Eigen::PlainObjectBase< Derived >::resize().

Referenced by massmatrix().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ repmat() [2/2]

template<typename T >
IGL_INLINE void igl::repmat ( const Eigen::SparseMatrix< T > &  A,
const int  r,
const int  c,
Eigen::SparseMatrix< T > &  B 
)
38{
39 assert(r>0);
40 assert(c>0);
41 B.resize(r*A.rows(),c*A.cols());
42 B.reserve(r*c*A.nonZeros());
43 for(int i = 0;i<r;i++)
44 {
45 for(int j = 0;j<c;j++)
46 {
47 // Loop outer level
48 for (int k=0; k<A.outerSize(); ++k)
49 {
50 // loop inner level
51 for (typename Eigen::SparseMatrix<T>::InnerIterator it(A,k); it; ++it)
52 {
53 B.insert(i*A.rows()+it.row(),j*A.cols() + it.col()) = it.value();
54 }
55 }
56 }
57 }
58 B.finalize();
59}
void finalize()
Definition SparseMatrix.h:422

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::cols(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::finalize(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::insert(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::nonZeros(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::outerSize(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::reserve(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::resize(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows().

+ Here is the call graph for this function:

◆ resolve_duplicated_faces()

template<typename DerivedF1 , typename DerivedF2 , typename DerivedJ >
IGL_INLINE void igl::resolve_duplicated_faces ( const Eigen::PlainObjectBase< DerivedF1 > &  F1,
Eigen::PlainObjectBase< DerivedF2 > &  F2,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
22 {
23
24 //typedef typename DerivedF1::Scalar Index;
25 Eigen::VectorXi IA,IC;
26 DerivedF1 uF;
27 igl::unique_simplices(F1,uF,IA,IC);
28
29 const size_t num_faces = F1.rows();
30 const size_t num_unique_faces = uF.rows();
31 assert((size_t) IA.rows() == num_unique_faces);
32 // faces on top of each unique face
33 std::vector<std::vector<int> > uF2F(num_unique_faces);
34 // signed counts
35 Eigen::VectorXi counts = Eigen::VectorXi::Zero(num_unique_faces);
36 Eigen::VectorXi ucounts = Eigen::VectorXi::Zero(num_unique_faces);
37 // loop over all faces
38 for (size_t i=0; i<num_faces; i++) {
39 const size_t ui = IC(i);
40 const bool consistent =
41 (F1(i,0) == uF(ui, 0) && F1(i,1) == uF(ui, 1) && F1(i,2) == uF(ui, 2)) ||
42 (F1(i,0) == uF(ui, 1) && F1(i,1) == uF(ui, 2) && F1(i,2) == uF(ui, 0)) ||
43 (F1(i,0) == uF(ui, 2) && F1(i,1) == uF(ui, 0) && F1(i,2) == uF(ui, 1));
44 uF2F[ui].push_back(int(i+1) * (consistent?1:-1));
45 counts(ui) += consistent ? 1:-1;
46 ucounts(ui)++;
47 }
48
49 std::vector<size_t> kept_faces;
50 for (size_t i=0; i<num_unique_faces; i++) {
51 if (ucounts[i] == 1) {
52 kept_faces.push_back(abs(uF2F[i][0])-1);
53 continue;
54 }
55 if (counts[i] == 1) {
56 bool found = false;
57 for (auto fid : uF2F[i]) {
58 if (fid > 0) {
59 kept_faces.push_back(abs(fid)-1);
60 found = true;
61 break;
62 }
63 }
64 assert(found);
65 } else if (counts[i] == -1) {
66 bool found = false;
67 for (auto fid : uF2F[i]) {
68 if (fid < 0) {
69 kept_faces.push_back(abs(fid)-1);
70 found = true;
71 break;
72 }
73 }
74 assert(found);
75 } else {
76 assert(counts[i] == 0);
77 }
78 }
79
80 const size_t num_kept = kept_faces.size();
81 J.resize(num_kept, 1);
82 std::copy(kept_faces.begin(), kept_faces.end(), J.data());
83 igl::slice(F1, J, 1, F2);
84}

References Eigen::PlainObjectBase< Derived >::data(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), slice(), and unique_simplices().

+ Here is the call graph for this function:

◆ rgb_to_hsv() [1/2]

template<typename DerivedR , typename DerivedH >
IGL_INLINE void igl::rgb_to_hsv ( const Eigen::PlainObjectBase< DerivedR > &  R,
Eigen::PlainObjectBase< DerivedH > &  H 
)
78{
79 assert(R.cols() == 3);
80 H.resizeLike(R);
81 for(typename DerivedR::Index r = 0;r<R.rows();r++)
82 {
83 typename DerivedR::Scalar rgb[3];
84 rgb[0] = R(r,0);
85 rgb[1] = R(r,1);
86 rgb[2] = R(r,2);
87 typename DerivedH::Scalar hsv[] = {0,0,0};
88 rgb_to_hsv(rgb,hsv);
89 H(r,0) = hsv[0];
90 H(r,1) = hsv[1];
91 H(r,2) = hsv[2];
92 }
93}

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::resizeLike(), rgb_to_hsv(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ rgb_to_hsv() [2/2]

template<typename R , typename H >
IGL_INLINE void igl::rgb_to_hsv ( const R *  rgb,
H *  hsv 
)
12{
13 // http://en.literateprograms.org/RGB_to_HSV_color_space_conversion_%28C%29
14 R rgb_max = 0.0;
15 R rgb_min = 1.0;
16 rgb_max = (rgb[0]>rgb_max?rgb[0]:rgb_max);
17 rgb_max = (rgb[1]>rgb_max?rgb[1]:rgb_max);
18 rgb_max = (rgb[2]>rgb_max?rgb[2]:rgb_max);
19 rgb_min = (rgb[0]<rgb_min?rgb[0]:rgb_min);
20 rgb_min = (rgb[1]<rgb_min?rgb[1]:rgb_min);
21 rgb_min = (rgb[2]<rgb_min?rgb[2]:rgb_min);
22 //hsv[2] = rgb_max;
23 hsv[2] = rgb_max;
24 if(hsv[2] == 0)
25 {
26 hsv[0]=hsv[1]=0;
27 return;
28 }
29 // normalize
30 R rgb_n[3];
31 rgb_n[0] = rgb[0]/hsv[2];
32 rgb_n[1] = rgb[1]/hsv[2];
33 rgb_n[2] = rgb[2]/hsv[2];
34 // Recomput max min?
35 rgb_max = 0;
36 rgb_max = (rgb_n[0]>rgb_max?rgb_n[0]:rgb_max);
37 rgb_max = (rgb_n[1]>rgb_max?rgb_n[1]:rgb_max);
38 rgb_max = (rgb_n[2]>rgb_max?rgb_n[2]:rgb_max);
39 rgb_min = 1;
40 rgb_min = (rgb_n[0]<rgb_min?rgb_n[0]:rgb_min);
41 rgb_min = (rgb_n[1]<rgb_min?rgb_n[1]:rgb_min);
42 rgb_min = (rgb_n[2]<rgb_min?rgb_n[2]:rgb_min);
43 hsv[1] = rgb_max - rgb_min;
44 if(hsv[1] == 0)
45 {
46 hsv[0] = 0;
47 return;
48 }
49 rgb_n[0] = (rgb_n[0] - rgb_min)/(rgb_max - rgb_min);
50 rgb_n[1] = (rgb_n[1] - rgb_min)/(rgb_max - rgb_min);
51 rgb_n[2] = (rgb_n[2] - rgb_min)/(rgb_max - rgb_min);
52 // Recomput max min?
53 rgb_max = 0;
54 rgb_max = (rgb_n[0]>rgb_max?rgb_n[0]:rgb_max);
55 rgb_max = (rgb_n[1]>rgb_max?rgb_n[1]:rgb_max);
56 rgb_max = (rgb_n[2]>rgb_max?rgb_n[2]:rgb_max);
57 rgb_min = 1;
58 rgb_min = (rgb_n[0]<rgb_min?rgb_n[0]:rgb_min);
59 rgb_min = (rgb_n[1]<rgb_min?rgb_n[1]:rgb_min);
60 rgb_min = (rgb_n[2]<rgb_min?rgb_n[2]:rgb_min);
61 if (rgb_max == rgb_n[0]) {
62 hsv[0] = 0.0 + 60.0*(rgb_n[1] - rgb_n[2]);
63 if (hsv[0] < 0.0) {
64 hsv[0] += 360.0;
65 }
66 } else if (rgb_max == rgb_n[1]) {
67 hsv[0] = 120.0 + 60.0*(rgb_n[2] - rgb_n[0]);
68 } else /* rgb_max == rgb_n[2] */ {
69 hsv[0] = 240.0 + 60.0*(rgb_n[0] - rgb_n[1]);
70 }
71}

Referenced by rgb_to_hsv().

+ Here is the caller graph for this function:

◆ rotate_by_quat()

template<typename Q_type >
IGL_INLINE void igl::rotate_by_quat ( const Q_type *  v,
const Q_type *  q,
Q_type *  out 
)
20{
21 // Quaternion form of v, copy data in v, (as a result out can be same pointer
22 // as v)
23 Q_type quat_v[4] = {v[0],v[1],v[2],0};
24
25 // normalize input
26 Q_type normalized_q[4];
27
28#ifndef NDEBUG
29 bool normalized =
30#endif
31 igl::normalize_quat<Q_type>(q,normalized_q);
32#ifndef NDEBUG
33 assert(normalized);
34#endif
35
36 // Conjugate of q
37 Q_type q_conj[4];
38 igl::quat_conjugate<Q_type>(normalized_q,q_conj);
39
40 // Rotate of vector v by quaternion q is:
41 // q*v*conj(q)
42 // Compute q*v
43 Q_type q_mult_quat_v[4];
44 igl::quat_mult<Q_type>(normalized_q,quat_v,q_mult_quat_v);
45 // Compute (q*v) * conj(q)
46 igl::quat_mult<Q_type>(q_mult_quat_v,q_conj,out);
47}

◆ rotate_vectors()

IGL_INLINE Eigen::MatrixXd igl::rotate_vectors ( const Eigen::MatrixXd &  V,
const Eigen::VectorXd &  A,
const Eigen::MatrixXd &  B1,
const Eigen::MatrixXd &  B2 
)
15{
16 Eigen::MatrixXd RV(V.rows(),V.cols());
17
18 for (unsigned i=0; i<V.rows();++i)
19 {
20 double norm = V.row(i).norm();
21
22 // project onto the tangent plane and convert to angle
23 double a = atan2(B2.row(i).dot(V.row(i)),B1.row(i).dot(V.row(i)));
24
25 // rotate
26 a += (A.size() == 1) ? A(0) : A(i);
27
28 // move it back to global coordinates
29 RV.row(i) = norm*cos(a) * B1.row(i) + norm*sin(a) * B2.row(i);
30 }
31
32 return RV;
33}

References cos(), and sin().

Referenced by line_field_missmatch().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ rotation_matrix_from_directions()

template<typename Scalar >
IGL_INLINE Eigen::Matrix< Scalar, 3, 3 > igl::rotation_matrix_from_directions ( const Eigen::Matrix< Scalar, 3, 1 >  v0,
const Eigen::Matrix< Scalar, 3, 1 >  v1 
)

control if there is no rotation

find the axis of rotation

construct rotation matrix

17{
19 const double epsilon=1e-8;
20 Scalar dot=v0.normalized().dot(v1.normalized());
22 if ((v0-v1).norm()<epsilon)
23 {
25 return rotM;
26 }
27 if ((v0+v1).norm()<epsilon)
28 {
30 rotM(0,0) = 1.;
31 std::cerr<<"igl::rotation_matrix_from_directions: rotating around x axis by 180o"<<std::endl;
32 return rotM;
33 }
36 axis=v0.cross(v1);
37 axis.normalize();
38
40 Scalar u=axis(0);
41 Scalar v=axis(1);
42 Scalar w=axis(2);
43 Scalar phi=acos(dot);
44 Scalar rcos = cos(phi);
45 Scalar rsin = sin(phi);
46
47 rotM(0,0) = rcos + u*u*(1-rcos);
48 rotM(1,0) = w * rsin + v*u*(1-rcos);
49 rotM(2,0) = -v * rsin + w*u*(1-rcos);
50 rotM(0,1) = -w * rsin + u*v*(1-rcos);
51 rotM(1,1) = rcos + v*v*(1-rcos);
52 rotM(2,1) = u * rsin + w*v*(1-rcos);
53 rotM(0,2) = v * rsin + u*w*(1-rcos);
54 rotM(1,2) = -u * rsin + v*w*(1-rcos);
55 rotM(2,2) = rcos + w*w*(1-rcos);
56
57 return rotM;
58}

References acos(), cos(), dot(), and sin().

Referenced by igl::CombLine< DerivedV, DerivedF >::comb(), igl::Comb< DerivedV, DerivedF >::comb(), igl::MissMatchCalculator< DerivedV, DerivedF, DerivedM >::MissMatchByCross(), and igl::MissMatchCalculatorLine< DerivedV, DerivedF, DerivedO >::MissMatchByLine().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ round() [1/2]

template<typename DerivedX >
DerivedX igl::round ( const DerivedX  r)

Referenced by round().

+ Here is the caller graph for this function:

◆ round() [2/2]

template<typename DerivedX , typename DerivedY >
IGL_INLINE void igl::round ( const Eigen::PlainObjectBase< DerivedX > &  X,
Eigen::PlainObjectBase< DerivedY > &  Y 
)
23{
24 Y.resizeLike(X);
25 // loop over rows
26 for(int i = 0;i<X.rows();i++)
27 {
28 // loop over cols
29 for(int j = 0;j<X.cols();j++)
30 {
31 Y(i,j) = igl::round(X(i,j));
32 }
33 }
34}
DerivedX round(const DerivedX r)

References round().

+ Here is the call graph for this function:

◆ rows_to_matrix()

template<class Row , class Mat >
IGL_INLINE bool igl::rows_to_matrix ( const std::vector< Row > &  V,
Mat &  M 
)
18{
19 // number of columns
20 int m = V.size();
21 if(m == 0)
22 {
23 fprintf(stderr,"Error: rows_to_matrix() list is empty()\n");
24 return false;
25 }
26 // number of rows
27 int n = igl::min_size(V);
28 if(n != igl::max_size(V))
29 {
30 fprintf(stderr,"Error: rows_to_matrix()"
31 " list elements are not all the same size\n");
32 return false;
33 }
34 assert(n != -1);
35 // Resize output
36 M.resize(m,n);
37
38 // Loop over rows
39 int i = 0;
40 typename std::vector<Row>::const_iterator iter = V.begin();
41 while(iter != V.end())
42 {
43 M.row(i) = V[i];
44 // increment index and iterator
45 i++;
46 iter++;
47 }
48
49 return true;
50}

References max_size(), and min_size().

+ Here is the call graph for this function:

◆ sample_edges()

IGL_INLINE void igl::sample_edges ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  E,
const int  k,
Eigen::MatrixXd &  S 
)
15{
16 using namespace Eigen;
17 // Resize output
18 S.resize(V.rows() + k * E.rows(),V.cols());
19 // Copy V at front of S
20 S.block(0,0,V.rows(),V.cols()) = V;
21
22 // loop over edges
23 for(int i = 0;i<E.rows();i++)
24 {
25 VectorXd tip = V.row(E(i,0));
26 VectorXd tail = V.row(E(i,1));
27 for(int s=0;s<k;s++)
28 {
29 double f = double(s+1)/double(k+1);
30 S.row(V.rows()+k*i+s) = f*tail + (1.0-f)*tip;
31 }
32 }
33}

References tail().

Referenced by igl::copyleft::tetgen::mesh_with_skeleton().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ seam_edges()

template<typename DerivedV , typename DerivedTC , typename DerivedF , typename DerivedFTC , typename Derivedseams , typename Derivedboundaries , typename Derivedfoldovers >
IGL_INLINE void igl::seam_edges ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedTC > &  TC,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedFTC > &  FTC,
Eigen::PlainObjectBase< Derivedseams > &  seams,
Eigen::PlainObjectBase< Derivedboundaries > &  boundaries,
Eigen::PlainObjectBase< Derivedfoldovers > &  foldovers 
)
32{
33 // Assume triangles.
34 assert( F.cols() == 3 );
35 assert( F.cols() == FTC.cols() );
36 assert( F.rows() == FTC.rows() );
37
38 // Assume 2D texture coordinates (foldovers tests).
39 assert( TC.cols() == 2 );
41 // Computes the orientation of `c` relative to the line between `a` and `b`.
42 // Assumes 2D vector input.
43 // Based on: https://www.cs.cmu.edu/~quake/robust.html
44 const auto& Orientation = [](
45 const Vector2S& a,
46 const Vector2S& b,
47 const Vector2S& c ) -> typename DerivedTC::Scalar
48 {
49 const Vector2S row0 = a - c;
50 const Vector2S row1 = b - c;
51 return row0(0)*row1(1) - row1(0)*row0(1);
52 };
53
54 seams .setZero( 3*F.rows(), 4 );
55 boundaries.setZero( 3*F.rows(), 2 );
56 foldovers .setZero( 3*F.rows(), 4 );
57
58 int num_seams = 0;
59 int num_boundaries = 0;
60 int num_foldovers = 0;
61
62 // A map from a pair of vertex indices to the index (face and endpoints)
63 // into face_position_indices.
64 // The following should be true for every key, value pair:
65 // key == face_position_indices[ value ]
66 // This gives us a "reverse map" so that we can look up other face
67 // attributes based on position edges.
68 // The value are written in the format returned by numpy.where(),
69 // which stores multi-dimensional indices such as array[a0,b0], array[a1,b1]
70 // as ( (a0,a1), (b0,b1) ).
71
72 // We need to make a hash function for our directed edges.
73 // We'll use i*V.rows() + j.
74 typedef std::pair< typename DerivedF::Scalar, typename DerivedF::Scalar >
75 directed_edge;
76 const int numV = V.rows();
77 const int numF = F.rows();
78 const auto& edge_hasher =
79 [numV]( directed_edge const& e ) { return e.first*numV + e.second; };
80 // When we pass a hash function object, we also need to specify the number of
81 // buckets. The Euler characteristic says that the number of undirected edges
82 // is numV + numF -2*genus.
83 std::unordered_map<directed_edge,std::pair<int,int>,decltype(edge_hasher) >
84 directed_position_edge2face_position_index(2*( numV + numF ), edge_hasher);
85 for( int fi = 0; fi < F.rows(); ++fi )
86 {
87 for( int i = 0; i < 3; ++i )
88 {
89 const int j = ( i+1 ) % 3;
90 directed_position_edge2face_position_index[
91 std::make_pair( F(fi,i), F(fi,j) ) ] = std::make_pair( fi, i );
92 }
93 }
94
95 // First find all undirected position edges (collect a canonical orientation
96 // of the directed edges).
97 std::unordered_set< directed_edge, decltype( edge_hasher ) >
98 undirected_position_edges( numV + numF, edge_hasher );
99 for( const auto& el : directed_position_edge2face_position_index )
100 {
101 // The canonical orientation is the one where the smaller of
102 // the two vertex indices is first.
103 undirected_position_edges.insert( std::make_pair(
104 std::min( el.first.first, el.first.second ),
105 std::max( el.first.first, el.first.second ) ) );
106 }
107
108 // Now we will iterate over all position edges.
109 // Seam edges are the edges whose two opposite directed edges have different
110 // texcoord indices (or one doesn't exist at all in the case of a mesh
111 // boundary).
112 for( const auto& vp_edge : undirected_position_edges )
113 {
114 // We should only see canonical edges,
115 // where the first vertex index is smaller.
116 assert( vp_edge.first < vp_edge.second );
117
118 const auto vp_edge_reverse = std::make_pair(vp_edge.second, vp_edge.first);
119 // If it and its opposite exist as directed edges, check if their
120 // texture coordinate indices match.
121 if( directed_position_edge2face_position_index.count( vp_edge ) &&
122 directed_position_edge2face_position_index.count( vp_edge_reverse ) )
123 {
124 const auto forwards =
125 directed_position_edge2face_position_index[ vp_edge ];
126 const auto backwards =
127 directed_position_edge2face_position_index[ vp_edge_reverse ];
128
129 // NOTE: They should never be equal.
130 assert( forwards != backwards );
131
132 // If the texcoord indices match (are similarly flipped),
133 // this edge is not a seam. It could be a foldover.
134 if(
135 std::make_pair(
136 FTC( forwards.first, forwards.second ),
137 FTC( forwards.first, ( forwards.second+1 ) % 3 ) )
138 ==
139 std::make_pair(
140 FTC( backwards.first, ( backwards.second+1 ) % 3 ),
141 FTC( backwards.first, backwards.second ) ))
142 {
143 // Check for foldovers in UV space.
144 // Get the edge (a,b) and the two opposite vertices's texture
145 // coordinates.
146 const Vector2S a = TC.row( FTC( forwards.first, forwards.second ) );
147 const Vector2S b =
148 TC.row( FTC( forwards.first, (forwards.second+1) % 3 ) );
149 const Vector2S c_forwards =
150 TC.row( FTC( forwards .first, (forwards .second+2) % 3 ) );
151 const Vector2S c_backwards =
152 TC.row( FTC( backwards.first, (backwards.second+2) % 3 ) );
153 // If the opposite vertices' texture coordinates fall on the same side
154 // of the edge, we have a UV-space foldover.
155 const auto orientation_forwards = Orientation( a, b, c_forwards );
156 const auto orientation_backwards = Orientation( a, b, c_backwards );
157 if( ( orientation_forwards > 0 && orientation_backwards > 0 ) ||
158 ( orientation_forwards < 0 && orientation_backwards < 0 )
159 ) {
160 foldovers( num_foldovers, 0 ) = forwards.first;
161 foldovers( num_foldovers, 1 ) = forwards.second;
162 foldovers( num_foldovers, 2 ) = backwards.first;
163 foldovers( num_foldovers, 3 ) = backwards.second;
164 num_foldovers += 1;
165 }
166 }
167 // Otherwise, we have a non-matching seam edge.
168 else
169 {
170 seams( num_seams, 0 ) = forwards.first;
171 seams( num_seams, 1 ) = forwards.second;
172 seams( num_seams, 2 ) = backwards.first;
173 seams( num_seams, 3 ) = backwards.second;
174 num_seams += 1;
175 }
176 }
177 // Otherwise, the edge and its opposite aren't both in the directed edges.
178 // One of them should be.
179 else if( directed_position_edge2face_position_index.count( vp_edge ) )
180 {
181 const auto forwards = directed_position_edge2face_position_index[vp_edge];
182 boundaries( num_boundaries, 0 ) = forwards.first;
183 boundaries( num_boundaries, 1 ) = forwards.second;
184 num_boundaries += 1;
185 } else if(
186 directed_position_edge2face_position_index.count( vp_edge_reverse ) )
187 {
188 const auto backwards =
189 directed_position_edge2face_position_index[ vp_edge_reverse ];
190 boundaries( num_boundaries, 0 ) = backwards.first;
191 boundaries( num_boundaries, 1 ) = backwards.second;
192 num_boundaries += 1;
193 } else {
194 // This should never happen! One of these two must have been seen.
195 assert(
196 directed_position_edge2face_position_index.count( vp_edge ) ||
197 directed_position_edge2face_position_index.count( vp_edge_reverse )
198 );
199 }
200 }
201
202 seams .conservativeResize( num_seams, Eigen::NoChange_t() );
203 boundaries.conservativeResize( num_boundaries, Eigen::NoChange_t() );
204 foldovers .conservativeResize( num_foldovers, Eigen::NoChange_t() );
205}
NoChange_t
Definition Constants.h:350
Orientation
Definition geometry_traits.hpp:131

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::conservativeResize(), Eigen::PlainObjectBase< Derived >::rows(), and Eigen::PlainObjectBase< Derived >::setZero().

+ Here is the call graph for this function:

◆ segments_intersect()

template<typename DerivedSource , typename DerivedDir >
IGL_INLINE bool igl::segments_intersect ( const Eigen::PlainObjectBase< DerivedSource > &  p,
const Eigen::PlainObjectBase< DerivedDir > &  r,
const Eigen::PlainObjectBase< DerivedSource > &  q,
const Eigen::PlainObjectBase< DerivedDir > &  s,
double &  t,
double &  u,
double  eps = 1e-6 
)
22{
23 // http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
24 // Search intersection between two segments
25 // p + t*r : t \in [0,1]
26 // q + u*s : u \in [0,1]
27
28 // p + t * r = q + u * s // x s
29 // t(r x s) = (q - p) x s
30 // t = (q - p) x s / (r x s)
31
32 // (r x s) ~ 0 --> directions are parallel, they will never cross
33 Eigen::RowVector3d rxs = r.cross(s);
34 if (rxs.norm() <= eps)
35 return false;
36
37 int sign;
38
39 double u;
40 // u = (q − p) × r / (r × s)
41 Eigen::RowVector3d u1 = (q - p).cross(r);
42 sign = ((u1.dot(rxs)) > 0) ? 1 : -1;
43 u = u1.norm() / rxs.norm();
44 u = u * sign;
45
46 if ((u - 1.) > eps || u < -eps)
47 return false;
48
49 double t;
50 // t = (q - p) x s / (r x s)
51 Eigen::RowVector3d t1 = (q - p).cross(s);
52 sign = ((t1.dot(rxs)) > 0) ? 1 : -1;
53 t = t1.norm() / rxs.norm();
54 t = t * sign;
55
56 if (t < -eps || fabs(t) < eps)
57 return false;
58
59 a_t = t;
60 a_u = u;
61
62 return true;
63};

References cross(), and sign().

+ Here is the call graph for this function:

◆ serialize() [1/3]

template<typename T >
bool igl::serialize ( const T &  obj,
const std::string &  filename 
)
inline
415 {
416 return serialize(obj,"obj",filename,true);
417 }
void serialize(Archive &ar, FacenamesSerializer &t, const std::uint32_t version)
Definition GLGizmoEmboss.cpp:1562

References serialize().

Referenced by igl::opengl::glfw::Viewer::save_scene(), serialize(), serialize(), igl::xml::XMLSerializable::XMLSerializationObject< T >::Serialize(), igl::Serializable::SerializationObject< T >::Serialize(), igl::xml::serialize_xml(), serializer(), serializer(), and serializer().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ serialize() [2/3]

template<typename T >
bool igl::serialize ( const T &  obj,
const std::string &  objectName,
const std::string &  filename,
bool  overwrite = false 
)
inline
421 {
422 bool success = false;
423
424 std::vector<char> buffer;
425
426 std::ios_base::openmode mode = std::ios::out | std::ios::binary;
427
428 if(overwrite)
429 mode |= std::ios::trunc;
430 else
431 mode |= std::ios::app;
432
433 std::ofstream file(filename.c_str(),mode);
434
435 if(file.is_open())
436 {
437 serialize(obj,objectName,buffer);
438
439 file.write(&buffer[0],buffer.size());
440
441 file.close();
442
443 success = true;
444 }
445 else
446 {
447 std::cerr << "serialization: file " << filename << " not found!" << std::endl;
448 }
449
450 return success;
451 }
IGL_INLINE void mode(const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &X, const int d, Eigen::Matrix< T, Eigen::Dynamic, 1 > &M)
Definition mode.cpp:14

References mode(), and serialize().

+ Here is the call graph for this function:

◆ serialize() [3/3]

template<typename T >
bool igl::serialize ( const T &  obj,
const std::string &  objectName,
std::vector< char > &  buffer 
)
inline
455 {
456 // serialize object data
457 size_t size = serialization::getByteSize(obj);
458 std::vector<char> tmp(size);
459 auto it = tmp.begin();
460 serialization::serialize(obj,tmp,it);
461
462 std::string objectType(typeid(obj).name());
463 size_t newObjectSize = tmp.size();
464 size_t newHeaderSize = serialization::getByteSize(objectName) + serialization::getByteSize(objectType) + sizeof(size_t);
465 size_t curSize = buffer.size();
466 size_t newSize = curSize + newHeaderSize + newObjectSize;
467
468 buffer.resize(newSize);
469
470 std::vector<char>::iterator iter = buffer.begin()+curSize;
471
472 // serialize object header (name/type/size)
473 serialization::serialize(objectName,buffer,iter);
474 serialization::serialize(objectType,buffer,iter);
475 serialization::serialize(newObjectSize,buffer,iter);
476
477 // copy serialized data to buffer
478 iter = std::copy(tmp.begin(),tmp.end(),iter);
479
480 return true;
481 }

References igl::serialization::getByteSize(), and igl::serialization::serialize().

+ Here is the call graph for this function:

◆ serializer() [1/3]

template<typename T >
bool igl::serializer ( bool  serialize,
T &  obj,
const std::string &  filename 
)
inline
560 {
561 return s ? serialize(obj,filename) : deserialize(obj,filename);
562 }

References deserialize(), and serialize().

+ Here is the call graph for this function:

◆ serializer() [2/3]

template<typename T >
bool igl::serializer ( bool  serialize,
T &  obj,
const std::string &  objectName,
const std::string &  filename,
bool  overwrite = false 
)
inline
566 {
567 return s ? serialize(obj,objectName,filename,overwrite) : deserialize(obj,objectName,filename);
568 }

References deserialize(), and serialize().

+ Here is the call graph for this function:

◆ serializer() [3/3]

template<typename T >
bool igl::serializer ( bool  serialize,
T &  obj,
const std::string &  objectName,
std::vector< char > &  buffer 
)
inline
572 {
573 return s ? serialize(obj,objectName,buffer) : deserialize(obj,objectName,buffer);
574 }

References deserialize(), and serialize().

+ Here is the call graph for this function:

◆ setdiff()

template<typename DerivedA , typename DerivedB , typename DerivedC , typename DerivedIA >
IGL_INLINE void igl::setdiff ( const Eigen::DenseBase< DerivedA > &  A,
const Eigen::DenseBase< DerivedB > &  B,
Eigen::PlainObjectBase< DerivedC > &  C,
Eigen::PlainObjectBase< DerivedIA > &  IA 
)
24{
25 using namespace Eigen;
26 using namespace std;
27 // boring base cases
28 if(A.size() == 0)
29 {
30 C.resize(0,1);
31 IA.resize(0,1);
32 return;
33 }
34
35 // Get rid of any duplicates
38 VectorA uA;
39 VectorB uB;
40 typedef DerivedIA IAType;
41 IAType uIA,uIuA,uIB,uIuB;
42 unique(A,uA,uIA,uIuA);
43 unique(B,uB,uIB,uIuB);
44
45 // Sort both
46 VectorA sA;
47 VectorB sB;
48 IAType sIA,sIB;
49 sort(uA,1,true,sA,sIA);
50 sort(uB,1,true,sB,sIB);
51
52 vector<typename DerivedB::Scalar> vC;
53 vector<typename DerivedIA::Scalar> vIA;
54 int bi = 0;
55 // loop over sA
56 bool past = false;
57 bool sBempty = sB.size()==0;
58 for(int a = 0;a<sA.size();a++)
59 {
60 while(!sBempty && !past && sA(a)>sB(bi))
61 {
62 bi++;
63 past = bi>=sB.size();
64 }
65 if(sBempty || past || sA(a)<sB(bi))
66 {
67 // then sA(a) did not appear in sB
68 vC.push_back(sA(a));
69 vIA.push_back(uIA(sIA(a)));
70 }
71 }
72 list_to_matrix(vC,C);
73 list_to_matrix(vIA,IA);
74}

References list_to_matrix(), Eigen::PlainObjectBase< Derived >::resize(), sort(), and unique().

Referenced by directed_edge_parents(), and setxor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setunion()

template<typename DerivedA , typename DerivedB , typename DerivedC , typename DerivedIA , typename DerivedIB >
IGL_INLINE void igl::setunion ( const Eigen::DenseBase< DerivedA > &  A,
const Eigen::DenseBase< DerivedB > &  B,
Eigen::PlainObjectBase< DerivedC > &  C,
Eigen::PlainObjectBase< DerivedIA > &  IA,
Eigen::PlainObjectBase< DerivedIB > &  IB 
)
23{
24 DerivedC CS(A.size()+B.size(),1);
25 {
26 int k = 0;
27 for(int j = 0;j<A.cols();j++)
28 {
29 for(int i = 0;i<A.rows();i++)
30 {
31 CS(k++) = A(i,j);
32 }
33 }
34 for(int j = 0;j<B.cols();j++)
35 {
36 for(int i = 0;i<B.rows();i++)
37 {
38 CS(k++) = B(i,j);
39 }
40 }
41 assert(k==CS.size());
42 }
43 DerivedIA IAC;
44 {
45 DerivedIA IC;
46 unique(CS,C,IAC,IC);
47 }
48 const int nia = (IAC.array()<A.size()).count();
49 IA.resize(nia);
50 IB.resize(IAC.size() - nia);
51 {
52 int ka = 0;
53 int kb = 0;
54 for(int i = 0;i<IAC.size();i++)
55 {
56 if(IAC(i)<A.size())
57 {
58 IA(ka++) = IAC(i);
59 }else
60 {
61 IB(kb++) = IAC(i)-A.size();
62 }
63 }
64 assert(ka == IA.size());
65 assert(kb == IB.size());
66 }
67
68}

References count(), Eigen::PlainObjectBase< Derived >::resize(), and unique().

Referenced by setxor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setxor()

template<typename DerivedA , typename DerivedB , typename DerivedC , typename DerivedIA , typename DerivedIB >
IGL_INLINE void igl::setxor ( const Eigen::DenseBase< DerivedA > &  A,
const Eigen::DenseBase< DerivedB > &  B,
Eigen::PlainObjectBase< DerivedC > &  C,
Eigen::PlainObjectBase< DerivedIA > &  IA,
Eigen::PlainObjectBase< DerivedIB > &  IB 
)
18{
19 DerivedC AB,BA;
20 DerivedIA IAB,IBA;
21 setdiff(A,B,AB,IAB);
22 setdiff(B,A,BA,IBA);
23 setunion(AB,BA,C,IA,IB);
24 slice(IAB,DerivedIA(IA),IA);
25 slice(IBA,DerivedIB(IB),IB);
26}
IGL_INLINE void setunion(const Eigen::DenseBase< DerivedA > &A, const Eigen::DenseBase< DerivedB > &B, Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedIA > &IA, Eigen::PlainObjectBase< DerivedIB > &IB)
Definition setunion.cpp:17

References setdiff(), setunion(), and slice().

Referenced by straighten_seams().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ shape_diameter_function() [1/4]

template<typename DerivedV , typename DerivedF , typename DerivedS >
IGL_INLINE void igl::shape_diameter_function ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const bool  per_face,
const int  num_samples,
Eigen::PlainObjectBase< DerivedS > &  S 
)
157{
158 if (per_face)
159 {
160 DerivedV N;
161 igl::per_face_normals(V, F, N);
162 DerivedV P;
163 igl::barycenter(V, F, P);
164 return igl::shape_diameter_function(V, F, P, N, num_samples, S);
165 }
166 else
167 {
168 DerivedV N;
170 return igl::shape_diameter_function(V, F, V, N, num_samples, S);
171 }
172}
IGL_INLINE void shape_diameter_function(const std::function< double(const Eigen::Vector3f &, const Eigen::Vector3f &) > &shoot_ray, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedN > &N, const int num_samples, Eigen::PlainObjectBase< DerivedS > &S)
Definition shape_diameter_function.cpp:25

References barycenter(), per_face_normals(), per_vertex_normals(), and shape_diameter_function().

+ Here is the call graph for this function:

◆ shape_diameter_function() [2/4]

template<typename DerivedV , typename DerivedF , typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void igl::shape_diameter_function ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedP > &  P,
const Eigen::PlainObjectBase< DerivedN > &  N,
const int  num_samples,
Eigen::PlainObjectBase< DerivedS > &  S 
)
122{
123 if(F.rows() < 100)
124 {
125 // Super naive
126 const auto & shoot_ray = [&V,&F](
127 const Eigen::Vector3f& _s,
128 const Eigen::Vector3f& dir)->double
129 {
130 Eigen::Vector3f s = _s+1e-4*dir;
131 igl::Hit hit;
132 if(ray_mesh_intersect(s,dir,V,F,hit))
133 {
134 return hit.t;
135 }else
136 {
137 return std::numeric_limits<double>::infinity();
138 }
139 };
140 return shape_diameter_function(shoot_ray,P,N,num_samples,S);
141 }
142 AABB<DerivedV,3> aabb;
143 aabb.init(V,F);
144 return shape_diameter_function(aabb,V,F,P,N,num_samples,S);
145}
IGL_INLINE void shape_diameter_function(const EmbreeIntersector &ei, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedN > &N, const int num_samples, Eigen::PlainObjectBase< DerivedS > &S)
Definition shape_diameter_function.cpp:17
float t
Definition Hit.h:22

References igl::AABB< DerivedV, DIM >::init(), ray_mesh_intersect(), and igl::Hit::t.

+ Here is the call graph for this function:

◆ shape_diameter_function() [3/4]

template<typename DerivedV , int DIM, typename DerivedF , typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void igl::shape_diameter_function ( const igl::AABB< DerivedV, DIM > &  aabb,
const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedP > &  P,
const Eigen::PlainObjectBase< DerivedN > &  N,
const int  num_samples,
Eigen::PlainObjectBase< DerivedS > &  S 
)
85{
86 const auto & shoot_ray = [&aabb,&V,&F](
87 const Eigen::Vector3f& _s,
88 const Eigen::Vector3f& dir)->double
89 {
90 Eigen::Vector3f s = _s+1e-4*dir;
91 igl::Hit hit;
92 if(aabb.intersect_ray(
93 V,
94 F,
95 s .cast<typename DerivedV::Scalar>().eval(),
96 dir.cast<typename DerivedV::Scalar>().eval(),
97 hit))
98 {
99 return hit.t;
100 }else
101 {
102 return std::numeric_limits<double>::infinity();
103 }
104 };
105 return shape_diameter_function(shoot_ray,P,N,num_samples,S);
106
107}

References igl::AABB< DerivedV, DIM >::intersect_ray(), and igl::Hit::t.

+ Here is the call graph for this function:

◆ shape_diameter_function() [4/4]

template<typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void igl::shape_diameter_function ( const std::function< double(const Eigen::Vector3f &, const Eigen::Vector3f &) > &  shoot_ray,
const Eigen::PlainObjectBase< DerivedP > &  P,
const Eigen::PlainObjectBase< DerivedN > &  N,
const int  num_samples,
Eigen::PlainObjectBase< DerivedS > &  S 
)
35{
36 using namespace Eigen;
37 const int n = P.rows();
38 // Resize output
39 S.resize(n,1);
40 // Embree seems to be parallel when constructing but not when tracing rays
41 const MatrixXf D = random_dir_stratified(num_samples).cast<float>();
42
43 const auto & inner = [&P,&N,&num_samples,&D,&S,&shoot_ray](const int p)
44 {
45 const Vector3f origin = P.row(p).template cast<float>();
46 const Vector3f normal = N.row(p).template cast<float>();
47 int num_hits = 0;
48 double total_distance = 0;
49 for(int s = 0;s<num_samples;s++)
50 {
51 Vector3f d = D.row(s);
52 // Shoot _inward_
53 if(d.dot(normal) > 0)
54 {
55 // reverse ray
56 d *= -1;
57 }
58 const double dist = shoot_ray(origin,d);
59 if(std::isfinite(dist))
60 {
61 total_distance += dist;
62 num_hits++;
63 }
64 }
65 S(p) = total_distance/(double)num_hits;
66 };
67 parallel_for(n,inner,1000);
68}

References parallel_for(), random_dir_stratified(), Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::rows().

Referenced by shape_diameter_function(), and igl::embree::shape_diameter_function().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ shapeup_identity_projection()

IGL_INLINE bool igl::shapeup_identity_projection ( const Eigen::PlainObjectBase< Eigen::MatrixXd > &  P,
const Eigen::PlainObjectBase< Eigen::VectorXi > &  SC,
const Eigen::PlainObjectBase< Eigen::MatrixXi > &  S,
Eigen::PlainObjectBase< Eigen::MatrixXd > &  projP 
)
22 {
23 projP.conservativeResize(SC.rows(), 3*SC.maxCoeff());
24 for (int i=0;i<S.rows();i++){
25 Eigen::RowVector3d avgCurrP=Eigen::RowVector3d::Zero();
26 for (int j=0;j<SC(i);j++)
27 avgCurrP+=P.row(S(i,j))/(double)(SC(i));
28
29 for (int j=0;j<SC(i);j++)
30 projP.block(i,3*j,1,3)=P.row(S(i,j))-avgCurrP;
31 }
32 return true;
33 }

References Eigen::PlainObjectBase< Derived >::conservativeResize(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ shapeup_precomputation()

template<typename DerivedP , typename DerivedSC , typename DerivedS , typename Derivedw >
IGL_INLINE bool igl::shapeup_precomputation ( const Eigen::PlainObjectBase< DerivedP > &  P,
const Eigen::PlainObjectBase< DerivedSC > &  SC,
const Eigen::PlainObjectBase< DerivedS > &  S,
const Eigen::PlainObjectBase< DerivedS > &  E,
const Eigen::PlainObjectBase< DerivedSC > &  b,
const Eigen::PlainObjectBase< Derivedw > &  wShape,
const Eigen::PlainObjectBase< Derivedw > &  wSmooth,
ShapeupData sudata 
)
89 {
90 using namespace std;
91 using namespace Eigen;
92 sudata.P=P;
93 sudata.SC=SC;
94 sudata.S=S;
95 sudata.b=b;
96 typedef typename DerivedP::Scalar Scalar;
97
98 //checking for consistency of the input
99 assert(SC.rows()==S.rows());
100 assert(SC.rows()==wShape.rows());
101 assert(E.rows()==wSmooth.rows());
102 assert(b.rows()!=0); //would lead to matrix becoming SPD
103
104 sudata.DShape.conservativeResize(SC.sum(), P.rows()); //Shape matrix (integration);
105 sudata.DClose.conservativeResize(b.rows(), P.rows()); //Closeness matrix for positional constraints
106 sudata.DSmooth.conservativeResize(E.rows(), P.rows()); //smoothness matrix
107
108 //Building shape matrix
109 std::vector<Triplet<Scalar> > DShapeTriplets;
110 int currRow=0;
111 for (int i=0;i<S.rows();i++){
112 Scalar avgCoeff=1.0/(Scalar)SC(i);
113
114 for (int j=0;j<SC(i);j++){
115 for (int k=0;k<SC(i);k++){
116 if (j==k)
117 DShapeTriplets.push_back(Triplet<Scalar>(currRow+j, S(i,k), (1.0-avgCoeff)));
118 else
119 DShapeTriplets.push_back(Triplet<Scalar>(currRow+j, S(i,k), (-avgCoeff)));
120 }
121 }
122 currRow+=SC(i);
123
124 }
125
126 sudata.DShape.setFromTriplets(DShapeTriplets.begin(), DShapeTriplets.end());
127
128 //Building closeness matrix
129 std::vector<Triplet<Scalar> > DCloseTriplets;
130 for (int i=0;i<b.size();i++)
131 DCloseTriplets.push_back(Triplet<Scalar>(i,b(i), 1.0));
132
133 sudata.DClose.setFromTriplets(DCloseTriplets.begin(), DCloseTriplets.end());
134
135 //Building smoothness matrix
136 std::vector<Triplet<Scalar> > DSmoothTriplets;
137 for (int i=0; i<E.rows(); i++) {
138 DSmoothTriplets.push_back(Triplet<Scalar>(i, E(i, 0), -1));
139 DSmoothTriplets.push_back(Triplet<Scalar>(i, E(i, 1), 1));
140 }
141
142 SparseMatrix<Scalar> tempMat;
143 igl::cat(1, sudata.DShape, sudata.DClose, tempMat);
144 igl::cat(1, tempMat, sudata.DSmooth, sudata.A);
145
146 //weight matrix
147 vector<Triplet<Scalar> > WTriplets;
148
149 //one weight per set in S.
150 currRow=0;
151 for (int i=0;i<SC.rows();i++){
152 for (int j=0;j<SC(i);j++)
153 WTriplets.push_back(Triplet<double>(currRow+j,currRow+j,sudata.shapeCoeff*wShape(i)));
154 currRow+=SC(i);
155 }
156
157 for (int i=0;i<b.size();i++)
158 WTriplets.push_back(Triplet<double>(SC.sum()+i, SC.sum()+i, sudata.closeCoeff));
159
160 for (int i=0;i<E.rows();i++)
161 WTriplets.push_back(Triplet<double>(SC.sum()+b.size()+i, SC.sum()+b.size()+i, sudata.smoothCoeff*wSmooth(i)));
162
163 sudata.W.conservativeResize(SC.sum()+b.size()+E.rows(), SC.sum()+b.size()+E.rows());
164 sudata.W.setFromTriplets(WTriplets.begin(), WTriplets.end());
165
166 sudata.At=sudata.A.transpose(); //for efficieny, as we use the transpose a lot in the iteration
167 sudata.Q=sudata.At*sudata.W*sudata.A;
168
169 return min_quad_with_fixed_precompute(sudata.Q,VectorXi(),SparseMatrix<double>(),true,sudata.solver_data);
170 }
void conservativeResize(Index rows, Index cols)
Definition SparseMatrix.h:553
Eigen::SparseMatrix< double > At
Definition shapeup.h:39
Eigen::SparseMatrix< double > Q
Definition shapeup.h:39
double closeCoeff
Definition shapeup.h:36
Eigen::SparseMatrix< double > DSmooth
Definition shapeup.h:39
Eigen::MatrixXd P
Definition shapeup.h:30
min_quad_with_fixed_data< double > solver_data
Definition shapeup.h:41
Eigen::SparseMatrix< double > DShape
Definition shapeup.h:39
Eigen::SparseMatrix< double > DClose
Definition shapeup.h:39
double shapeCoeff
Definition shapeup.h:36
Eigen::VectorXi b
Definition shapeup.h:33
Eigen::SparseMatrix< double > A
Definition shapeup.h:39
Eigen::VectorXi SC
Definition shapeup.h:31
Eigen::SparseMatrix< double > W
Definition shapeup.h:39
double smoothCoeff
Definition shapeup.h:36
Eigen::MatrixXi S
Definition shapeup.h:32

References igl::ShapeupData::A, igl::ShapeupData::At, igl::ShapeupData::b, cat(), igl::ShapeupData::closeCoeff, Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::conservativeResize(), igl::ShapeupData::DClose, igl::ShapeupData::DShape, igl::ShapeupData::DSmooth, min_quad_with_fixed_precompute(), igl::ShapeupData::P, igl::ShapeupData::Q, Eigen::PlainObjectBase< Derived >::rows(), igl::ShapeupData::S, igl::ShapeupData::SC, Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets(), igl::ShapeupData::shapeCoeff, igl::ShapeupData::smoothCoeff, igl::ShapeupData::solver_data, Eigen::SparseMatrixBase< Derived >::transpose(), and igl::ShapeupData::W.

+ Here is the call graph for this function:

◆ shapeup_regular_face_projection()

IGL_INLINE bool igl::shapeup_regular_face_projection ( const Eigen::PlainObjectBase< Eigen::MatrixXd > &  P,
const Eigen::PlainObjectBase< Eigen::VectorXi > &  SC,
const Eigen::PlainObjectBase< Eigen::MatrixXi > &  S,
Eigen::PlainObjectBase< Eigen::MatrixXd > &  projP 
)
37 {
38 projP.conservativeResize(SC.rows(), 3*SC.maxCoeff());
39 for (int currRow=0;currRow<SC.rows();currRow++){
40 //computing average
41 int N=SC(currRow);
42 const Eigen::RowVectorXi SRow=S.row(currRow);
43 Eigen::RowVector3d avgCurrP=Eigen::RowVector3d::Zero();
44 Eigen::MatrixXd targetPolygon(N, 3);
45 Eigen::MatrixXd sourcePolygon(N, 3);
46 for (int j=0;j<N;j++)
47 avgCurrP+=P.row(SRow(j))/(double)(N);
48
49 for (int j=0;j<N;j++)
50 targetPolygon.row(j)=P.row(SRow(j))-avgCurrP;
51
52 //creating perfectly regular source polygon
53 for (int j=0;j<N;j++)
54 sourcePolygon.row(j)<<cos(2*igl::PI*(double)j/(double(N))), sin(2*igl::PI*(double)j/(double(N))),0.0;
55
56 //finding closest similarity transformation between source and target
57 Eigen::MatrixXd corrMat=sourcePolygon.transpose()*targetPolygon;
59 Eigen::MatrixXd R=svd.matrixU()*svd.matrixV().transpose();
60 //getting scale by edge length change average. TODO: by singular values
61 Eigen::VectorXd sourceEdgeLengths(N);
62 Eigen::VectorXd targetEdgeLengths(N);
63 for (int j=0;j<N;j++){
64 sourceEdgeLengths(j)=(sourcePolygon.row((j+1)%N)-sourcePolygon.row(j)).norm();
65 targetEdgeLengths(j)=(targetPolygon.row((j+1)%N)-targetPolygon.row(j)).norm();
66 }
67 double scale=(targetEdgeLengths.cwiseQuotient(sourceEdgeLengths)).mean();
68
69 for (int j=0;j<N;j++)
70 projP.block(currRow,3*j,1,3)=sourcePolygon.row(j)*R*scale;
71 }
72
73 return true;
74 }

References Eigen::ComputeFullU, Eigen::ComputeFullV, Eigen::PlainObjectBase< Derived >::conservativeResize(), cos(), Eigen::SVDBase< Derived >::matrixU(), Eigen::SVDBase< Derived >::matrixV(), PI, Eigen::PlainObjectBase< Derived >::rows(), scale(), and sin().

+ Here is the call graph for this function:

◆ shapeup_solve()

template<typename DerivedP , typename DerivedSC , typename DerivedS >
IGL_INLINE bool igl::shapeup_solve ( const Eigen::PlainObjectBase< DerivedP > &  bc,
const std::function< bool(const Eigen::PlainObjectBase< DerivedP > &, const Eigen::PlainObjectBase< DerivedSC > &, const Eigen::PlainObjectBase< DerivedS > &, Eigen::PlainObjectBase< DerivedP > &)> &  local_projection,
const Eigen::PlainObjectBase< DerivedP > &  P0,
const ShapeupData sudata,
const bool  quietIterations,
Eigen::PlainObjectBase< DerivedP > &  P 
)
183 {
184 using namespace Eigen;
185 using namespace std;
186 MatrixXd currP=P0;
187 MatrixXd prevP=P0;
188 MatrixXd projP;
189
190 assert(bc.rows()==sudata.b.rows());
191
192 MatrixXd rhs(sudata.A.rows(), 3); rhs.setZero();
193 rhs.block(sudata.DShape.rows(), 0, sudata.b.rows(),3)=bc; //this stays constant throughout the iterations
194
195 if (!quietIterations){
196 cout<<"Shapeup Iterations, "<<sudata.DShape.rows()<<" constraints, solution size "<<P0.size()<<endl;
197 cout<<"**********************************************************************************************"<<endl;
198 }
199 projP.conservativeResize(sudata.SC.rows(), 3*sudata.SC.maxCoeff());
200 for (int iter=0;iter<sudata.maxIterations;iter++){
201
202 local_projection(currP, sudata.SC,sudata.S,projP);
203
204 //constructing the projection part of the (DShape rows of the) right hand side
205 int currRow=0;
206 for (int i=0;i<sudata.S.rows();i++)
207 for (int j=0;j<sudata.SC(i);j++)
208 rhs.row(currRow++)=projP.block(i, 3*j, 1,3);
209
210 DerivedP lsrhs=-sudata.At*sudata.W*rhs;
211 MatrixXd Y(0,3), Beq(0,3); //We do not use the min_quad_solver fixed variables mechanism; they are treated with the closeness energy of ShapeUp.
212 min_quad_with_fixed_solve(sudata.solver_data, lsrhs,Y,Beq,currP);
213
214 double currChange=(currP-prevP).lpNorm<Infinity>();
215 if (!quietIterations)
216 cout << "Iteration "<<iter<<", integration Linf error: "<<currChange<< endl;
217 prevP=currP;
218 if (currChange<sudata.pTolerance){
219 P=currP;
220 return true;
221 }
222 }
223
224 P=currP;
225 return false; //we went over maxIterations
226
227 }
double pTolerance
Definition shapeup.h:35
int maxIterations
Definition shapeup.h:34

References igl::ShapeupData::A, igl::ShapeupData::At, igl::ShapeupData::b, Eigen::PlainObjectBase< Derived >::conservativeResize(), igl::ShapeupData::DShape, igl::ShapeupData::maxIterations, min_quad_with_fixed_solve(), igl::ShapeupData::pTolerance, Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::rows(), igl::ShapeupData::S, igl::ShapeupData::SC, igl::ShapeupData::solver_data, and igl::ShapeupData::W.

+ Here is the call graph for this function:

◆ shortest_edge_and_midpoint()

IGL_INLINE void igl::shortest_edge_and_midpoint ( const int  e,
const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  ,
const Eigen::MatrixXi &  E,
const Eigen::VectorXi &  ,
const Eigen::MatrixXi &  ,
const Eigen::MatrixXi &  ,
double &  cost,
Eigen::RowVectorXd &  p 
)
20{
21 cost = (V.row(E(e,0))-V.row(E(e,1))).norm();
22 p = 0.5*(V.row(E(e,0))+V.row(E(e,1)));
23}

Referenced by decimate().

+ Here is the caller graph for this function:

◆ signed_angle()

template<typename DerivedA , typename DerivedB , typename DerivedP >
IGL_INLINE DerivedA::Scalar igl::signed_angle ( const Eigen::MatrixBase< DerivedA > &  A,
const Eigen::MatrixBase< DerivedB > &  B,
const Eigen::MatrixBase< DerivedP > &  P 
)
13{
14 typedef typename DerivedA::Scalar SType;
15 // Gather vectors to source and destination
16 SType o2A[2];
17 SType o2B[2];
18 // and lengths
19 SType o2Al = 0;
20 SType o2Bl = 0;
21 for(int i = 0;i<2;i++)
22 {
23 o2A[i] = P(i) - A(i);
24 o2B[i] = P(i) - B(i);
25 o2Al += o2A[i]*o2A[i];
26 o2Bl += o2B[i]*o2B[i];
27 }
28 o2Al = sqrt(o2Al);
29 o2Bl = sqrt(o2Bl);
30 // Normalize
31 for(int i = 0;i<2;i++)
32 {
33 // Matlab crashes on NaN
34 if(o2Al!=0)
35 {
36 o2A[i] /= o2Al;
37 }
38 if(o2Bl!=0)
39 {
40 o2B[i] /= o2Bl;
41 }
42 }
43 return
44 -atan2(o2B[0]*o2A[1]-o2B[1]*o2A[0],o2B[0]*o2A[0]+o2B[1]*o2A[1])/
45 (2.*igl::PI);
46}

References PI, and sqrt().

Referenced by winding_number().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ signed_distance() [1/2]

template<typename DerivedP , typename DerivedV , typename DerivedF , typename DerivedS , typename DerivedI , typename DerivedC , typename DerivedN >
IGL_INLINE void igl::signed_distance ( const Eigen::MatrixBase< DerivedP > &  P,
const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const SignedDistanceType  sign_type,
const typename DerivedV::Scalar  lower_bound,
const typename DerivedV::Scalar  upper_bound,
Eigen::PlainObjectBase< DerivedS > &  S,
Eigen::PlainObjectBase< DerivedI > &  I,
Eigen::PlainObjectBase< DerivedC > &  C,
Eigen::PlainObjectBase< DerivedN > &  N 
)
37{
38 using namespace Eigen;
39 using namespace std;
40 const int dim = V.cols();
41 assert((V.cols() == 3||V.cols() == 2) && "V should have 3d or 2d positions");
42 assert((P.cols() == 3||P.cols() == 2) && "P should have 3d or 2d positions");
43 assert(V.cols() == P.cols() && "V should have same dimension as P");
44 // Only unsigned distance is supported for non-triangles
45 if(sign_type != SIGNED_DISTANCE_TYPE_UNSIGNED)
46 {
47 assert(F.cols() == dim && "F should have co-dimension 0 simplices");
48 }
50
51 // Prepare distance computation
52 AABB<DerivedV,3> tree3;
53 AABB<DerivedV,2> tree2;
54 switch(dim)
55 {
56 default:
57 case 3:
58 tree3.init(V,F);
59 break;
60 case 2:
61 tree2.init(V,F);
62 break;
63 }
64
68 WindingNumberAABB<RowVector3S,DerivedV,DerivedF> hier3;
69 switch(sign_type)
70 {
71 default:
72 assert(false && "Unknown SignedDistanceType");
74 // do nothing
75 break;
78 switch(dim)
79 {
80 default:
81 case 3:
82 hier3.set_mesh(V,F);
83 hier3.grow();
84 break;
85 case 2:
86 // no precomp, no hierarchy
87 break;
88 }
89 break;
91 switch(dim)
92 {
93 default:
94 case 3:
95 // "Signed Distance Computation Using the Angle Weighted Pseudonormal"
96 // [Bærentzen & Aanæs 2005]
97 per_face_normals(V,F,FN);
98 per_vertex_normals(V,F,PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE,FN,VN);
100 V,F,PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM,FN,EN,E,EMAP);
101 break;
102 case 2:
103 FN.resize(F.rows(),2);
104 VN = DerivedV::Zero(V.rows(),2);
105 for(int e = 0;e<F.rows();e++)
106 {
107 // rotate edge vector
108 FN(e,0) = (V(F(e,1),1)-V(F(e,0),1));
109 FN(e,1) = -(V(F(e,1),0)-V(F(e,0),0));
110 FN.row(e).normalize();
111 // add to vertex normal
112 VN.row(F(e,1)) += FN.row(e);
113 VN.row(F(e,0)) += FN.row(e);
114 }
115 // normalize to average
116 VN.rowwise().normalize();
117 break;
118 }
119 N.resize(P.rows(),dim);
120 break;
121 }
122 //
123 // convert to bounds on (unsiged) squared distances
124 typedef typename DerivedV::Scalar Scalar;
125 const Scalar max_abs = std::max(std::abs(lower_bound),std::abs(upper_bound));
126 const Scalar up_sqr_d = std::pow(max_abs,2.0);
127 const Scalar low_sqr_d =
128 std::pow(std::max(max_abs-(upper_bound-lower_bound),(Scalar)0.0),2.0);
129
130 S.resize(P.rows(),1);
131 I.resize(P.rows(),1);
132 C.resize(P.rows(),dim);
133
134 parallel_for(P.rows(),[&](const int p)
135 //for(int p = 0;p<P.rows();p++)
136 {
137 RowVector3S q3;
138 Eigen::Matrix<typename DerivedV::Scalar,1,2> q2;
139 switch(P.cols())
140 {
141 default:
142 case 3:
143 q3.head(P.row(p).size()) = P.row(p);
144 break;
145 case 2:
146 q2 = P.row(p).head(2);
147 break;
148 }
149 typename DerivedV::Scalar s=1,sqrd=0;
151 RowVector3S c3;
153 int i=-1;
154 // in all cases compute squared unsiged distances
155 sqrd = dim==3?
156 tree3.squared_distance(V,F,q3,low_sqr_d,up_sqr_d,i,c3):
157 tree2.squared_distance(V,F,q2,low_sqr_d,up_sqr_d,i,c2);
158 if(sqrd >= up_sqr_d || sqrd <= low_sqr_d)
159 {
160 // Out of bounds gets a nan (nans on grids can be flood filled later using
161 // igl::flood_fill)
162 S(p) = std::numeric_limits<double>::quiet_NaN();
163 I(p) = F.rows()+1;
164 C.row(p).setConstant(0);
165 }else
166 {
167 // Determine sign
168 switch(sign_type)
169 {
170 default:
171 assert(false && "Unknown SignedDistanceType");
173 break;
176 {
177 Scalar w = 0;
178 if(dim == 3)
179 {
180 s = 1.-2.*hier3.winding_number(q3.transpose());
181 }else
182 {
183 assert(!V.derived().IsRowMajor);
184 assert(!F.derived().IsRowMajor);
185 s = 1.-2.*winding_number(V,F,q2);
186 }
187 break;
188 }
190 {
191 RowVector3S n3;
193 dim==3 ?
194 pseudonormal_test(V,F,FN,VN,EN,EMAP,q3,i,c3,s,n3):
195 pseudonormal_test(V,E,EN,VN,q2,i,c2,s,n2);
197 (dim==3 ? n = n3 : n = n2);
198 N.row(p) = n;
199 break;
200 }
201 }
202 I(p) = i;
203 S(p) = s*sqrt(sqrd);
204 C.row(p) = (dim==3 ? c=c3 : c=c2);
205 }
206 }
207 ,10000);
208}
IGL_INLINE void winding_number(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedO > &O, Eigen::PlainObjectBase< DerivedW > &W)
Definition winding_number.cpp:22
IGL_INLINE void pseudonormal_test(Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 1, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< int, -1, 3, 1, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 0, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< float, -1, 3, 0, -1, 3 > > const &, Eigen::MatrixBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > const &, int, Eigen::PlainObjectBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > &, float &, Eigen::PlainObjectBase< Eigen::Matrix< float, 1, 2, 1, 1, 2 > > &)
Definition pseudonormal_test.cpp:192

References igl::WindingNumberAABB< Point, DerivedV, DerivedF >::grow(), igl::AABB< DerivedV, DIM >::init(), Eigen::DenseBase< Derived >::IsRowMajor, parallel_for(), per_edge_normals(), PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM, per_face_normals(), per_vertex_normals(), PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE, pseudonormal_test(), Eigen::PlainObjectBase< Derived >::resize(), igl::WindingNumberAABB< Point, DerivedV, DerivedF >::set_mesh(), Eigen::PlainObjectBase< Derived >::setConstant(), SIGNED_DISTANCE_TYPE_DEFAULT, SIGNED_DISTANCE_TYPE_PSEUDONORMAL, SIGNED_DISTANCE_TYPE_UNSIGNED, SIGNED_DISTANCE_TYPE_WINDING_NUMBER, sqrt(), igl::AABB< DerivedV, DIM >::squared_distance(), winding_number(), and igl::WindingNumberTree< Point, DerivedV, DerivedF >::winding_number().

Referenced by igl::copyleft::offset_surface(), and signed_distance().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ signed_distance() [2/2]

template<typename DerivedP , typename DerivedV , typename DerivedF , typename DerivedS , typename DerivedI , typename DerivedC , typename DerivedN >
IGL_INLINE void igl::signed_distance ( const Eigen::MatrixBase< DerivedP > &  P,
const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const SignedDistanceType  sign_type,
Eigen::PlainObjectBase< DerivedS > &  S,
Eigen::PlainObjectBase< DerivedI > &  I,
Eigen::PlainObjectBase< DerivedC > &  C,
Eigen::PlainObjectBase< DerivedN > &  N 
)
227{
228 typedef typename DerivedV::Scalar Scalar;
229 Scalar lower = std::numeric_limits<Scalar>::min();
230 Scalar upper = std::numeric_limits<Scalar>::max();
231 return signed_distance(P,V,F,sign_type,lower,upper,S,I,C,N);
232}
IGL_INLINE void signed_distance(const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const SignedDistanceType sign_type, const typename DerivedV::Scalar lower_bound, const typename DerivedV::Scalar upper_bound, Eigen::PlainObjectBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedN > &N)
Definition signed_distance.cpp:26

References signed_distance().

+ Here is the call graph for this function:

◆ signed_distance_pseudonormal() [1/4]

template<typename DerivedV , typename DerivedE , typename DerivedEN , typename DerivedVN , typename Derivedq , typename Scalar , typename Derivedc , typename Derivedn >
IGL_INLINE void igl::signed_distance_pseudonormal ( const AABB< DerivedV, 2 > &  tree,
const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedE > &  E,
const Eigen::MatrixBase< DerivedEN > &  EN,
const Eigen::MatrixBase< DerivedVN > &  VN,
const Eigen::MatrixBase< Derivedq > &  q,
Scalar &  s,
Scalar &  sqrd,
int &  i,
Eigen::PlainObjectBase< Derivedc > &  c,
Eigen::PlainObjectBase< Derivedn > &  n 
)
366{
367 using namespace Eigen;
368 using namespace std;
370 sqrd = tree.squared_distance(V,E,RowVector2S(q),i,(RowVector2S&)c);
371 pseudonormal_test(V,E,EN,VN,q,i,c,s,n);
372}

References pseudonormal_test(), and igl::AABB< DerivedV, DIM >::squared_distance().

+ Here is the call graph for this function:

◆ signed_distance_pseudonormal() [2/4]

template<typename DerivedV , typename DerivedF , typename DerivedFN , typename DerivedVN , typename DerivedEN , typename DerivedEMAP , typename Derivedq >
IGL_INLINE DerivedV::Scalar igl::signed_distance_pseudonormal ( const AABB< DerivedV, 3 > &  tree,
const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< DerivedFN > &  FN,
const Eigen::MatrixBase< DerivedVN > &  VN,
const Eigen::MatrixBase< DerivedEN > &  EN,
const Eigen::MatrixBase< DerivedEMAP > &  EMAP,
const Eigen::MatrixBase< Derivedq > &  q 
)
252{
253 typename DerivedV::Scalar s,sqrd;
255 int i = -1;
256 signed_distance_pseudonormal(tree,V,F,FN,VN,EN,EMAP,q,s,sqrd,i,c,n);
257 return s*sqrt(sqrd);
258}
IGL_INLINE DerivedV::Scalar signed_distance_pseudonormal(const AABB< DerivedV, 3 > &tree, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedFN > &FN, const Eigen::MatrixBase< DerivedVN > &VN, const Eigen::MatrixBase< DerivedEN > &EN, const Eigen::MatrixBase< DerivedEMAP > &EMAP, const Eigen::MatrixBase< Derivedq > &q)
Definition signed_distance.cpp:243

References signed_distance_pseudonormal(), and sqrt().

Referenced by igl::copyleft::cgal::signed_distance_isosurface(), signed_distance_pseudonormal(), and signed_distance_pseudonormal().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ signed_distance_pseudonormal() [3/4]

template<typename DerivedV , typename DerivedF , typename DerivedFN , typename DerivedVN , typename DerivedEN , typename DerivedEMAP , typename Derivedq , typename Scalar , typename Derivedc , typename Derivedn >
IGL_INLINE void igl::signed_distance_pseudonormal ( const AABB< DerivedV, 3 > &  tree,
const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< DerivedFN > &  FN,
const Eigen::MatrixBase< DerivedVN > &  VN,
const Eigen::MatrixBase< DerivedEN > &  EN,
const Eigen::MatrixBase< DerivedEMAP > &  EMAP,
const Eigen::MatrixBase< Derivedq > &  q,
Scalar &  s,
Scalar &  sqrd,
int &  i,
Eigen::PlainObjectBase< Derivedc > &  c,
Eigen::PlainObjectBase< Derivedn > &  n 
)
333{
334 using namespace Eigen;
335 using namespace std;
336 //typedef Eigen::Matrix<typename DerivedV::Scalar,1,3> RowVector3S;
337 // Alec: Why was this constructor around q necessary?
338 //sqrd = tree.squared_distance(V,F,RowVector3S(q),i,(RowVector3S&)c);
339 // Alec: Why was this constructor around c necessary?
340 //sqrd = tree.squared_distance(V,F,q,i,(RowVector3S&)c);
341 sqrd = tree.squared_distance(V,F,q,i,c);
342 pseudonormal_test(V,F,FN,VN,EN,EMAP,q,i,c,s,n);
343}

References pseudonormal_test(), and igl::AABB< DerivedV, DIM >::squared_distance().

+ Here is the call graph for this function:

◆ signed_distance_pseudonormal() [4/4]

template<typename DerivedP , typename DerivedV , typename DerivedF , typename DerivedFN , typename DerivedVN , typename DerivedEN , typename DerivedEMAP , typename DerivedS , typename DerivedI , typename DerivedC , typename DerivedN >
IGL_INLINE void igl::signed_distance_pseudonormal ( const Eigen::MatrixBase< DerivedP > &  P,
const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const AABB< DerivedV, 3 > &  tree,
const Eigen::MatrixBase< DerivedFN > &  FN,
const Eigen::MatrixBase< DerivedVN > &  VN,
const Eigen::MatrixBase< DerivedEN > &  EN,
const Eigen::MatrixBase< DerivedEMAP > &  EMAP,
Eigen::PlainObjectBase< DerivedS > &  S,
Eigen::PlainObjectBase< DerivedI > &  I,
Eigen::PlainObjectBase< DerivedC > &  C,
Eigen::PlainObjectBase< DerivedN > &  N 
)
285{
286 using namespace Eigen;
287 const size_t np = P.rows();
288 S.resize(np,1);
289 I.resize(np,1);
290 N.resize(np,3);
291 C.resize(np,3);
292 typedef typename AABB<DerivedV,3>::RowVectorDIMS RowVector3S;
293# pragma omp parallel for if(np>1000)
294 for(size_t p = 0;p<np;p++)
295 {
296 typename DerivedV::Scalar s,sqrd;
297 RowVector3S n,c;
298 int i = -1;
299 RowVector3S q = P.row(p);
300 signed_distance_pseudonormal(tree,V,F,FN,VN,EN,EMAP,q,s,sqrd,i,c,n);
301 S(p) = s*sqrt(sqrd);
302 I(p) = i;
303 N.row(p) = n;
304 C.row(p) = c;
305 }
306}

References Eigen::PlainObjectBase< Derived >::resize(), signed_distance_pseudonormal(), and sqrt().

+ Here is the call graph for this function:

◆ signed_distance_winding_number() [1/3]

template<typename DerivedV , typename DerivedF , typename Derivedq , typename Scalar , typename Derivedc >
IGL_INLINE void igl::signed_distance_winding_number ( const AABB< DerivedV, 2 > &  tree,
const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< Derivedq > &  q,
Scalar &  s,
Scalar &  sqrd,
int &  i,
Eigen::PlainObjectBase< Derivedc > &  c 
)
434{
435 using namespace Eigen;
436 using namespace std;
438 sqrd = tree.squared_distance(V,F,RowVector2S(q),i,(RowVector2S&)c);
439 Scalar w;
440 // TODO: using .data() like this is very dangerous... This is assuming
441 // colmajor order
442 assert(!V.derived().IsRowMajor);
443 assert(!F.derived().IsRowMajor);
444 s = 1.-2.*winding_number(V,F,q);
445}

References Eigen::DenseBase< Derived >::IsRowMajor, igl::AABB< DerivedV, DIM >::squared_distance(), and winding_number().

+ Here is the call graph for this function:

◆ signed_distance_winding_number() [2/3]

template<typename DerivedV , typename DerivedF , typename Derivedq >
IGL_INLINE DerivedV::Scalar igl::signed_distance_winding_number ( const AABB< DerivedV, 3 > &  tree,
const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const igl::WindingNumberAABB< Derivedq, DerivedV, DerivedF > &  hier,
const Eigen::MatrixBase< Derivedq > &  q 
)
384{
385 typedef typename DerivedV::Scalar Scalar;
386 Scalar s,sqrd;
388 int i=-1;
389 signed_distance_winding_number(tree,V,F,hier,q,s,sqrd,i,c);
390 return s*sqrt(sqrd);
391}
IGL_INLINE DerivedV::Scalar signed_distance_winding_number(const AABB< DerivedV, 3 > &tree, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const igl::WindingNumberAABB< Derivedq, DerivedV, DerivedF > &hier, const Eigen::MatrixBase< Derivedq > &q)
Definition signed_distance.cpp:378

References signed_distance_winding_number(), and sqrt().

Referenced by igl::copyleft::cgal::signed_distance_isosurface(), and signed_distance_winding_number().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ signed_distance_winding_number() [3/3]

template<typename DerivedV , typename DerivedF , typename Derivedq , typename Scalar , typename Derivedc >
IGL_INLINE void igl::signed_distance_winding_number ( const AABB< DerivedV, 3 > &  tree,
const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const igl::WindingNumberAABB< Derivedq, DerivedV, DerivedF > &  hier,
const Eigen::MatrixBase< Derivedq > &  q,
Scalar &  s,
Scalar &  sqrd,
int &  i,
Eigen::PlainObjectBase< Derivedc > &  c 
)
410{
411 using namespace Eigen;
412 using namespace std;
414 sqrd = tree.squared_distance(V,F,RowVector3S(q),i,(RowVector3S&)c);
415 const Scalar w = hier.winding_number(q.transpose());
416 s = 1.-2.*w;
417}
DerivedV::Scalar winding_number(const Point &p) const
Definition WindingNumberTree.h:285

References igl::AABB< DerivedV, DIM >::squared_distance(), Eigen::DenseBase< Derived >::transpose(), and igl::WindingNumberTree< Point, DerivedV, DerivedF >::winding_number().

+ Here is the call graph for this function:

◆ simplify_polyhedron()

IGL_INLINE void igl::simplify_polyhedron ( const Eigen::MatrixXd &  OV,
const Eigen::MatrixXi &  OF,
Eigen::MatrixXd &  V,
Eigen::MatrixXi &  F,
Eigen::VectorXi &  J 
)
21{
22 // TODO: to generalize to open meshes, 0-cost should keep all incident
23 // boundary edges on their original lines. (for non-manifold meshes,
24 // igl::decimate needs to be generalized)
25
26 Eigen::MatrixXd N;
27 // Function for computing cost of collapsing edge (0 if at least one
28 // direction doesn't change pointset, inf otherwise) and placement (in lowest
29 // cost direction).
30 const auto & perfect= [&N](
31 const int e,
32 const Eigen::MatrixXd & V,
33 const Eigen::MatrixXi & F,
34 const Eigen::MatrixXi & E,
35 const Eigen::VectorXi & EMAP,
36 const Eigen::MatrixXi & EF,
37 const Eigen::MatrixXi & EI,
38 double & cost,
39 Eigen::RowVectorXd & p)
40 {
41 // Function for ocmputing cost (0 or inf) of collapsing edge by placing
42 // vertex at `positive` end of edge.
43 const auto & perfect_directed = [&N](
44 const int e,
45 const bool positive,
46 const Eigen::MatrixXd & V,
47 const Eigen::MatrixXi & F,
48 const Eigen::MatrixXi & E,
49 const Eigen::VectorXi & EMAP,
50 const Eigen::MatrixXi & EF,
51 const Eigen::MatrixXi & EI,
52 double & cost,
53 Eigen::RowVectorXd & p)
54 {
55 const auto vi = E(e,positive);
56 const auto vj = E(e,!positive);
57 p = V.row(vj);
58 std::vector<int> faces = igl::circulation(e,positive,F,E,EMAP,EF,EI);
59 cost = 0;
60 for(auto f : faces)
61 {
62 // Skip the faces being collapsed
63 if(f == EF(e,0) || f == EF(e,1))
64 {
65 continue;
66 }
67 const Eigen::RowVectorXd nbefore = N.row(f);
68 // Face with vi replaced with vj
69 const Eigen::RowVector3i fafter(
70 F(f,0) == vi ? vj : F(f,0),
71 F(f,1) == vi ? vj : F(f,1),
72 F(f,2) == vi ? vj : F(f,2));
73 Eigen::RowVectorXd nafter;
74 igl::per_face_normals(V,fafter,nafter);
75 const double epsilon = 1e-10;
76 // if normal changed then not feasible, break
77 if((nbefore-nafter).norm() > epsilon)
78 {
79 cost = std::numeric_limits<double>::infinity();
80 break;
81 }
82 }
83 };
84 p.resize(3);
85 double cost0, cost1;
86 Eigen::RowVectorXd p0, p1;
87 perfect_directed(e,false,V,F,E,EMAP,EF,EI,cost0,p0);
88 perfect_directed(e,true,V,F,E,EMAP,EF,EI,cost1,p1);
89 if(cost0 < cost1)
90 {
91 cost = cost0;
92 p = p0;
93 }else
94 {
95 cost = cost1;
96 p = p1;
97 }
98 };
99 igl::per_face_normals(OV,OF,N);
100 Eigen::VectorXi I;
102 OV,OF,
103 perfect,
105 V,F,J,I);
106}

References circulation(), decimate(), infinite_cost_stopping_condition(), and per_face_normals().

+ Here is the call graph for this function:

◆ slice() [1/6]

template<typename DerivedX , typename DerivedR , typename DerivedC , typename DerivedY >
IGL_INLINE void igl::slice ( const Eigen::DenseBase< DerivedX > &  X,
const Eigen::DenseBase< DerivedR > &  R,
const Eigen::DenseBase< DerivedC > &  C,
Eigen::PlainObjectBase< DerivedY > &  Y 
)
181{
182#ifndef NDEBUG
183 int xm = X.rows();
184 int xn = X.cols();
185#endif
186 int ym = R.size();
187 int yn = C.size();
188
189 // special case when R or C is empty
190 if(ym == 0 || yn == 0)
191 {
192 Y.resize(ym,yn);
193 return;
194 }
195
196 assert(R.minCoeff() >= 0);
197 assert(R.maxCoeff() < xm);
198 assert(C.minCoeff() >= 0);
199 assert(C.maxCoeff() < xn);
200
201 // Resize output
202 Y.resize(ym,yn);
203 // loop over output rows, then columns
204 for(int i = 0;i<ym;i++)
205 {
206 for(int j = 0;j<yn;j++)
207 {
208 Y(i,j) = X(R(i),C(j));
209 }
210 }
211}

References Eigen::DenseBase< Derived >::maxCoeff(), and Eigen::DenseBase< Derived >::minCoeff().

+ Here is the call graph for this function:

◆ slice() [2/6]

template<typename DerivedX >
IGL_INLINE DerivedX igl::slice ( const Eigen::DenseBase< DerivedX > &  X,
const Eigen::Matrix< int, Eigen::Dynamic, 1 > &  R 
)
231{
232 DerivedX Y;
233 igl::slice(X,R,Y);
234 return Y;
235}

References slice().

+ Here is the call graph for this function:

◆ slice() [3/6]

template<typename DerivedX >
IGL_INLINE DerivedX igl::slice ( const Eigen::DenseBase< DerivedX > &  X,
const Eigen::Matrix< int, Eigen::Dynamic, 1 > &  R,
const int  dim 
)
242{
243 DerivedX Y;
244 igl::slice(X,R,dim,Y);
245 return Y;
246}

References slice().

+ Here is the call graph for this function:

◆ slice() [4/6]

template<typename DerivedX , typename DerivedY >
IGL_INLINE void igl::slice ( const Eigen::DenseBase< DerivedX > &  X,
const Eigen::Matrix< int, Eigen::Dynamic, 1 > &  R,
Eigen::PlainObjectBase< DerivedY > &  Y 
)
219{
220 // phony column indices
222 C.resize(1);
223 C(0) = 0;
224 return igl::slice(X,R,C,Y);
225}

References Eigen::PlainObjectBase< Derived >::resize(), and slice().

+ Here is the call graph for this function:

◆ slice() [5/6]

template<typename TX , typename TY >
IGL_INLINE void igl::slice ( const Eigen::SparseMatrix< TX > &  X,
const Eigen::Matrix< int, Eigen::Dynamic, 1 > &  R,
const Eigen::Matrix< int, Eigen::Dynamic, 1 > &  C,
Eigen::SparseMatrix< TY > &  Y 
)
20{
21#if 1
22 int xm = X.rows();
23 int xn = X.cols();
24 int ym = R.size();
25 int yn = C.size();
26
27 // special case when R or C is empty
28 if(ym == 0 || yn == 0)
29 {
30 Y.resize(ym,yn);
31 return;
32 }
33
34 assert(R.minCoeff() >= 0);
35 assert(R.maxCoeff() < xm);
36 assert(C.minCoeff() >= 0);
37 assert(C.maxCoeff() < xn);
38
39 // Build reindexing maps for columns and rows, -1 means not in map
40 std::vector<std::vector<int> > RI;
41 RI.resize(xm);
42 for(int i = 0;i<ym;i++)
43 {
44 RI[R(i)].push_back(i);
45 }
46 std::vector<std::vector<int> > CI;
47 CI.resize(xn);
48 // initialize to -1
49 for(int i = 0;i<yn;i++)
50 {
51 CI[C(i)].push_back(i);
52 }
53 // Resize output
55 // Take a guess at the number of nonzeros (this assumes uniform distribution
56 // not banded or heavily diagonal)
57 dyn_Y.reserve((X.nonZeros()/(X.rows()*X.cols())) * (ym*yn));
58 // Iterate over outside
59 for(int k=0; k<X.outerSize(); ++k)
60 {
61 // Iterate over inside
62 for(typename Eigen::SparseMatrix<TX>::InnerIterator it (X,k); it; ++it)
63 {
64 std::vector<int>::iterator rit, cit;
65 for(rit = RI[it.row()].begin();rit != RI[it.row()].end(); rit++)
66 {
67 for(cit = CI[it.col()].begin();cit != CI[it.col()].end(); cit++)
68 {
69 dyn_Y.coeffRef(*rit,*cit) = it.value();
70 }
71 }
72 }
73 }
75#else
76
77 // Alec: This is _not_ valid for arbitrary R,C since they don't necessary
78 // representation a strict permutation of the rows and columns: rows or
79 // columns could be removed or replicated. The removal of rows seems to be
80 // handled here (although it's not clear if there is a performance gain when
81 // the #removals >> #remains). If this is sufficiently faster than the
82 // correct code above, one could test whether all entries in R and C are
83 // unique and apply the permutation version if appropriate.
84 //
85
86 int xm = X.rows();
87 int xn = X.cols();
88 int ym = R.size();
89 int yn = C.size();
90
91 // special case when R or C is empty
92 if(ym == 0 || yn == 0)
93 {
94 Y.resize(ym,yn);
95 return;
96 }
97
98 assert(R.minCoeff() >= 0);
99 assert(R.maxCoeff() < xm);
100 assert(C.minCoeff() >= 0);
101 assert(C.maxCoeff() < xn);
102
103 // initialize row and col permutation vectors
104 Eigen::VectorXi rowIndexVec = igl::LinSpaced<Eigen::VectorXi >(xm,0,xm-1);
105 Eigen::VectorXi rowPermVec = igl::LinSpaced<Eigen::VectorXi >(xm,0,xm-1);
106 for(int i=0;i<ym;i++)
107 {
108 int pos = rowIndexVec.coeffRef(R(i));
109 if(pos != i)
110 {
111 int& val = rowPermVec.coeffRef(i);
112 std::swap(rowIndexVec.coeffRef(val),rowIndexVec.coeffRef(R(i)));
113 std::swap(rowPermVec.coeffRef(i),rowPermVec.coeffRef(pos));
114 }
115 }
117
118 Eigen::VectorXi colIndexVec = igl::LinSpaced<Eigen::VectorXi >(xn,0,xn-1);
119 Eigen::VectorXi colPermVec = igl::LinSpaced<Eigen::VectorXi >(xn,0,xn-1);
120 for(int i=0;i<yn;i++)
121 {
122 int pos = colIndexVec.coeffRef(C(i));
123 if(pos != i)
124 {
125 int& val = colPermVec.coeffRef(i);
126 std::swap(colIndexVec.coeffRef(val),colIndexVec.coeffRef(C(i)));
127 std::swap(colPermVec.coeffRef(i),colPermVec.coeffRef(pos));
128 }
129 }
131
132 Eigen::SparseMatrix<T> M = (rowPerm * X);
133 Y = (M * colPerm).block(0,0,ym,yn);
134#endif
135}
EIGEN_DOC_BLOCK_ADDONS_NOT_INNER_PANEL EIGEN_DEVICE_FUNC BlockXpr block(Index startRow, Index startCol, Index blockRows, Index blockCols)
This is the const version of block(Index,Index,Index,Index). *‍/.
Definition BlockMethods.h:64
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar & coeffRef(Index rowId, Index colId)
Definition PlainObjectBase.h:183
Permutation matrix.
Definition PermutationMatrix.h:309

References block(), Eigen::DynamicSparseMatrix< _Scalar, _Options, _StorageIndex >::coeffRef(), Eigen::Matrix< _Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols >::coeffRef(), and Eigen::DynamicSparseMatrix< _Scalar, _Options, _StorageIndex >::reserve().

Referenced by active_set(), arap_dof_precomputation(), arap_dof_update(), arap_precomputation(), bijective_composite_harmonic_mapping(), decimate(), directed_edge_parents(), ears(), edges_to_path(), eigs(), linprog(), min_quad_with_fixed_precompute(), min_quad_with_fixed_solve(), igl::copyleft::cgal::minkowski_sum(), igl::copyleft::cgal::minkowski_sum(), normal_derivative(), igl::copyleft::cgal::point_areas(), qslim(), ramer_douglas_peucker(), remove_duplicate_vertices(), remove_unreferenced(), resolve_duplicated_faces(), setxor(), slice(), slice(), slice(), slice(), slice_cached_precompute(), slice_mask(), slice_mask(), sort_triangles(), straighten_seams(), uniformly_sample_two_manifold(), uniformly_sample_two_manifold_at_vertices(), and igl::copyleft::cgal::wire_mesh().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ slice() [6/6]

template<typename MatX , typename DerivedR , typename MatY >
IGL_INLINE void igl::slice ( const MatX &  X,
const Eigen::DenseBase< DerivedR > &  R,
const int  dim,
MatY &  Y 
)
143{
145 switch(dim)
146 {
147 case 1:
148 // boring base case
149 if(X.cols() == 0)
150 {
151 Y.resize(R.size(),0);
152 return;
153 }
154 igl::colon(0,X.cols()-1,C);
155 return slice(X,R,C,Y);
156 case 2:
157 // boring base case
158 if(X.rows() == 0)
159 {
160 Y.resize(0,R.size());
161 return;
162 }
163 igl::colon(0,X.rows()-1,C);
164 return slice(X,C,R,Y);
165 default:
166 assert(false && "Unsupported dimension");
167 return;
168 }
169}

References colon(), and slice().

+ Here is the call graph for this function:

◆ slice_cached()

template<typename TX , typename TY , typename DerivedI >
IGL_INLINE void igl::slice_cached ( const Eigen::SparseMatrix< TX > &  X,
const Eigen::MatrixBase< DerivedI > &  data,
Eigen::SparseMatrix< TY > &  Y 
)
49{
50 for (unsigned i=0; i<data.size(); ++i)
51 *(Y.valuePtr() + i) = *(X.valuePtr() + data[i]);
52}

◆ slice_cached_precompute()

template<typename TX , typename TY , typename DerivedI >
IGL_INLINE void igl::slice_cached_precompute ( const Eigen::SparseMatrix< TX > &  X,
const Eigen::Matrix< int, Eigen::Dynamic, 1 > &  R,
const Eigen::Matrix< int, Eigen::Dynamic, 1 > &  C,
Eigen::MatrixBase< DerivedI > &  data,
Eigen::SparseMatrix< TY > &  Y 
)
23{
24 // Create a sparse matrix whose entries are the ids
25 Eigen::SparseMatrix<unsigned> TS = X.template cast<unsigned>();
26
27 TS.makeCompressed();
28 for (unsigned i=0;i<TS.nonZeros();++i)
29 *(TS.valuePtr() + i) = i;
30
32 igl::slice(TS,R,C,TS_sliced);
33 Y = TS_sliced.cast<TY>();
34
35 data.resize(TS_sliced.nonZeros());
36 for (unsigned i=0;i<data.size();++i)
37 {
38 data[i] = *(TS_sliced.valuePtr() + i);
39 *(Y.valuePtr() + i) = *(X.valuePtr() + data[i]);
40 }
41}

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::makeCompressed(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::nonZeros(), slice(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::valuePtr().

+ Here is the call graph for this function:

◆ slice_into() [1/4]

template<typename DerivedX , typename DerivedY >
IGL_INLINE void igl::slice_into ( const Eigen::DenseBase< DerivedX > &  X,
const Eigen::Matrix< int, Eigen::Dynamic, 1 > &  R,
const Eigen::Matrix< int, Eigen::Dynamic, 1 > &  C,
Eigen::PlainObjectBase< DerivedY > &  Y 
)
56{
57
58 int xm = X.rows();
59 int xn = X.cols();
60#ifndef NDEBUG
61 assert(R.size() == xm);
62 assert(C.size() == xn);
63 int ym = Y.size();
64 int yn = Y.size();
65 assert(R.minCoeff() >= 0);
66 assert(R.maxCoeff() < ym);
67 assert(C.minCoeff() >= 0);
68 assert(C.maxCoeff() < yn);
69#endif
70
71 // Build reindexing maps for columns and rows, -1 means not in map
73 RI.resize(xm);
74 for(int i = 0;i<xm;i++)
75 {
76 for(int j = 0;j<xn;j++)
77 {
78 Y(R(i),C(j)) = X(i,j);
79 }
80 }
81}

References Eigen::PlainObjectBase< Derived >::resize().

+ Here is the call graph for this function:

◆ slice_into() [2/4]

template<typename DerivedX , typename DerivedY >
IGL_INLINE void igl::slice_into ( const Eigen::DenseBase< DerivedX > &  X,
const Eigen::Matrix< int, Eigen::Dynamic, 1 > &  R,
Eigen::PlainObjectBase< DerivedY > &  Y 
)
122{
123 // phony column indices
125 C.resize(1);
126 C(0) = 0;
127 return igl::slice_into(X,R,C,Y);
128}

References Eigen::PlainObjectBase< Derived >::resize(), and slice_into().

+ Here is the call graph for this function:

◆ slice_into() [3/4]

template<typename T >
IGL_INLINE void igl::slice_into ( const Eigen::SparseMatrix< T > &  X,
const Eigen::Matrix< int, Eigen::Dynamic, 1 > &  R,
const Eigen::Matrix< int, Eigen::Dynamic, 1 > &  C,
Eigen::SparseMatrix< T > &  Y 
)
21{
22
23#ifndef NDEBUG
24 int xm = X.rows();
25 int xn = X.cols();
26 assert(R.size() == xm);
27 assert(C.size() == xn);
28 int ym = Y.size();
29 int yn = Y.size();
30 assert(R.minCoeff() >= 0);
31 assert(R.maxCoeff() < ym);
32 assert(C.minCoeff() >= 0);
33 assert(C.maxCoeff() < yn);
34#endif
35
36 // create temporary dynamic sparse matrix
38 // Iterate over outside
39 for(int k=0; k<X.outerSize(); ++k)
40 {
41 // Iterate over inside
42 for(typename Eigen::SparseMatrix<T>::InnerIterator it (X,k); it; ++it)
43 {
44 dyn_Y.coeffRef(R(it.row()),C(it.col())) = it.value();
45 }
46 }
48}

References Eigen::DynamicSparseMatrix< _Scalar, _Options, _StorageIndex >::coeffRef().

Referenced by active_set(), igl::mosek::bbw(), igl::copyleft::comiso::PoissonSolver< DerivedV, DerivedF >::BuildLaplacianMatrix(), directed_edge_parents(), linprog(), slice_into(), slice_into(), and straighten_seams().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ slice_into() [4/4]

template<typename MatX , typename MatY >
IGL_INLINE void igl::slice_into ( const MatX &  X,
const Eigen::Matrix< int, Eigen::Dynamic, 1 > &  R,
const int  dim,
MatY &  Y 
)
89{
90 Eigen::VectorXi C;
91 switch(dim)
92 {
93 case 1:
94 assert(R.size() == X.rows());
95 // boring base case
96 if(X.cols() == 0)
97 {
98 return;
99 }
100 igl::colon(0,X.cols()-1,C);
101 return slice_into(X,R,C,Y);
102 case 2:
103 assert(R.size() == X.cols());
104 // boring base case
105 if(X.rows() == 0)
106 {
107 return;
108 }
109 igl::colon(0,X.rows()-1,C);
110 return slice_into(X,C,R,Y);
111 default:
112 assert(false && "Unsupported dimension");
113 return;
114 }
115}

References colon(), and slice_into().

+ Here is the call graph for this function:

◆ slice_mask() [1/6]

template<typename DerivedX >
IGL_INLINE DerivedX igl::slice_mask ( const Eigen::DenseBase< DerivedX > &  X,
const Eigen::Array< bool, Eigen::Dynamic, 1 > &  R,
const Eigen::Array< bool, Eigen::Dynamic, 1 > &  C 
)
103{
104 DerivedX Y;
105 igl::slice_mask(X,R,C,Y);
106 return Y;
107}

References slice_mask().

+ Here is the call graph for this function:

◆ slice_mask() [2/6]

template<typename DerivedX , typename DerivedY >
IGL_INLINE void igl::slice_mask ( const Eigen::DenseBase< DerivedX > &  X,
const Eigen::Array< bool, Eigen::Dynamic, 1 > &  R,
const Eigen::Array< bool, Eigen::Dynamic, 1 > &  C,
Eigen::PlainObjectBase< DerivedY > &  Y 
)
19{
20 int xm = X.rows();
21 int xn = X.cols();
22 int ym = R.count();
23 int yn = C.count();
24 assert(R.size() == X.rows() && "R.size() should match X.rows()");
25 assert(C.size() == X.cols() && "C.size() should match X.cols()");
26 Y.resize(ym,yn);
27 {
28 int yi = 0;
29 for(int i = 0;i<xm;i++)
30 {
31 if(R(i))
32 {
33 int yj = 0;
34 for(int j = 0;j<xn;j++)
35 {
36 if(C(j))
37 {
38 Y(yi,yj) = X(i,j);
39 yj++;
40 }
41 }
42 yi++;
43 }
44 }
45 }
46}

Referenced by igl::triangle::cdt(), decimate(), igl::copyleft::cgal::minkowski_sum(), igl::copyleft::cgal::point_solid_signed_squared_distance(), qslim(), ramer_douglas_peucker(), slice_mask(), slice_mask(), straighten_seams(), and igl::copyleft::cgal::trim_with_solid().

+ Here is the caller graph for this function:

◆ slice_mask() [3/6]

template<typename DerivedX >
IGL_INLINE DerivedX igl::slice_mask ( const Eigen::DenseBase< DerivedX > &  X,
const Eigen::Array< bool, Eigen::Dynamic, 1 > &  R,
const int  dim 
)
114{
115 DerivedX Y;
116 igl::slice_mask(X,R,dim,Y);
117 return Y;
118}

References slice_mask().

+ Here is the call graph for this function:

◆ slice_mask() [4/6]

template<typename DerivedX , typename DerivedY >
IGL_INLINE void igl::slice_mask ( const Eigen::DenseBase< DerivedX > &  X,
const Eigen::Array< bool, Eigen::Dynamic, 1 > &  R,
const int  dim,
Eigen::PlainObjectBase< DerivedY > &  Y 
)
54{
55 switch(dim)
56 {
57 case 1:
58 {
59 const int ym = R.count();
60 assert(X.rows() == R.size() && "X.rows() should match R.size()");
61 Y.resize(ym,X.cols());
62 {
63 int yi = 0;
64 for(int i = 0;i<X.rows();i++)
65 {
66 if(R(i))
67 {
68 Y.row(yi++) = X.row(i);
69 }
70 }
71 }
72 return;
73 }
74 case 2:
75 {
76 const auto & C = R;
77 const int yn = C.count();
78 Y.resize(X.rows(),yn);
79 assert(X.cols() == R.size() && "X.cols() should match R.size()");
80 {
81 int yj = 0;
82 for(int j = 0;j<X.cols();j++)
83 {
84 if(C(j))
85 {
86 Y.col(yj++) = X.col(j);
87 }
88 }
89 }
90 return;
91 }
92 default:
93 assert(false && "Unsupported dimension");
94 return;
95 }
96}

◆ slice_mask() [5/6]

template<typename XType , typename YType >
IGL_INLINE void igl::slice_mask ( const Eigen::SparseMatrix< XType > &  X,
const Eigen::Array< bool, Eigen::Dynamic, 1 > &  R,
const Eigen::Array< bool, Eigen::Dynamic, 1 > &  C,
Eigen::SparseMatrix< YType > &  Y 
)
140{
141 // Cheapskate solution
142 Eigen::VectorXi Ri;
143 find(R,Ri);
144 Eigen::VectorXi Ci;
145 find(C,Ci);
146 return slice(X,Ri,Ci,Y);
147}

References find(), and slice().

+ Here is the call graph for this function:

◆ slice_mask() [6/6]

template<typename XType , typename YType >
IGL_INLINE void igl::slice_mask ( const Eigen::SparseMatrix< XType > &  X,
const Eigen::Array< bool, Eigen::Dynamic, 1 > &  R,
const int  dim,
Eigen::SparseMatrix< YType > &  Y 
)
127{
128 // Cheapskate solution
129 Eigen::VectorXi Ri;
130 find(R,Ri);
131 return slice(X,Ri,dim,Y);
132}

References find(), and slice().

+ Here is the call graph for this function:

◆ slice_tets() [1/3]

template<typename DerivedV , typename DerivedT , typename DerivedS , typename DerivedSV , typename DerivedSF , typename DerivedJ >
IGL_INLINE void igl::slice_tets ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedT > &  T,
const Eigen::MatrixBase< DerivedS > &  S,
Eigen::PlainObjectBase< DerivedSV > &  SV,
Eigen::PlainObjectBase< DerivedSF > &  SF,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
65{
66 Eigen::MatrixXi sE;
68 igl::slice_tets(V,T,S,SV,SF,J,sE,lambda);
69}
IGL_INLINE void slice_tets(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedT > &T, const Eigen::MatrixBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedSV > &SV, Eigen::PlainObjectBase< DerivedSF > &SF, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::SparseMatrix< BCType > &BC)
Definition slice_tets.cpp:28

References slice_tets().

+ Here is the call graph for this function:

◆ slice_tets() [2/3]

template<typename DerivedV , typename DerivedT , typename DerivedS , typename DerivedSV , typename DerivedSF , typename DerivedJ , typename DerivedsE , typename Derivedlambda >
IGL_INLINE void igl::slice_tets ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedT > &  T,
const Eigen::MatrixBase< DerivedS > &  S,
Eigen::PlainObjectBase< DerivedSV > &  SV,
Eigen::PlainObjectBase< DerivedSF > &  SF,
Eigen::PlainObjectBase< DerivedJ > &  J,
Eigen::PlainObjectBase< DerivedsE > &  sE,
Eigen::PlainObjectBase< Derivedlambda > &  lambda 
)
89{
90
91 using namespace Eigen;
92 using namespace std;
93 assert(V.cols() == 3 && "V should be #V by 3");
94 assert(T.cols() == 4 && "T should be #T by 4");
95
96 static const Eigen::Matrix<int,12,4> flipped_order =
98 3,2,0,1,
99 3,1,2,0,
100 3,0,1,2,
101 2,3,1,0,
102 2,1,0,3,
103 2,0,3,1,
104 1,3,0,2,
105 1,2,3,0,
106 1,0,2,3,
107 0,3,2,1,
108 0,2,1,3,
109 0,1,3,2
110 ).finished();
111
112 // number of tets
113 const size_t m = T.rows();
114
115 typedef typename DerivedS::Scalar Scalar;
116 typedef typename DerivedT::Scalar Index;
117 typedef Matrix<Scalar,Dynamic,1> VectorXS;
118 typedef Matrix<Scalar,Dynamic,4> MatrixX4S;
119 typedef Matrix<Scalar,Dynamic,3> MatrixX3S;
120 typedef Matrix<Scalar,Dynamic,2> MatrixX2S;
121 typedef Matrix<Index,Dynamic,4> MatrixX4I;
122 typedef Matrix<Index,Dynamic,3> MatrixX3I;
123 typedef Matrix<Index,Dynamic,2> MatrixX2I;
124 typedef Matrix<Index,Dynamic,1> VectorXI;
125 typedef Array<bool,Dynamic,1> ArrayXb;
126
127 MatrixX4S IT(m,4);
128 for(size_t t = 0;t<m;t++)
129 {
130 for(size_t c = 0;c<4;c++)
131 {
132 IT(t,c) = S(T(t,c));
133 }
134 }
135
136 // Essentially, just a glorified slice(X,1)
137 //
138 // Inputs:
139 // T #T by 4 list of tet indices into V
140 // IT #IT by 4 list of isosurface values at each tet
141 // I #I list of bools whether to grab data corresponding to each tet
142 const auto & extract_rows = [](
143 const MatrixBase<DerivedT> & T,
144 const MatrixX4S & IT,
145 const ArrayXb & I,
146 MatrixX4I & TI,
147 MatrixX4S & ITI,
148 VectorXI & JI)
149 {
150 const Index num_I = std::count(I.data(),I.data()+I.size(),true);
151 TI.resize(num_I,4);
152 ITI.resize(num_I,4);
153 JI.resize(num_I,1);
154 {
155 size_t k = 0;
156 for(size_t t = 0;t<(size_t)T.rows();t++)
157 {
158 if(I(t))
159 {
160 TI.row(k) = T.row(t);
161 ITI.row(k) = IT.row(t);
162 JI(k) = t;
163 k++;
164 }
165 }
166 assert(k == num_I);
167 }
168 };
169
170 ArrayXb I13 = (IT.array()<0).rowwise().count()==1;
171 ArrayXb I31 = (IT.array()>0).rowwise().count()==1;
172 ArrayXb I22 = (IT.array()<0).rowwise().count()==2;
173 MatrixX4I T13,T31,T22;
174 MatrixX4S IT13,IT31,IT22;
175 VectorXI J13,J31,J22;
176 extract_rows(T,IT,I13,T13,IT13,J13);
177 extract_rows(T,IT,I31,T31,IT31,J31);
178 extract_rows(T,IT,I22,T22,IT22,J22);
179
180 const auto & apply_sort4 = [] (
181 const MatrixX4I & T,
182 const MatrixX4I & sJ,
183 MatrixX4I & sT)
184 {
185 sT.resize(T.rows(),4);
186 for(size_t t = 0;t<(size_t)T.rows();t++)
187 {
188 for(size_t c = 0;c<4;c++)
189 {
190 sT(t,c) = T(t,sJ(t,c));
191 }
192 }
193 };
194
195 const auto & apply_sort2 = [] (
196 const MatrixX2I & E,
197 const MatrixX2I & sJ,
199 {
200 sE.resize(E.rows(),2);
201 for(size_t t = 0;t<(size_t)E.rows();t++)
202 {
203 for(size_t c = 0;c<2;c++)
204 {
205 sE(t,c) = E(t,sJ(t,c));
206 }
207 }
208 };
209
210 const auto & one_below = [&apply_sort4](
211 const MatrixX4I & T,
212 const MatrixX4S & IT,
213 MatrixX2I & U,
214 MatrixX3I & SF)
215 {
216 // Number of tets
217 const size_t m = T.rows();
218 if(m == 0)
219 {
220 U.resize(0,2);
221 SF.resize(0,3);
222 return;
223 }
224 MatrixX4S sIT;
225 MatrixX4I sJ;
226 sort(IT,2,true,sIT,sJ);
227 MatrixX4I sT;
228 apply_sort4(T,sJ,sT);
229 U.resize(3*m,2);
230 U<<
231 sT.col(0),sT.col(1),
232 sT.col(0),sT.col(2),
233 sT.col(0),sT.col(3);
234 SF.resize(m,3);
235 for(size_t c = 0;c<3;c++)
236 {
237 SF.col(c) =
240 (m,0+c*m,(m-1)+c*m);
241 }
242 ArrayXb flip;
243 {
244 VectorXi _;
245 ismember_rows(sJ,flipped_order,flip,_);
246 }
247 for(int i = 0;i<m;i++)
248 {
249 if(flip(i))
250 {
251 SF.row(i) = SF.row(i).reverse().eval();
252 }
253 }
254 };
255
256 const auto & two_below = [&apply_sort4](
257 const MatrixX4I & T,
258 const MatrixX4S & IT,
259 MatrixX2I & U,
260 MatrixX3I & SF)
261 {
262 // Number of tets
263 const size_t m = T.rows();
264 if(m == 0)
265 {
266 U.resize(0,2);
267 SF.resize(0,3);
268 return;
269 }
270 MatrixX4S sIT;
271 MatrixX4I sJ;
272 sort(IT,2,true,sIT,sJ);
273 MatrixX4I sT;
274 apply_sort4(T,sJ,sT);
275 U.resize(4*m,2);
276 U<<
277 sT.col(0),sT.col(2),
278 sT.col(0),sT.col(3),
279 sT.col(1),sT.col(2),
280 sT.col(1),sT.col(3);
281 SF.resize(2*m,3);
282 SF.block(0,0,m,1) = igl::LinSpaced<VectorXI >(m,0+0*m,(m-1)+0*m);
283 SF.block(0,1,m,1) = igl::LinSpaced<VectorXI >(m,0+1*m,(m-1)+1*m);
284 SF.block(0,2,m,1) = igl::LinSpaced<VectorXI >(m,0+3*m,(m-1)+3*m);
285 SF.block(m,0,m,1) = igl::LinSpaced<VectorXI >(m,0+0*m,(m-1)+0*m);
286 SF.block(m,1,m,1) = igl::LinSpaced<VectorXI >(m,0+3*m,(m-1)+3*m);
287 SF.block(m,2,m,1) = igl::LinSpaced<VectorXI >(m,0+2*m,(m-1)+2*m);
288 ArrayXb flip;
289 {
290 VectorXi _;
291 ismember_rows(sJ,flipped_order,flip,_);
292 }
293 for(int i = 0;i<m;i++)
294 {
295 if(flip(i))
296 {
297 SF.row(i ) = SF.row(i ).reverse().eval();
298 SF.row(i+m) = SF.row(i+m).reverse().eval();
299 }
300 }
301 };
302
303 MatrixX3I SF13,SF31,SF22;
304 MatrixX2I U13,U31,U22;
305 one_below(T13, IT13,U13,SF13);
306 one_below(T31,-IT31,U31,SF31);
307 two_below(T22, IT22,U22,SF22);
308 // https://forum.kde.org/viewtopic.php?f=74&t=107974
309 const MatrixX2I U =
310 (MatrixX2I(U13.rows()+ U31.rows()+ U22.rows(),2)<<U13,U31,U22).finished();
311 MatrixX2I sU;
312 {
313 MatrixX2I _;
314 sort(U,2,true,sU,_);
315 }
316 MatrixX2I E;
317 VectorXI uI,uJ;
318 unique_rows(sU,E,uI,uJ);
319 MatrixX2S IE(E.rows(),2);
320 for(size_t t = 0;t<E.rows();t++)
321 {
322 for(size_t c = 0;c<2;c++)
323 {
324 IE(t,c) = S(E(t,c));
325 }
326 }
327 MatrixX2S sIE;
328 MatrixX2I sJ;
329 sort(IE,2,true,sIE,sJ);
330 apply_sort2(E,sJ,sE);
331 lambda = sIE.col(1).array() / (sIE.col(1)-sIE.col(0)).array();
332 SV.resize(sE.rows(),V.cols());
333 for(int e = 0;e<sE.rows();e++)
334 {
335 SV.row(e) = V.row(sE(e,0)).template cast<Scalar>()*lambda(e) +
336 V.row(sE(e,1)).template cast<Scalar>()*(1.0-lambda(e));
337 }
338 SF.resize( SF13.rows()+SF31.rows()+SF22.rows(),3);
339 SF<<
340 SF13,
341 U13.rows()+ SF31.rowwise().reverse().array(),
342 U13.rows()+U31.rows()+SF22.array();
343
344 std::for_each(
345 SF.data(),
346 SF.data()+SF.size(),
347 [&uJ](typename DerivedSF::Scalar & i){i=uJ(i);});
348
349 J.resize(SF.rows());
350 J<<J13,J31,J22,J22;
351}
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:50
Derived LinSpaced(typename Derived::Index size, const typename Derived::Scalar &low, const typename Derived::Scalar &high)
Definition LinSpaced.h:44

References _, Eigen::PlainObjectBase< Derived >::data(), ismember_rows(), LinSpaced(), Eigen::DenseBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), sort(), and unique_rows().

+ Here is the call graph for this function:

◆ slice_tets() [3/3]

template<typename DerivedV , typename DerivedT , typename DerivedS , typename DerivedSV , typename DerivedSF , typename DerivedJ , typename BCType >
IGL_INLINE void igl::slice_tets ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedT > &  T,
const Eigen::MatrixBase< DerivedS > &  S,
Eigen::PlainObjectBase< DerivedSV > &  SV,
Eigen::PlainObjectBase< DerivedSF > &  SF,
Eigen::PlainObjectBase< DerivedJ > &  J,
Eigen::SparseMatrix< BCType > &  BC 
)
36{
37 Eigen::MatrixXi sE;
39 igl::slice_tets(V,T,S,SV,SF,J,sE,lambda);
40 const int ns = SV.rows();
41 std::vector<Eigen::Triplet<BCType> > BCIJV(ns*2);
42 for(int i = 0;i<ns;i++)
43 {
44 BCIJV[2*i+0] = Eigen::Triplet<BCType>(i,sE(i,0), lambda(i));
45 BCIJV[2*i+1] = Eigen::Triplet<BCType>(i,sE(i,1),1.0-lambda(i));
46 }
47 BC.resize(SV.rows(),V.rows());
48 BC.setFromTriplets(BCIJV.begin(),BCIJV.end());
49}

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::resize(), Eigen::PlainObjectBase< Derived >::rows(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets(), and slice_tets().

Referenced by slice_tets(), and slice_tets().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ slim_precompute()

IGL_INLINE void igl::slim_precompute ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const Eigen::MatrixXd &  V_init,
SLIMData data,
SLIMData::SLIM_ENERGY  slim_energy,
Eigen::VectorXi &  b,
Eigen::MatrixXd &  bc,
double  soft_p 
)

Slim Implementation.

908{
909
910 data.V = V;
911 data.F = F;
912 data.V_o = V_init;
913
914 data.v_num = V.rows();
915 data.f_num = F.rows();
916
917 data.slim_energy = slim_energy;
918
919 data.b = b;
920 data.bc = bc;
921 data.soft_const_p = soft_p;
922
923 data.proximal_p = 0.0001;
924
925 igl::doublearea(V, F, data.M);
926 data.M /= 2.;
927 data.mesh_area = data.M.sum();
928 data.mesh_improvement_3d = false; // whether to use a jacobian derived from a real mesh or an abstract regular mesh (used for mesh improvement)
929 data.exp_factor = 1.0; // param used only for exponential energies (e.g exponential symmetric dirichlet)
930
931 assert (F.cols() == 3 || F.cols() == 4);
932
934 data.energy = igl::slim::compute_energy(data,data.V_o) / data.mesh_area;
935}
IGL_INLINE void pre_calc(igl::SLIMData &s)
Definition slim.cpp:439
IGL_INLINE double compute_energy(igl::SLIMData &s, Eigen::MatrixXd &V_new)
Definition slim.cpp:574

References igl::slim::compute_energy(), doublearea(), and igl::slim::pre_calc().

+ Here is the call graph for this function:

◆ slim_solve()

IGL_INLINE Eigen::MatrixXd igl::slim_solve ( SLIMData data,
int  iter_num 
)
938{
939 for (int i = 0; i < iter_num; i++)
940 {
941 Eigen::MatrixXd dest_res;
942 dest_res = data.V_o;
943
944 // Solve Weighted Proxy
945 igl::slim::update_weights_and_closest_rotations(data,data.V, data.F, dest_res);
946 igl::slim::solve_weighted_arap(data,data.V, data.F, dest_res, data.b, data.bc);
947
948 double old_energy = data.energy;
949
950 std::function<double(Eigen::MatrixXd &)> compute_energy = [&](
951 Eigen::MatrixXd &aaa) { return igl::slim::compute_energy(data,aaa); };
952
953 data.energy = igl::flip_avoiding_line_search(data.F, data.V_o, dest_res, compute_energy,
954 data.energy * data.mesh_area) / data.mesh_area;
955 }
956 return data.V_o;
957}
IGL_INLINE void update_weights_and_closest_rotations(igl::SLIMData &s, const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, Eigen::MatrixXd &uv)
Definition slim.cpp:119
IGL_INLINE void solve_weighted_arap(igl::SLIMData &s, const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, Eigen::MatrixXd &uv, Eigen::VectorXi &soft_b_p, Eigen::MatrixXd &soft_bc_p)
Definition slim.cpp:394
IGL_INLINE double flip_avoiding_line_search(const Eigen::MatrixXi F, Eigen::MatrixXd &cur_v, Eigen::MatrixXd &dst_v, std::function< double(Eigen::MatrixXd &)> energy, double cur_energy=-1)
Definition flip_avoiding_line_search.cpp:303

References igl::slim::compute_energy(), flip_avoiding_line_search(), igl::slim::solve_weighted_arap(), and igl::slim::update_weights_and_closest_rotations().

+ Here is the call graph for this function:

◆ snap_points() [1/3]

template<typename DerivedC , typename DerivedV , typename DerivedI >
IGL_INLINE void igl::snap_points ( const Eigen::PlainObjectBase< DerivedC > &  C,
const Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedI > &  I 
)
78{
80 return igl::snap_points(C,V,I,minD);
81}
IGL_INLINE void snap_points(const Eigen::PlainObjectBase< DerivedC > &C, const Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedminD > &minD, Eigen::PlainObjectBase< DerivedVI > &VI)
Definition snap_points.cpp:18

References snap_points().

+ Here is the call graph for this function:

◆ snap_points() [2/3]

template<typename DerivedC , typename DerivedV , typename DerivedI , typename DerivedminD >
IGL_INLINE void igl::snap_points ( const Eigen::PlainObjectBase< DerivedC > &  C,
const Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedI > &  I,
Eigen::PlainObjectBase< DerivedminD > &  minD 
)
44{
45 using namespace std;
46 const int n = V.rows();
47 const int m = C.rows();
48 assert(V.cols() == C.cols() && "Dimensions should match");
49 // O(m*n)
50 //
51 // I believe there should be a way to do this in O(m*log(n) + n) assuming
52 // reasonably distubed points.
53 I.resize(m,1);
54 typedef typename DerivedV::Scalar Scalar;
55 minD.setConstant(m,1,numeric_limits<Scalar>::max());
56 for(int v = 0;v<n;v++)
57 {
58 for(int c = 0;c<m;c++)
59 {
60 const Scalar d = (C.row(c) - V.row(v)).squaredNorm();
61 if(d < minD(c))
62 {
63 minD(c,0) = d;
64 I(c,0) = v;
65 }
66 }
67 }
68}

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), and Eigen::PlainObjectBase< Derived >::setConstant().

+ Here is the call graph for this function:

◆ snap_points() [3/3]

template<typename DerivedC , typename DerivedV , typename DerivedI , typename DerivedminD , typename DerivedVI >
IGL_INLINE void igl::snap_points ( const Eigen::PlainObjectBase< DerivedC > &  C,
const Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedI > &  I,
Eigen::PlainObjectBase< DerivedminD > &  minD,
Eigen::PlainObjectBase< DerivedVI > &  VI 
)
24{
25 snap_points(C,V,I,minD);
26 const int m = C.rows();
27 VI.resize(m,V.cols());
28 for(int c = 0;c<m;c++)
29 {
30 VI.row(c) = V.row(I(c));
31 }
32}

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::rows(), and snap_points().

Referenced by snap_points(), and snap_points().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ snap_to_canonical_view_quat() [1/2]

template<typename Scalarq , typename Scalars >
IGL_INLINE bool igl::snap_to_canonical_view_quat ( const Eigen::Quaternion< Scalarq > &  q,
const double  threshold,
Eigen::Quaternion< Scalars > &  s 
)
104{
105 return snap_to_canonical_view_quat<Scalars>(
106 q.coeffs().data(),threshold,s.coeffs().data());
107}
EIGEN_DEVICE_FUNC Coefficients & coeffs()
Definition Quaternion.h:284

References Eigen::Quaternion< _Scalar, _Options >::coeffs().

+ Here is the call graph for this function:

◆ snap_to_canonical_view_quat() [2/2]

template<typename Q_type >
IGL_INLINE bool igl::snap_to_canonical_view_quat ( const Q_type *  q,
const Q_type  threshold,
Q_type *  s 
)
28{
29 // Copy input into output
30 // CANNOT use std::copy here according to:
31 // http://www.cplusplus.com/reference/algorithm/copy/
32 s[0] = q[0];
33 s[1] = q[1];
34 s[2] = q[2];
35 s[3] = q[3];
36
37 // Normalize input quaternion
38 Q_type qn[4];
39 bool valid_len =
41 // If normalizing valid then don't bother
42 if(!valid_len)
43 {
44 return false;
45 }
46
47 // 0.290019
48 const Q_type MAX_DISTANCE = 0.4;
49 Q_type min_distance = 2*MAX_DISTANCE;
50 int min_index = -1;
51 double min_sign = 0;
52 // loop over canonical view quaternions
53 for(double sign = -1;sign<=1;sign+=2)
54 {
55 for(int i = 0; i<NUM_CANONICAL_VIEW_QUAT; i++)
56 {
57 Q_type distance = 0.0;
58 // loop over coordinates
59 for(int j = 0;j<4;j++)
60 {
61 // Double cast because of bug in llvm version 4.2 with -O3
62 distance +=
63 (qn[j]-sign*igl::CANONICAL_VIEW_QUAT<Q_type>(i,j))*
64 (qn[j]-sign*igl::CANONICAL_VIEW_QUAT<Q_type>(i,j));
65 }
66 if(min_distance > distance)
67 {
68 min_distance = distance;
69 min_index = i;
70 min_sign = sign;
71 }
72 }
73 }
74
75 if(MAX_DISTANCE < min_distance)
76 {
77 fprintf(
78 stderr,
79 "ERROR: found new max MIN_DISTANCE: %g\n"
80 "PLEASE update snap_to_canonical_quat()",
81 min_distance);
82 }
83
84 assert(min_distance < MAX_DISTANCE);
85 assert(min_index >= 0);
86
87 if( min_distance/MAX_DISTANCE <= threshold)
88 {
89 // loop over coordinates
90 for(int j = 0;j<4;j++)
91 {
92 s[j] = min_sign*igl::CANONICAL_VIEW_QUAT<Q_type>(min_index,j);
93 }
94 return true;
95 }
96 return false;
97}
#define NUM_CANONICAL_VIEW_QUAT
Definition canonical_quaternions.h:104
IGL_INLINE bool normalize_quat(const Q_type *q, Q_type *out)
Definition normalize_quat.cpp:14
double distance(const P &p1, const P &p2)
Definition geometry_traits.hpp:329

References normalize_quat(), NUM_CANONICAL_VIEW_QUAT, and sign().

Referenced by igl::opengl::glfw::Viewer::snap_to_canonical_quaternion().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ snap_to_fixed_up()

template<typename Qtype >
IGL_INLINE void igl::snap_to_fixed_up ( const Eigen::Quaternion< Qtype > &  q,
Eigen::Quaternion< Qtype > &  s 
)
14{
15 using namespace Eigen;
16 typedef Eigen::Matrix<Qtype,3,1> Vector3Q;
17 const Vector3Q up = q.matrix() * Vector3Q(0,1,0);
18 Vector3Q proj_up(0,up(1),up(2));
19 if(proj_up.norm() == 0)
20 {
21 proj_up = Vector3Q(0,1,0);
22 }
23 proj_up.normalize();
25 dq = Quaternion<Qtype>::FromTwoVectors(up,proj_up);
26 s = dq * q;
27}
EIGEN_DEVICE_FUNC RotationMatrixType matrix() const
Definition RotationBase.h:50

References Eigen::RotationBase< Derived, _Dim >::matrix().

Referenced by igl::opengl::ViewerCore::set_rotation_type().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ solid_angle()

template<typename DerivedA , typename DerivedB , typename DerivedC , typename DerivedP >
IGL_INLINE DerivedA::Scalar igl::solid_angle ( const Eigen::MatrixBase< DerivedA > &  A,
const Eigen::MatrixBase< DerivedB > &  B,
const Eigen::MatrixBase< DerivedC > &  C,
const Eigen::MatrixBase< DerivedP > &  P 
)
15{
16 typedef typename DerivedA::Scalar SType;
17 // Gather vectors to corners
19 // Don't use this since it will freak out for templates with != 3 size
20 //v<< (A-P),(B-P),(C-P);
21 for(int d = 0;d<3;d++)
22 {
23 v(0,d) = A(d)-P(d);
24 v(1,d) = B(d)-P(d);
25 v(2,d) = C(d)-P(d);
26 }
27 Eigen::Matrix<SType,1,3> vl = v.rowwise().norm();
28 //printf("\n");
29 // Compute determinant
30 SType detf =
31 v(0,0)*v(1,1)*v(2,2)+
32 v(1,0)*v(2,1)*v(0,2)+
33 v(2,0)*v(0,1)*v(1,2)-
34 v(2,0)*v(1,1)*v(0,2)-
35 v(1,0)*v(0,1)*v(2,2)-
36 v(0,0)*v(2,1)*v(1,2);
37 // Compute pairwise dotproducts
39 dp(0) = v(1,0)*v(2,0);
40 dp(0) += v(1,1)*v(2,1);
41 dp(0) += v(1,2)*v(2,2);
42 dp(1) = v(2,0)*v(0,0);
43 dp(1) += v(2,1)*v(0,1);
44 dp(1) += v(2,2)*v(0,2);
45 dp(2) = v(0,0)*v(1,0);
46 dp(2) += v(0,1)*v(1,1);
47 dp(2) += v(0,2)*v(1,2);
48 // Compute winding number
49 // Only divide by TWO_PI instead of 4*pi because there was a 2 out front
50 return atan2(detf,
51 vl(0)*vl(1)*vl(2) +
52 dp(0)*vl(0) +
53 dp(1)*vl(1) +
54 dp(2)*vl(2)) / (2.*igl::PI);
55}

References PI.

Referenced by winding_number().

+ Here is the caller graph for this function:

◆ sort() [1/2]

template<typename DerivedX , typename DerivedY , typename DerivedIX >
IGL_INLINE void igl::sort ( const Eigen::DenseBase< DerivedX > &  X,
const int  dim,
const bool  ascending,
Eigen::PlainObjectBase< DerivedY > &  Y,
Eigen::PlainObjectBase< DerivedIX > &  IX 
)
27{
28 typedef typename DerivedX::Scalar Scalar;
29 // get number of rows (or columns)
30 int num_inner = (dim == 1 ? X.rows() : X.cols() );
31 // Special case for swapping
32 switch(num_inner)
33 {
34 default:
35 break;
36 case 2:
37 return igl::sort2(X,dim,ascending,Y,IX);
38 case 3:
39 return igl::sort3(X,dim,ascending,Y,IX);
40 }
41 using namespace Eigen;
42 // get number of columns (or rows)
43 int num_outer = (dim == 1 ? X.cols() : X.rows() );
44 // dim must be 2 or 1
45 assert(dim == 1 || dim == 2);
46 // Resize output
47 Y.resizeLike(X);
48 IX.resizeLike(X);
49 // idea is to process each column (or row) as a std vector
50 // loop over columns (or rows)
51 for(int i = 0; i<num_outer;i++)
52 {
53 // Unsorted index map for this column (or row)
54 std::vector<size_t> index_map(num_inner);
55 std::vector<Scalar> data(num_inner);
56 for(int j = 0;j<num_inner;j++)
57 {
58 if(dim == 1)
59 {
60 data[j] = (Scalar) X(j,i);
61 }else
62 {
63 data[j] = (Scalar) X(i,j);
64 }
65 }
66 // sort this column (or row)
67 igl::sort( data, ascending, data, index_map);
68 // Copy into Y and IX
69 for(int j = 0;j<num_inner;j++)
70 {
71 if(dim == 1)
72 {
73 Y(j,i) = data[j];
74 IX(j,i) = index_map[j];
75 }else
76 {
77 Y(i,j) = data[j];
78 IX(i,j) = index_map[j];
79 }
80 }
81 }
82}
IGL_INLINE void sort3(const Eigen::DenseBase< DerivedX > &X, const int dim, const bool ascending, Eigen::PlainObjectBase< DerivedY > &Y, Eigen::PlainObjectBase< DerivedIX > &IX)
Definition sort.cpp:198
IGL_INLINE void sort2(const Eigen::DenseBase< DerivedX > &X, const int dim, const bool ascending, Eigen::PlainObjectBase< DerivedY > &Y, Eigen::PlainObjectBase< DerivedIX > &IX)
Definition sort.cpp:153

References Eigen::PlainObjectBase< Derived >::resizeLike(), sort(), sort2(), and sort3().

Referenced by boundary_conditions(), doublearea(), edges_to_path(), eigs(), exterior_edges(), face_occurrences(), igl::AABB< DerivedV, DIM >::init(), is_boundary_edge(), is_boundary_edge(), ismember(), orientable_patches(), setdiff(), slice_tets(), sort(), sort_triangles(), sort_vectors_ccw(), unique(), and unique_simplices().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sort() [2/2]

template<class T >
IGL_INLINE void igl::sort ( const std::vector< T > &  unsorted,
const bool  ascending,
std::vector< T > &  sorted,
std::vector< size_t > &  index_map 
)
293{
294// Original unsorted index map
295index_map.resize(unsorted.size());
296for(size_t i=0;i<unsorted.size();i++)
297{
298 index_map[i] = i;
299}
300// Sort the index map, using unsorted for comparison
301std::sort(
302 index_map.begin(),
303 index_map.end(),
304 igl::IndexLessThan<const std::vector<T>& >(unsorted));
305
306// if not ascending then reverse
307if(!ascending)
308{
309 std::reverse(index_map.begin(),index_map.end());
310}
311 // make space for output without clobbering
312 sorted.resize(unsorted.size());
313 // reorder unsorted into sorted using index map
314 igl::reorder(unsorted,index_map,sorted);
315}
IGL_INLINE void reorder(const std::vector< T > &unordered, std::vector< size_t > const &index_map, std::vector< T > &ordered)
Definition reorder.cpp:16
Definition IndexComparison.h:17

References reorder().

+ Here is the call graph for this function:

◆ sort2()

template<typename DerivedX , typename DerivedY , typename DerivedIX >
IGL_INLINE void igl::sort2 ( const Eigen::DenseBase< DerivedX > &  X,
const int  dim,
const bool  ascending,
Eigen::PlainObjectBase< DerivedY > &  Y,
Eigen::PlainObjectBase< DerivedIX > &  IX 
)
159{
160 using namespace Eigen;
161 using namespace std;
162 typedef typename DerivedY::Scalar YScalar;
163 Y = X.derived().template cast<YScalar>();
164
165
166 // get number of columns (or rows)
167 int num_outer = (dim == 1 ? X.cols() : X.rows() );
168 // get number of rows (or columns)
169 int num_inner = (dim == 1 ? X.rows() : X.cols() );
170 assert(num_inner == 2);(void)num_inner;
171 typedef typename DerivedIX::Scalar Index;
172 IX.resizeLike(X);
173 if(dim==1)
174 {
175 IX.row(0).setConstant(0);// = DerivedIX::Zero(1,IX.cols());
176 IX.row(1).setConstant(1);// = DerivedIX::Ones (1,IX.cols());
177 }else
178 {
179 IX.col(0).setConstant(0);// = DerivedIX::Zero(IX.rows(),1);
180 IX.col(1).setConstant(1);// = DerivedIX::Ones (IX.rows(),1);
181 }
182 // loop over columns (or rows)
183 for(int i = 0;i<num_outer;i++)
184 {
185 YScalar & a = (dim==1 ? Y(0,i) : Y(i,0));
186 YScalar & b = (dim==1 ? Y(1,i) : Y(i,1));
187 Index & ai = (dim==1 ? IX(0,i) : IX(i,0));
188 Index & bi = (dim==1 ? IX(1,i) : IX(i,1));
189 if((ascending && a>b) || (!ascending && a<b))
190 {
191 std::swap(a,b);
192 std::swap(ai,bi);
193 }
194 }
195}

References Eigen::PlainObjectBase< Derived >::resizeLike(), Eigen::PlainObjectBase< Derived >::setConstant(), and void().

Referenced by sort(), and sort_new().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sort3()

template<typename DerivedX , typename DerivedY , typename DerivedIX >
IGL_INLINE void igl::sort3 ( const Eigen::DenseBase< DerivedX > &  X,
const int  dim,
const bool  ascending,
Eigen::PlainObjectBase< DerivedY > &  Y,
Eigen::PlainObjectBase< DerivedIX > &  IX 
)
204{
205 using namespace Eigen;
206 using namespace std;
207 typedef typename DerivedY::Scalar YScalar;
208 Y = X.derived().template cast<YScalar>();
209 Y.resizeLike(X);
210 for(int j=0;j<X.cols();j++)for(int i=0;i<X.rows();i++)Y(i,j)=(YScalar)X(i,j);
211
212 // get number of columns (or rows)
213 int num_outer = (dim == 1 ? X.cols() : X.rows() );
214 // get number of rows (or columns)
215 int num_inner = (dim == 1 ? X.rows() : X.cols() );
216 assert(num_inner == 3);(void)num_inner;
217 typedef typename DerivedIX::Scalar Index;
218 IX.resizeLike(X);
219 if(dim==1)
220 {
221 IX.row(0).setConstant(0);// = DerivedIX::Zero(1,IX.cols());
222 IX.row(1).setConstant(1);// = DerivedIX::Ones (1,IX.cols());
223 IX.row(2).setConstant(2);// = DerivedIX::Ones (1,IX.cols());
224 }else
225 {
226 IX.col(0).setConstant(0);// = DerivedIX::Zero(IX.rows(),1);
227 IX.col(1).setConstant(1);// = DerivedIX::Ones (IX.rows(),1);
228 IX.col(2).setConstant(2);// = DerivedIX::Ones (IX.rows(),1);
229 }
230
231
232 const auto & inner = [&IX,&Y,&dim,&ascending](const Index & i)
233 {
234 YScalar & a = (dim==1 ? Y(0,i) : Y(i,0));
235 YScalar & b = (dim==1 ? Y(1,i) : Y(i,1));
236 YScalar & c = (dim==1 ? Y(2,i) : Y(i,2));
237 Index & ai = (dim==1 ? IX(0,i) : IX(i,0));
238 Index & bi = (dim==1 ? IX(1,i) : IX(i,1));
239 Index & ci = (dim==1 ? IX(2,i) : IX(i,2));
240 if(ascending)
241 {
242 // 123 132 213 231 312 321
243 if(a > b)
244 {
245 std::swap(a,b);
246 std::swap(ai,bi);
247 }
248 // 123 132 123 231 132 231
249 if(b > c)
250 {
251 std::swap(b,c);
252 std::swap(bi,ci);
253 // 123 123 123 213 123 213
254 if(a > b)
255 {
256 std::swap(a,b);
257 std::swap(ai,bi);
258 }
259 // 123 123 123 123 123 123
260 }
261 }else
262 {
263 // 123 132 213 231 312 321
264 if(a < b)
265 {
266 std::swap(a,b);
267 std::swap(ai,bi);
268 }
269 // 213 312 213 321 312 321
270 if(b < c)
271 {
272 std::swap(b,c);
273 std::swap(bi,ci);
274 // 231 321 231 321 321 321
275 if(a < b)
276 {
277 std::swap(a,b);
278 std::swap(ai,bi);
279 }
280 // 321 321 321 321 321 321
281 }
282 }
283 };
284 parallel_for(num_outer,inner,16000);
285}

References parallel_for(), Eigen::PlainObjectBase< Derived >::resizeLike(), Eigen::PlainObjectBase< Derived >::setConstant(), and void().

Referenced by sort(), and sort_new().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sort_angles()

template<typename DerivedM , typename DerivedR >
IGL_INLINE void igl::sort_angles ( const Eigen::PlainObjectBase< DerivedM > &  M,
Eigen::PlainObjectBase< DerivedR > &  R 
)
15 {
16 const size_t num_rows = M.rows();
17 const size_t num_cols = M.cols();
18 assert(num_cols >= 2);
19
20 R.resize(num_rows);
21 // Have to use << instead of = because Eigen's PlainObjectBase is annoying
22 R << igl::LinSpaced<
24 (num_rows, 0, num_rows-1);
25
26 // |
27 // (pi/2, pi) | (0, pi/2)
28 // |
29 // -------------+--------------
30 // |
31 // (-pi, -pi/2) | (-pi/2, 0)
32 // |
33 auto comp = [&](size_t i, size_t j) {
34 auto yi = M(i, 0);
35 auto xi = M(i, 1);
36 auto yj = M(j, 0);
37 auto xj = M(j, 1);
38
39 if (xi == xj && yi == yj) {
40 for (size_t idx=2; idx<num_cols; idx++) {
41 auto i_val = M(i, idx);
42 auto j_val = M(j, idx);
43 if (i_val != j_val) {
44 return i_val < j_val;
45 }
46 }
47 // If the entire rows are equal, use the row index.
48 return i < j;
49 }
50
51 if (xi >= 0 && yi >= 0) {
52 if (xj >=0 && yj >= 0) {
53 if (xi != xj) {
54 return xi > xj;
55 } else {
56 return yi < yj;
57 }
58 } else if (xj < 0 && yj >= 0) {
59 return true;
60 } else if (xj < 0 && yj < 0) {
61 return false;
62 } else {
63 return false;
64 }
65 } else if (xi < 0 && yi >= 0) {
66 if (xj >= 0 && yj >= 0) {
67 return false;
68 } else if (xj < 0 && yj >= 0) {
69 if (xi != xj) {
70 return xi > xj;
71 } else {
72 return yi > yj;
73 }
74 } else if (xj < 0 && yj < 0) {
75 return false;
76 } else {
77 return false;
78 }
79 } else if (xi < 0 && yi < 0) {
80 if (xj >= 0 && yj >= 0) {
81 return true;
82 } else if (xj < 0 && yj >= 0) {
83 return true;
84 } else if (xj < 0 && yj < 0) {
85 if (xi != xj) {
86 return xi < xj;
87 } else {
88 return yi > yj;
89 }
90 } else {
91 return true;
92 }
93 } else {
94 if (xj >= 0 && yj >= 0) {
95 return true;
96 } else if (xj < 0 && yj >= 0) {
97 return true;
98 } else if (xj < 0 && yj < 0) {
99 return false;
100 } else {
101 if (xi != xj) {
102 return xi < xj;
103 } else {
104 return yi < yj;
105 }
106 }
107 }
108 };
109 std::sort(R.data(), R.data() + num_rows, comp);
110}

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::data(), LinSpaced(), Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::rows().

Referenced by igl::copyleft::cgal::order_facets_around_edges().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sort_new()

template<typename DerivedX , typename DerivedY , typename DerivedIX >
IGL_INLINE void igl::sort_new ( const Eigen::DenseBase< DerivedX > &  X,
const int  dim,
const bool  ascending,
Eigen::PlainObjectBase< DerivedY > &  Y,
Eigen::PlainObjectBase< DerivedIX > &  IX 
)
91{
92 // get number of rows (or columns)
93 int num_inner = (dim == 1 ? X.rows() : X.cols() );
94 // Special case for swapping
95 switch(num_inner)
96 {
97 default:
98 break;
99 case 2:
100 return igl::sort2(X,dim,ascending,Y,IX);
101 case 3:
102 return igl::sort3(X,dim,ascending,Y,IX);
103 }
104 using namespace Eigen;
105 // get number of columns (or rows)
106 int num_outer = (dim == 1 ? X.cols() : X.rows() );
107 // dim must be 2 or 1
108 assert(dim == 1 || dim == 2);
109 // Resize output
110 Y.resizeLike(X);
111 IX.resizeLike(X);
112 // idea is to process each column (or row) as a std vector
113 // loop over columns (or rows)
114 for(int i = 0; i<num_outer;i++)
115 {
116 Eigen::VectorXi ix;
117 colon(0,num_inner-1,ix);
118 // Sort the index map, using unsorted for comparison
119 if(dim == 1)
120 {
121 std::sort(
122 ix.data(),
123 ix.data()+ix.size(),
125 }else
126 {
127 std::sort(
128 ix.data(),
129 ix.data()+ix.size(),
131 }
132 // if not ascending then reverse
133 if(!ascending)
134 {
135 std::reverse(ix.data(),ix.data()+ix.size());
136 }
137 for(int j = 0;j<num_inner;j++)
138 {
139 if(dim == 1)
140 {
141 Y(j,i) = X(ix[j],i);
142 IX(j,i) = ix[j];
143 }else
144 {
145 Y(i,j) = X(i,ix[j]);
146 IX(i,j) = ix[j];
147 }
148 }
149 }
150}
Definition IndexComparison.h:39

References colon(), Eigen::PlainObjectBase< Derived >::resizeLike(), sort2(), and sort3().

+ Here is the call graph for this function:

◆ sort_triangles()

template<typename DerivedV , typename DerivedF , typename DerivedMV , typename DerivedP , typename DerivedFF , typename DerivedI >
IGL_INLINE void igl::sort_triangles ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedMV > &  MV,
const Eigen::PlainObjectBase< DerivedP > &  P,
Eigen::PlainObjectBase< DerivedFF > &  FF,
Eigen::PlainObjectBase< DerivedI > &  I 
)
32{
33 using namespace Eigen;
34 using namespace std;
35
36
37 // Barycenter, centroid
40 barycenter(V,F,BC);
41 D = BC*(MV.transpose()*P.transpose().eval().col(2));
42 sort(D,1,false,sD,I);
43
45 //Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,1> D,sD;
46 //D.setConstant(F.rows(),1,-1e26);
47 //for(int c = 0;c<3;c++)
48 //{
49 // Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,4> C;
50 // Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,1> DC;
51 // C.resize(F.rows(),4);
52 // for(int f = 0;f<F.rows();f++)
53 // {
54 // C(f,0) = V(F(f,c),0);
55 // C(f,1) = V(F(f,c),1);
56 // C(f,2) = V(F(f,c),2);
57 // C(f,3) = 1;
58 // }
59 // DC = C*(MV.transpose()*P.transpose().eval().col(2));
60 // D = (DC.array()>D.array()).select(DC,D).eval();
61 //}
62 //sort(D,1,false,sD,I);
63
65 //Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,3> D,sD,ssD;
66 //D.resize(F.rows(),3);
67 //for(int c = 0;c<3;c++)
68 //{
69 // Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,4> C;
70 // C.resize(F.rows(),4);
71 // for(int f = 0;f<F.rows();f++)
72 // {
73 // C(f,0) = V(F(f,c),0);
74 // C(f,1) = V(F(f,c),1);
75 // C(f,2) = V(F(f,c),2);
76 // C(f,3) = 1;
77 // }
78 // D.col(c) = C*(MV.transpose()*P.transpose().eval().col(2));
79 //}
80 //VectorXi _;
81 //sort(D,2,false,sD,_);
82 //sortrows(sD,false,ssD,I);
83
84
85 slice(F,I,1,FF);
86}

References barycenter(), slice(), and sort().

+ Here is the call graph for this function:

◆ sort_vectors_ccw() [1/4]

template<typename DerivedS , typename DerivedI >
IGL_INLINE void igl::sort_vectors_ccw ( const Eigen::PlainObjectBase< DerivedS > &  P,
const Eigen::PlainObjectBase< DerivedS > &  N,
Eigen::PlainObjectBase< DerivedI > &  order 
)
17{
18 int half_degree = P.cols()/3;
19 //local frame
20 Eigen::Matrix<typename DerivedS::Scalar,1,3> e1 = P.head(3).normalized();
23
24 Eigen::Matrix<typename DerivedS::Scalar,3,3> F; F<<e1.transpose(),e2.transpose(),e3.transpose();
25
27 for (int i=0; i<half_degree; ++i)
28 {
29 Eigen::Matrix<typename DerivedS::Scalar,1,3> Pl = F.colPivHouseholderQr().solve(P.segment(i*3,3).transpose()).transpose();
30// assert(fabs(Pl(2))/Pl.cwiseAbs().maxCoeff() <1e-5);
31 angles[i] = atan2(Pl(1),Pl(0));
32 }
33
34 igl::sort( angles, 1, true, angles, order);
35 //make sure that the first element is always at the top
36 while (order[0] != 0)
37 {
38 //do a circshift
39 int temp = order[0];
40 for (int i =0; i< half_degree-1; ++i)
41 order[i] = order[i+1];
42 order(half_degree-1) = temp;
43 }
44}

References Eigen::PlainObjectBase< Derived >::cols(), and sort().

+ Here is the call graph for this function:

◆ sort_vectors_ccw() [2/4]

template<typename DerivedS , typename DerivedI >
IGL_INLINE void igl::sort_vectors_ccw ( const Eigen::PlainObjectBase< DerivedS > &  P,
const Eigen::PlainObjectBase< DerivedS > &  N,
Eigen::PlainObjectBase< DerivedI > &  order,
Eigen::PlainObjectBase< DerivedI > &  inv_order 
)
66 {
67 int half_degree = P.cols()/3;
68 igl::sort_vectors_ccw(P,N,order);
69 inv_order.resize(half_degree,1);
70 for (int i=0; i<half_degree; ++i)
71 {
72 for (int j=0; j<half_degree; ++j)
73 if (order[j] ==i)
74 {
75 inv_order(i) = j;
76 break;
77 }
78 }
79 assert(inv_order[0] == 0);
80 }
IGL_INLINE void sort_vectors_ccw(const Eigen::PlainObjectBase< DerivedS > &P, const Eigen::PlainObjectBase< DerivedS > &N, Eigen::PlainObjectBase< DerivedI > &order, Eigen::PlainObjectBase< DerivedS > &sorted, Eigen::PlainObjectBase< DerivedI > &inv_order)
Definition sort_vectors_ccw.cpp:83

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::resize(), and sort_vectors_ccw().

+ Here is the call graph for this function:

◆ sort_vectors_ccw() [3/4]

template<typename DerivedS , typename DerivedI >
IGL_INLINE void igl::sort_vectors_ccw ( const Eigen::PlainObjectBase< DerivedS > &  P,
const Eigen::PlainObjectBase< DerivedS > &  N,
Eigen::PlainObjectBase< DerivedI > &  order,
Eigen::PlainObjectBase< DerivedS > &  sorted 
)
52 {
53 int half_degree = P.cols()/3;
54 igl::sort_vectors_ccw(P,N,order);
55 sorted.resize(1,half_degree*3);
56 for (int i=0; i<half_degree; ++i)
57 sorted.segment(i*3,3) = P.segment(order[i]*3,3);
58 }

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::resize(), and sort_vectors_ccw().

+ Here is the call graph for this function:

◆ sort_vectors_ccw() [4/4]

template<typename DerivedS , typename DerivedI >
IGL_INLINE void igl::sort_vectors_ccw ( const Eigen::PlainObjectBase< DerivedS > &  P,
const Eigen::PlainObjectBase< DerivedS > &  N,
Eigen::PlainObjectBase< DerivedI > &  order,
Eigen::PlainObjectBase< DerivedS > &  sorted,
Eigen::PlainObjectBase< DerivedI > &  inv_order 
)
89{
90 int half_degree = P.cols()/3;
91
92 igl::sort_vectors_ccw(P,N,order,inv_order);
93
94 sorted.resize(1,half_degree*3);
95 for (int i=0; i<half_degree; ++i)
96 sorted.segment(i*3,3) = P.segment(order[i]*3,3);
97}

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::resize(), and sort_vectors_ccw().

Referenced by sort_vectors_ccw(), sort_vectors_ccw(), and sort_vectors_ccw().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sortrows()

template<typename DerivedX , typename DerivedI >
IGL_INLINE void igl::sortrows ( const Eigen::DenseBase< DerivedX > &  X,
const bool  ascending,
Eigen::PlainObjectBase< DerivedX > &  Y,
Eigen::PlainObjectBase< DerivedI > &  I 
)

Referenced by ismember_rows(), lexicographic_triangulation(), and unique_rows().

+ Here is the caller graph for this function:

◆ sparse() [1/4]

template<typename DerivedD >
IGL_INLINE Eigen::SparseMatrix< typename DerivedD::Scalar > igl::sparse ( const Eigen::PlainObjectBase< DerivedD > &  D)
101{
102 assert(false && "Obsolete. Just call D.sparseView() directly");
104 igl::sparse(D,X);
105 return X;
106}

References sparse().

+ Here is the call graph for this function:

◆ sparse() [2/4]

template<typename DerivedD , typename T >
IGL_INLINE void igl::sparse ( const Eigen::PlainObjectBase< DerivedD > &  D,
Eigen::SparseMatrix< T > &  X 
)
77{
78 assert(false && "Obsolete. Just call D.sparseView() directly");
79 using namespace std;
80 using namespace Eigen;
81 vector<Triplet<T> > DIJV;
82 const int m = D.rows();
83 const int n = D.cols();
84 for(int i = 0;i<m;i++)
85 {
86 for(int j = 0;j<n;j++)
87 {
88 if(D(i,j)!=0)
89 {
90 DIJV.push_back(Triplet<T>(i,j,D(i,j)));
91 }
92 }
93 }
94 X.resize(m,n);
95 X.setFromTriplets(DIJV.begin(),DIJV.end());
96}

References Eigen::PlainObjectBase< Derived >::cols(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ sparse() [3/4]

template<class IndexVector , class ValueVector , typename T >
IGL_INLINE void igl::sparse ( const IndexVector &  I,
const IndexVector &  J,
const ValueVector &  V,
Eigen::SparseMatrix< T > &  X 
)
19{
20 size_t m = (size_t)I.maxCoeff()+1;
21 size_t n = (size_t)J.maxCoeff()+1;
22 return igl::sparse(I,J,V,m,n,X);
23}

References sparse().

Referenced by massmatrix(), sparse(), sparse(), and straighten_seams().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sparse() [4/4]

template<class IndexVectorI , class IndexVectorJ , class ValueVector , typename T >
IGL_INLINE void igl::sparse ( const IndexVectorI &  I,
const IndexVectorJ &  J,
const ValueVector &  V,
const size_t  m,
const size_t  n,
Eigen::SparseMatrix< T > &  X 
)
38{
39 using namespace std;
40 using namespace Eigen;
41 assert((int)I.maxCoeff() < (int)m);
42 assert((int)I.minCoeff() >= 0);
43 assert((int)J.maxCoeff() < (int)n);
44 assert((int)J.minCoeff() >= 0);
45 assert(I.size() == J.size());
46 assert(J.size() == V.size());
47 // Really we just need .size() to be the same, but this is safer
48 assert(I.rows() == J.rows());
49 assert(J.rows() == V.rows());
50 assert(I.cols() == J.cols());
51 assert(J.cols() == V.cols());
53 //int nv = V.size();
54
55 //Eigen::DynamicSparseMatrix<T, Eigen::RowMajor> dyn_X(m,n);
57 //dyn_X.reserve(I.size());
58 //for(int i = 0;i < nv;i++)
59 //{
60 // dyn_X.coeffRef((int)I(i),(int)J(i)) += (T)V(i);
61 //}
62 //X = Eigen::SparseMatrix<T>(dyn_X);
63 vector<Triplet<T> > IJV;
64 IJV.reserve(I.size());
65 for(int x = 0;x<I.size();x++)
66 {
67 IJV.push_back(Triplet<T >(I(x),J(x),V(x)));
68 }
69 X.resize(m,n);
70 X.setFromTriplets(IJV.begin(),IJV.end());
71}

◆ sparse_cached() [1/2]

template<typename DerivedV , typename Scalar >
IGL_INLINE void igl::sparse_cached ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::VectorXi &  data,
Eigen::SparseMatrix< Scalar > &  X 
)
106{
107 assert(V.size() == data.size());
108
109 // Clear it first
110 for (unsigned i = 0; i<data.size(); ++i)
111 *(X.valuePtr() + data[i]) = 0;
112
113 // Then sum them up
114 for (unsigned i = 0; i<V.size(); ++i)
115 *(X.valuePtr() + data[i]) += V[i];
116}

◆ sparse_cached() [2/2]

template<typename Scalar >
IGL_INLINE void igl::sparse_cached ( const std::vector< Eigen::Triplet< Scalar > > &  triplets,
const Eigen::VectorXi &  data,
Eigen::SparseMatrix< Scalar > &  X 
)
89{
90 assert(triplets.size() == data.size());
91
92 // Clear it first
93 for (unsigned i = 0; i<data.size(); ++i)
94 *(X.valuePtr() + data[i]) = 0;
95
96 // Then sum them up
97 for (unsigned i = 0; i<triplets.size(); ++i)
98 *(X.valuePtr() + data[i]) += triplets[i].value();
99}

Referenced by igl::slim::build_linear_system().

+ Here is the caller graph for this function:

◆ sparse_cached_precompute() [1/2]

template<typename DerivedI , typename Scalar >
IGL_INLINE void igl::sparse_cached_precompute ( const Eigen::MatrixBase< DerivedI > &  I,
const Eigen::MatrixBase< DerivedI > &  J,
Eigen::VectorXi &  data,
Eigen::SparseMatrix< Scalar > &  X 
)
23{
24 // Generates the triplets
25 std::vector<Eigen::Triplet<double> > t(I.size());
26 for (unsigned i = 0; i<I.size(); ++i)
27 t[i] = Eigen::Triplet<double>(I[i],J[i],1);
28
29 // Call the triplets version
31}
IGL_INLINE void sparse_cached_precompute(const Eigen::MatrixBase< DerivedI > &I, const Eigen::MatrixBase< DerivedI > &J, Eigen::VectorXi &data, Eigen::SparseMatrix< Scalar > &X)
Definition sparse_cached.cpp:18

References sparse_cached_precompute().

Referenced by igl::slim::build_linear_system(), and sparse_cached_precompute().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sparse_cached_precompute() [2/2]

template<typename Scalar >
IGL_INLINE void igl::sparse_cached_precompute ( const std::vector< Eigen::Triplet< Scalar > > &  triplets,
Eigen::VectorXi &  data,
Eigen::SparseMatrix< Scalar > &  X 
)
38{
39 // Construct an empty sparse matrix
40 X.setFromTriplets(triplets.begin(),triplets.end());
41 X.makeCompressed();
42
43 std::vector<std::array<int,3> > T(triplets.size());
44 for (unsigned i=0; i<triplets.size(); ++i)
45 {
46 T[i][0] = triplets[i].col();
47 T[i][1] = triplets[i].row();
48 T[i][2] = i;
49 }
50
51 std::sort(T.begin(), T.end());
52
53 data.resize(triplets.size());
54
55 int t = 0;
56
57 for (unsigned k=0; k<X.outerSize(); ++k)
58 {
59 unsigned outer_index = *(X.outerIndexPtr()+k);
60 unsigned next_outer_index = (k+1 == X.outerSize()) ? X.nonZeros() : *(X.outerIndexPtr()+k+1);
61
62 for (unsigned l=outer_index; l<next_outer_index; ++l)
63 {
64 int col = k;
65 int row = *(X.innerIndexPtr()+l);
66 int value_index = l;
67 assert(col < X.cols());
68 assert(col >= 0);
69 assert(row < X.rows());
70 assert(row >= 0);
71 assert(value_index >= 0);
72 assert(value_index < X.nonZeros());
73
74 std::pair<int,int> p_m = std::make_pair(row,col);
75
76 while (t<T.size() && (p_m == std::make_pair(T[t][1],T[t][0])))
77 data[T[t++][2]] = value_index;
78 }
79 }
80 assert(t==T.size());
81
82}

References col(), and row().

+ Here is the call graph for this function:

◆ speye() [1/2]

template<typename T >
IGL_INLINE void igl::speye ( const int  n,
const int  m,
Eigen::SparseMatrix< T > &  I 
)
12{
13 // size of diagonal
14 int d = (m<n?m:n);
16 I.reserve(d);
17 for(int i = 0;i<d;i++)
18 {
19 I.insert(i,i) = 1.0;
20 }
21 I.finalize();
22}

References Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::finalize(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::insert(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::reserve().

Referenced by arap_dof_precomputation(), arap_precomputation(), harmonic(), and speye().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ speye() [2/2]

template<typename T >
IGL_INLINE void igl::speye ( const int  n,
Eigen::SparseMatrix< T > &  I 
)
26{
27 return igl::speye(n,n,I);
28}

References speye().

+ Here is the call graph for this function:

◆ splitColumns()

template<typename MatL , typename MatLsep >
static void igl::splitColumns ( const MatL &  L,
int  numBones,
int  dim,
int  dimp1,
MatLsep &  Lsep 
)
static
408 {
409 assert(L.cols() == 1);
410 assert(L.rows() == dim*(dimp1)*numBones);
411
412 assert(Lsep.rows() == (dimp1)*numBones && Lsep.cols() == dim);
413
414 for (int b=0; b<numBones; b++)
415 {
416 for (int coord=0; coord<dimp1; coord++)
417 {
418 for (int c=0; c<dim; c++)
419 {
420 Lsep(coord*numBones + b, c) = L(coord*numBones*dim + c*numBones + b, 0);
421 }
422 }
423 }
424 }

References L.

Referenced by arap_dof_update().

+ Here is the caller graph for this function:

◆ squared_edge_lengths()

template<typename DerivedV , typename DerivedF , typename DerivedL >
IGL_INLINE void igl::squared_edge_lengths ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedL > &  L 
)
17{
18 using namespace std;
19 const int m = F.rows();
20 switch(F.cols())
21 {
22 case 2:
23 {
24 L.resize(F.rows(),1);
25 for(int i = 0;i<F.rows();i++)
26 {
27 L(i,0) = (V.row(F(i,1))-V.row(F(i,0))).squaredNorm();
28 }
29 break;
30 }
31 case 3:
32 {
33 L.resize(m,3);
34 // loop over faces
36 m,
37 [&V,&F,&L](const int i)
38 {
39 L(i,0) = (V.row(F(i,1))-V.row(F(i,2))).squaredNorm();
40 L(i,1) = (V.row(F(i,2))-V.row(F(i,0))).squaredNorm();
41 L(i,2) = (V.row(F(i,0))-V.row(F(i,1))).squaredNorm();
42 },
43 1000);
44 break;
45 }
46 case 4:
47 {
48 L.resize(m,6);
49 // loop over faces
51 m,
52 [&V,&F,&L](const int i)
53 {
54 L(i,0) = (V.row(F(i,3))-V.row(F(i,0))).squaredNorm();
55 L(i,1) = (V.row(F(i,3))-V.row(F(i,1))).squaredNorm();
56 L(i,2) = (V.row(F(i,3))-V.row(F(i,2))).squaredNorm();
57 L(i,3) = (V.row(F(i,1))-V.row(F(i,2))).squaredNorm();
58 L(i,4) = (V.row(F(i,2))-V.row(F(i,0))).squaredNorm();
59 L(i,5) = (V.row(F(i,0))-V.row(F(i,1))).squaredNorm();
60 },
61 1000);
62 break;
63 }
64 default:
65 {
66 cerr<< "squared_edge_lengths.h: Error: Simplex size ("<<F.cols()<<
67 ") not supported"<<endl;
68 assert(false);
69 }
70 }
71}

References L, and parallel_for().

Referenced by cotmatrix_entries(), edge_lengths(), and internal_angles().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ stdin_to_temp()

IGL_INLINE bool igl::stdin_to_temp ( FILE **  temp_file)
13{
14 // get a temporary file
15 *temp_file = tmpfile();
16 if(*temp_file == NULL)
17 {
18 fprintf(stderr,"IOError: temp file could not be created.\n");
19 return false;
20 }
21 char c;
22 // c++'s cin handles the stdind input in a reasonable way
23 while (std::cin.good())
24 {
25 c = std::cin.get();
26 if(std::cin.good())
27 {
28 if(1 != fwrite(&c,sizeof(char),1,*temp_file))
29 {
30 fprintf(stderr,"IOError: error writing to tempfile.\n");
31 return false;
32 }
33 }
34 }
35 // rewind file getting it ready to read from
36 rewind(*temp_file);
37 return true;
38}

◆ straighten_seams()

template<typename DerivedV , typename DerivedF , typename DerivedVT , typename DerivedFT , typename Scalar , typename DerivedUE , typename DerivedUT , typename DerivedOT >
IGL_INLINE void igl::straighten_seams ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< DerivedVT > &  VT,
const Eigen::MatrixBase< DerivedFT > &  FT,
const Scalar  tol,
Eigen::PlainObjectBase< DerivedUE > &  UE,
Eigen::PlainObjectBase< DerivedUT > &  UT,
Eigen::PlainObjectBase< DerivedOT > &  OT 
)
48{
49 using namespace Eigen;
50 // number of faces
51 assert(FT.rows() == F.rows() && "#FT must == #F");
52 assert(F.cols() == 3 && "F should contain triangles");
53 assert(FT.cols() == 3 && "FT should contain triangles");
54 const int m = F.rows();
55 // Boundary edges of the texture map and 3d meshes
58 on_boundary(FT,_,BT);
59 on_boundary(F,_,BF);
60 assert((!((BF && (BT!=true)).any())) &&
61 "Not dealing with boundaries of mesh that get 'stitched' in texture mesh");
63 const MatrixX2I ET = (MatrixX2I(FT.rows()*3,2)
64 <<FT.col(1),FT.col(2),FT.col(2),FT.col(0),FT.col(0),FT.col(1)).finished();
65 // "half"-edges with indices into 3D-mesh
66 const MatrixX2I EF = (MatrixX2I(F.rows()*3,2)
67 <<F.col(1),F.col(2),F.col(2),F.col(0),F.col(0),F.col(1)).finished();
68 // Find unique (undirected) edges in F
69 VectorXi EFMAP;
70 {
71 MatrixX2I _1;
72 VectorXi _2;
73 unique_simplices(EF,_1,_2,EFMAP);
74 }
77 MatrixX2I OF;
78 slice_mask(ET,vBT,1,OT);
79 slice_mask(EF,vBT,1,OF);
80 VectorXi OFMAP;
81 slice_mask(EFMAP,vBT,1,OFMAP);
82 // Two boundary edges on the texture-mapping are "equivalent" to each other on
83 // the 3D-mesh if their 3D-mesh vertex indices match
85 {
87 sparse(
88 igl::LinSpaced<VectorXi >(OT.rows(),0,OT.rows()-1),
89 OFMAP,
91 OT.rows(),
92 m*3,
93 OEQR);
94 OEQ = OEQR * OEQR.transpose();
95 // Remove diagonal
96 OEQ.prune([](const int r, const int c, const bool)->bool{return r!=c;});
97 }
98 // For each edge in OT, for each endpoint, how many _other_ texture-vertices
99 // are images of all the 3d-mesh vertices in F who map from "corners" in F/FT
100 // mapping to this endpoint.
101 //
102 // Adjacency matrix between 3d-vertices and texture-vertices
104 sparse(
105 F,
106 FT,
107 Array<bool,Dynamic,3>::Ones(F.rows(),F.cols()),
108 V.rows(),
109 VT.rows(),
110 V2VT);
111 // For each 3d-vertex count how many different texture-coordinates its getting
112 // from different incident corners
113 VectorXi DV;
114 count(V2VT,2,DV);
115 VectorXi M,I;
116 max(V2VT,1,M,I);
117 assert( (M.array() == 1).all() );
118 VectorXi DT;
119 // Map counts onto texture-vertices
120 slice(DV,I,1,DT);
121 // Boundary in 3D && UV
123 slice_mask(vBF, vBT, 1, BTF);
124 // Texture-vertex is "sharp" if incident on "half-"edge that is not a
125 // boundary in the 3D mesh but is a boundary in the texture-mesh AND is not
126 // "cut cleanly" (the vertex is mapped to exactly 2 locations)
128 //std::cout<<"#SV: "<<SV.count()<<std::endl;
129 assert(BTF.size() == OT.rows());
130 for(int h = 0;h<BTF.size();h++)
131 {
132 if(!BTF(h))
133 {
134 SV(OT(h,0)) = true;
135 SV(OT(h,1)) = true;
136 }
137 }
138 //std::cout<<"#SV: "<<SV.count()<<std::endl;
139 Array<bool,Dynamic,1> CL = DT.array()==2;
141 {
142 Eigen::MatrixXi I =
143 igl::LinSpaced<VectorXi >(OT.rows(),0,OT.rows()-1).replicate(1,2);
144 sparse(
145 OT,
146 I,
148 VT.rows(),
149 OT.rows(),
150 VTOT);
152 count( (VTOT*OEQ).eval(), 2, cuts);
153 CL = (CL && (cuts.array() == 2)).eval();
154 }
155 //std::cout<<"#CL: "<<CL.count()<<std::endl;
156 assert(CL.size() == SV.size());
157 for(int c = 0;c<CL.size();c++) if(CL(c)) SV(c) = false;
158 {}
159 //std::cout<<"#SV: "<<SV.count()<<std::endl;
160
161 {
162 // vertices at the corner of ears are declared to be sharp. This is
163 // conservative: for example, if the ear is strictly convex and stays
164 // strictly convex then the ear won't be flipped.
165 VectorXi ear,ear_opp;
166 ears(FT,ear,ear_opp);
167 //std::cout<<"#ear: "<<ear.size()<<std::endl;
168 // There might be an ear on one copy, so mark vertices on other copies, too
169 // ears as they live on the 3D mesh
171 for(int e = 0;e<ear.size();e++) earT(FT(ear(e),ear_opp(e))) = 1;
172 //std::cout<<"#earT: "<<earT.count()<<std::endl;
173 // Even if ear-vertices are marked as sharp if it changes, e.g., from
174 // convex to concave then it will _force_ a flip of the ear triangle. So,
175 // declare that neighbors of ears are also sharp.
177 adjacency_matrix(FT,A);
178 earT = (earT || (A*earT.matrix()).array()).eval();
179 //std::cout<<"#earT: "<<earT.count()<<std::endl;
180 assert(earT.size() == SV.size());
181 for(int e = 0;e<earT.size();e++) if(earT(e)) SV(e) = true;
182 //std::cout<<"#SV: "<<SV.count()<<std::endl;
183 }
184
185 {
186 SparseMatrix<bool> V2VTSV,V2VTC;
187 slice_mask(V2VT,SV,2,V2VTSV);
189 any(V2VTSV,2,Cb);
190 slice_mask(V2VT,Cb,1,V2VTC);
191 any(V2VTC,1,SV);
192 }
193 //std::cout<<"#SV: "<<SV.count()<<std::endl;
194
195 SparseMatrix<bool> OTVT = VTOT.transpose();
196 int nc;
197 ArrayXi C;
198 {
199 // Doesn't Compile on older Eigen:
200 //SparseMatrix<bool> A = OTVT * (!SV).matrix().asDiagonal() * VTOT;
201 SparseMatrix<bool> A = OTVT * (SV!=true).matrix().asDiagonal() * VTOT;
202 components(A,C);
203 nc = C.maxCoeff()+1;
204 }
205 //std::cout<<"nc: "<<nc<<std::endl;
206 // New texture-vertex locations
207 UT = VT;
208 // Indices into UT of coarse output polygon edges
209 std::vector<std::vector<typename DerivedUE::Scalar> > vUE;
210 // loop over each component
211 std::vector<bool> done(nc,false);
212 for(int c = 0;c<nc;c++)
213 {
214 if(done[c])
215 {
216 continue;
217 }
218 done[c] = true;
219 // edges of this component
220 Eigen::VectorXi Ic;
221 find(C==c,Ic);
222 if(Ic.size() == 0)
223 {
224 continue;
225 }
226 SparseMatrix<bool> OEQIc;
227 slice(OEQ,Ic,1,OEQIc);
228 Eigen::VectorXi N;
229 sum(OEQIc,2,N);
230 const int ncopies = N(0)+1;
231 assert((N.array() == ncopies-1).all());
232 assert((ncopies == 1 || ncopies == 2) &&
233 "Not dealing with non-manifold meshes");
234 Eigen::VectorXi vpath,epath,eend;
236 switch(ncopies)
237 {
238 case 1:
239 {
240 MatrixX2I OTIc;
241 slice(OT,Ic,1,OTIc);
242 edges_to_path(OTIc,vpath,epath,eend);
243 Array<bool,Dynamic,1> SVvpath;
244 slice(SV,vpath,1,SVvpath);
245 assert(
246 (vpath(0) != vpath(vpath.size()-1) || !SVvpath.any()) &&
247 "Not dealing with 1-loops touching 'sharp' corners");
248 // simple open boundary
249 MatrixX2S PI;
250 slice(VT,vpath,1,PI);
251 const Scalar bbd =
252 (PI.colwise().maxCoeff() - PI.colwise().minCoeff()).norm();
253 // Do not collapse boundaries to fewer than 3 vertices
254 const bool allow_boundary_collapse = false;
255 assert(PI.size() >= 2);
256 const bool is_closed = PI(0) == PI(PI.size()-1);
257 assert(!is_closed || vpath.size() >= 4);
258 Scalar eff_tol = std::min(tol,2.);
259 VectorXi UIc;
260 while(true)
261 {
262 MatrixX2S UPI,UTvpath;
263 ramer_douglas_peucker(PI,eff_tol*bbd,UPI,UIc,UTvpath);
264 slice_into(UTvpath,vpath,1,UT);
265 if(!is_closed || allow_boundary_collapse)
266 {
267 break;
268 }
269 if(UPI.rows()>=4)
270 {
271 break;
272 }
273 eff_tol = eff_tol*0.5;
274 }
275 for(int i = 0;i<UIc.size()-1;i++)
276 {
277 vUE.push_back({vpath(UIc(i)),vpath(UIc(i+1))});
278 }
279 }
280 break;
281 case 2:
282 {
283 // Find copies
284 VectorXi Icc;
285 {
286 VectorXi II;
288 SparseMatrix<bool> OEQIcT = OEQIc.transpose().eval();
289 find(OEQIcT,Icc,II,IV);
290 assert(II.size() == Ic.size() &&
291 (II.array() ==
292 igl::LinSpaced<VectorXi >(Ic.size(),0,Ic.size()-1).array()).all());
293 assert(Icc.size() == Ic.size());
294 const int cc = C(Icc(0));
295 Eigen::VectorXi CIcc;
296 slice(C,Icc,1,CIcc);
297 assert((CIcc.array() == cc).all());
298 assert(!done[cc]);
299 done[cc] = true;
300 }
301 Array<bool,Dynamic,1> flipped;
302 {
303 MatrixX2I OFIc,OFIcc;
304 slice(OF,Ic,1,OFIc);
305 slice(OF,Icc,1,OFIcc);
306 Eigen::VectorXi XOR,IA,IB;
307 setxor(OFIc,OFIcc,XOR,IA,IB);
308 assert(XOR.size() == 0);
309 flipped = OFIc.array().col(0) != OFIcc.array().col(0);
310 }
311 if(Ic.size() == 1)
312 {
313 // No change to UT
314 vUE.push_back({OT(Ic(0),0),OT(Ic(0),1)});
315 assert(Icc.size() == 1);
316 vUE.push_back({OT(Icc(0),flipped(0)?1:0),OT(Icc(0),flipped(0)?0:1)});
317 }else
318 {
319 MatrixX2I OTIc;
320 slice(OT,Ic,1,OTIc);
321 edges_to_path(OTIc,vpath,epath,eend);
322 // Flip endpoints if needed
323 for(int e = 0;e<eend.size();e++)if(flipped(e))eend(e)=1-eend(e);
324 VectorXi vpathc(epath.size()+1);
325 for(int e = 0;e<epath.size();e++)
326 {
327 vpathc(e) = OT(Icc(epath(e)),eend(e));
328 }
329 vpathc(epath.size()) =
330 OT(Icc(epath(epath.size()-1)),1-eend(eend.size()-1));
331 assert(vpath.size() == vpathc.size());
332 Matrix<Scalar,Dynamic,Dynamic> PI(vpath.size(),VT.cols()*2);
333 for(int p = 0;p<PI.rows();p++)
334 {
335 for(int d = 0;d<VT.cols();d++)
336 {
337 PI(p, d) = VT( vpath(p),d);
338 PI(p,VT.cols()+d) = VT(vpathc(p),d);
339 }
340 }
341 const Scalar bbd =
342 (PI.colwise().maxCoeff() - PI.colwise().minCoeff()).norm();
344 VectorXi UIc;
345 ramer_douglas_peucker(PI,tol*bbd,UPI,UIc,SI);
346 slice_into(SI.leftCols (VT.cols()), vpath,1,UT);
347 slice_into(SI.rightCols(VT.cols()),vpathc,1,UT);
348 for(int i = 0;i<UIc.size()-1;i++)
349 {
350 vUE.push_back({vpath(UIc(i)),vpath(UIc(i+1))});
351 }
352 for(int i = 0;i<UIc.size()-1;i++)
353 {
354 vUE.push_back({vpathc(UIc(i)),vpathc(UIc(i+1))});
355 }
356 }
357 }
358 break;
359 default:
360 assert(false && "Should never reach here");
361 }
362 }
363 list_to_matrix(vUE,UE);
364}
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half() max(const half &a, const half &b)
Definition Half.h:516
bool is_closed(unsigned c)
Definition agg_basics.h:478
IGL_INLINE void ears(const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< Derivedear > &ear, Eigen::PlainObjectBase< Derivedear_opp > &ear_opp)
Definition ears.cpp:12
IGL_INLINE void edges_to_path(const Eigen::MatrixBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::PlainObjectBase< DerivedK > &K)
Definition edges_to_path.cpp:14
IGL_INLINE void setxor(const Eigen::DenseBase< DerivedA > &A, const Eigen::DenseBase< DerivedB > &B, Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedIA > &IA, Eigen::PlainObjectBase< DerivedIB > &IB)
Definition setxor.cpp:12

References _, adjacency_matrix(), any(), Eigen::PlainObjectBase< Derived >::cols(), components(), count(), Eigen::PlainObjectBase< Derived >::data(), done, ears(), edges_to_path(), find(), list_to_matrix(), on_boundary(), PI, Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::prune(), ramer_douglas_peucker(), Eigen::PlainObjectBase< Derived >::rows(), setxor(), slice(), slice_into(), slice_mask(), sparse(), sum(), Eigen::SparseMatrixBase< Derived >::transpose(), and unique_simplices().

+ Here is the call graph for this function:

◆ sum() [1/2]

template<typename AType , typename DerivedB >
IGL_INLINE void igl::sum ( const Eigen::SparseMatrix< AType > &  A,
const int  dim,
Eigen::PlainObjectBase< DerivedB > &  B 
)
52{
53 typedef typename DerivedB::Scalar Scalar;
54 igl::redux(A,dim,[](Scalar a, Scalar b){ return a+b;},B);
55}

References redux().

+ Here is the call graph for this function:

◆ sum() [2/2]

template<typename T >
IGL_INLINE void igl::sum ( const Eigen::SparseMatrix< T > &  X,
const int  dim,
Eigen::SparseVector< T > &  S 
)
16{
17 assert((dim == 1 || dim == 2) && "dim must be 2 or 1");
18 // Get size of input
19 int m = X.rows();
20 int n = X.cols();
21 // resize output
22 if(dim==1)
23 {
25 }else
26 {
28 }
29
30 // Iterate over outside
31 for(int k=0; k<X.outerSize(); ++k)
32 {
33 // Iterate over inside
34 for(typename Eigen::SparseMatrix<T>::InnerIterator it (X,k); it; ++it)
35 {
36 if(dim == 1)
37 {
38 S.coeffRef(it.col()) += it.value();
39 }else
40 {
41 S.coeffRef(it.row()) += it.value();
42 }
43 }
44 }
45}

References Eigen::SparseVector< _Scalar, _Options, _StorageIndex >::coeffRef().

Referenced by biharmonic_coordinates(), boundary_conditions(), bounding_box_diagonal(), igl::geodesic::Mesh::build_adjacencies(), cumsum(), fast_winding_number(), igl::AABB< DerivedV, DIM >::find(), fit_plane(), harmonic(), normalize_row_sums(), project_to_line(), igl::copyleft::quadprog(), straighten_seams(), and igl::WindingNumberTree< Point, DerivedV, DerivedF >::winding_number().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ svd3x3()

template<typename T >
IGL_INLINE void igl::svd3x3 ( const Eigen::Matrix< T, 3, 3 > &  A,
Eigen::Matrix< T, 3, 3 > &  U,
Eigen::Matrix< T, 3, 1 > &  S,
Eigen::Matrix< T, 3, 3 > &  V 
)
23{
24 // this code only supports the scalar version (otherwise we'd need to pass arrays of matrices)
25
27
28 ENABLE_SCALAR_IMPLEMENTATION(Sa11.f=A(0,0);) ENABLE_SSE_IMPLEMENTATION(Va11=_mm_loadu_ps(a11);) ENABLE_AVX_IMPLEMENTATION(Va11=_mm256_loadu_ps(a11);)
29 ENABLE_SCALAR_IMPLEMENTATION(Sa21.f=A(1,0);) ENABLE_SSE_IMPLEMENTATION(Va21=_mm_loadu_ps(a21);) ENABLE_AVX_IMPLEMENTATION(Va21=_mm256_loadu_ps(a21);)
30 ENABLE_SCALAR_IMPLEMENTATION(Sa31.f=A(2,0);) ENABLE_SSE_IMPLEMENTATION(Va31=_mm_loadu_ps(a31);) ENABLE_AVX_IMPLEMENTATION(Va31=_mm256_loadu_ps(a31);)
31 ENABLE_SCALAR_IMPLEMENTATION(Sa12.f=A(0,1);) ENABLE_SSE_IMPLEMENTATION(Va12=_mm_loadu_ps(a12);) ENABLE_AVX_IMPLEMENTATION(Va12=_mm256_loadu_ps(a12);)
32 ENABLE_SCALAR_IMPLEMENTATION(Sa22.f=A(1,1);) ENABLE_SSE_IMPLEMENTATION(Va22=_mm_loadu_ps(a22);) ENABLE_AVX_IMPLEMENTATION(Va22=_mm256_loadu_ps(a22);)
33 ENABLE_SCALAR_IMPLEMENTATION(Sa32.f=A(2,1);) ENABLE_SSE_IMPLEMENTATION(Va32=_mm_loadu_ps(a32);) ENABLE_AVX_IMPLEMENTATION(Va32=_mm256_loadu_ps(a32);)
34 ENABLE_SCALAR_IMPLEMENTATION(Sa13.f=A(0,2);) ENABLE_SSE_IMPLEMENTATION(Va13=_mm_loadu_ps(a13);) ENABLE_AVX_IMPLEMENTATION(Va13=_mm256_loadu_ps(a13);)
35 ENABLE_SCALAR_IMPLEMENTATION(Sa23.f=A(1,2);) ENABLE_SSE_IMPLEMENTATION(Va23=_mm_loadu_ps(a23);) ENABLE_AVX_IMPLEMENTATION(Va23=_mm256_loadu_ps(a23);)
36 ENABLE_SCALAR_IMPLEMENTATION(Sa33.f=A(2,2);) ENABLE_SSE_IMPLEMENTATION(Va33=_mm_loadu_ps(a33);) ENABLE_AVX_IMPLEMENTATION(Va33=_mm256_loadu_ps(a33);)
37
38#include "Singular_Value_Decomposition_Main_Kernel_Body.hpp"
39
40 ENABLE_SCALAR_IMPLEMENTATION(U(0,0)=Su11.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(u11,Vu11);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(u11,Vu11);)
41 ENABLE_SCALAR_IMPLEMENTATION(U(1,0)=Su21.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(u21,Vu21);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(u21,Vu21);)
42 ENABLE_SCALAR_IMPLEMENTATION(U(2,0)=Su31.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(u31,Vu31);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(u31,Vu31);)
43 ENABLE_SCALAR_IMPLEMENTATION(U(0,1)=Su12.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(u12,Vu12);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(u12,Vu12);)
44 ENABLE_SCALAR_IMPLEMENTATION(U(1,1)=Su22.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(u22,Vu22);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(u22,Vu22);)
45 ENABLE_SCALAR_IMPLEMENTATION(U(2,1)=Su32.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(u32,Vu32);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(u32,Vu32);)
46 ENABLE_SCALAR_IMPLEMENTATION(U(0,2)=Su13.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(u13,Vu13);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(u13,Vu13);)
47 ENABLE_SCALAR_IMPLEMENTATION(U(1,2)=Su23.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(u23,Vu23);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(u23,Vu23);)
48 ENABLE_SCALAR_IMPLEMENTATION(U(2,2)=Su33.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(u33,Vu33);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(u33,Vu33);)
49
50 ENABLE_SCALAR_IMPLEMENTATION(V(0,0)=Sv11.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(v11,Vv11);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(v11,Vv11);)
51 ENABLE_SCALAR_IMPLEMENTATION(V(1,0)=Sv21.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(v21,Vv21);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(v21,Vv21);)
52 ENABLE_SCALAR_IMPLEMENTATION(V(2,0)=Sv31.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(v31,Vv31);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(v31,Vv31);)
53 ENABLE_SCALAR_IMPLEMENTATION(V(0,1)=Sv12.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(v12,Vv12);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(v12,Vv12);)
54 ENABLE_SCALAR_IMPLEMENTATION(V(1,1)=Sv22.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(v22,Vv22);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(v22,Vv22);)
55 ENABLE_SCALAR_IMPLEMENTATION(V(2,1)=Sv32.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(v32,Vv32);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(v32,Vv32);)
56 ENABLE_SCALAR_IMPLEMENTATION(V(0,2)=Sv13.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(v13,Vv13);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(v13,Vv13);)
57 ENABLE_SCALAR_IMPLEMENTATION(V(1,2)=Sv23.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(v23,Vv23);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(v23,Vv23);)
58 ENABLE_SCALAR_IMPLEMENTATION(V(2,2)=Sv33.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(v33,Vv33);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(v33,Vv33);)
59
60 ENABLE_SCALAR_IMPLEMENTATION(S(0,0)=Sa11.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(sigma1,Va11);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(sigma1,Va11);)
61 ENABLE_SCALAR_IMPLEMENTATION(S(1,0)=Sa22.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(sigma2,Va22);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(sigma2,Va22);)
62 ENABLE_SCALAR_IMPLEMENTATION(S(2,0)=Sa33.f;) ENABLE_SSE_IMPLEMENTATION(_mm_storeu_ps(sigma3,Va33);) ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(sigma3,Va33);)
63}
Sa23
Definition Singular_Value_Decomposition_Kernel_Declarations.hpp:88
Sa21
Definition Singular_Value_Decomposition_Kernel_Declarations.hpp:82
Sa12
Definition Singular_Value_Decomposition_Kernel_Declarations.hpp:84
Sa32
Definition Singular_Value_Decomposition_Kernel_Declarations.hpp:86
#define ENABLE_AVX_IMPLEMENTATION(X)
Definition Singular_Value_Decomposition_Preamble.hpp:51
#define ENABLE_SSE_IMPLEMENTATION(X)
Definition Singular_Value_Decomposition_Preamble.hpp:42
#define ENABLE_SCALAR_IMPLEMENTATION(X)
Definition Singular_Value_Decomposition_Preamble.hpp:36

References ENABLE_AVX_IMPLEMENTATION, ENABLE_SCALAR_IMPLEMENTATION, ENABLE_SSE_IMPLEMENTATION, Sa12, Sa21, Sa23, and Sa32.

Referenced by polar_svd3x3().

+ Here is the caller graph for this function:

◆ svd3x3_avx()

template<typename T >
IGL_INLINE void igl::svd3x3_avx ( const Eigen::Matrix< T, 3 *8, 3 > &  A,
Eigen::Matrix< T, 3 *8, 3 > &  U,
Eigen::Matrix< T, 3 *8, 1 > &  S,
Eigen::Matrix< T, 3 *8, 3 > &  V 
)

◆ svd3x3_sse()

template<typename T >
IGL_INLINE void igl::svd3x3_sse ( const Eigen::Matrix< T, 3 *4, 3 > &  A,
Eigen::Matrix< T, 3 *4, 3 > &  U,
Eigen::Matrix< T, 3 *4, 1 > &  S,
Eigen::Matrix< T, 3 *4, 3 > &  V 
)

◆ swept_volume_bounding_box()

IGL_INLINE void igl::swept_volume_bounding_box ( const size_t &  n,
const std::function< Eigen::RowVector3d(const size_t vi, const double t)> &  V,
const size_t &  steps,
Eigen::AlignedBox3d &  box 
)
16{
17 using namespace Eigen;
18 box.setEmpty();
19 const VectorXd t = igl::LinSpaced<VectorXd >(steps,0,1);
20 // Find extent over all time steps
21 for(int ti = 0;ti<t.size();ti++)
22 {
23 for(size_t vi = 0;vi<n;vi++)
24 {
25 box.extend(V(vi,t(ti)).transpose());
26 }
27 }
28}

Referenced by igl::copyleft::swept_volume().

+ Here is the caller graph for this function:

◆ swept_volume_signed_distance() [1/2]

IGL_INLINE void igl::swept_volume_signed_distance ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const std::function< Eigen::Affine3d(const double t)> &  transform,
const size_t &  steps,
const Eigen::MatrixXd &  GV,
const Eigen::RowVector3i &  res,
const double  h,
const double  isolevel,
const Eigen::VectorXd &  S0,
Eigen::VectorXd &  S 
)
32{
33 using namespace std;
34 using namespace igl;
35 using namespace Eigen;
36 S = S0;
37 const VectorXd t = igl::LinSpaced<VectorXd >(steps,0,1);
38 const bool finite_iso = isfinite(isolevel);
39 const double extension = (finite_iso ? isolevel : 0) + sqrt(3.0)*h;
40 Eigen::AlignedBox3d box(
41 V.colwise().minCoeff().array()-extension,
42 V.colwise().maxCoeff().array()+extension);
43 // Precomputation
44 Eigen::MatrixXd FN,VN,EN;
45 Eigen::MatrixXi E;
46 Eigen::VectorXi EMAP;
47 per_face_normals(V,F,FN);
48 per_vertex_normals(V,F,PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE,FN,VN);
50 V,F,PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM,FN,EN,E,EMAP);
52 tree.init(V,F);
53 for(int ti = 0;ti<t.size();ti++)
54 {
55 const Affine3d At = transform(t(ti));
56 for(int g = 0;g<GV.rows();g++)
57 {
58 // Don't bother finding out how deep inside points are.
59 if(finite_iso && S(g)==S(g) && S(g)<isolevel-sqrt(3.0)*h)
60 {
61 continue;
62 }
63 const RowVector3d gv =
64 (GV.row(g) - At.translation().transpose())*At.linear();
65 // If outside of extended box, then consider it "far away enough"
66 if(finite_iso && !box.contains(gv.transpose()))
67 {
68 continue;
69 }
70 RowVector3d c,n;
71 int i;
72 double sqrd,s;
73 //signed_distance_pseudonormal(tree,V,F,FN,VN,EN,EMAP,gv,s,sqrd,i,c,n);
74 const double min_sqrd =
75 finite_iso ?
76 pow(sqrt(3.)*h+isolevel,2) :
77 numeric_limits<double>::infinity();
78 sqrd = tree.squared_distance(V,F,gv,min_sqrd,i,c);
79 if(sqrd<min_sqrd)
80 {
81 pseudonormal_test(V,F,FN,VN,EN,EMAP,gv,i,c,s,n);
82 if(S(g) == S(g))
83 {
84 S(g) = std::min(S(g),s*sqrt(sqrd));
85 }else
86 {
87 S(g) = s*sqrt(sqrd);
88 }
89 }
90 }
91 }
92
93 if(finite_iso)
94 {
95 flood_fill(res,S);
96 }else
97 {
98#ifndef NDEBUG
99 // Check for nans
100 std::for_each(S.data(),S.data()+S.size(),[](const double s){assert(s==s);});
101#endif
102 }
103}
EIGEN_DEVICE_FUNC ConstLinearPart linear() const
Definition Transform.h:400
EIGEN_DEVICE_FUNC ConstTranslationPart translation() const
Definition Transform.h:410
IGL_INLINE void flood_fill(const Eigen::MatrixBase< Derivedres > &res, Eigen::PlainObjectBase< DerivedS > &S)
Definition flood_fill.cpp:12

References flood_fill(), igl::AABB< DerivedV, DIM >::init(), Eigen::Transform< _Scalar, _Dim, _Mode, _Options >::linear(), per_edge_normals(), PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM, per_face_normals(), per_vertex_normals(), PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE, pseudonormal_test(), sqrt(), igl::AABB< DerivedV, DIM >::squared_distance(), and Eigen::Transform< _Scalar, _Dim, _Mode, _Options >::translation().

Referenced by igl::copyleft::swept_volume(), and swept_volume_signed_distance().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ swept_volume_signed_distance() [2/2]

IGL_INLINE void igl::swept_volume_signed_distance ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const std::function< Eigen::Affine3d(const double t)> &  transform,
const size_t &  steps,
const Eigen::MatrixXd &  GV,
const Eigen::RowVector3i &  res,
const double  h,
const double  isolevel,
Eigen::VectorXd &  S 
)
115{
116 using namespace std;
117 using namespace igl;
118 using namespace Eigen;
119 S = VectorXd::Constant(GV.rows(),1,numeric_limits<double>::quiet_NaN());
120 return
121 swept_volume_signed_distance(V,F,transform,steps,GV,res,h,isolevel,S,S);
122}
IGL_INLINE void swept_volume_signed_distance(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const std::function< Eigen::Affine3d(const double t)> &transform, const size_t &steps, const Eigen::MatrixXd &GV, const Eigen::RowVector3i &res, const double h, const double isolevel, const Eigen::VectorXd &S0, Eigen::VectorXd &S)
Definition swept_volume_signed_distance.cpp:21

References swept_volume_signed_distance().

+ Here is the call graph for this function:

◆ trackball() [1/3]

template<typename Scalardown_quat , typename Scalarquat >
IGL_INLINE void igl::trackball ( const double  w,
const double  h,
const double  speed_factor,
const Eigen::Quaternion< Scalardown_quat > &  down_quat,
const double  down_mouse_x,
const double  down_mouse_y,
const double  mouse_x,
const double  mouse_y,
Eigen::Quaternion< Scalarquat > &  quat 
)
146{
147 using namespace std;
148 return trackball(
149 w,
150 h,
151 (Scalarquat)speed_factor,
152 down_quat.coeffs().data(),
153 down_mouse_x,
154 down_mouse_y,
155 mouse_x,
156 mouse_y,
157 quat.coeffs().data());
158}
IGL_INLINE void trackball(const double w, const double h, const Q_type speed_factor, const double down_mouse_x, const double down_mouse_y, const double mouse_x, const double mouse_y, Q_type *quat)
Definition trackball.cpp:43

References Eigen::Quaternion< _Scalar, _Options >::coeffs(), and trackball().

+ Here is the call graph for this function:

◆ trackball() [2/3]

template<typename Q_type >
IGL_INLINE void igl::trackball ( const double  w,
const double  h,
const Q_type  speed_factor,
const double  down_mouse_x,
const double  down_mouse_y,
const double  mouse_x,
const double  mouse_y,
Q_type *  quat 
)
52{
53 assert(speed_factor > 0);
54
55 double original_x =
56 _QuatIX<Q_type>(speed_factor*(down_mouse_x-w/2)+w/2, w, h);
57 double original_y =
58 _QuatIY<Q_type>(speed_factor*(down_mouse_y-h/2)+h/2, w, h);
59
60 double x = _QuatIX<Q_type>(speed_factor*(mouse_x-w/2)+w/2, w, h);
61 double y = _QuatIY<Q_type>(speed_factor*(mouse_y-h/2)+h/2, w, h);
62
63 double z = 1;
64 double n0 = sqrt(original_x*original_x + original_y*original_y + z*z);
65 double n1 = sqrt(x*x + y*y + z*z);
67 {
68 double v0[] = { original_x/n0, original_y/n0, z/n0 };
69 double v1[] = { x/n1, y/n1, z/n1 };
70 double axis[3];
71 cross(v0,v1,axis);
72 double sa = sqrt(dot(axis, axis));
73 double ca = dot(v0, v1);
74 double angle = atan2(sa, ca);
75 if( x*x+y*y>1.0 )
76 {
77 angle *= 1.0 + 0.2f*(sqrt(x*x+y*y)-1.0);
78 }
79 double qrot[4];
80 axis_angle_to_quat(axis,angle,qrot);
81 quat[0] = qrot[0];
82 quat[1] = qrot[1];
83 quat[2] = qrot[2];
84 quat[3] = qrot[3];
85 }
86}
int BLASFUNC() qrot(int *, double *, int *, double *, int *, double *, double *)
IGL_INLINE void axis_angle_to_quat(const Q_type *axis, const Q_type angle, Q_type *out)
Definition axis_angle_to_quat.cpp:14
const double DOUBLE_EPS
Definition EPS.h:14

References axis_angle_to_quat(), cross(), dot(), DOUBLE_EPS, qrot(), and sqrt().

Referenced by igl::opengl2::RotateWidget::drag(), igl::opengl::glfw::Viewer::mouse_move(), and trackball().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ trackball() [3/3]

template<typename Q_type >
IGL_INLINE void igl::trackball ( const double  w,
const double  h,
const Q_type  speed_factor,
const Q_type *  down_quat,
const double  down_mouse_x,
const double  down_mouse_y,
const double  mouse_x,
const double  mouse_y,
Q_type *  quat 
)
100{
101 double qrot[4], qres[4], qorig[4];
102 igl::trackball<double>(
103 w,h,
104 speed_factor,
105 down_mouse_x,down_mouse_y,
106 mouse_x,mouse_y,
107 qrot);
108 double nqorig =
109 sqrt(down_quat[0]*down_quat[0]+
110 down_quat[1]*down_quat[1]+
111 down_quat[2]*down_quat[2]+
112 down_quat[3]*down_quat[3]);
113
114 if( fabs(nqorig)>igl::DOUBLE_EPS_SQ )
115 {
116 qorig[0] = down_quat[0]/nqorig;
117 qorig[1] = down_quat[1]/nqorig;
118 qorig[2] = down_quat[2]/nqorig;
119 qorig[3] = down_quat[3]/nqorig;
120 igl::quat_mult<double>(qrot,qorig,qres);
121 quat[0] = qres[0];
122 quat[1] = qres[1];
123 quat[2] = qres[2];
124 quat[3] = qres[3];
125 }
126 else
127 {
128 quat[0] = qrot[0];
129 quat[1] = qrot[1];
130 quat[2] = qrot[2];
131 quat[3] = qrot[3];
132 }
133}
const double DOUBLE_EPS_SQ
Definition EPS.h:15

References DOUBLE_EPS_SQ, qrot(), and sqrt().

+ Here is the call graph for this function:

◆ transpose_blocks()

template<typename T >
IGL_INLINE void igl::transpose_blocks ( const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &  A,
const size_t  k,
const size_t  dim,
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &  B 
)
18{
19 // Eigen matrices must be 2d so dim must be only 1 or 2
20 assert(dim == 1 || dim == 2);
21 // Output is not allowed to be input
22 assert(&A != &B);
23
24
25 // block height, width, and number of blocks
26 int m,n;
27 if(dim == 1)
28 {
29 m = A.rows()/k;
30 n = A.cols();
31 }else// dim == 2
32 {
33 m = A.rows();
34 n = A.cols()/k;
35 }
36
37 // resize output
38 if(dim == 1)
39 {
40 B.resize(n*k,m);
41 }else//dim ==2
42 {
43 B.resize(n,m*k);
44 }
45
46 // loop over blocks
47 for(int b = 0;b<(int)k;b++)
48 {
49 if(dim == 1)
50 {
51 B.block(b*n,0,n,m) = A.block(b*m,0,m,n).transpose();
52 }else//dim ==2
53 {
54 B.block(0,b*m,n,m) = A.block(0,b*n,m,n).transpose();
55 }
56 }
57}

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ triangle_fan() [1/2]

IGL_INLINE Eigen::MatrixXi igl::triangle_fan ( const Eigen::MatrixXi &  E)
50{
51 Eigen::MatrixXi cap;
52 triangle_fan(E,cap);
53 return cap;
54}
IGL_INLINE void triangle_fan(const Eigen::MatrixXi &E, Eigen::MatrixXi &cap)
Definition triangle_fan.cpp:12

References triangle_fan().

+ Here is the call graph for this function:

◆ triangle_fan() [2/2]

IGL_INLINE void igl::triangle_fan ( const Eigen::MatrixXi &  E,
Eigen::MatrixXi &  cap 
)
15{
16 using namespace std;
17 using namespace Eigen;
18
19 // Handle lame base case
20 if(E.size() == 0)
21 {
22 cap.resize(0,E.cols()+1);
23 return;
24 }
25 // "Triangulate" aka "close" the E trivially with facets
26 // Note: in 2D we need to know if E endpoints are incoming or
27 // outgoing (left or right). Thus this will not work.
28 assert(E.cols() == 2);
29 // Arbitrary starting vertex
30 //int s = E(int(((double)rand() / RAND_MAX)*E.rows()),0);
31 int s = E(rand()%E.rows(),0);
32 vector<vector<int> > lcap;
33 for(int i = 0;i<E.rows();i++)
34 {
35 // Skip edges incident on s (they would be zero-area)
36 if(E(i,0) == s || E(i,1) == s)
37 {
38 continue;
39 }
40 vector<int> e(3);
41 e[0] = s;
42 e[1] = E(i,0);
43 e[2] = E(i,1);
44 lcap.push_back(e);
45 }
46 list_to_matrix(lcap,cap);
47}

References list_to_matrix().

Referenced by igl::WindingNumberTree< Point, DerivedV, DerivedF >::set_mesh(), and triangle_fan().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ triangle_triangle_adjacency() [1/6]

template<typename DerivedE , typename DerivedEMAP , typename uE2EType , typename TTIndex , typename TTiIndex >
IGL_INLINE void igl::triangle_triangle_adjacency ( const Eigen::MatrixBase< DerivedE > &  E,
const Eigen::MatrixBase< DerivedEMAP > &  EMAP,
const std::vector< std::vector< uE2EType > > &  uE2E,
const bool  construct_TTi,
std::vector< std::vector< std::vector< TTIndex > > > &  TT,
std::vector< std::vector< std::vector< TTiIndex > > > &  TTi 
)
206{
207 using namespace std;
208 using namespace Eigen;
209 typedef typename DerivedE::Index Index;
210 const size_t m = E.rows()/3;
211 assert((size_t)E.rows() == m*3 && "E should come from list of triangles.");
212 // E2E[i] --> {j,k,...} means face edge i corresponds to other faces edges j
213 // and k
214 TT.resize (m,vector<vector<TTIndex> >(3));
215 if(construct_TTi)
216 {
217 TTi.resize(m,vector<vector<TTiIndex> >(3));
218 }
219
220 // No race conditions because TT*[f][c]'s are in bijection with e's
221 // Minimum number of items per thread
222 //const size_t num_e = E.rows();
223 // Slightly better memory access than loop over E
225 m,
226 [&](const Index & f)
227 {
228 for(Index c = 0;c<3;c++)
229 {
230 const Index e = f + m*c;
231 //const Index c = e/m;
232 const vector<uE2EType> & N = uE2E[EMAP(e)];
233 for(const auto & ne : N)
234 {
235 const Index nf = ne%m;
236 // don't add self
237 if(nf != f)
238 {
239 TT[f][c].push_back(nf);
240 if(construct_TTi)
241 {
242 const Index nc = ne/m;
243 TTi[f][c].push_back(nc);
244 }
245 }
246 }
247 }
248 },
249 1000ul);
250
251
252}

References parallel_for().

+ Here is the call graph for this function:

◆ triangle_triangle_adjacency() [2/6]

template<typename DerivedF , typename TTIndex , typename TTiIndex >
IGL_INLINE void igl::triangle_triangle_adjacency ( const Eigen::MatrixBase< DerivedF > &  F,
const bool  construct_TTi,
std::vector< std::vector< std::vector< TTIndex > > > &  TT,
std::vector< std::vector< std::vector< TTiIndex > > > &  TTi 
)
178{
179 using namespace Eigen;
180 using namespace std;
181 assert(F.cols() == 3 && "Faces must be triangles");
182 // number of faces
183 typedef typename DerivedF::Index Index;
186 MatrixX2I E,uE;
187 VectorXI EMAP;
188 vector<vector<Index> > uE2E;
189 unique_edge_map(F,E,uE,EMAP,uE2E);
190 return triangle_triangle_adjacency(E,EMAP,uE2E,construct_TTi,TT,TTi);
191}

References triangle_triangle_adjacency(), and unique_edge_map().

+ Here is the call graph for this function:

◆ triangle_triangle_adjacency() [3/6]

template<typename DerivedF , typename DerivedTT >
IGL_INLINE void igl::triangle_triangle_adjacency ( const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedTT > &  TT 
)
41{
42 const int n = F.maxCoeff()+1;
44 VectorXI VF,NI;
46 TT = DerivedTT::Constant(F.rows(),3,-1);
47 // Loop over faces
48 igl::parallel_for(F.rows(),[&](int f)
49 {
50 // Loop over corners
51 for (int k = 0; k < 3; k++)
52 {
53 int vi = F(f,k), vin = F(f,(k+1)%3);
54 // Loop over face neighbors incident on this corner
55 for (int j = NI[vi]; j < NI[vi+1]; j++)
56 {
57 int fn = VF[j];
58 // Not this face
59 if (fn != f)
60 {
61 // Face neighbor also has [vi,vin] edge
62 if (F(fn,0) == vin || F(fn,1) == vin || F(fn,2) == vin)
63 {
64 TT(f,k) = fn;
65 break;
66 }
67 }
68 }
69 }
70 });
71}

References parallel_for(), and vertex_triangle_adjacency().

+ Here is the call graph for this function:

◆ triangle_triangle_adjacency() [4/6]

template<typename DerivedF , typename DerivedTT , typename DerivedTTi >
IGL_INLINE void igl::triangle_triangle_adjacency ( const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedTT > &  TT,
Eigen::PlainObjectBase< DerivedTTi > &  TTi 
)
120{
122 TTi = DerivedTTi::Constant(TT.rows(),TT.cols(),-1);
123 //for(int f = 0; f<F.rows(); f++)
124 igl::parallel_for(F.rows(),[&](int f)
125 {
126 for(int k = 0;k<3;k++)
127 {
128 int vi = F(f,k), vj = F(f,(k+1)%3);
129 int fn = TT(f,k);
130 if(fn >= 0)
131 {
132 for(int kn = 0;kn<3;kn++)
133 {
134 int vin = F(fn,kn), vjn = F(fn,(kn+1)%3);
135 if(vi == vjn && vin == vj)
136 {
137 TTi(f,k) = kn;
138 break;
139 }
140 }
141 }
142 }
143 });
144}

References Eigen::PlainObjectBase< Derived >::cols(), parallel_for(), Eigen::PlainObjectBase< Derived >::rows(), and triangle_triangle_adjacency().

Referenced by igl::Comb< DerivedV, DerivedF >::Comb(), igl::CombLine< DerivedV, DerivedF >::CombLine(), igl::copyleft::comiso::FrameInterpolator::FrameInterpolator(), igl::MeshCutter< DerivedV, DerivedF, DerivedM, DerivedO >::MeshCutter(), igl::copyleft::comiso::MIQ_class< DerivedV, DerivedF, DerivedU >::MIQ_class(), igl::MissMatchCalculator< DerivedV, DerivedF, DerivedM >::MissMatchCalculator(), igl::MissMatchCalculatorLine< DerivedV, DerivedF, DerivedO >::MissMatchCalculatorLine(), igl::copyleft::comiso::NRosyField::NRosyField(), boundary_loop(), cut_mesh(), igl::copyleft::cgal::extract_cells(), facet_components(), is_border_vertex(), is_vertex_manifold(), loop(), igl::copyleft::cgal::outer_hull_legacy(), triangle_triangle_adjacency(), triangle_triangle_adjacency(), triangle_triangle_adjacency(), triangle_triangle_adjacency(), and upsample().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ triangle_triangle_adjacency() [5/6]

template<typename DerivedF , typename TTIndex >
IGL_INLINE void igl::triangle_triangle_adjacency ( const Eigen::MatrixBase< DerivedF > &  F,
std::vector< std::vector< std::vector< TTIndex > > > &  TT 
)
164{
165 std::vector<std::vector<std::vector<TTIndex> > > not_used;
166 return triangle_triangle_adjacency(F,false,TT,not_used);
167}

References triangle_triangle_adjacency().

+ Here is the call graph for this function:

◆ triangle_triangle_adjacency() [6/6]

template<typename DerivedF , typename TTIndex , typename TTiIndex >
IGL_INLINE void igl::triangle_triangle_adjacency ( const Eigen::MatrixBase< DerivedF > &  F,
std::vector< std::vector< std::vector< TTIndex > > > &  TT,
std::vector< std::vector< std::vector< TTiIndex > > > &  TTi 
)
154{
155 return triangle_triangle_adjacency(F,true,TT,TTi);
156}

References triangle_triangle_adjacency().

+ Here is the call graph for this function:

◆ triangle_triangle_adjacency_extractTT()

template<typename DerivedF , typename TTT_type , typename DerivedTT >
IGL_INLINE void igl::triangle_triangle_adjacency_extractTT ( const Eigen::MatrixBase< DerivedF > &  F,
std::vector< std::vector< TTT_type > > &  TTT,
Eigen::PlainObjectBase< DerivedTT > &  TT 
)
22{
23 TT.setConstant((int)(F.rows()),F.cols(),-1);
24
25 for(int i=1;i<(int)TTT.size();++i)
26 {
27 std::vector<int>& r1 = TTT[i-1];
28 std::vector<int>& r2 = TTT[i];
29 if ((r1[0] == r2[0]) && (r1[1] == r2[1]))
30 {
31 TT(r1[2],r1[3]) = r2[2];
32 TT(r2[2],r2[3]) = r1[2];
33 }
34 }
35}

References Eigen::PlainObjectBase< Derived >::setConstant().

+ Here is the call graph for this function:

◆ triangle_triangle_adjacency_extractTTi()

template<typename DerivedF , typename TTT_type , typename DerivedTTi >
IGL_INLINE void igl::triangle_triangle_adjacency_extractTTi ( const Eigen::MatrixBase< DerivedF > &  F,
std::vector< std::vector< TTT_type > > &  TTT,
Eigen::PlainObjectBase< DerivedTTi > &  TTi 
)
99{
100 TTi.setConstant((int)(F.rows()),F.cols(),-1);
101
102 for(int i=1;i<(int)TTT.size();++i)
103 {
104 std::vector<int>& r1 = TTT[i-1];
105 std::vector<int>& r2 = TTT[i];
106 if ((r1[0] == r2[0]) && (r1[1] == r2[1]))
107 {
108 TTi(r1[2],r1[3]) = r2[3];
109 TTi(r2[2],r2[3]) = r1[3];
110 }
111 }
112}

References Eigen::PlainObjectBase< Derived >::setConstant().

+ Here is the call graph for this function:

◆ triangle_triangle_adjacency_preprocess()

template<typename DerivedF , typename TTT_type >
IGL_INLINE void igl::triangle_triangle_adjacency_preprocess ( const Eigen::MatrixBase< DerivedF > &  F,
std::vector< std::vector< TTT_type > > &  TTT 
)
77{
78 for(int f=0;f<F.rows();++f)
79 for (int i=0;i<F.cols();++i)
80 {
81 // v1 v2 f ei
82 int v1 = F(f,i);
83 int v2 = F(f,(i+1)%F.cols());
84 if (v1 > v2) std::swap(v1,v2);
85 std::vector<int> r(4);
86 r[0] = v1; r[1] = v2;
87 r[2] = f; r[3] = i;
88 TTT.push_back(r);
89 }
90 std::sort(TTT.begin(),TTT.end());
91}

◆ triangles_from_strip()

template<typename DerivedS , typename DerivedF >
IGL_INLINE void igl::triangles_from_strip ( const Eigen::MatrixBase< DerivedS > &  S,
Eigen::PlainObjectBase< DerivedF > &  F 
)
15{
16 using namespace std;
17 F.resize(S.size()-2,3);
18 for(int s = 0;s < S.size()-2;s++)
19 {
20 if(s%2 == 0)
21 {
22 F(s,0) = S(s+2);
23 F(s,1) = S(s+1);
24 F(s,2) = S(s+0);
25 }else
26 {
27 F(s,0) = S(s+0);
28 F(s,1) = S(s+1);
29 F(s,2) = S(s+2);
30 }
31 }
32}

◆ two_axis_valuator_fixed_up()

template<typename Scalardown_quat , typename Scalarquat >
IGL_INLINE void igl::two_axis_valuator_fixed_up ( const int  w,
const int  h,
const double  speed,
const Eigen::Quaternion< Scalardown_quat > &  down_quat,
const int  down_x,
const int  down_y,
const int  mouse_x,
const int  mouse_y,
Eigen::Quaternion< Scalarquat > &  quat 
)
22{
23 using namespace Eigen;
24 Matrix<Scalarquat,3,1> axis(0,1,0);
25 quat = down_quat *
28 PI*((Scalarquat)(mouse_x-down_x))/(Scalarquat)w*speed/2.0,
29 axis.normalized()));
30 quat.normalize();
31 {
32 Matrix<Scalarquat,3,1> axis(1,0,0);
33 if(axis.norm() != 0)
34 {
35 quat =
38 PI*(mouse_y-down_y)/(Scalarquat)h*speed/2.0,
39 axis.normalized())) * quat;
40 quat.normalize();
41 }
42 }
43}
EIGEN_DEVICE_FUNC void normalize()
Definition Quaternion.h:129
Represents a 3D rotation as a rotation angle around an arbitrary 3D axis.
Definition AngleAxis.h:50

References Eigen::QuaternionBase< Derived >::normalize(), and PI.

Referenced by igl::opengl::glfw::Viewer::mouse_move().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ uniformly_sample_two_manifold()

IGL_INLINE void igl::uniformly_sample_two_manifold ( const Eigen::MatrixXd &  W,
const Eigen::MatrixXi &  F,
const int  k,
const double  push,
Eigen::MatrixXd &  WS 
)
30{
31 using namespace Eigen;
32 using namespace std;
33
34 // Euclidean distance between two points on a mesh given as barycentric
35 // coordinates
36 // Inputs:
37 // W #W by dim positions of mesh in weight space
38 // F #F by 3 indices of triangles
39 // face_A face index where 1st point lives
40 // bary_A barycentric coordinates of 1st point on face_A
41 // face_B face index where 2nd point lives
42 // bary_B barycentric coordinates of 2nd point on face_B
43 // Returns distance in euclidean space
44 const auto & bary_dist = [] (
45 const Eigen::MatrixXd & W,
46 const Eigen::MatrixXi & F,
47 const int face_A,
48 const Eigen::Vector3d & bary_A,
49 const int face_B,
50 const Eigen::Vector3d & bary_B) -> double
51 {
52 return
53 ((bary_A(0)*W.row(F(face_A,0)) +
54 bary_A(1)*W.row(F(face_A,1)) +
55 bary_A(2)*W.row(F(face_A,2)))
56 -
57 (bary_B(0)*W.row(F(face_B,0)) +
58 bary_B(1)*W.row(F(face_B,1)) +
59 bary_B(2)*W.row(F(face_B,2)))).norm();
60 };
61
62 // Base case if F is a tet list, find all faces and pass as non-manifold
63 // triangle mesh
64 if(F.cols() == 4)
65 {
66 verbose("uniform_sample.h: sampling tet mesh\n");
67 MatrixXi T0 = F.col(0);
68 MatrixXi T1 = F.col(1);
69 MatrixXi T2 = F.col(2);
70 MatrixXi T3 = F.col(3);
71 // Faces from tets
72 MatrixXi TF =
73 cat(1,
74 cat(1,
75 cat(2,T0, cat(2,T1,T2)),
76 cat(2,T0, cat(2,T2,T3))),
77 cat(1,
78 cat(2,T0, cat(2,T3,T1)),
79 cat(2,T1, cat(2,T3,T2)))
80 );
81 assert(TF.rows() == 4*F.rows());
82 assert(TF.cols() == 3);
83 uniformly_sample_two_manifold(W,TF,k,push,WS);
84 return;
85 }
86
87 double start = get_seconds();
88
89 VectorXi S;
90 // First get sampling as best as possible on mesh
92 verbose("Lap: %g\n",get_seconds()-start);
93 slice(W,S,colon<int>(0,W.cols()-1),WS);
94 //cout<<"WSmesh=["<<endl<<WS<<endl<<"];"<<endl;
95
96//#ifdef EXTREME_VERBOSE
97 //cout<<"S=["<<endl<<S<<endl<<"];"<<endl;
98//#endif
99
100 // Build map from vertices to list of incident faces
101 vector<vector<int> > VF,VFi;
102 vertex_triangle_adjacency(W,F,VF,VFi);
103
104 // List of list of face indices, for each sample gives index to face it is on
105 vector<vector<int> > sample_faces; sample_faces.resize(k);
106 // List of list of barycentric coordinates, for each sample gives b-coords in
107 // face its on
108 vector<vector<Eigen::Vector3d> > sample_barys; sample_barys.resize(k);
109 // List of current maxmins amongst samples
110 vector<int> cur_maxmin; cur_maxmin.resize(k);
111 // List of distance matrices, D(i)(s,j) reveals distance from i's sth sample
112 // to jth seed if j<k or (j-k)th "pushed" corner
113 vector<MatrixXd> D; D.resize(k);
114
115 // Precompute an W.cols() by W.cols() identity matrix
116 MatrixXd I(MatrixXd::Identity(W.cols(),W.cols()));
117
118 // Describe each seed as a face index and barycentric coordinates
119 for(int i = 0;i < k;i++)
120 {
121 // Unreferenced vertex?
122 assert(VF[S(i)].size() > 0);
123 sample_faces[i].push_back(VF[S(i)][0]);
124 // We're right on a face vertex so barycentric coordinates are 0, but 1 at
125 // that vertex
126 Eigen::Vector3d bary(0,0,0);
127 bary( VFi[S(i)][0] ) = 1;
128 sample_barys[i].push_back(bary);
129 // initialize this to current maxmin
130 cur_maxmin[i] = 0;
131 }
132
133 // initialize radius
134 double radius = 1.0;
135 // minimum radius (bound on precision)
136 //double min_radius = 1e-5;
137 double min_radius = 1e-5;
138 int max_num_rand_samples_per_triangle = 100;
139 int max_sample_attempts_per_triangle = 1000;
140 // Max number of outer iterations for a given radius
141 int max_iters = 1000;
142
143 // continue iterating until radius is smaller than some threshold
144 while(radius > min_radius)
145 {
146 // initialize each seed
147 for(int i = 0;i < k;i++)
148 {
149 // Keep track of cur_maxmin data
150 int face_i = sample_faces[i][cur_maxmin[i]];
151 Eigen::Vector3d bary(sample_barys[i][cur_maxmin[i]]);
152 // Find index in face of closest mesh vertex (on this face)
153 int index_in_face =
154 (bary(0) > bary(1) ? (bary(0) > bary(2) ? 0 : 2)
155 : (bary(1) > bary(2) ? 1 : 2));
156 // find closest mesh vertex
157 int vertex_i = F(face_i,index_in_face);
158 // incident triangles
159 vector<int> incident_F = VF[vertex_i];
160 // We're going to try to place num_rand_samples_per_triangle samples on
161 // each sample *after* this location
162 sample_barys[i].clear();
163 sample_faces[i].clear();
164 cur_maxmin[i] = 0;
165 sample_barys[i].push_back(bary);
166 sample_faces[i].push_back(face_i);
167 // Current seed location in weight space
168 VectorXd seed =
169 bary(0)*W.row(F(face_i,0)) +
170 bary(1)*W.row(F(face_i,1)) +
171 bary(2)*W.row(F(face_i,2));
172#ifdef EXTREME_VERBOSE
173 verbose("i: %d\n",i);
174 verbose("face_i: %d\n",face_i);
175 //cout<<"bary: "<<bary<<endl;
176 verbose("index_in_face: %d\n",index_in_face);
177 verbose("vertex_i: %d\n",vertex_i);
178 verbose("incident_F.size(): %d\n",incident_F.size());
179 //cout<<"seed: "<<seed<<endl;
180#endif
181 // loop over indcident triangles
182 for(int f=0;f<(int)incident_F.size();f++)
183 {
184#ifdef EXTREME_VERBOSE
185 verbose("incident_F[%d]: %d\n",f,incident_F[f]);
186#endif
187 int face_f = incident_F[f];
188 int num_samples_f = 0;
189 for(int s=0;s<max_sample_attempts_per_triangle;s++)
190 {
191 // Randomly sample unit square
192 double u,v;
193// double ru = fgenrand();
194// double rv = fgenrand();
195 double ru = (double)rand() / RAND_MAX;
196 double rv = (double)rand() / RAND_MAX;
197 // Reflect to lower triangle if above
198 if((ru+rv)>1)
199 {
200 u = 1-rv;
201 v = 1-ru;
202 }else
203 {
204 u = ru;
205 v = rv;
206 }
207 Eigen::Vector3d sample_bary(u,v,1-u-v);
208 double d = bary_dist(W,F,face_i,bary,face_f,sample_bary);
209 // check that sample is close enough
210 if(d<radius)
211 {
212 // add sample to list
213 sample_faces[i].push_back(face_f);
214 sample_barys[i].push_back(sample_bary);
215 num_samples_f++;
216 }
217 // Keep track of which random samples came from which face
218 if(num_samples_f >= max_num_rand_samples_per_triangle)
219 {
220#ifdef EXTREME_VERBOSE
221 verbose("Reached maximum number of samples per face\n");
222#endif
223 break;
224 }
225 if(s==(max_sample_attempts_per_triangle-1))
226 {
227#ifdef EXTREME_VERBOSE
228 verbose("Reached maximum sample attempts per triangle\n");
229#endif
230 }
231 }
232#ifdef EXTREME_VERBOSE
233 verbose("sample_faces[%d].size(): %d\n",i,sample_faces[i].size());
234 verbose("sample_barys[%d].size(): %d\n",i,sample_barys[i].size());
235#endif
236 }
237 }
238
239 // Precompute distances from each seed's random samples to each "pushed"
240 // corner
241 // Put -1 in entries corresponding distance of a seed's random samples to
242 // self
243 // Loop over seeds
244 for(int i = 0;i < k;i++)
245 {
246 // resize distance matrix for new samples
247 D[i].resize(sample_faces[i].size(),k+W.cols());
248 // Loop over i's samples
249 for(int s = 0;s<(int)sample_faces[i].size();s++)
250 {
251 int sample_face = sample_faces[i][s];
252 Eigen::Vector3d sample_bary = sample_barys[i][s];
253 // Loop over other seeds
254 for(int j = 0;j < k;j++)
255 {
256 // distance from sample(i,s) to seed j
257 double d;
258 if(i==j)
259 {
260 // phony self distance: Ilya's idea of infinite
261 d = 10;
262 }else
263 {
264 int seed_j_face = sample_faces[j][cur_maxmin[j]];
265 Eigen::Vector3d seed_j_bary(sample_barys[j][cur_maxmin[j]]);
266 d = bary_dist(W,F,sample_face,sample_bary,seed_j_face,seed_j_bary);
267 }
268 D[i](s,j) = d;
269 }
270 // Loop over corners
271 for(int j = 0;j < W.cols();j++)
272 {
273 // distance from sample(i,s) to corner j
274 double d =
275 ((sample_bary(0)*W.row(F(sample_face,0)) +
276 sample_bary(1)*W.row(F(sample_face,1)) +
277 sample_bary(2)*W.row(F(sample_face,2)))
278 - I.row(j)).norm()/push;
279 // append after distances to seeds
280 D[i](s,k+j) = d;
281 }
282 }
283 }
284
285 int iters = 0;
286 while(true)
287 {
288 bool has_changed = false;
289 // try to move each seed
290 for(int i = 0;i < k;i++)
291 {
292 // for each sample look at distance to closest seed/corner
293 VectorXd minD = D[i].rowwise().minCoeff();
294 assert(minD.size() == (int)sample_faces[i].size());
295 // find random sample with maximum minimum distance to other seeds
296 int old_cur_maxmin = cur_maxmin[i];
297 double max_min = -2;
298 for(int s = 0;s<(int)sample_faces[i].size();s++)
299 {
300 if(max_min < minD(s))
301 {
302 max_min = minD(s);
303 // Set this as the new seed location
304 cur_maxmin[i] = s;
305 }
306 }
307#ifdef EXTREME_VERBOSE
308 verbose("max_min: %g\n",max_min);
309 verbose("cur_maxmin[%d]: %d->%d\n",i,old_cur_maxmin,cur_maxmin[i]);
310#endif
311 // did location change?
312 has_changed |= (old_cur_maxmin!=cur_maxmin[i]);
313 // update distances of random samples of other seeds
314 }
315 // if no seed moved, exit
316 if(!has_changed)
317 {
318 break;
319 }
320 iters++;
321 if(iters>=max_iters)
322 {
323 verbose("Hit max iters (%d) before converging\n",iters);
324 }
325 }
326 // shrink radius
327 //radius *= 0.9;
328 //radius *= 0.99;
329 radius *= 0.9;
330 }
331 // Collect weight space locations
332 WS.resize(k,W.cols());
333 for(int i = 0;i<k;i++)
334 {
335 int face_i = sample_faces[i][cur_maxmin[i]];
336 Eigen::Vector3d bary(sample_barys[i][cur_maxmin[i]]);
337 WS.row(i) =
338 bary(0)*W.row(F(face_i,0)) +
339 bary(1)*W.row(F(face_i,1)) +
340 bary(2)*W.row(F(face_i,2));
341 }
342 verbose("Lap: %g\n",get_seconds()-start);
343 //cout<<"WSafter=["<<endl<<WS<<endl<<"];"<<endl;
344}
vertex_base< int > vertex_i
Definition agg_basics.h:528
IGL_INLINE void uniformly_sample_two_manifold_at_vertices(const Eigen::MatrixXd &OW, const int k, const double push, Eigen::VectorXi &S)
Definition uniformly_sample_two_manifold.cpp:346

References cat(), get_seconds(), slice(), uniformly_sample_two_manifold(), uniformly_sample_two_manifold_at_vertices(), verbose, and vertex_triangle_adjacency().

Referenced by uniformly_sample_two_manifold().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ uniformly_sample_two_manifold_at_vertices()

IGL_INLINE void igl::uniformly_sample_two_manifold_at_vertices ( const Eigen::MatrixXd &  OW,
const int  k,
const double  push,
Eigen::VectorXi &  S 
)
351{
352 using namespace Eigen;
353 using namespace std;
354
355 // Copy weights and faces
356 const MatrixXd & W = OW;
357 /*const MatrixXi & F = OF;*/
358
359 // Initialize seeds
360 VectorXi G;
362 partition(W,k+W.cols(),G,S,ignore);
363 // Remove corners, which better be at top
364 S = S.segment(W.cols(),k).eval();
365
366 MatrixXd WS;
367 slice(W,S,colon<int>(0,W.cols()-1),WS);
368 //cout<<"WSpartition=["<<endl<<WS<<endl<<"];"<<endl;
369
370 // number of vertices
371 int n = W.rows();
372 // number of dimensions in weight space
373 int m = W.cols();
374 // Corners of weight space
375 MatrixXd I = MatrixXd::Identity(m,m);
376 // append corners to bottom of weights
377 MatrixXd WI(n+m,m);
378 WI << W,I;
379 // Weights at seeds and corners
380 MatrixXd WSC(k+m,m);
381 for(int i = 0;i<k;i++)
382 {
383 WSC.row(i) = W.row(S(i));
384 }
385 for(int i = 0;i<m;i++)
386 {
387 WSC.row(i+k) = WI.row(n+i);
388 }
389 // initialize all pairs sqaured distances
390 MatrixXd sqrD;
391 all_pairs_distances(WI,WSC,true,sqrD);
392 // bring in corners by push factor (squared because distances are squared)
393 sqrD.block(0,k,sqrD.rows(),m) /= push*push;
394
395 int max_iters = 30;
396 int j = 0;
397 for(;j<max_iters;j++)
398 {
399 bool has_changed = false;
400 // loop over seeds
401 for(int i =0;i<k;i++)
402 {
403 int old_si = S(i);
404 // set distance to ilya's idea of infinity
405 sqrD.col(i).setZero();
406 sqrD.col(i).array() += 10;
407 // find vertex farthers from all other seeds
408 MatrixXd minsqrD = sqrD.rowwise().minCoeff();
409 MatrixXd::Index si,PHONY;
410 minsqrD.maxCoeff(&si,&PHONY);
411 MatrixXd Wsi = W.row(si);
412 MatrixXd sqrDi;
413 all_pairs_distances(WI,Wsi,true,sqrDi);
414 sqrD.col(i) = sqrDi;
415 S(i) = si;
416 has_changed |= si!=old_si;
417 }
418 if(j == max_iters)
419 {
420 verbose("uniform_sample.h: Warning: hit max iters\n");
421 }
422 if(!has_changed)
423 {
424 break;
425 }
426 }
427}
IGL_INLINE void partition(const Eigen::MatrixXd &W, const int k, Eigen::Matrix< int, Eigen::Dynamic, 1 > &G, Eigen::Matrix< int, Eigen::Dynamic, 1 > &S, Eigen::Matrix< double, Eigen::Dynamic, 1 > &D)
Definition partition.cpp:11
IGL_INLINE void all_pairs_distances(const Mat &V, const Mat &U, const bool squared, Mat &D)
Definition all_pairs_distances.cpp:12

References all_pairs_distances(), partition(), slice(), and verbose.

Referenced by uniformly_sample_two_manifold().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unique() [1/4]

template<typename DerivedA , typename DerivedC >
IGL_INLINE void igl::unique ( const Eigen::DenseBase< DerivedA > &  A,
Eigen::PlainObjectBase< DerivedC > &  C 
)
104{
105 using namespace std;
106 using namespace Eigen;
107 vector<typename DerivedA::Scalar > vA;
108 vector<typename DerivedC::Scalar > vC;
109 vector<size_t> vIA,vIC;
110 matrix_to_list(A,vA);
111 unique(vA,vC,vIA,vIC);
112 list_to_matrix(vC,C);
113}

References list_to_matrix(), matrix_to_list(), and unique().

+ Here is the call graph for this function:

◆ unique() [2/4]

template<typename DerivedA , typename DerivedC , typename DerivedIA , typename DerivedIC >
IGL_INLINE void igl::unique ( const Eigen::DenseBase< DerivedA > &  A,
Eigen::PlainObjectBase< DerivedC > &  C,
Eigen::PlainObjectBase< DerivedIA > &  IA,
Eigen::PlainObjectBase< DerivedIC > &  IC 
)
84{
85 using namespace std;
86 using namespace Eigen;
87 vector<typename DerivedA::Scalar > vA;
88 vector<typename DerivedC::Scalar > vC;
89 vector<size_t> vIA,vIC;
90 matrix_to_list(A,vA);
91 unique(vA,vC,vIA,vIC);
92 list_to_matrix(vC,C);
93 list_to_matrix(vIA,IA);
94 list_to_matrix(vIC,IC);
95}

References list_to_matrix(), matrix_to_list(), and unique().

+ Here is the call graph for this function:

◆ unique() [3/4]

template<typename T >
IGL_INLINE void igl::unique ( const std::vector< T > &  A,
std::vector< T > &  C 
)
69{
70 std::vector<size_t> IA,IC;
71 return igl::unique(A,C,IA,IC);
72}

References unique().

+ Here is the call graph for this function:

◆ unique() [4/4]

template<typename T >
IGL_INLINE void igl::unique ( const std::vector< T > &  A,
std::vector< T > &  C,
std::vector< size_t > &  IA,
std::vector< size_t > &  IC 
)
26{
27 using namespace std;
28 std::vector<size_t> IM;
29 std::vector<T> sortA;
30 igl::sort(A,true,sortA,IM);
31 // Original unsorted index map
32 IA.resize(sortA.size());
33 for(int i=0;i<(int)sortA.size();i++)
34 {
35 IA[i] = i;
36 }
37 IA.erase(
38 std::unique(
39 IA.begin(),
40 IA.end(),
41 igl::IndexEquals<const std::vector<T>& >(sortA)),IA.end());
42
43 IC.resize(A.size());
44 {
45 int j = 0;
46 for(int i = 0;i<(int)sortA.size();i++)
47 {
48 if(sortA[IA[j]] != sortA[i])
49 {
50 j++;
51 }
52 IC[IM[i]] = j;
53 }
54 }
55 C.resize(IA.size());
56 // Reindex IA according to IM
57 for(int i = 0;i<(int)IA.size();i++)
58 {
59 IA[i] = IM[IA[i]];
60 C[i] = A[IA[i]];
61 }
62
63}
Definition IndexComparison.h:28

References sort().

Referenced by boundary_conditions(), edge_collapse_is_valid(), edges_to_path(), is_vertex_manifold(), ismember(), igl::copyleft::cgal::SelfIntersectMesh< Kernel, DerivedV, DerivedF, DerivedVV, DerivedFF, DerivedIF, DerivedJ, DerivedIM >::process_intersecting_boxes(), igl::copyleft::progressive_hulls_cost_and_placement(), setdiff(), setunion(), igl::copyleft::cgal::snap_rounding(), igl::copyleft::cgal::subdivide_segments(), igl::copyleft::cgal::triangle_triangle_squared_distance(), unique(), unique(), and unique().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unique_edge_map()

template<typename DerivedF , typename DerivedE , typename DeriveduE , typename DerivedEMAP , typename uE2EType >
IGL_INLINE void igl::unique_edge_map ( const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedE > &  E,
Eigen::PlainObjectBase< DeriveduE > &  uE,
Eigen::PlainObjectBase< DerivedEMAP > &  EMAP,
std::vector< std::vector< uE2EType > > &  uE2E 
)
25{
26 using namespace Eigen;
27 using namespace std;
28 // All occurrences of directed edges
29 oriented_facets(F,E);
30 const size_t ne = E.rows();
31 // This is 2x faster to create than a map from pairs to lists of edges and 5x
32 // faster to access (actually access is probably assympotically faster O(1)
33 // vs. O(log m)
35 unique_simplices(E,uE,IA,EMAP);
36 uE2E.resize(uE.rows());
37 // This does help a little
38 for_each(uE2E.begin(),uE2E.end(),[](vector<uE2EType > & v){v.reserve(2);});
39 assert((size_t)EMAP.size() == ne);
40 for(uE2EType e = 0;e<(uE2EType)ne;e++)
41 {
42 uE2E[EMAP(e)].push_back(e);
43 }
44}

References for_each(), oriented_facets(), Eigen::PlainObjectBase< Derived >::rows(), and unique_simplices().

Referenced by delaunay_triangulation(), edge_flaps(), igl::copyleft::cgal::extract_cells(), igl::copyleft::cgal::extract_feature(), extract_manifold_patches(), igl::copyleft::cgal::mesh_boolean(), igl::copyleft::cgal::outer_hull_legacy(), piecewise_constant_winding_number(), igl::copyleft::cgal::propagate_winding_numbers(), and triangle_triangle_adjacency().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unique_rows()

template<typename DerivedA , typename DerivedC , typename DerivedIA , typename DerivedIC >
IGL_INLINE void igl::unique_rows ( const Eigen::DenseBase< DerivedA > &  A,
Eigen::PlainObjectBase< DerivedC > &  C,
Eigen::PlainObjectBase< DerivedIA > &  IA,
Eigen::PlainObjectBase< DerivedIC > &  IC 
)
22{
23 using namespace std;
24 using namespace Eigen;
25 VectorXi IM;
26 DerivedA sortA;
27 sortrows(A,true,sortA,IM);
28
29
30 const int num_rows = sortA.rows();
31 const int num_cols = sortA.cols();
32 vector<int> vIA(num_rows);
33 for(int i=0;i<num_rows;i++)
34 {
35 vIA[i] = i;
36 }
37
38 auto index_equal = [&sortA, &num_cols](const size_t i, const size_t j) {
39 for (size_t c=0; c<num_cols; c++) {
40 if (sortA(i,c) != sortA(j,c))
41 return false;
42 }
43 return true;
44 };
45 vIA.erase(
46 std::unique(
47 vIA.begin(),
48 vIA.end(),
49 index_equal
50 ),vIA.end());
51
52 IC.resize(A.rows(),1);
53 {
54 int j = 0;
55 for(int i = 0;i<num_rows;i++)
56 {
57 if(sortA.row(vIA[j]) != sortA.row(i))
58 {
59 j++;
60 }
61 IC(IM(i,0),0) = j;
62 }
63 }
64 const int unique_rows = vIA.size();
65 C.resize(unique_rows,A.cols());
66 IA.resize(unique_rows,1);
67 // Reindex IA according to IM
68 for(int i = 0;i<unique_rows;i++)
69 {
70 IA(i,0) = IM(vIA[i],0);
71 C.row(i) = A.row(IA(i,0));
72 }
73}

References Eigen::PlainObjectBase< Derived >::resize(), sortrows(), and unique_rows().

Referenced by exterior_edges(), is_boundary_edge(), is_boundary_edge(), ismember_rows(), igl::copyleft::cgal::minkowski_sum(), orientable_patches(), igl::copyleft::cgal::remesh_intersections(), remove_duplicate_vertices(), slice_tets(), unique_rows(), unique_simplices(), and unzip_corners().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unique_simplices() [1/2]

template<typename DerivedF , typename DerivedFF >
IGL_INLINE void igl::unique_simplices ( const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedFF > &  FF 
)
43{
44 Eigen::VectorXi IA,IC;
45 return unique_simplices(F,FF,IA,IC);
46}

References unique_simplices().

+ Here is the call graph for this function:

◆ unique_simplices() [2/2]

template<typename DerivedF , typename DerivedFF , typename DerivedIA , typename DerivedIC >
IGL_INLINE void igl::unique_simplices ( const Eigen::MatrixBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedFF > &  FF,
Eigen::PlainObjectBase< DerivedIA > &  IA,
Eigen::PlainObjectBase< DerivedIC > &  IC 
)
23{
24 using namespace Eigen;
25 using namespace std;
26 // Sort each face
27 MatrixXi sortF, unusedI;
28 igl::sort(F,2,true,sortF,unusedI);
29 // Find unique faces
30 MatrixXi C;
31 igl::unique_rows(sortF,C,IA,IC);
32 FF.resize(IA.size(),F.cols());
33 const size_t mff = FF.rows();
34 parallel_for(mff,[&F,&IA,&FF](size_t & i){FF.row(i) = F.row(IA(i));},1000ul);
35}

References parallel_for(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), sort(), and unique_rows().

Referenced by crouzeix_raviart_cotmatrix(), crouzeix_raviart_massmatrix(), is_edge_manifold(), per_edge_normals(), resolve_duplicated_faces(), straighten_seams(), unique_edge_map(), and unique_simplices().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unproject() [1/2]

template<typename Scalar >
IGL_INLINE Eigen::Matrix< Scalar, 3, 1 > igl::unproject ( const Eigen::Matrix< Scalar, 3, 1 > &  win,
const Eigen::Matrix< Scalar, 4, 4 > &  model,
const Eigen::Matrix< Scalar, 4, 4 > &  proj,
const Eigen::Matrix< Scalar, 4, 1 > &  viewport 
)
63{
65 unproject(win,model,proj,viewport,scene);
66 return scene;
67}

◆ unproject() [2/2]

template<typename Derivedwin , typename Derivedmodel , typename Derivedproj , typename Derivedviewport , typename Derivedscene >
IGL_INLINE void igl::unproject ( const Eigen::MatrixBase< Derivedwin > &  win,
const Eigen::MatrixBase< Derivedmodel > &  model,
const Eigen::MatrixBase< Derivedproj > &  proj,
const Eigen::MatrixBase< Derivedviewport > &  viewport,
Eigen::PlainObjectBase< Derivedscene > &  scene 
)
25{
26 if(win.cols() != 3)
27 {
28 assert(win.rows() == 3);
29 // needless transposes
31 unproject(win.transpose().eval(),model,proj,viewport,sceneT);
32 scene = sceneT.head(3);
33 return;
34 }
35 assert(win.cols() == 3);
36 const int n = win.rows();
37 scene.resize(n,3);
38 for(int i = 0;i<n;i++)
39 {
40 typedef typename Derivedscene::Scalar Scalar;
42 (proj.template cast<Scalar>() * model.template cast<Scalar>()).inverse();
43
45 tmp << win.row(i).head(3).transpose(), 1;
46 tmp(0) = (tmp(0) - viewport(0)) / viewport(2);
47 tmp(1) = (tmp(1) - viewport(1)) / viewport(3);
48 tmp = tmp.array() * 2.0f - 1.0f;
49
50 Eigen::Matrix<Scalar,4,1> obj = Inverse * tmp;
51 obj /= obj(3);
52
53 scene.row(i).head(3) = obj.head(3);
54 }
55}
EIGEN_DEVICE_FUNC const InverseReturnType inverse() const
Definition ArrayCwiseUnaryOps.h:332

References inverse(), Eigen::PlainObjectBase< Derived >::resize(), and Eigen::DenseBase< Derived >::transpose().

Referenced by Slic3r::GUI::GLCanvas3D::_mouse_to_3d(), igl::opengl::glfw::Viewer::mouse_move(), Slic3r::GUI::CameraUtils::ray_from_ortho_screen_pos(), Slic3r::GUI::CameraUtils::ray_from_persp_screen_pos(), igl::opengl2::unproject(), and unproject_ray().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unproject_in_mesh() [1/3]

template<typename DerivedV , typename DerivedF , typename Derivedobj >
IGL_INLINE int igl::unproject_in_mesh ( const Eigen::Vector2f &  pos,
const Eigen::Matrix4f &  model,
const Eigen::Matrix4f &  proj,
const Eigen::Vector4f &  viewport,
const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< Derivedobj > &  obj 
)
88{
89 std::vector<igl::Hit> hits;
90 return unproject_in_mesh(pos,model,proj,viewport,V,F,obj,hits);
91}

◆ unproject_in_mesh() [2/3]

template<typename DerivedV , typename DerivedF , typename Derivedobj >
IGL_INLINE int igl::unproject_in_mesh ( const Eigen::Vector2f &  pos,
const Eigen::Matrix4f &  model,
const Eigen::Matrix4f &  proj,
const Eigen::Vector4f &  viewport,
const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< Derivedobj > &  obj,
std::vector< igl::Hit > &  hits 
)
66{
67 using namespace std;
68 using namespace Eigen;
69 const auto & shoot_ray = [&V,&F](
70 const Eigen::Vector3f& s,
71 const Eigen::Vector3f& dir,
72 std::vector<igl::Hit> & hits)
73 {
74 ray_mesh_intersect(s,dir,V,F,hits);
75 };
76 return unproject_in_mesh(pos,model,proj,viewport,shoot_ray,obj,hits);
77}

References ray_mesh_intersect().

Referenced by igl::embree::unproject_in_mesh().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unproject_in_mesh() [3/3]

template<typename Derivedobj >
IGL_INLINE int igl::unproject_in_mesh ( const Eigen::Vector2f &  pos,
const Eigen::Matrix4f &  model,
const Eigen::Matrix4f &  proj,
const Eigen::Vector4f &  viewport,
const std::function< void(const Eigen::Vector3f &, const Eigen::Vector3f &, std::vector< igl::Hit > &) > &  shoot_ray,
Eigen::PlainObjectBase< Derivedobj > &  obj,
std::vector< igl::Hit > &  hits 
)
26{
27 using namespace std;
28 using namespace Eigen;
29 Vector3f s,dir;
30 unproject_ray(pos,model,proj,viewport,s,dir);
31 shoot_ray(s,dir,hits);
32 switch(hits.size())
33 {
34 case 0:
35 break;
36 case 1:
37 {
38 obj = (s + dir*hits[0].t).cast<typename Derivedobj::Scalar>();
39 break;
40 }
41 case 2:
42 default:
43 {
44 obj = 0.5*((s + dir*hits[0].t) + (s + dir*hits[1].t)).cast<typename Derivedobj::Scalar>();
45 break;
46 }
47 }
48 return hits.size();
49}
IGL_INLINE void unproject_ray(const Eigen::PlainObjectBase< Derivedpos > &pos, const Eigen::PlainObjectBase< Derivedmodel > &model, const Eigen::PlainObjectBase< Derivedproj > &proj, const Eigen::PlainObjectBase< Derivedviewport > &viewport, Eigen::PlainObjectBase< Deriveds > &s, Eigen::PlainObjectBase< Deriveddir > &dir)
dir direction of ray (d - s) where d is pos unprojected with z=1
Definition unproject_ray.cpp:18

References unproject_ray().

+ Here is the call graph for this function:

◆ unproject_onto_mesh() [1/2]

template<typename DerivedV , typename DerivedF , typename Derivedbc >
IGL_INLINE bool igl::unproject_onto_mesh ( const Eigen::Vector2f &  pos,
const Eigen::Matrix4f &  model,
const Eigen::Matrix4f &  proj,
const Eigen::Vector4f &  viewport,
const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
int &  fid,
Eigen::PlainObjectBase< Derivedbc > &  bc 
)
24{
25 using namespace std;
26 using namespace Eigen;
27 const auto & shoot_ray = [&V,&F](
28 const Eigen::Vector3f& s,
29 const Eigen::Vector3f& dir,
30 igl::Hit & hit)->bool
31 {
32 std::vector<igl::Hit> hits;
33 if(!ray_mesh_intersect(s,dir,V,F,hits))
34 {
35 return false;
36 }
37 hit = hits[0];
38 return true;
39 };
40 return unproject_onto_mesh(pos,model,proj,viewport,shoot_ray,fid,bc);
41}
IGL_INLINE bool unproject_onto_mesh(const Eigen::Vector2f &pos, const Eigen::MatrixXi &F, const Eigen::Matrix4f &model, const Eigen::Matrix4f &proj, const Eigen::Vector4f &viewport, const EmbreeIntersector &ei, int &fid, Eigen::Vector3f &bc)
Definition unproject_onto_mesh.cpp:13

References ray_mesh_intersect().

Referenced by igl::embree::unproject_onto_mesh().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unproject_onto_mesh() [2/2]

template<typename Derivedbc >
IGL_INLINE bool igl::unproject_onto_mesh ( const Eigen::Vector2f &  pos,
const Eigen::Matrix4f &  model,
const Eigen::Matrix4f &  proj,
const Eigen::Vector4f &  viewport,
const std::function< bool(const Eigen::Vector3f &, const Eigen::Vector3f &, igl::Hit &) > &  shoot_ray,
int &  fid,
Eigen::PlainObjectBase< Derivedbc > &  bc 
)
57{
58 using namespace std;
59 using namespace Eigen;
60 Vector3f s,dir;
61 unproject_ray(pos,model,proj,viewport,s,dir);
62 Hit hit;
63 if(!shoot_ray(s,dir,hit))
64 {
65 return false;
66 }
67 bc.resize(3);
68 bc << 1.0-hit.u-hit.v, hit.u, hit.v;
69 fid = hit.id;
70 return true;
71}
float u
Definition Hit.h:21
int id
Definition Hit.h:19
float v
Definition Hit.h:21

References igl::Hit::id, igl::Hit::u, unproject_ray(), and igl::Hit::v.

+ Here is the call graph for this function:

◆ unproject_ray()

template<typename Derivedpos , typename Derivedmodel , typename Derivedproj , typename Derivedviewport , typename Deriveds , typename Deriveddir >
IGL_INLINE void igl::unproject_ray ( const Eigen::PlainObjectBase< Derivedpos > &  pos,
const Eigen::PlainObjectBase< Derivedmodel > &  model,
const Eigen::PlainObjectBase< Derivedproj > &  proj,
const Eigen::PlainObjectBase< Derivedviewport > &  viewport,
Eigen::PlainObjectBase< Deriveds > &  s,
Eigen::PlainObjectBase< Deriveddir > &  dir 
)

dir direction of ray (d - s) where d is pos unprojected with z=1

25{
26 using namespace std;
27 using namespace Eigen;
28 // Source and direction on screen
30 Vec3 win_s(pos(0),pos(1),0);
31 Vec3 win_d(pos(0),pos(1),1);
32 // Source, destination and direction in world
33 Vec3 d;
34 igl::unproject(win_s,model,proj,viewport,s);
35 igl::unproject(win_d,model,proj,viewport,d);
36 dir = d-s;
37}
IGL_INLINE void unproject(const Eigen::MatrixBase< Derivedwin > &win, const Eigen::MatrixBase< Derivedmodel > &model, const Eigen::MatrixBase< Derivedproj > &proj, const Eigen::MatrixBase< Derivedviewport > &viewport, Eigen::PlainObjectBase< Derivedscene > &scene)
Definition unproject.cpp:19

References unproject().

Referenced by unproject_in_mesh(), and unproject_onto_mesh().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unzip_corners()

template<typename DerivedA , typename DerivedU , typename DerivedG , typename DerivedJ >
IGL_INLINE void igl::unzip_corners ( const std::vector< std::reference_wrapper< DerivedA > > &  A,
Eigen::PlainObjectBase< DerivedU > &  U,
Eigen::PlainObjectBase< DerivedG > &  G,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
19{
20 if(A.size() == 0)
21 {
22 U.resize(0,0);
23 G.resize(0,3);
24 J.resize(0,0);
25 return;
26 }
27 const size_t num_a = A.size();
28 const typename DerivedA::Index m = A[0].get().rows();
29 DerivedU C(m*3,num_a);
30 for(int a = 0;a<num_a;a++)
31 {
32 assert(A[a].get().rows() == m && "All attributes should be same size");
33 assert(A[a].get().cols() == 3 && "Must be triangles");
34 C.block(0*m,a,m,1) = A[a].get().col(0);
35 C.block(1*m,a,m,1) = A[a].get().col(1);
36 C.block(2*m,a,m,1) = A[a].get().col(2);
37 }
38 DerivedJ I;
39 igl::unique_rows(C,U,I,J);
40 G.resize(m,3);
41 for(int f = 0;f<m;f++)
42 {
43 for(int c = 0;c<3;c++)
44 {
45 G(f,c) = J(f+c*m);
46 }
47 }
48}

References Eigen::PlainObjectBase< Derived >::resize(), and unique_rows().

+ Here is the call graph for this function:

◆ upsample() [1/3]

template<typename DerivedV , typename DerivedF , typename DerivedNV , typename DerivedNF >
IGL_INLINE void igl::upsample ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedNV > &  NV,
Eigen::PlainObjectBase< DerivedNF > &  NF,
const int  number_of_subdivs = 1 
)
114{
115 NV = V;
116 NF = F;
117 for(int i=0; i<number_of_subdivs; ++i)
118 {
119 DerivedNF tempF = NF;
121 upsample(NV.rows(), tempF, S, NF);
122 // This .eval is super important
123 NV = (S*NV).eval();
124 }
125}
IGL_INLINE void upsample(const int n_verts, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::SparseMatrix< SType > &S, Eigen::PlainObjectBase< DerivedNF > &NF)
Definition upsample.cpp:17

References Eigen::PlainObjectBase< Derived >::rows(), and upsample().

+ Here is the call graph for this function:

◆ upsample() [2/3]

template<typename DerivedF , typename SType , typename DerivedNF >
IGL_INLINE void igl::upsample ( const int  n_verts,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::SparseMatrix< SType > &  S,
Eigen::PlainObjectBase< DerivedNF > &  NF 
)
22{
23 using namespace std;
24 using namespace Eigen;
25
26 typedef Eigen::Triplet<SType> Triplet_t;
27
29 FF,FFi;
31
32 // TODO: Cache optimization missing from here, it is a mess
33
34 // Compute the number and positions of the vertices to insert (on edges)
35 Eigen::MatrixXi NI = Eigen::MatrixXi::Constant(FF.rows(),FF.cols(),-1);
36 Eigen::MatrixXi NIdoubles = Eigen::MatrixXi::Zero(FF.rows(), FF.cols());
37 int counter = 0;
38
39 for(int i=0;i<FF.rows();++i)
40 {
41 for(int j=0;j<3;++j)
42 {
43 if(NI(i,j) == -1)
44 {
45 NI(i,j) = counter;
46 NIdoubles(i,j) = 0;
47 if (FF(i,j) != -1) {
48 //If it is not a boundary
49 NI(FF(i,j), FFi(i,j)) = counter;
50 NIdoubles(i,j) = 1;
51 }
52 ++counter;
53 }
54 }
55 }
56
57 const int& n_odd = n_verts;
58 const int& n_even = counter;
59 const int n_newverts = n_odd + n_even;
60
61 //Construct vertex positions
62 std::vector<Triplet_t> tripletList;
63
64 // Fill the odd vertices position
65 for (int i=0; i<n_odd; ++i)
66 {
67 tripletList.emplace_back(i, i, 1.);
68 }
69
70 for(int i=0;i<FF.rows();++i)
71 {
72 for(int j=0;j<3;++j)
73 {
74 if(NIdoubles(i,j)==0) {
75 tripletList.emplace_back(NI(i,j) + n_odd, F(i,j), 1./2.);
76 tripletList.emplace_back(NI(i,j) + n_odd, F(i,(j+1)%3), 1./2.);
77 }
78 }
79 }
80 S.resize(n_newverts, n_verts);
81 S.setFromTriplets(tripletList.begin(), tripletList.end());
82
83 // Build the new topology (Every face is replaced by four)
84 NF.resize(F.rows()*4,3);
85 for(int i=0; i<F.rows();++i)
86 {
87 VectorXi VI(6);
88 VI << F(i,0), F(i,1), F(i,2), NI(i,0) + n_odd, NI(i,1) + n_odd, NI(i,2) + n_odd;
89
90 VectorXi f0(3), f1(3), f2(3), f3(3);
91 f0 << VI(0), VI(3), VI(5);
92 f1 << VI(1), VI(4), VI(3);
93 f2 << VI(3), VI(4), VI(5);
94 f3 << VI(4), VI(2), VI(5);
95
96 NF.row((i*4)+0) = f0;
97 NF.row((i*4)+1) = f1;
98 NF.row((i*4)+2) = f2;
99 NF.row((i*4)+3) = f3;
100 }
101}

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::resize(), Eigen::PlainObjectBase< Derived >::rows(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets(), and triangle_triangle_adjacency().

Referenced by upsample(), and upsample().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ upsample() [3/3]

template<typename MatV , typename MatF >
IGL_INLINE void igl::upsample ( MatV &  V,
MatF &  F,
const int  number_of_subdivs = 1 
)
134{
135 const MatV V_copy = V;
136 const MatF F_copy = F;
137 return upsample(V_copy,F_copy,V,F,number_of_subdivs);
138}

References upsample().

+ Here is the call graph for this function:

◆ vector_area_matrix()

template<typename DerivedF , typename Scalar >
IGL_INLINE void igl::vector_area_matrix ( const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::SparseMatrix< Scalar > &  A 
)
22{
23 using namespace Eigen;
24 using namespace std;
25
26 // number of vertices
27 const int n = F.maxCoeff()+1;
28
29 MatrixXi E;
30 boundary_facets(F,E);
31
32 //Prepare a vector of triplets to set the matrix
33 vector<Triplet<Scalar> > tripletList;
34 tripletList.reserve(4*E.rows());
35
36 for(int k = 0; k < E.rows(); k++)
37 {
38 int i = E(k,0);
39 int j = E(k,1);
40 tripletList.push_back(Triplet<Scalar>(i+n, j, -0.25));
41 tripletList.push_back(Triplet<Scalar>(j, i+n, -0.25));
42 tripletList.push_back(Triplet<Scalar>(i, j+n, 0.25));
43 tripletList.push_back(Triplet<Scalar>(j+n, i, 0.25));
44 }
45
46 //Set A from triplets (Eigen will sum triplets with same coordinates)
47 A.resize(n * 2, n * 2);
48 A.setFromTriplets(tripletList.begin(), tripletList.end());
49}

References boundary_facets(), Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::resize(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets().

Referenced by lscm().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ verbose()

int igl::verbose ( const char *  msg,
  ... 
)
inline
41{
42 return 0;
43}

◆ vertex_triangle_adjacency() [1/3]

template<typename DerivedF , typename DerivedVF , typename DerivedNI >
IGL_INLINE void igl::vertex_triangle_adjacency ( const Eigen::MatrixBase< DerivedF > &  F,
const int  n,
Eigen::PlainObjectBase< DerivedVF > &  VF,
Eigen::PlainObjectBase< DerivedNI > &  NI 
)
55{
57 // vfd #V list so that vfd(i) contains the vertex-face degree (number of
58 // faces incident on vertex i)
59 VectorXI vfd = VectorXI::Zero(n);
60 for (int i = 0; i < F.rows(); i++)
61 {
62 for (int j = 0; j < 3; j++)
63 {
64 vfd[F(i,j)]++;
65 }
66 }
67 igl::cumsum(vfd,1,NI);
68 // Prepend a zero
69 NI = (DerivedNI(n+1)<<0,NI).finished();
70 // vfd now acts as a counter
71 vfd = NI;
72
73 VF.derived()= Eigen::VectorXi(3*F.rows());
74 for (int i = 0; i < F.rows(); i++)
75 {
76 for (int j = 0; j < 3; j++)
77 {
78 VF[vfd[F(i,j)]] = i;
79 vfd[F(i,j)]++;
80 }
81 }
82}

References cumsum().

+ Here is the call graph for this function:

◆ vertex_triangle_adjacency() [2/3]

template<typename DerivedV , typename DerivedF , typename IndexType >
IGL_INLINE void igl::vertex_triangle_adjacency ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
std::vector< std::vector< IndexType > > &  VF,
std::vector< std::vector< IndexType > > &  VFi 
)
42{
43 return vertex_triangle_adjacency(V.rows(),F,VF,VFi);
44}

References vertex_triangle_adjacency().

+ Here is the call graph for this function:

◆ vertex_triangle_adjacency() [3/3]

template<typename DerivedF , typename VFType , typename VFiType >
IGL_INLINE void igl::vertex_triangle_adjacency ( const typename DerivedF::Scalar  n,
const Eigen::MatrixBase< DerivedF > &  F,
std::vector< std::vector< VFType > > &  VF,
std::vector< std::vector< VFiType > > &  VFi 
)
17{
18 VF.clear();
19 VFi.clear();
20
21 VF.resize(n);
22 VFi.resize(n);
23
24 typedef typename DerivedF::Index Index;
25 for(Index fi=0; fi<F.rows(); ++fi)
26 {
27 for(Index i = 0; i < F.cols(); ++i)
28 {
29 VF[F(fi,i)].push_back(fi);
30 VFi[F(fi,i)].push_back(i);
31 }
32 }
33}

Referenced by igl::MissMatchCalculator< DerivedV, DerivedF, DerivedM >::MissMatchCalculator(), igl::MissMatchCalculatorLine< DerivedV, DerivedF, DerivedO >::MissMatchCalculatorLine(), igl::copyleft::comiso::PoissonSolver< DerivedV, DerivedF >::PoissonSolver(), boundary_loop(), igl::copyleft::cgal::closest_facet(), cut_mesh(), igl::copyleft::cgal::extract_cells(), find_cross_field_singularities(), CurvatureCalculator::init(), is_vertex_manifold(), per_corner_normals(), per_corner_normals(), igl::Frame_field_deformer::precompute_opt(), triangle_triangle_adjacency(), uniformly_sample_two_manifold(), and vertex_triangle_adjacency().

+ Here is the caller graph for this function:

◆ volume() [1/3]

template<typename DerivedA , typename DerivedB , typename DerivedC , typename DerivedD , typename Derivedvol >
IGL_INLINE void igl::volume ( const Eigen::MatrixBase< DerivedA > &  A,
const Eigen::MatrixBase< DerivedB > &  B,
const Eigen::MatrixBase< DerivedC > &  C,
const Eigen::MatrixBase< DerivedD > &  D,
Eigen::PlainObjectBase< Derivedvol > &  vol 
)
46{
47 const auto & AmD = A-D;
48 const auto & BmD = B-D;
49 const auto & CmD = C-D;
50 DerivedA BmDxCmD;
51 cross(BmD.eval(),CmD.eval(),BmDxCmD);
52 const auto & AmDdx = (AmD.array() * BmDxCmD.array()).rowwise().sum();
53 vol = -AmDdx/6.;
54}

References cross().

+ Here is the call graph for this function:

◆ volume() [2/3]

template<typename DerivedL , typename Derivedvol >
IGL_INLINE void igl::volume ( const Eigen::MatrixBase< DerivedL > &  L,
Eigen::PlainObjectBase< Derivedvol > &  vol 
)
77{
78 using namespace Eigen;
79 const int m = L.rows();
80 typedef typename Derivedvol::Scalar ScalarS;
81 vol.resize(m,1);
82 for(int t = 0;t<m;t++)
83 {
84 const ScalarS u = L(t,0);
85 const ScalarS v = L(t,1);
86 const ScalarS w = L(t,2);
87 const ScalarS U = L(t,3);
88 const ScalarS V = L(t,4);
89 const ScalarS W = L(t,5);
90 const ScalarS X = (w - U + v)*(U + v + w);
91 const ScalarS x = (U - v + w)*(v - w + U);
92 const ScalarS Y = (u - V + w)*(V + w + u);
93 const ScalarS y = (V - w + u)*(w - u + V);
94 const ScalarS Z = (v - W + u)*(W + u + v);
95 const ScalarS z = (W - u + v)*(u - v + W);
96 const ScalarS a = sqrt(x*Y*Z);
97 const ScalarS b = sqrt(y*Z*X);
98 const ScalarS c = sqrt(z*X*Y);
99 const ScalarS d = sqrt(x*y*z);
100 vol(t) = sqrt(
101 (-a + b + c + d)*
102 ( a - b + c + d)*
103 ( a + b - c + d)*
104 ( a + b + c - d))/
105 (192.*u*v*w);
106 }
107}

References L, Eigen::PlainObjectBase< Derived >::resize(), and sqrt().

+ Here is the call graph for this function:

◆ volume() [3/3]

template<typename DerivedV , typename DerivedT , typename Derivedvol >
IGL_INLINE void igl::volume ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedT > &  T,
Eigen::PlainObjectBase< Derivedvol > &  vol 
)
19{
20 using namespace Eigen;
21 const int m = T.rows();
22 vol.resize(m,1);
23 for(int t = 0;t<m;t++)
24 {
26 const RowVector3S & a = V.row(T(t,0));
27 const RowVector3S & b = V.row(T(t,1));
28 const RowVector3S & c = V.row(T(t,2));
29 const RowVector3S & d = V.row(T(t,3));
30 vol(t) = -(a-d).dot((b-d).cross(c-d))/6.;
31 }
32}

References dot(), and Eigen::PlainObjectBase< Derived >::resize().

Referenced by barycentric_coordinates(), cotmatrix_entries(), crouzeix_raviart_massmatrix(), and grad_tet().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ volume_single()

template<typename VecA , typename VecB , typename VecC , typename VecD >
IGL_INLINE VecA::Scalar igl::volume_single ( const VecA &  a,
const VecB &  b,
const VecC &  c,
const VecD &  d 
)
66{
67 return -(a-d).dot((b-d).cross(c-d))/6.;
68}

References dot().

Referenced by igl::AABB< DerivedV, DIM >::find().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ voxel_grid()

template<typename Scalar , typename DerivedGV , typename Derivedside >
IGL_INLINE void igl::voxel_grid ( const Eigen::AlignedBox< Scalar, 3 > &  box,
const int  s,
const int  pad_count,
Eigen::PlainObjectBase< DerivedGV > &  GV,
Eigen::PlainObjectBase< Derivedside > &  side 
)
21{
22 using namespace Eigen;
23 using namespace std;
24 typename DerivedGV::Index si = -1;
25 box.diagonal().maxCoeff(&si);
26 //DerivedGV::Index si = 0;
27 //assert(si>=0);
28 const Scalar s_len = box.diagonal()(si);
29 assert(in_s>(pad_count*2+1) && "s should be > 2*pad_count+1");
30 const Scalar s = in_s - 2*pad_count;
31 side(si) = s;
32 for(int i = 0;i<3;i++)
33 {
34 if(i!=si)
35 {
36 side(i) = std::ceil(s * (box.max()(i)-box.min()(i))/s_len);
37 }
38 }
39 side.array() += 2*pad_count;
40 grid(side,GV);
41 // A * p/s + B = min
42 // A * (1-p/s) + B = max
43 // B = min - A * p/s
44 // A * (1-p/s) + min - A * p/s = max
45 // A * (1-p/s) - A * p/s = max-min
46 // A * (1-2p/s) = max-min
47 // A = (max-min)/(1-2p/s)
48 const Array<Scalar,3,1> ps=
49 (Scalar)(pad_count)/(side.transpose().template cast<Scalar>().array()-1.);
50 const Array<Scalar,3,1> A = box.diagonal().array()/(1.0-2.*ps);
52 //const Array<Scalar,3,1> B = box.min().array() - A.array()*ps;
53 //GV.array().rowwise() *= A.transpose();
54 //GV.array().rowwise() += B.transpose();
55 // Instead scale by largest factor and move to match center
56 typename Array<Scalar,3,1>::Index ai = -1;
57 Scalar a = A.maxCoeff(&ai);
58 const Array<Scalar,1,3> ratio =
59 a*(side.template cast<Scalar>().array()-1.0)/(Scalar)(side(ai)-1.0);
60 GV.array().rowwise() *= ratio;
61 const Eigen::Matrix<Scalar,1,3> offset = (box.center().transpose()-GV.colwise().mean()).eval();
62 GV.rowwise() += offset;
63}
EIGEN_DEVICE_FUNC CwiseBinaryOp< internal::scalar_difference_op< Scalar, Scalar >, const VectorType, const VectorType > diagonal() const
Definition AlignedBox.h:134
IGL_INLINE void grid(const Eigen::MatrixBase< Derivedres > &res, Eigen::PlainObjectBase< DerivedGV > &GV)
Definition grid.cpp:13

References Eigen::AlignedBox< _Scalar, _AmbientDim >::diagonal(), grid(), Eigen::AlignedBox< _Scalar, _AmbientDim >::max(), and Eigen::AlignedBox< _Scalar, _AmbientDim >::min().

Referenced by igl::copyleft::offset_surface(), and igl::copyleft::swept_volume().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ winding_number() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedO , typename DerivedW >
IGL_INLINE void igl::winding_number ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< DerivedO > &  O,
Eigen::PlainObjectBase< DerivedW > &  W 
)
27{
28 using namespace Eigen;
29 // make room for output
30 W.resize(O.rows(),1);
31 switch(F.cols())
32 {
33 case 2:
34 {
35 igl::parallel_for(O.rows(),[&](const int o)
36 {
37 W(o) = winding_number(V,F,O.row(o));
38 },10000);
39 return;
40 }
41 case 3:
42 {
43 WindingNumberAABB<
45 DerivedV,
46 DerivedF>
47 hier(V,F);
48 hier.grow();
49 // loop over origins
50 igl::parallel_for(O.rows(),[&](const int o)
51 {
52 W(o) = hier.winding_number(O.row(o));
53 },10000);
54 break;
55 }
56 default: assert(false && "Bad simplex size"); break;
57 }
58}

References parallel_for(), and Eigen::PlainObjectBase< Derived >::resize().

Referenced by igl::WindingNumberAABB< Point, DerivedV, DerivedF >::max_simple_abs_winding_number(), signed_distance(), signed_distance_winding_number(), igl::WindingNumberTree< Point, DerivedV, DerivedF >::winding_number_all(), and igl::WindingNumberTree< Point, DerivedV, DerivedF >::winding_number_boundary().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ winding_number() [2/2]

template<typename DerivedV , typename DerivedF , typename Derivedp >
IGL_INLINE DerivedV::Scalar igl::winding_number ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< Derivedp > &  p 
)
68{
69 typedef typename DerivedV::Scalar wType;
70 const int ss = F.cols();
71 const int m = F.rows();
72 wType w = 0;
73 for(int f = 0;f<m;f++)
74 {
75 switch(ss)
76 {
77 case 2:
78 {
79 w += igl::signed_angle( V.row(F(f,0)),V.row(F(f,1)),p);
80 break;
81 }
82 case 3:
83 {
84 w += igl::solid_angle(V.row(F(f,0)), V.row(F(f,1)), V.row(F(f,2)),p);
85 break;
86 }
87 default: assert(false); break;
88 }
89 }
90 return w;
91}
IGL_INLINE DerivedA::Scalar solid_angle(const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &B, const Eigen::MatrixBase< DerivedC > &C, const Eigen::MatrixBase< DerivedP > &P)
Definition solid_angle.cpp:10
IGL_INLINE DerivedA::Scalar signed_angle(const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &B, const Eigen::MatrixBase< DerivedP > &P)
Definition signed_angle.cpp:9

References signed_angle(), and solid_angle().

+ Here is the call graph for this function:

◆ write_triangle_mesh()

template<typename DerivedV , typename DerivedF >
IGL_INLINE bool igl::write_triangle_mesh ( const std::string  str,
const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const bool  force_ascii = true 
)
25{
26 using namespace std;
27 // dirname, basename, extension and filename
28 string d,b,e,f;
29 pathinfo(str,d,b,e,f);
30 // Convert extension to lower case
31 std::transform(e.begin(), e.end(), e.begin(), ::tolower);
32 if(e == "mesh")
33 {
34 Eigen::MatrixXi _1;
35 return writeMESH(str,V,_1,F);
36 }else if(e == "obj")
37 {
38 return writeOBJ(str,V,F);
39 }else if(e == "off")
40 {
41 return writeOFF(str,V,F);
42 }else if(e == "ply")
43 {
44 return writePLY(str,V,F,force_ascii);
45 }else if(e == "stl")
46 {
47 return writeSTL(str,V,F,force_ascii);
48 }else if(e == "wrl")
49 {
50 return writeWRL(str,V,F);
51 }else
52 {
53 assert("Unsupported file format");
54 cerr<<"Unsupported file format: ."<<e<<endl;
55 return false;
56 }
57}
IGL_INLINE bool writeOFF(const std::string str, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedC > &C)
Definition writeOFF.cpp:38
IGL_INLINE bool writeSTL(const std::string &filename, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedN > &N, const bool ascii=true)
Definition writeSTL.cpp:12
IGL_INLINE bool writeMESH(const std::string mesh_file_name, const std::vector< std::vector< Scalar > > &V, const std::vector< std::vector< Index > > &T, const std::vector< std::vector< Index > > &F)
Definition writeMESH.cpp:19
IGL_INLINE bool writePLY(const std::string &filename, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedN > &N, const Eigen::MatrixBase< DerivedUV > &UV, const bool ascii=true)
Definition writePLY.cpp:32
IGL_INLINE bool writeWRL(const std::string &str, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F)
Definition writeWRL.cpp:12

References pathinfo(), writeMESH(), writeOBJ(), writeOFF(), writePLY(), writeSTL(), and writeWRL().

Referenced by igl::xml::write_triangle_mesh().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ writeBF()

template<typename DerivedWI , typename DerivedP , typename DerivedO >
IGL_INLINE bool igl::writeBF ( const std::string &  filename,
const Eigen::PlainObjectBase< DerivedWI > &  WI,
const Eigen::PlainObjectBase< DerivedP > &  P,
const Eigen::PlainObjectBase< DerivedO > &  O 
)
20{
21 using namespace Eigen;
22 using namespace std;
23 const int n = WI.rows();
24 assert(n == WI.rows() && "WI must have n rows");
25 assert(n == P.rows() && "P must have n rows");
26 assert(n == O.rows() && "O must have n rows");
27 MatrixXd WIPO(n,1+1+3);
28 for(int i = 0;i<n;i++)
29 {
30 WIPO(i,0) = WI(i);
31 WIPO(i,1) = P(i);
32 WIPO(i,2+0) = O(i,0);
33 WIPO(i,2+1) = O(i,1);
34 WIPO(i,2+2) = O(i,2);
35 }
36 ofstream s(filename);
37 if(!s.is_open())
38 {
39 fprintf(stderr,"IOError: writeBF() could not open %s\n",filename.c_str());
40 return false;
41 }
42 s<<
43 WIPO.format(IOFormat(FullPrecision,DontAlignCols," ","\n","","","","\n"));
44 return true;
45}

References Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ writeDMAT() [1/3]

template<typename DerivedW >
IGL_INLINE bool igl::writeDMAT ( const std::string  file_name,
const Eigen::MatrixBase< DerivedW > &  W,
const bool  ascii = true 
)
19{
20 FILE * fp = fopen(file_name.c_str(),"wb");
21 if(fp == NULL)
22 {
23 fprintf(stderr,"IOError: writeDMAT() could not open %s...",file_name.c_str());
24 return false;
25 }
26 if(ascii)
27 {
28 // first line contains number of rows and number of columns
29 fprintf(fp,"%d %d\n",(int)W.cols(),(int)W.rows());
30 // Loop over columns slowly
31 for(int j = 0;j < W.cols();j++)
32 {
33 // loop over rows (down columns) quickly
34 for(int i = 0;i < W.rows();i++)
35 {
36 fprintf(fp,"%0.17lg\n",(double)W(i,j));
37 }
38 }
39 }else
40 {
41 // write header for ascii
42 fprintf(fp,"0 0\n");
43 // first line contains number of rows and number of columns
44 fprintf(fp,"%d %d\n",(int)W.cols(),(int)W.rows());
45 // reader assumes the binary part is double precision
46 Eigen::MatrixXd Wd = W.template cast<double>();
47 fwrite(Wd.data(),sizeof(double),Wd.size(),fp);
49 //for(int j = 0;j < W.cols();j++)
50 //{
51 // // loop over rows (down columns) quickly
52 // for(int i = 0;i < W.rows();i++)
53 // {
54 // double d = (double)W(i,j);
55 // fwrite(&d,sizeof(double),1,fp);
56 // }
57 //}
58 }
59 fclose(fp);
60 return true;
61}
@ ascii
Definition stl.h:70

References ascii.

Referenced by writeDMAT(), and writeDMAT().

+ Here is the caller graph for this function:

◆ writeDMAT() [2/3]

template<typename Scalar >
IGL_INLINE bool igl::writeDMAT ( const std::string  file_name,
const std::vector< Scalar > &  W,
const bool  ascii = true 
)
79{
81 list_to_matrix(W,mW);
82 return igl::writeDMAT(file_name,mW,ascii);
83}
IGL_INLINE bool writeDMAT(const std::string file_name, const Eigen::MatrixBase< DerivedW > &W, const bool ascii=true)
Definition writeDMAT.cpp:15

References ascii, list_to_matrix(), and writeDMAT().

+ Here is the call graph for this function:

◆ writeDMAT() [3/3]

template<typename Scalar >
IGL_INLINE bool igl::writeDMAT ( const std::string  file_name,
const std::vector< std::vector< Scalar > > &  W,
const bool  ascii = true 
)

References ascii, list_to_matrix(), and writeDMAT().

+ Here is the call graph for this function:

◆ writeMESH() [1/2]

template<typename Scalar , typename Index >
IGL_INLINE bool igl::writeMESH ( const std::string  mesh_file_name,
const std::vector< std::vector< Scalar > > &  V,
const std::vector< std::vector< Index > > &  T,
const std::vector< std::vector< Index > > &  F 
)
24{
25 Eigen::MatrixXd mV;
26 Eigen::MatrixXi mT,mF;
27 bool is_rect;
28 is_rect = list_to_matrix(V,mV);
29 if(!is_rect)
30 {
31 return false;
32 }
33 is_rect = list_to_matrix(T,mT);
34 if(!is_rect)
35 {
36 return false;
37 }
38 is_rect = list_to_matrix(F,mF);
39 if(!is_rect)
40 {
41 return false;
42 }
43 return igl::writeMESH(mesh_file_name,mV,mT,mF);
44}

References list_to_matrix(), and writeMESH().

Referenced by launch_medit(), write_triangle_mesh(), and writeMESH().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ writeMESH() [2/2]

template<typename DerivedV , typename DerivedT , typename DerivedF >
IGL_INLINE bool igl::writeMESH ( const std::string  str,
const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedT > &  T,
const Eigen::PlainObjectBase< DerivedF > &  F 
)
53{
54 using namespace std;
55 using namespace Eigen;
56
58 //ofstream mesh_file;
59 //mesh_file.open(str.c_str());
60 //if(!mesh_file.is_open())
61 //{
62 // cerr<<"IOError: "<<str<<" could not be opened..."<<endl;
63 // return false;
64 //}
65 //IOFormat format(FullPrecision,DontAlignCols," ","\n",""," 1","","");
66 //mesh_file<<"MeshVersionFormatted 1\n";
67 //mesh_file<<"Dimension 3\n";
68 //mesh_file<<"Vertices\n";
69 //mesh_file<<V.rows()<<"\n";
70 //mesh_file<<V.format(format)<<"\n";
71 //mesh_file<<"Triangles\n";
72 //mesh_file<<F.rows()<<"\n";
73 //mesh_file<<(F.array()+1).eval().format(format)<<"\n";
74 //mesh_file<<"Tetrahedra\n";
75 //mesh_file<<T.rows()<<"\n";
76 //mesh_file<<(T.array()+1).eval().format(format)<<"\n";
77 //mesh_file.close();
78
79 FILE * mesh_file = fopen(str.c_str(),"w");
80 if(NULL==mesh_file)
81 {
82 fprintf(stderr,"IOError: %s could not be opened...",str.c_str());
83 return false;
84 }
85 // print header
86 fprintf(mesh_file,"MeshVersionFormatted 1\n");
87 fprintf(mesh_file,"Dimension 3\n");
88 // print tet vertices
89 fprintf(mesh_file,"Vertices\n");
90 // print number of tet vertices
91 int number_of_tet_vertices = V.rows();
92 fprintf(mesh_file,"%d\n",number_of_tet_vertices);
93 // loop over tet vertices
94 for(int i = 0;i<number_of_tet_vertices;i++)
95 {
96 // print position of ith tet vertex
97 fprintf(mesh_file,"%.17lg %.17lg %.17lg 1\n",
98 (double)V(i,0),
99 (double)V(i,1),
100 (double)V(i,2));
101 }
102 verbose("WARNING: save_mesh() assumes that vertices have"
103 " same indices in surface as volume...\n");
104 // print faces
105 fprintf(mesh_file,"Triangles\n");
106 // print number of triangles
107 int number_of_triangles = F.rows();
108 fprintf(mesh_file,"%d\n",number_of_triangles);
109 // loop over faces
110 for(int i = 0;i<number_of_triangles;i++)
111 {
112 // loop over vertices in face
113 fprintf(mesh_file,"%d %d %d 1\n",
114 (int)F(i,0)+1,
115 (int)F(i,1)+1,
116 (int)F(i,2)+1);
117 }
118 // print tetrahedra
119 fprintf(mesh_file,"Tetrahedra\n");
120 int number_of_tetrahedra = T.rows();
121 // print number of tetrahedra
122 fprintf(mesh_file,"%d\n",number_of_tetrahedra);
123 // loop over tetrahedra
124 for(int i = 0; i < number_of_tetrahedra;i++)
125 {
126 // mesh standard uses 1-based indexing
127 fprintf(mesh_file, "%d %d %d %d 1\n",
128 (int)T(i,0)+1,
129 (int)T(i,1)+1,
130 (int)T(i,2)+1,
131 (int)T(i,3)+1);
132 }
133 fclose(mesh_file);
134 return true;
135}

References Eigen::PlainObjectBase< Derived >::rows(), and verbose.

+ Here is the call graph for this function:

◆ writeOBJ() [1/2]

template<typename DerivedV , typename DerivedF >
IGL_INLINE bool igl::writeOBJ ( const std::string  str,
const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F 
)
105{
106 using namespace std;
107 using namespace Eigen;
108 assert(V.cols() == 3 && "V should have 3 columns");
109 ofstream s(str);
110 if(!s.is_open())
111 {
112 fprintf(stderr,"IOError: writeOBJ() could not open %s\n",str.c_str());
113 return false;
114 }
115 s<<
116 V.format(IOFormat(FullPrecision,DontAlignCols," ","\n","v ","","","\n"))<<
117 (F.array()+1).format(IOFormat(FullPrecision,DontAlignCols," ","\n","f ","","","\n"));
118 return true;
119}

References Eigen::DenseBase< Derived >::format().

+ Here is the call graph for this function:

◆ writeOBJ() [2/2]

template<typename DerivedV , typename DerivedF , typename DerivedCN , typename DerivedFN , typename DerivedTC , typename DerivedFTC >
IGL_INLINE bool igl::writeOBJ ( const std::string  str,
const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< DerivedCN > &  CN,
const Eigen::MatrixBase< DerivedFN > &  FN,
const Eigen::MatrixBase< DerivedTC > &  TC,
const Eigen::MatrixBase< DerivedFTC > &  FTC 
)
32{
33 FILE * obj_file = fopen(str.c_str(),"w");
34 if(NULL==obj_file)
35 {
36 printf("IOError: %s could not be opened for writing...",str.c_str());
37 return false;
38 }
39 // Loop over V
40 for(int i = 0;i<(int)V.rows();i++)
41 {
42 fprintf(obj_file,"v");
43 for(int j = 0;j<(int)V.cols();++j)
44 {
45 fprintf(obj_file," %0.17g", V(i,j));
46 }
47 fprintf(obj_file,"\n");
48 }
49 bool write_N = CN.rows() >0;
50
51 if(write_N)
52 {
53 for(int i = 0;i<(int)CN.rows();i++)
54 {
55 fprintf(obj_file,"vn %0.17g %0.17g %0.17g\n",
56 CN(i,0),
57 CN(i,1),
58 CN(i,2)
59 );
60 }
61 fprintf(obj_file,"\n");
62 }
63
64 bool write_texture_coords = TC.rows() >0;
65
66 if(write_texture_coords)
67 {
68 for(int i = 0;i<(int)TC.rows();i++)
69 {
70 fprintf(obj_file, "vt %0.17g %0.17g\n",TC(i,0),TC(i,1));
71 }
72 fprintf(obj_file,"\n");
73 }
74
75 // loop over F
76 for(int i = 0;i<(int)F.rows();++i)
77 {
78 fprintf(obj_file,"f");
79 for(int j = 0; j<(int)F.cols();++j)
80 {
81 // OBJ is 1-indexed
82 fprintf(obj_file," %u",F(i,j)+1);
83
84 if(write_texture_coords)
85 fprintf(obj_file,"/%u",FTC(i,j)+1);
86 if(write_N)
87 {
88 if (write_texture_coords)
89 fprintf(obj_file,"/%u",FN(i,j)+1);
90 else
91 fprintf(obj_file,"//%u",FN(i,j)+1);
92 }
93 }
94 fprintf(obj_file,"\n");
95 }
96 fclose(obj_file);
97 return true;
98}

Referenced by igl::opengl::glfw::Viewer::save_mesh_to_file(), and write_triangle_mesh().

+ Here is the caller graph for this function:

◆ writeOFF() [1/2]

template<typename DerivedV , typename DerivedF >
IGL_INLINE bool igl::writeOFF ( const std::string  str,
const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F 
)
18{
19 using namespace std;
20 using namespace Eigen;
21 assert(V.cols() == 3 && "V should have 3 columns");
22 ofstream s(fname);
23 if(!s.is_open())
24 {
25 fprintf(stderr,"IOError: writeOFF() could not open %s\n",fname.c_str());
26 return false;
27 }
28
29 s<<
30 "OFF\n"<<V.rows()<<" "<<F.rows()<<" 0\n"<<
31 V.format(IOFormat(FullPrecision,DontAlignCols," ","\n","","","","\n"))<<
32 (F.array()).format(IOFormat(FullPrecision,DontAlignCols," ","\n","3 ","","","\n"));
33 return true;
34}

References Eigen::PlainObjectBase< Derived >::cols(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ writeOFF() [2/2]

template<typename DerivedV , typename DerivedF , typename DerivedC >
IGL_INLINE bool igl::writeOFF ( const std::string  str,
const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedC > &  C 
)
43{
44 using namespace std;
45 using namespace Eigen;
46 assert(V.cols() == 3 && "V should have 3 columns");
47 assert(C.cols() == 3 && "C should have 3 columns");
48
49 if(V.rows() != C.rows())
50 {
51 fprintf(stderr,"IOError: writeOFF() Only color per vertex supported. V and C should have same size.\n");
52 return false;
53 }
54
55 ofstream s(fname);
56 if(!s.is_open())
57 {
58 fprintf(stderr,"IOError: writeOFF() could not open %s\n",fname.c_str());
59 return false;
60 }
61
62 //Check if RGB values are in the range [0..1] or [0..255]
63 int rgbScale = (C.maxCoeff() <= 1.0)?255:1;
64 // Use RGB_Array instead of RGB because of clash with mingw macro
65 // (https://github.com/libigl/libigl/pull/679)
66 Eigen::MatrixXd RGB_Array = rgbScale * C;
67
68 s<< "COFF\n"<<V.rows()<<" "<<F.rows()<<" 0\n";
69 for (unsigned i=0; i< V.rows(); i++)
70 {
71 s <<V.row(i).format(IOFormat(FullPrecision,DontAlignCols," "," ","","",""," "));
72 s << unsigned(RGB_Array(i,0)) << " " << unsigned(RGB_Array(i,1)) << " " << unsigned(RGB_Array(i,2)) << " 255\n";
73 }
74
75 s<<(F.array()).format(IOFormat(FullPrecision,DontAlignCols," ","\n","3 ","","","\n"));
76 return true;
77}
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:44

References Eigen::PlainObjectBase< Derived >::cols(), and Eigen::PlainObjectBase< Derived >::rows().

Referenced by igl::opengl::glfw::Viewer::save_mesh_to_file(), and write_triangle_mesh().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ writePLY() [1/2]

template<typename DerivedV , typename DerivedF >
IGL_INLINE bool igl::writePLY ( const std::string &  filename,
const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const bool  ascii = true 
)

References ascii, and writePLY().

+ Here is the call graph for this function:

◆ writePLY() [2/2]

template<typename DerivedV , typename DerivedF , typename DerivedN , typename DerivedUV >
IGL_INLINE bool igl::writePLY ( const std::string &  filename,
const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< DerivedN > &  N,
const Eigen::MatrixBase< DerivedUV > &  UV,
const bool  ascii = true 
)
39{
40 // Largely based on obj2ply.c
41 typedef typename DerivedV::Scalar VScalar;
42 typedef typename DerivedN::Scalar NScalar;
43 typedef typename DerivedUV::Scalar UVScalar;
44 typedef typename DerivedF::Scalar FScalar;
45
46 typedef struct Vertex
47 {
48 VScalar x,y,z,w; /* position */
49 NScalar nx,ny,nz; /* surface normal */
50 UVScalar s,t; /* texture coordinates */
51 } Vertex;
52
53 typedef struct Face
54 {
55 unsigned char nverts; /* number of vertex indices in list */
56 FScalar *verts; /* vertex index list */
57 } Face;
58
59 igl::ply::PlyProperty vert_props[] =
60 { /* list of property information for a vertex */
61 {"x", ply_type<VScalar>(), ply_type<VScalar>(),offsetof(Vertex,x),0,0,0,0},
62 {"y", ply_type<VScalar>(), ply_type<VScalar>(),offsetof(Vertex,y),0,0,0,0},
63 {"z", ply_type<VScalar>(), ply_type<VScalar>(),offsetof(Vertex,z),0,0,0,0},
64 {"nx",ply_type<NScalar>(), ply_type<NScalar>(),offsetof(Vertex,nx),0,0,0,0},
65 {"ny",ply_type<NScalar>(), ply_type<NScalar>(),offsetof(Vertex,ny),0,0,0,0},
66 {"nz",ply_type<NScalar>(), ply_type<NScalar>(),offsetof(Vertex,nz),0,0,0,0},
67 {"s", ply_type<UVScalar>(),ply_type<UVScalar>(),offsetof(Vertex,s),0,0,0,0},
68 {"t", ply_type<UVScalar>(),ply_type<UVScalar>(),offsetof(Vertex,t),0,0,0,0},
69 };
70
71 igl::ply::PlyProperty face_props[] =
72 { /* list of property information for a face */
73 {"vertex_indices", ply_type<FScalar>(), ply_type<FScalar>(),
74 offsetof(Face,verts), 1, PLY_UCHAR, PLY_UCHAR, offsetof(Face,nverts)},
75 };
76 const bool has_normals = N.rows() > 0;
77 const bool has_texture_coords = UV.rows() > 0;
78 std::vector<Vertex> vlist(V.rows());
79 std::vector<Face> flist(F.rows());
80 for(size_t i = 0;i<(size_t)V.rows();i++)
81 {
82 vlist[i].x = V(i,0);
83 vlist[i].y = V(i,1);
84 vlist[i].z = V(i,2);
85 if(has_normals)
86 {
87 vlist[i].nx = N(i,0);
88 vlist[i].ny = N(i,1);
89 vlist[i].nz = N(i,2);
90 }
91 if(has_texture_coords)
92 {
93 vlist[i].s = UV(i,0);
94 vlist[i].t = UV(i,1);
95 }
96 }
97 for(size_t i = 0;i<(size_t)F.rows();i++)
98 {
99 flist[i].nverts = F.cols();
100 flist[i].verts = new FScalar[F.cols()];
101 for(size_t c = 0;c<(size_t)F.cols();c++)
102 {
103 flist[i].verts[c] = F(i,c);
104 }
105 }
106
107 const char * elem_names[] = {"vertex","face"};
108 FILE * fp = fopen(filename.c_str(),"w");
109 if(fp==NULL)
110 {
111 return false;
112 }
113 igl::ply::PlyFile * ply = igl::ply::ply_write(fp, 2,elem_names,
115 if(ply==NULL)
116 {
117 return false;
118 }
119
120 std::vector<igl::ply::PlyProperty> plist;
121 plist.push_back(vert_props[0]);
122 plist.push_back(vert_props[1]);
123 plist.push_back(vert_props[2]);
124 if (has_normals)
125 {
126 plist.push_back(vert_props[3]);
127 plist.push_back(vert_props[4]);
128 plist.push_back(vert_props[5]);
129 }
130 if (has_texture_coords)
131 {
132 plist.push_back(vert_props[6]);
133 plist.push_back(vert_props[7]);
134 }
135 ply_describe_element(ply, "vertex", V.rows(),plist.size(),
136 &plist[0]);
137
138 ply_describe_element(ply, "face", F.rows(),1,&face_props[0]);
140 int native_binary_type = igl::ply::get_native_binary_type2();
141 ply_put_element_setup(ply, "vertex");
142 for(const auto v : vlist)
143 {
144 ply_put_element(ply, (void *) &v, &native_binary_type);
145 }
146 ply_put_element_setup(ply, "face");
147 for(const auto f : flist)
148 {
149 ply_put_element(ply, (void *) &f, &native_binary_type);
150 }
151
152 ply_close(ply);
153 for(size_t i = 0;i<(size_t)F.rows();i++)
154 {
155 delete[] flist[i].verts;
156 }
157 return true;
158}
void ply_put_element_setup(PlyFile *, const char *)
Definition ply.h:821
void ply_header_complete(PlyFile *)
Definition ply.h:748
PlyFile * ply_write(FILE *, int, const char **, int)
Definition ply.h:451
void ply_describe_element(PlyFile *, const char *, int, int, PlyProperty *)
Definition ply.h:570
void ply_put_element(PlyFile *, void *, int *)
Definition ply.h:845
#define PLY_ASCII
Definition ply.h:85
#define PLY_BINARY_LE
Definition ply.h:87

References ascii, igl::ply::get_native_binary_type2(), PLY_ASCII, PLY_BINARY_LE, PLY_UCHAR, and igl::ply::ply_write().

Referenced by igl::copyleft::cgal::peel_outer_hull_layers(), igl::copyleft::cgal::propagate_winding_numbers(), write_triangle_mesh(), and writePLY().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ writeSTL() [1/2]

template<typename DerivedV , typename DerivedF >
IGL_INLINE bool igl::writeSTL ( const std::string &  filename,
const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const bool  ascii = true 
)
107{
108 return writeSTL(filename,V,F, DerivedV(), ascii);
109}

References ascii, and writeSTL().

+ Here is the call graph for this function:

◆ writeSTL() [2/2]

template<typename DerivedV , typename DerivedF , typename DerivedN >
IGL_INLINE bool igl::writeSTL ( const std::string &  filename,
const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedN > &  N,
const bool  ascii = true 
)
18{
19 using namespace std;
20 assert(N.rows() == 0 || F.rows() == N.rows());
21 if(ascii)
22 {
23 FILE * stl_file = fopen(filename.c_str(),"w");
24 if(stl_file == NULL)
25 {
26 cerr<<"IOError: "<<filename<<" could not be opened for writing."<<endl;
27 return false;
28 }
29 fprintf(stl_file,"solid %s\n",filename.c_str());
30 for(int f = 0;f<F.rows();f++)
31 {
32 fprintf(stl_file,"facet normal ");
33 if(N.rows()>0)
34 {
35 fprintf(stl_file,"%e %e %e\n",
36 (float)N(f,0),
37 (float)N(f,1),
38 (float)N(f,2));
39 }else
40 {
41 fprintf(stl_file,"0 0 0\n");
42 }
43 fprintf(stl_file,"outer loop\n");
44 for(int c = 0;c<F.cols();c++)
45 {
46 fprintf(stl_file,"vertex %e %e %e\n",
47 (float)V(F(f,c),0),
48 (float)V(F(f,c),1),
49 (float)V(F(f,c),2));
50 }
51 fprintf(stl_file,"endloop\n");
52 fprintf(stl_file,"endfacet\n");
53 }
54 fprintf(stl_file,"endsolid %s\n",filename.c_str());
55 fclose(stl_file);
56 return true;
57 }else
58 {
59 FILE * stl_file = fopen(filename.c_str(),"wb");
60 if(stl_file == NULL)
61 {
62 cerr<<"IOError: "<<filename<<" could not be opened for writing."<<endl;
63 return false;
64 }
65 // Write unused 80-char header
66 for(char h = 0;h<80;h++)
67 {
68 fwrite(&h,sizeof(char),1,stl_file);
69 }
70 // Write number of triangles
71 unsigned int num_tri = F.rows();
72 fwrite(&num_tri,sizeof(unsigned int),1,stl_file);
73 assert(F.cols() == 3);
74 // Write each triangle
75 for(int f = 0;f<F.rows();f++)
76 {
77 vector<float> n(3,0);
78 if(N.rows() > 0)
79 {
80 n[0] = N(f,0);
81 n[1] = N(f,1);
82 n[2] = N(f,2);
83 }
84 fwrite(&n[0],sizeof(float),3,stl_file);
85 for(int c = 0;c<3;c++)
86 {
87 vector<float> v(3);
88 v[0] = V(F(f,c),0);
89 v[1] = V(F(f,c),1);
90 v[2] = V(F(f,c),2);
91 fwrite(&v[0],sizeof(float),3,stl_file);
92 }
93 unsigned short att_count = 0;
94 fwrite(&att_count,sizeof(unsigned short),1,stl_file);
95 }
96 fclose(stl_file);
97 return true;
98 }
99}

References ascii, and Eigen::PlainObjectBase< Derived >::rows().

Referenced by write_triangle_mesh(), and writeSTL().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ writeTGF() [1/2]

IGL_INLINE bool igl::writeTGF ( const std::string  tgf_filename,
const Eigen::MatrixXd &  C,
const Eigen::MatrixXi &  E 
)
65{
66 using namespace std;
67 vector<vector<double> > vC;
68 vector<vector<int> > vE;
69 matrix_to_list(C,vC);
70 matrix_to_list(E,vE);
71 return writeTGF(tgf_filename,vC,vE);
72}
IGL_INLINE bool writeTGF(const std::string tgf_filename, const std::vector< std::vector< double > > &C, const std::vector< std::vector< int > > &E)
Definition writeTGF.cpp:11

References matrix_to_list(), and writeTGF().

+ Here is the call graph for this function:

◆ writeTGF() [2/2]

IGL_INLINE bool igl::writeTGF ( const std::string  tgf_filename,
const std::vector< std::vector< double > > &  C,
const std::vector< std::vector< int > > &  E 
)
15{
16 FILE * tgf_file = fopen(tgf_filename.c_str(),"w");
17 if(NULL==tgf_file)
18 {
19 printf("IOError: %s could not be opened\n",tgf_filename.c_str());
20 return false;
21 }
22 // Loop over vertices
23 for(int i = 0; i<(int)C.size();i++)
24 {
25 assert(C[i].size() == 3);
26 // print a line with vertex number then "description"
27 // Where "description" in our case is the 3d position in space
28 //
29 fprintf(tgf_file,
30 "%4d "
31 "%10.17g %10.17g %10.17g " // current location
32 // All others are not needed for this legacy support
33 "\n",
34 i+1,
35 C[i][0], C[i][1], C[i][2]);
36 }
37
38 // print a comment to separate vertices and edges
39 fprintf(tgf_file,"#\n");
40
41 // loop over edges
42 for(int i = 0;i<(int)E.size();i++)
43 {
44 assert(E[i].size()==2);
45 fprintf(tgf_file,"%4d %4d\n",
46 E[i][0]+1,
47 E[i][1]+1);
48 }
49
50 // print a comment to separate edges and faces
51 fprintf(tgf_file,"#\n");
52
53 fclose(tgf_file);
54
55 return true;
56}

Referenced by writeTGF().

+ Here is the caller graph for this function:

◆ writeWRL() [1/2]

template<typename DerivedV , typename DerivedF >
IGL_INLINE bool igl::writeWRL ( const std::string &  str,
const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F 
)
16{
17 using namespace std;
18 using namespace Eigen;
19 assert(V.cols() == 3 && "V should have 3 columns");
20 assert(F.cols() == 3 && "F should have 3 columns");
21 ofstream s(str);
22 if(!s.is_open())
23 {
24 cerr<<"IOError: writeWRL() could not open "<<str<<endl;
25 return false;
26 }
27 // Append column of -1 to F
29 FF.leftCols(3) = F;
30 FF.col(3).setConstant(-1);
31
32 s<<R"(#VRML V2.0 utf8
33DEF default Transform {
34translation 0 0 0
35children [
36Shape {
37geometry DEF default-FACES IndexedFaceSet {
38ccw TRUE
39)"<<
40 V.format(
42 FullPrecision,
43 DontAlignCols,
44 " ",",\n","","",
45 "coord DEF default-COORD Coordinate { point [ \n","]\n}\n"))<<
46 FF.format(

References Eigen::PlainObjectBase< Derived >::cols(), and Eigen::PlainObjectBase< Derived >::setConstant().

Referenced by write_triangle_mesh().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ writeWRL() [2/2]

template<typename DerivedV , typename DerivedF , typename DerivedC >
IGL_INLINE bool igl::writeWRL ( const std::string &  str,
const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedC > &  C 
)
63{
64 using namespace std;
65 using namespace Eigen;
66 assert(V.cols() == 3 && "V should have 3 columns");
67 assert(F.cols() == 3 && "F should have 3 columns");
68 ofstream s(str);
69 if(!s.is_open())
70 {
71 cerr<<"IOError: writeWRL() could not open "<<str<<endl;
72 return false;
73 }
74 // Append column of -1 to F
76 FF.leftCols(3) = F;
77 FF.col(3).setConstant(-1);
78
79
80 //Check if RGB values are in the range [0..1] or [0..255]
81 double rgbScale = (C.maxCoeff() <= 1.0)?1.0:1.0/255.0;
82 Eigen::MatrixXd RGB = rgbScale * C;
83
84 s<<R"(#VRML V2.0 utf8
85DEF default Transform {
86translation 0 0 0
87children [
88Shape {
89geometry DEF default-FACES IndexedFaceSet {
90ccw TRUE
91)"<<
92 V.format(
94 FullPrecision,
95 DontAlignCols,
96 " ",",\n","","",
97 "coord DEF default-COORD Coordinate { point [ \n","]\n}\n"))<<
98 FF.format(

Variable Documentation

◆ BBW_LINE_COLOR

const float igl::BBW_LINE_COLOR[4] = {106./255.,106./255.,255./255.,255./255.}

◆ BBW_POINT_COLOR

const float igl::BBW_POINT_COLOR[4] = {239./255.,213./255.,46./255.,255.0/255.0}

◆ BLACK

const float igl::BLACK[4] = { 0.0/255.0,0.0/255.0,0.0/255.0,1.0f }

◆ CANONICAL_VIEW_QUAT_D

const double igl::CANONICAL_VIEW_QUAT_D[][4]

◆ CANONICAL_VIEW_QUAT_F

const float igl::CANONICAL_VIEW_QUAT_F[][4]

◆ CHAR_ONE

const char igl::CHAR_ONE = 1

◆ CHAR_ZERO

const char igl::CHAR_ZERO = 0

◆ CYAN_AMBIENT

const float igl::CYAN_AMBIENT[4] = { 59.0/255.0, 68.0/255.0,255.0/255.0,1.0f }

◆ CYAN_DIFFUSE

const float igl::CYAN_DIFFUSE[4] = { 94.0/255.0,185.0/255.0,238.0/255.0,1.0f }

◆ CYAN_SPECULAR

const float igl::CYAN_SPECULAR[4] = { 163.0/255.0,221.0/255.0,255.0/255.0,1.0f }

◆ DENIS_PURPLE_DIFFUSE

const float igl::DENIS_PURPLE_DIFFUSE[4] = { 80.0/255.0,64.0/255.0,255.0/255.0,1.0f }

◆ DOUBLE_EPS

◆ DOUBLE_EPS_SQ

const double igl::DOUBLE_EPS_SQ = 1.0e-28

Referenced by trackball().

◆ DOUBLE_ONE

const double igl::DOUBLE_ONE = 1

◆ DOUBLE_ZERO

const double igl::DOUBLE_ZERO = 0

◆ EASTER_RED_DIFFUSE

const float igl::EASTER_RED_DIFFUSE[4] = {0.603922,0.494118f,0.603922f,1.0f}

◆ FAST_BLUE_DIFFUSE

const float igl::FAST_BLUE_DIFFUSE[4] = { 106.0f/255.0f, 106.0f/255.0f, 255.0f/255.0f, 1.0f}

◆ FAST_GRAY_DIFFUSE

const float igl::FAST_GRAY_DIFFUSE[4] = { 150.0f/255.0f, 150.0f/255.0f, 150.0f/255.0f, 1.0f}

◆ FAST_GREEN_DIFFUSE

const float igl::FAST_GREEN_DIFFUSE[4] = { 113.0f/255.0f, 239.0f/255.0f, 46.0f/255.0f, 1.0f}

◆ FAST_RED_DIFFUSE

const float igl::FAST_RED_DIFFUSE[4] = { 255.0f/255.0f, 65.0f/255.0f, 46.0f/255.0f, 1.0f}

◆ FLOAT_EPS

◆ FLOAT_EPS_SQ

const float igl::FLOAT_EPS_SQ = 1.0e-14f

◆ FLOAT_ONE

const float igl::FLOAT_ONE = 1

◆ FLOAT_ZERO

const float igl::FLOAT_ZERO = 0

◆ GOLD_AMBIENT

const float igl::GOLD_AMBIENT[4] = { 51.0/255.0, 43.0/255.0,33.3/255.0,1.0f }

◆ GOLD_DIFFUSE

const float igl::GOLD_DIFFUSE[4] = { 255.0/255.0,228.0/255.0,58.0/255.0,1.0f }

◆ GOLD_SPECULAR

const float igl::GOLD_SPECULAR[4] = { 255.0/255.0,235.0/255.0,80.0/255.0,1.0f }

◆ IDENTITY_QUAT_D

const double igl::IDENTITY_QUAT_D[4] = {0,0,0,1}

◆ IDENTITY_QUAT_F

const float igl::IDENTITY_QUAT_F[4] = {0,0,0,1}

◆ inferno_cm

double igl::inferno_cm[256][3]
static

Referenced by colormap().

◆ INT_ONE

const int igl::INT_ONE = 1

◆ INT_ZERO

const int igl::INT_ZERO = 0

◆ LADISLAV_ORANGE_DIFFUSE

const float igl::LADISLAV_ORANGE_DIFFUSE[4] = {1.0f, 125.0f / 255.0f, 19.0f / 255.0f, 0.0f}

◆ magma_cm

double igl::magma_cm[256][3]
static

Referenced by colormap().

◆ MIDNIGHT_BLUE_DIFFUSE

const float igl::MIDNIGHT_BLUE_DIFFUSE[4] = { 21.0f/255.0f, 27.0f/255.0f, 84.0f/255.0f, 1.0f}

◆ parula_cm

double igl::parula_cm[256][3]
static

Referenced by colormap().

◆ PI

◆ plasma_cm

double igl::plasma_cm[256][3]
static

Referenced by colormap().

◆ SILVER_AMBIENT

const float igl::SILVER_AMBIENT[4] = { 0.2f, 0.2f, 0.2f, 1.0f }

◆ SILVER_DIFFUSE

const float igl::SILVER_DIFFUSE[4] = { 1.0f, 1.0f, 1.0f, 1.0f }

◆ SILVER_SPECULAR

const float igl::SILVER_SPECULAR[4] = { 1.0f, 1.0f, 1.0f, 1.0f }

◆ UNSIGNED_INT_ONE

const unsigned int igl::UNSIGNED_INT_ONE = 1

◆ UNSIGNED_INT_ZERO

const unsigned int igl::UNSIGNED_INT_ZERO = 0

◆ viridis_cm

double igl::viridis_cm[256][3]
static

Referenced by colormap().

◆ WHITE

const float igl::WHITE[4] = { 255.0/255.0,255.0/255.0,255.0/255.0,1.0f }

◆ WHITE_AMBIENT

const float igl::WHITE_AMBIENT[4] = { 255.0/255.0,255.0/255.0,255.0/255.0,1.0f }

◆ WHITE_DIFFUSE

const float igl::WHITE_DIFFUSE[4] = { 255.0/255.0,255.0/255.0,255.0/255.0,1.0f }

◆ WHITE_SPECULAR

const float igl::WHITE_SPECULAR[4] = { 255.0/255.0,255.0/255.0,255.0/255.0,1.0f }

◆ WN_NON_MANIFOLD_EDGE_COLOR

const float igl::WN_NON_MANIFOLD_EDGE_COLOR[4] = {201./255., 51./255.,255./255.,1.0f}

◆ WN_OPEN_BOUNDARY_COLOR

const float igl::WN_OPEN_BOUNDARY_COLOR[4] = {154./255.,0./255.,0./255.,1.0f}

◆ XY_PLANE_QUAT_D

const double igl::XY_PLANE_QUAT_D[4] = {0,0,0,1}

◆ XY_PLANE_QUAT_F

const float igl::XY_PLANE_QUAT_F[4] = {0,0,0,1}

◆ XZ_PLANE_QUAT_D

const double igl::XZ_PLANE_QUAT_D[4] = {-SQRT_2_OVER_2,0,0,SQRT_2_OVER_2}

◆ XZ_PLANE_QUAT_F

const float igl::XZ_PLANE_QUAT_F[4] = {-SQRT_2_OVER_2,0,0,SQRT_2_OVER_2}

◆ YZ_PLANE_QUAT_D

const double igl::YZ_PLANE_QUAT_D[4] = {-0.5,-0.5,-0.5,0.5}

◆ YZ_PLANE_QUAT_F

const float igl::YZ_PLANE_QUAT_F[4] = {-0.5,-0.5,-0.5,0.5}