Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
igl::copyleft::cgal Namespace Reference

Namespaces

namespace  points_inside_component_helper
 

Classes

class  BinaryWindingNumberOperations
 
class  BinaryWindingNumberOperations< MESH_BOOLEAN_TYPE_INTERSECT >
 
class  BinaryWindingNumberOperations< MESH_BOOLEAN_TYPE_MINUS >
 
class  BinaryWindingNumberOperations< MESH_BOOLEAN_TYPE_RESOLVE >
 
class  BinaryWindingNumberOperations< MESH_BOOLEAN_TYPE_UNION >
 
class  BinaryWindingNumberOperations< MESH_BOOLEAN_TYPE_XOR >
 
class  CSGTree
 
struct  RemeshSelfIntersectionsParam
 
class  SelfIntersectMesh
 
class  WindingNumberFilter
 
class  WindingNumberFilter< KEEP_ALL >
 
class  WindingNumberFilter< KEEP_INSIDE >
 

Typedefs

typedef BinaryWindingNumberOperations< MESH_BOOLEAN_TYPE_UNIONBinaryUnion
 
typedef BinaryWindingNumberOperations< MESH_BOOLEAN_TYPE_INTERSECTBinaryIntersect
 
typedef BinaryWindingNumberOperations< MESH_BOOLEAN_TYPE_MINUSBinaryMinus
 
typedef BinaryWindingNumberOperations< MESH_BOOLEAN_TYPE_XORBinaryXor
 
typedef BinaryWindingNumberOperations< MESH_BOOLEAN_TYPE_RESOLVEBinaryResolve
 
typedef WindingNumberFilter< KEEP_INSIDEKeepInside
 
typedef WindingNumberFilter< KEEP_ALLKeepAll
 

Enumerations

enum  KeeperType { KEEP_INSIDE , KEEP_ALL }
 

Functions

template<typename DerivedC , typename DerivedD >
IGL_INLINE void assign (const Eigen::MatrixBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedD > &D)
 
template<typename ReturnScalar , typename DerivedC >
IGL_INLINE Eigen::Matrix< ReturnScalar, DerivedC::RowsAtCompileTime, DerivedC::ColsAtCompileTime, 1, DerivedC::MaxRowsAtCompileTime, DerivedC::MaxColsAtCompileTime > assign (const Eigen::MatrixBase< DerivedC > &C)
 
IGL_INLINE void assign_scalar (const CGAL::Epeck::FT &cgal, CGAL::Epeck::FT &d)
 
IGL_INLINE void assign_scalar (const CGAL::Epeck::FT &cgal, double &d)
 
IGL_INLINE void assign_scalar (const CGAL::Epeck::FT &cgal, float &d)
 
IGL_INLINE void assign_scalar (const double &c, double &d)
 
IGL_INLINE void assign_scalar (const float &c, float &d)
 
IGL_INLINE void assign_scalar (const float &c, double &d)
 
IGL_INLINE void assign_scalar (const CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT &cgal, CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT &d)
 
IGL_INLINE void assign_scalar (const CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT &cgal, double &d)
 
IGL_INLINE void assign_scalar (const CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT &cgal, float &d)
 
IGL_INLINE void assign_scalar (const CGAL::Simple_cartesian< mpq_class >::FT &cgal, CGAL::Simple_cartesian< mpq_class >::FT &d)
 
IGL_INLINE void assign_scalar (const CGAL::Simple_cartesian< mpq_class >::FT &cgal, double &d)
 
IGL_INLINE void assign_scalar (const CGAL::Simple_cartesian< mpq_class >::FT &cgal, float &d)
 
template<typename DerivedC >
IGL_INLINE void cell_adjacency (const Eigen::PlainObjectBase< DerivedC > &per_patch_cells, const size_t num_cells, std::vector< std::set< std::tuple< typename DerivedC::Scalar, bool, size_t > > > &adjacency_list)
 
template<typename DerivedV , typename DerivedF , typename DerivedI , typename DerivedP , typename uE2EType , typename DerivedEMAP , typename DerivedR , typename DerivedS >
IGL_INLINE void closest_facet (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedI > &I, const Eigen::PlainObjectBase< DerivedP > &P, const std::vector< std::vector< uE2EType > > &uE2E, const Eigen::PlainObjectBase< DerivedEMAP > &EMAP, Eigen::PlainObjectBase< DerivedR > &R, Eigen::PlainObjectBase< DerivedS > &S)
 
template<typename DerivedV , typename DerivedF , typename DerivedP , typename uE2EType , typename DerivedEMAP , typename DerivedR , typename DerivedS >
IGL_INLINE void closest_facet (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedP > &P, const std::vector< std::vector< uE2EType > > &uE2E, const Eigen::PlainObjectBase< DerivedEMAP > &EMAP, Eigen::PlainObjectBase< DerivedR > &R, Eigen::PlainObjectBase< DerivedS > &S)
 
template<typename DerivedV , typename DerivedF , typename DerivedI , typename DerivedP , typename uE2EType , typename DerivedEMAP , typename Kernel , typename DerivedR , typename DerivedS >
IGL_INLINE void closest_facet (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedI > &I, const Eigen::PlainObjectBase< DerivedP > &P, const std::vector< std::vector< uE2EType > > &uE2E, const Eigen::PlainObjectBase< DerivedEMAP > &EMAP, const std::vector< std::vector< size_t > > &VF, const std::vector< std::vector< size_t > > &VFi, const CGAL::AABB_tree< CGAL::AABB_traits< Kernel, CGAL::AABB_triangle_primitive< Kernel, typename std::vector< typename Kernel::Triangle_3 >::iterator > > > &tree, const std::vector< typename Kernel::Triangle_3 > &triangles, const std::vector< bool > &in_I, Eigen::PlainObjectBase< DerivedR > &R, Eigen::PlainObjectBase< DerivedS > &S)
 
template<typename Tr , typename DerivedV , typename DerivedF >
IGL_INLINE bool complex_to_mesh (const CGAL::Complex_2_in_triangulation_3< Tr > &c2t3, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename DerivedV , typename DerivedF , typename DerivedI >
IGL_INLINE bool component_inside_component (const Eigen::PlainObjectBase< DerivedV > &V1, const Eigen::PlainObjectBase< DerivedF > &F1, const Eigen::PlainObjectBase< DerivedI > &I1, const Eigen::PlainObjectBase< DerivedV > &V2, const Eigen::PlainObjectBase< DerivedF > &F2, const Eigen::PlainObjectBase< DerivedI > &I2)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE bool component_inside_component (const Eigen::PlainObjectBase< DerivedV > &V1, const Eigen::PlainObjectBase< DerivedF > &F1, const Eigen::PlainObjectBase< DerivedV > &V2, const Eigen::PlainObjectBase< DerivedF > &F2)
 
template<typename DerivedV , typename DerivedW , typename DerivedG >
IGL_INLINE void convex_hull (const Eigen::MatrixBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedW > &W, Eigen::PlainObjectBase< DerivedG > &G)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE void convex_hull (const Eigen::MatrixBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE void delaunay_triangulation (const Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename DerivedV , typename DerivedF , typename DerivedC >
IGL_INLINE size_t extract_cells (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedC > &cells)
 
template<typename DerivedV , typename DerivedF , typename DerivedP , typename DerivedE , typename DeriveduE , typename uE2EType , typename DerivedEMAP , typename DerivedC >
IGL_INLINE size_t extract_cells (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedE > &E, const Eigen::PlainObjectBase< DeriveduE > &uE, const std::vector< std::vector< uE2EType > > &uE2E, const Eigen::PlainObjectBase< DerivedEMAP > &EMAP, Eigen::PlainObjectBase< DerivedC > &cells)
 
template<typename DerivedV , typename DerivedF , typename DerivedP , typename DeriveduE , typename uE2EType , typename DerivedEMAP , typename DerivedC >
IGL_INLINE size_t extract_cells_single_component (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DeriveduE > &uE, const std::vector< std::vector< uE2EType > > &uE2E, const Eigen::PlainObjectBase< DerivedEMAP > &EMAP, Eigen::PlainObjectBase< DerivedC > &cells)
 
template<typename DerivedV , typename DerivedF , typename DerivedE >
IGL_INLINE void extract_feature (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const double tol, Eigen::PlainObjectBase< DerivedE > &feature_edges)
 
template<typename DerivedV , typename DerivedF , typename DerivedE >
IGL_INLINE void extract_feature (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const double tol, const Eigen::PlainObjectBase< DerivedE > &E, const Eigen::PlainObjectBase< DerivedE > &uE, const std::vector< std::vector< typename DerivedE::Scalar > > &uE2E, Eigen::PlainObjectBase< DerivedE > &feature_edges)
 
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 >
IGL_INLINE void half_space_box (const CGAL::Plane_3< CGAL::Epeck > &P, const Eigen::MatrixBase< DerivedV > &V, Eigen::Matrix< CGAL::Epeck::FT, 8, 3 > &BV, Eigen::Matrix< int, 12, 3 > &BF)
 
template<typename Derivedp , typename Derivedn , typename DerivedV >
IGL_INLINE void half_space_box (const Eigen::MatrixBase< Derivedp > &p, const Eigen::MatrixBase< Derivedn > &n, const Eigen::MatrixBase< DerivedV > &V, Eigen::Matrix< CGAL::Epeck::FT, 8, 3 > &BV, Eigen::Matrix< int, 12, 3 > &BF)
 
template<typename Derivedequ , typename DerivedV >
IGL_INLINE void half_space_box (const Eigen::MatrixBase< Derivedequ > &equ, const Eigen::MatrixBase< DerivedV > &V, Eigen::Matrix< CGAL::Epeck::FT, 8, 3 > &BV, Eigen::Matrix< int, 12, 3 > &BF)
 
template<typename DerivedV , typename Kernel , typename Scalar >
IGL_INLINE void hausdorff (const Eigen::MatrixBase< DerivedV > &V, const CGAL::AABB_tree< CGAL::AABB_traits< Kernel, CGAL::AABB_triangle_primitive< Kernel, typename std::vector< CGAL::Triangle_3< Kernel > >::iterator > > > &treeB, const std::vector< CGAL::Triangle_3< Kernel > > &TB, Scalar &l, Scalar &u)
 
template<typename Scalar >
IGL_INLINE short incircle (const Scalar pa[2], const Scalar pb[2], const Scalar pc[2], const Scalar pd[2])
 
template<typename Kernel >
IGL_INLINE void insert_into_cdt (const CGAL::Object &obj, const CGAL::Plane_3< Kernel > &P, CGAL::Constrained_triangulation_plus_2< CGAL::Constrained_Delaunay_triangulation_2< Kernel, CGAL::Triangulation_data_structure_2< CGAL::Triangulation_vertex_base_2< Kernel >, CGAL::Constrained_triangulation_face_base_2< Kernel > >, CGAL::Exact_intersections_tag > > &cdt)
 
template<typename Scalar >
IGL_INLINE short insphere (const Scalar pa[3], const Scalar pb[3], const Scalar pc[3], const Scalar pd[3], const Scalar pe[3])
 
template<typename DerivedF >
static IGL_INLINE void push_result (const Eigen::PlainObjectBase< DerivedF > &F, const int f, const int f_other, const CGAL::Object &result, std::map< typename DerivedF::Index, std::vector< std::pair< typename DerivedF::Index, CGAL::Object > > > &offending)
 
template<typename Kernel , typename DerivedVA , typename DerivedFA , typename DerivedVB , typename DerivedFB , typename DerivedIF , typename DerivedVVAB , typename DerivedFFAB , typename DerivedJAB , typename DerivedIMAB >
static IGL_INLINE bool intersect_other_helper (const Eigen::PlainObjectBase< DerivedVA > &VA, const Eigen::PlainObjectBase< DerivedFA > &FA, const Eigen::PlainObjectBase< DerivedVB > &VB, const Eigen::PlainObjectBase< DerivedFB > &FB, const RemeshSelfIntersectionsParam &params, Eigen::PlainObjectBase< DerivedIF > &IF, Eigen::PlainObjectBase< DerivedVVAB > &VVAB, Eigen::PlainObjectBase< DerivedFFAB > &FFAB, Eigen::PlainObjectBase< DerivedJAB > &JAB, Eigen::PlainObjectBase< DerivedIMAB > &IMAB)
 
template<typename DerivedVA , typename DerivedFA , typename DerivedVB , typename DerivedFB , typename DerivedIF , typename DerivedVVAB , typename DerivedFFAB , typename DerivedJAB , typename DerivedIMAB >
IGL_INLINE bool intersect_other (const Eigen::PlainObjectBase< DerivedVA > &VA, const Eigen::PlainObjectBase< DerivedFA > &FA, const Eigen::PlainObjectBase< DerivedVB > &VB, const Eigen::PlainObjectBase< DerivedFB > &FB, const RemeshSelfIntersectionsParam &params, Eigen::PlainObjectBase< DerivedIF > &IF, Eigen::PlainObjectBase< DerivedVVAB > &VVAB, Eigen::PlainObjectBase< DerivedFFAB > &FFAB, Eigen::PlainObjectBase< DerivedJAB > &JAB, Eigen::PlainObjectBase< DerivedIMAB > &IMAB)
 
IGL_INLINE bool intersect_other (const Eigen::MatrixXd &VA, const Eigen::MatrixXi &FA, const Eigen::MatrixXd &VB, const Eigen::MatrixXi &FB, const bool first_only, Eigen::MatrixXi &IF)
 
template<typename DerivedV , typename DerivedF , typename Derivedp , typename Derivedn , typename DerivedVC , typename DerivedFC , typename DerivedJ >
IGL_INLINE bool intersect_with_half_space (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< Derivedp > &p, const Eigen::MatrixBase< Derivedn > &n, Eigen::PlainObjectBase< DerivedVC > &VC, Eigen::PlainObjectBase< DerivedFC > &FC, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<typename DerivedV , typename DerivedF , typename Derivedequ , typename DerivedVC , typename DerivedFC , typename DerivedJ >
IGL_INLINE bool intersect_with_half_space (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< Derivedequ > &equ, Eigen::PlainObjectBase< DerivedVC > &VC, Eigen::PlainObjectBase< DerivedFC > &FC, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<typename DerivedV , typename DerivedF , typename DerivedVC , typename DerivedFC , typename DerivedJ >
IGL_INLINE bool intersect_with_half_space (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const CGAL::Plane_3< CGAL::Epeck > &P, Eigen::PlainObjectBase< DerivedVC > &VC, Eigen::PlainObjectBase< DerivedFC > &FC, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<typename DerivedP , typename DerivedF >
IGL_INLINE void lexicographic_triangulation (const Eigen::PlainObjectBase< DerivedP > &P, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename DerivedVA , typename DerivedFA , typename DerivedVB , typename DerivedFB , typename DerivedVC , typename DerivedFC , typename DerivedJ >
IGL_INLINE bool mesh_boolean (const Eigen::MatrixBase< DerivedVA > &VA, const Eigen::MatrixBase< DerivedFA > &FA, const Eigen::MatrixBase< DerivedVB > &VB, const Eigen::MatrixBase< DerivedFB > &FB, const MeshBooleanType &type, Eigen::PlainObjectBase< DerivedVC > &VC, Eigen::PlainObjectBase< DerivedFC > &FC, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<typename DerivedVA , typename DerivedFA , typename DerivedVB , typename DerivedFB , typename DerivedVC , typename DerivedFC , typename DerivedJ >
IGL_INLINE bool mesh_boolean (const Eigen::MatrixBase< DerivedVA > &VA, const Eigen::MatrixBase< DerivedFA > &FA, const Eigen::MatrixBase< DerivedVB > &VB, const Eigen::MatrixBase< DerivedFB > &FB, const std::string &type_str, Eigen::PlainObjectBase< DerivedVC > &VC, Eigen::PlainObjectBase< DerivedFC > &FC, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<typename DerivedVA , typename DerivedFA , typename DerivedVB , typename DerivedFB , typename DerivedVC , typename DerivedFC , typename DerivedJ >
IGL_INLINE bool mesh_boolean (const Eigen::MatrixBase< DerivedVA > &VA, const Eigen::MatrixBase< DerivedFA > &FA, const Eigen::MatrixBase< DerivedVB > &VB, const Eigen::MatrixBase< DerivedFB > &FB, const std::function< int(const Eigen::Matrix< int, 1, Eigen::Dynamic >) > &wind_num_op, const std::function< int(const int, const int)> &keep, Eigen::PlainObjectBase< DerivedVC > &VC, Eigen::PlainObjectBase< DerivedFC > &FC, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<typename DerivedV , typename DerivedF , typename DerivedVC , typename DerivedFC , typename DerivedJ >
IGL_INLINE bool mesh_boolean (const std::vector< DerivedV > &Vlist, const std::vector< DerivedF > &Flist, const std::function< int(const Eigen::Matrix< int, 1, Eigen::Dynamic >) > &wind_num_op, const std::function< int(const int, const int)> &keep, Eigen::PlainObjectBase< DerivedVC > &VC, Eigen::PlainObjectBase< DerivedFC > &FC, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<typename DerivedV , typename DerivedF , typename DerivedVC , typename DerivedFC , typename DerivedJ >
IGL_INLINE bool mesh_boolean (const std::vector< DerivedV > &Vlist, const std::vector< DerivedF > &Flist, const MeshBooleanType &type, Eigen::PlainObjectBase< DerivedVC > &VC, Eigen::PlainObjectBase< DerivedFC > &FC, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<typename DerivedVV , typename DerivedFF , typename Derivedsizes , typename DerivedVC , typename DerivedFC , typename DerivedJ >
IGL_INLINE bool mesh_boolean (const Eigen::MatrixBase< DerivedVV > &VV, const Eigen::MatrixBase< DerivedFF > &FF, const Eigen::MatrixBase< Derivedsizes > &sizes, const std::function< int(const Eigen::Matrix< int, 1, Eigen::Dynamic >) > &wind_num_op, const std::function< int(const int, const int)> &keep, Eigen::PlainObjectBase< DerivedVC > &VC, Eigen::PlainObjectBase< DerivedFC > &FC, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<typename DerivedVA , typename DerivedFA , typename DerivedVB , typename DerivedFB , typename DerivedVC , typename DerivedFC >
IGL_INLINE bool mesh_boolean (const Eigen::MatrixBase< DerivedVA > &VA, const Eigen::MatrixBase< DerivedFA > &FA, const Eigen::MatrixBase< DerivedVB > &VB, const Eigen::MatrixBase< DerivedFB > &FB, const MeshBooleanType &type, Eigen::PlainObjectBase< DerivedVC > &VC, Eigen::PlainObjectBase< DerivedFC > &FC)
 
IGL_INLINE void mesh_boolean_type_to_funcs (const MeshBooleanType &type, std::function< int(const Eigen::Matrix< int, 1, Eigen::Dynamic >) > &wind_num_op, std::function< int(const int, const int)> &keep)
 
template<typename DerivedV , typename DerivedF , typename Kernel >
IGL_INLINE void mesh_to_cgal_triangle_list (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, std::vector< CGAL::Triangle_3< Kernel > > &T)
 
template<typename Polyhedron >
IGL_INLINE bool mesh_to_polyhedron (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, Polyhedron &poly)
 
template<typename DerivedVA , typename DerivedFA , typename DerivedVB , typename DerivedFB , typename DerivedW , typename DerivedG , typename DerivedJ >
IGL_INLINE void minkowski_sum (const Eigen::MatrixBase< DerivedVA > &VA, const Eigen::MatrixBase< DerivedFA > &FA, const Eigen::MatrixBase< DerivedVB > &VB, const Eigen::MatrixBase< DerivedFB > &FB, const bool resolve_overlaps, Eigen::PlainObjectBase< DerivedW > &W, Eigen::PlainObjectBase< DerivedG > &G, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<typename DerivedVA , typename DerivedFA , typename sType , int sCols, int sOptions, typename dType , int dCols, int dOptions, typename DerivedW , typename DerivedG , typename DerivedJ >
IGL_INLINE void minkowski_sum (const Eigen::MatrixBase< DerivedVA > &VA, const Eigen::MatrixBase< DerivedFA > &FA, const Eigen::Matrix< sType, 1, sCols, sOptions > &s, const Eigen::Matrix< dType, 1, dCols, dOptions > &d, const bool resolve_overlaps, Eigen::PlainObjectBase< DerivedW > &W, Eigen::PlainObjectBase< DerivedG > &G, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<typename DerivedVA , typename DerivedFA , typename sType , int sCols, int sOptions, typename dType , int dCols, int dOptions, typename DerivedW , typename DerivedG , typename DerivedJ >
IGL_INLINE void minkowski_sum (const Eigen::MatrixBase< DerivedVA > &VA, const Eigen::MatrixBase< DerivedFA > &FA, const Eigen::Matrix< sType, 1, sCols, sOptions > &s, const Eigen::Matrix< dType, 1, dCols, dOptions > &d, Eigen::PlainObjectBase< DerivedW > &W, Eigen::PlainObjectBase< DerivedG > &G, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<typename DerivedV , typename DerivedF , typename DerivedI >
IGL_INLINE void order_facets_around_edge (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, size_t s, size_t d, const std::vector< int > &adj_faces, Eigen::PlainObjectBase< DerivedI > &order, bool debug=false)
 
template<typename DerivedV , typename DerivedF , typename DerivedI >
IGL_INLINE void order_facets_around_edge (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, size_t s, size_t d, const std::vector< int > &adj_faces, const Eigen::PlainObjectBase< DerivedV > &pivot_point, Eigen::PlainObjectBase< DerivedI > &order)
 
template<typename DerivedV , typename DerivedF , typename DerivedN , typename DeriveduE , typename uE2EType , typename uE2oEType , typename uE2CType >
IGL_INLINE std::enable_if<!std::is_same< typenameDerivedV::Scalar, typenameCGAL::Exact_predicates_exact_constructions_kernel::FT >::value, void >::type order_facets_around_edges (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedN > &N, const Eigen::PlainObjectBase< DeriveduE > &uE, const std::vector< std::vector< uE2EType > > &uE2E, std::vector< std::vector< uE2oEType > > &uE2oE, std::vector< std::vector< uE2CType > > &uE2C)
 
template<typename DerivedV , typename DerivedF , typename DerivedN , typename DeriveduE , typename uE2EType , typename uE2oEType , typename uE2CType >
IGL_INLINE std::enable_if< std::is_same< typenameDerivedV::Scalar, typenameCGAL::Exact_predicates_exact_constructions_kernel::FT >::value, void >::type order_facets_around_edges (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedN > &N, const Eigen::PlainObjectBase< DeriveduE > &uE, const std::vector< std::vector< uE2EType > > &uE2E, std::vector< std::vector< uE2oEType > > &uE2oE, std::vector< std::vector< uE2CType > > &uE2C)
 
template<typename DerivedV , typename DerivedF , typename DeriveduE , typename uE2EType , typename uE2oEType , typename uE2CType >
IGL_INLINE void order_facets_around_edges (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DeriveduE > &uE, const std::vector< std::vector< uE2EType > > &uE2E, std::vector< std::vector< uE2oEType > > &uE2oE, std::vector< std::vector< uE2CType > > &uE2C)
 
template<typename Scalar >
IGL_INLINE short orient2D (const Scalar pa[2], const Scalar pb[2], const Scalar pc[2])
 
template<typename Scalar >
IGL_INLINE short orient3D (const Scalar pa[3], const Scalar pb[3], const Scalar pc[3], const Scalar pd[3])
 
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 DerivedI , typename IndexType >
IGL_INLINE void outer_facet (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedI > &I, IndexType &f, bool &flipped)
 
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 DerivedV , typename DerivedF , typename DerivedHV , typename DerivedHF , typename DerivedJ , typename Derivedflip >
IGL_INLINE void outer_hull (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedHV > &HV, Eigen::PlainObjectBase< DerivedHF > &HF, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::PlainObjectBase< Derivedflip > &flip)
 
template<typename DerivedV , typename DerivedF , typename DerivedG , typename DerivedJ , typename Derivedflip >
IGL_INLINE void outer_hull_legacy (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedG > &G, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::PlainObjectBase< Derivedflip > &flip)
 
template<typename DerivedV , typename DerivedF , typename DerivedI , typename Derivedflip >
IGL_INLINE size_t peel_outer_hull_layers (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< Derivedflip > &flip)
 
template<typename DerivedV , typename DerivedF , typename DerivedW >
IGL_INLINE size_t peel_winding_number_layers (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedW > &W)
 
template<typename DerivedV , typename DerivedF >
IGL_INLINE bool piecewise_constant_winding_number (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename DerivedP , typename DerivedI , typename DerivedN , typename DerivedA >
IGL_INLINE void point_areas (const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedI > &I, const Eigen::MatrixBase< DerivedN > &N, Eigen::PlainObjectBase< DerivedA > &A)
 
template<typename DerivedP , typename DerivedI , typename DerivedN , typename DerivedA , typename DerivedT >
IGL_INLINE void point_areas (const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedI > &I, const Eigen::MatrixBase< DerivedN > &N, Eigen::PlainObjectBase< DerivedA > &A, Eigen::PlainObjectBase< DerivedT > &T)
 
template<typename Kernel , typename DerivedP , typename DerivedV , typename DerivedF , 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::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedsqrD > &sqrD, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedC > &C)
 
template<typename Kernel , typename DerivedV , typename DerivedF >
IGL_INLINE void point_mesh_squared_distance_precompute (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, CGAL::AABB_tree< CGAL::AABB_traits< Kernel, CGAL::AABB_triangle_primitive< Kernel, typename std::vector< CGAL::Triangle_3< Kernel > >::iterator > > > &tree, std::vector< CGAL::Triangle_3< Kernel > > &T)
 
template<typename Kernel , typename DerivedP , typename DerivedsqrD , typename DerivedI , typename DerivedC >
IGL_INLINE void point_mesh_squared_distance (const Eigen::PlainObjectBase< DerivedP > &P, const CGAL::AABB_tree< CGAL::AABB_traits< Kernel, CGAL::AABB_triangle_primitive< Kernel, typename std::vector< CGAL::Triangle_3< Kernel > >::iterator > > > &tree, const std::vector< CGAL::Triangle_3< Kernel > > &T, Eigen::PlainObjectBase< DerivedsqrD > &sqrD, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedC > &C)
 
template<typename Kernel >
IGL_INLINE void point_segment_squared_distance (const CGAL::Point_3< Kernel > &P1, const CGAL::Segment_3< Kernel > &S2, CGAL::Point_3< Kernel > &P2, typename Kernel::FT &d)
 
template<typename DerivedQ , typename DerivedVB , typename DerivedFB , typename DerivedD >
IGL_INLINE void point_solid_signed_squared_distance (const Eigen::PlainObjectBase< DerivedQ > &Q, const Eigen::PlainObjectBase< DerivedVB > &VB, const Eigen::PlainObjectBase< DerivedFB > &FB, Eigen::PlainObjectBase< DerivedD > &D)
 
template<typename Kernel >
IGL_INLINE void point_triangle_squared_distance (const CGAL::Point_3< Kernel > &P1, const CGAL::Triangle_3< Kernel > &T2, CGAL::Point_3< Kernel > &P2, typename Kernel::FT &d)
 
template<typename DerivedV , typename DerivedF , typename DerivedI , typename DerivedP , typename DerivedB >
IGL_INLINE void points_inside_component (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedI > &I, const Eigen::PlainObjectBase< DerivedP > &P, Eigen::PlainObjectBase< DerivedB > &inside)
 
template<typename DerivedV , typename DerivedF , typename DerivedP , typename DerivedB >
IGL_INLINE void points_inside_component (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedP > &P, Eigen::PlainObjectBase< DerivedB > &inside)
 
template<typename Polyhedron , typename DerivedV , typename DerivedF >
IGL_INLINE void polyhedron_to_mesh (const Polyhedron &poly, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename Kernel , typename Index >
IGL_INLINE void projected_cdt (const std::vector< CGAL::Object > &objects, const CGAL::Plane_3< Kernel > &P, std::vector< CGAL::Point_3< Kernel > > &vertices, std::vector< std::vector< Index > > &faces)
 
template<typename Kernel , typename DerivedV , typename DerivedF >
IGL_INLINE void projected_cdt (const std::vector< CGAL::Object > &objects, const CGAL::Plane_3< Kernel > &P, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F)
 
template<typename Kernel >
IGL_INLINE void projected_delaunay (const CGAL::Triangle_3< Kernel > &A, const std::vector< CGAL::Object > &A_objects_3, CGAL::Constrained_triangulation_plus_2< CGAL::Constrained_Delaunay_triangulation_2< Kernel, CGAL::Triangulation_data_structure_2< CGAL::Triangulation_vertex_base_2< Kernel >, CGAL::Constrained_triangulation_face_base_2< Kernel > >, CGAL::Exact_intersections_tag > > &cdt)
 
template<typename DerivedV , typename DerivedF , typename DerivedL , typename DerivedW >
IGL_INLINE bool propagate_winding_numbers (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedL > &labels, Eigen::PlainObjectBase< DerivedW > &W)
 
template<typename DerivedV , typename DerivedF , typename DeriveduE , typename uE2EType , typename DerivedP , typename DerivedC , typename DerivedL , typename DerivedW >
IGL_INLINE bool propagate_winding_numbers (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DeriveduE > &uE, const std::vector< std::vector< uE2EType > > &uE2E, const size_t num_patches, const Eigen::PlainObjectBase< DerivedP > &P, const size_t num_cells, const Eigen::PlainObjectBase< DerivedC > &C, const Eigen::PlainObjectBase< DerivedL > &labels, Eigen::PlainObjectBase< DerivedW > &W)
 
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 , typename DerivedP , typename DerivedC , typename FT , typename DerivedW >
IGL_INLINE void relabel_small_immersed_cells (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const size_t num_patches, const Eigen::PlainObjectBase< DerivedP > &P, const size_t num_cells, const Eigen::PlainObjectBase< DerivedC > &C, const FT vol_threashold, Eigen::PlainObjectBase< DerivedW > &W)
 
template<typename DerivedV , typename DerivedF , typename Kernel , typename DerivedVV , typename DerivedFF , typename DerivedJ , typename DerivedIM >
IGL_INLINE void remesh_intersections (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const std::vector< CGAL::Triangle_3< Kernel > > &T, const std::map< typename DerivedF::Index, std::vector< std::pair< typename DerivedF::Index, CGAL::Object > > > &offending, bool stitch_all, Eigen::PlainObjectBase< DerivedVV > &VV, Eigen::PlainObjectBase< DerivedFF > &FF, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::PlainObjectBase< DerivedIM > &IM)
 
template<typename DerivedV , typename DerivedF , typename Kernel , typename DerivedVV , typename DerivedFF , typename DerivedJ , typename DerivedIM >
IGL_INLINE void remesh_intersections (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const std::vector< CGAL::Triangle_3< Kernel > > &T, const std::map< typename DerivedF::Index, std::vector< std::pair< typename DerivedF::Index, CGAL::Object > > > &offending, Eigen::PlainObjectBase< DerivedVV > &VV, Eigen::PlainObjectBase< DerivedFF > &FF, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::PlainObjectBase< DerivedIM > &IM)
 
template<typename DerivedV , typename DerivedF , typename DerivedVV , typename DerivedFF , typename DerivedIF , typename DerivedJ , typename DerivedIM >
IGL_INLINE void remesh_self_intersections (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const RemeshSelfIntersectionsParam &params, Eigen::PlainObjectBase< DerivedVV > &VV, Eigen::PlainObjectBase< DerivedFF > &FF, Eigen::PlainObjectBase< DerivedIF > &IF, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::PlainObjectBase< DerivedIM > &IM)
 
template<typename DerivedV , typename DerivedE , typename DerivedVI , typename DerivedEI , typename DerivedJ , typename DerivedIM >
IGL_INLINE void resolve_intersections (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedVI > &VI, Eigen::PlainObjectBase< DerivedEI > &EI, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::PlainObjectBase< DerivedIM > &IM)
 
template<typename Kernel , typename DerivedV >
IGL_INLINE CGAL::Point_2< Kernelrow_to_point (const Eigen::PlainObjectBase< DerivedV > &V, const typename DerivedV::Index &i)
 
template<typename Kernel >
IGL_INLINE bool segment_segment_squared_distance (const CGAL::Segment_3< Kernel > &S1, const CGAL::Segment_3< Kernel > &S2, CGAL::Point_3< Kernel > &P1, CGAL::Point_3< Kernel > &P2, typename Kernel::FT &d)
 
IGL_INLINE bool signed_distance_isosurface (const Eigen::MatrixXd &IV, const Eigen::MatrixXi &IF, const double level, const double angle_bound, const double radius_bound, const double distance_bound, const SignedDistanceType sign_type, Eigen::MatrixXd &V, Eigen::MatrixXi &F)
 
template<typename DerivedV , typename DerivedE , typename DerivedVI , typename DerivedEI , typename DerivedJ >
IGL_INLINE void snap_rounding (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedVI > &VI, Eigen::PlainObjectBase< DerivedEI > &EI, Eigen::PlainObjectBase< DerivedJ > &J)
 
IGL_INLINE bool string_to_mesh_boolean_type (const std::string &s, MeshBooleanType &type)
 
IGL_INLINE MeshBooleanType string_to_mesh_boolean_type (const std::string &s)
 
template<typename DerivedV , typename DerivedE , typename Kernel , typename DerivedVI , typename DerivedEI , typename DerivedJ , typename DerivedIM >
IGL_INLINE void subdivide_segments (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedE > &E, const std::vector< std::vector< CGAL::Point_2< Kernel > > > &steiner, Eigen::PlainObjectBase< DerivedVI > &VI, Eigen::PlainObjectBase< DerivedEI > &EI, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::PlainObjectBase< DerivedIM > &IM)
 
template<typename DerivedV , typename DerivedF , typename DerivedI , typename Kernel >
IGL_INLINE void submesh_aabb_tree (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedI > &I, CGAL::AABB_tree< CGAL::AABB_traits< Kernel, CGAL::AABB_triangle_primitive< Kernel, typename std::vector< typename Kernel::Triangle_3 >::iterator > > > &tree, std::vector< typename Kernel::Triangle_3 > &triangles, std::vector< bool > &in_I)
 
template<typename Kernel >
IGL_INLINE bool triangle_triangle_squared_distance (const CGAL::Triangle_3< Kernel > &T1, const CGAL::Triangle_3< Kernel > &T2, CGAL::Point_3< Kernel > &P1, CGAL::Point_3< Kernel > &P2, typename Kernel::FT &d)
 
template<typename DerivedVA , typename DerivedFA , typename DerivedVB , typename DerivedFB , typename DerivedV , typename DerivedF , typename DerivedD , typename DerivedJ >
IGL_INLINE void trim_with_solid (const Eigen::PlainObjectBase< DerivedVA > &VA, const Eigen::PlainObjectBase< DerivedFA > &FA, const Eigen::PlainObjectBase< DerivedVB > &VB, const Eigen::PlainObjectBase< DerivedFB > &FB, Eigen::PlainObjectBase< DerivedV > &Vd, Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedD > &D, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<typename DerivedWV , typename DerivedWE , typename DerivedV , typename DerivedF , typename DerivedJ >
IGL_INLINE void wire_mesh (const Eigen::MatrixBase< DerivedWV > &WV, const Eigen::MatrixBase< DerivedWE > &WE, const double th, const int poly_size, const bool solid, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedJ > &J)
 
template<typename DerivedWV , typename DerivedWE , typename DerivedV , typename DerivedF , typename DerivedJ >
IGL_INLINE void wire_mesh (const Eigen::MatrixBase< DerivedWV > &WV, const Eigen::MatrixBase< DerivedWE > &WE, const double th, const int poly_size, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedJ > &J)
 

Typedef Documentation

◆ BinaryIntersect

◆ BinaryMinus

◆ BinaryResolve

◆ BinaryUnion

◆ BinaryXor

◆ KeepAll

◆ KeepInside

Enumeration Type Documentation

◆ KeeperType

Enumerator
KEEP_INSIDE 
KEEP_ALL 
126 {
129 };
@ KEEP_ALL
Definition BinaryWindingNumberOperations.h:128
@ KEEP_INSIDE
Definition BinaryWindingNumberOperations.h:127

Function Documentation

◆ assign() [1/2]

template<typename ReturnScalar , typename DerivedC >
IGL_INLINE Eigen::Matrix< ReturnScalar, DerivedC::RowsAtCompileTime, DerivedC::ColsAtCompileTime, 1, DerivedC::MaxRowsAtCompileTime, DerivedC::MaxColsAtCompileTime > igl::copyleft::cgal::assign ( const Eigen::MatrixBase< DerivedC > &  C)
37{
39 ReturnScalar,
40 DerivedC::RowsAtCompileTime,
41 DerivedC::ColsAtCompileTime,
42 1,
43 DerivedC::MaxRowsAtCompileTime,
44 DerivedC::MaxColsAtCompileTime> D;
45 assign(C,D);
46 return D;
47}
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:180
IGL_INLINE void assign(const Eigen::MatrixBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedD > &D)
Definition assign.cpp:12

References assign().

+ Here is the call graph for this function:

◆ assign() [2/2]

template<typename DerivedC , typename DerivedD >
IGL_INLINE void igl::copyleft::cgal::assign ( const Eigen::MatrixBase< DerivedC > &  C,
Eigen::PlainObjectBase< DerivedD > &  D 
)
15{
16 D.resizeLike(C);
17 for(int i = 0;i<C.rows();i++)
18 {
19 for(int j = 0;j<C.cols();j++)
20 {
21 assign_scalar(C(i,j),D(i,j));
22 }
23 }
24}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resizeLike(const EigenBase< OtherDerived > &_other)
Definition PlainObjectBase.h:362
IGL_INLINE void assign_scalar(const CGAL::Epeck::FT &cgal, CGAL::Epeck::FT &d)
Definition assign_scalar.cpp:10

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

Referenced by assign(), mesh_to_cgal_triangle_list(), outer_hull(), propagate_winding_numbers(), read_triangle_mesh(), relabel_small_immersed_cells(), and trim_with_solid().

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

◆ assign_scalar() [1/12]

IGL_INLINE void igl::copyleft::cgal::assign_scalar ( const CGAL::Epeck::FT &  cgal,
CGAL::Epeck::FT &  d 
)
13{
14 d = cgal;
15}

Referenced by assign(), igl::copyleft::cgal::points_inside_component_helper::determine_point_edge_orientation(), half_space_box(), point_mesh_squared_distance(), projected_cdt(), remesh_intersections(), and subdivide_segments().

+ Here is the caller graph for this function:

◆ assign_scalar() [2/12]

IGL_INLINE void igl::copyleft::cgal::assign_scalar ( const CGAL::Epeck::FT &  cgal,
double &  d 
)
20{
21 // FORCE evaluation of the exact type otherwise interval might be huge.
22 const CGAL::Epeck::FT cgal = _cgal.exact();
23 const auto interval = CGAL::to_interval(cgal);
24 d = interval.first;
25 do {
26 const double next = nextafter(d, interval.second);
27 if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
28 d = next;
29 } while (d < interval.second);
30}

◆ assign_scalar() [3/12]

IGL_INLINE void igl::copyleft::cgal::assign_scalar ( const CGAL::Epeck::FT &  cgal,
float &  d 
)
35{
36 // FORCE evaluation of the exact type otherwise interval might be huge.
37 const CGAL::Epeck::FT cgal = _cgal.exact();
38 const auto interval = CGAL::to_interval(cgal);
39 d = interval.first;
40 do {
41 const float next = nextafter(d, float(interval.second));
42 if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
43 d = next;
44 } while (d < float(interval.second));
45}

◆ assign_scalar() [4/12]

IGL_INLINE void igl::copyleft::cgal::assign_scalar ( const CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT &  cgal,
CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT &  d 
)
71{
72 d = cgal;
73}

◆ assign_scalar() [5/12]

IGL_INLINE void igl::copyleft::cgal::assign_scalar ( const CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT &  cgal,
double &  d 
)
78{
79 const auto interval = CGAL::to_interval(cgal);
80 d = interval.first;
81 do {
82 const double next = nextafter(d, interval.second);
83 if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
84 d = next;
85 } while (d < interval.second);
86}

◆ assign_scalar() [6/12]

IGL_INLINE void igl::copyleft::cgal::assign_scalar ( const CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT &  cgal,
float &  d 
)
91{
92 const auto interval = CGAL::to_interval(cgal);
93 d = interval.first;
94 do {
95 const float next = nextafter(d, float(interval.second));
96 if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
97 d = next;
98 } while (d < float(interval.second));
99}

◆ assign_scalar() [7/12]

IGL_INLINE void igl::copyleft::cgal::assign_scalar ( const CGAL::Simple_cartesian< mpq_class >::FT &  cgal,
CGAL::Simple_cartesian< mpq_class >::FT &  d 
)
106{
107 d = cgal;
108}

◆ assign_scalar() [8/12]

IGL_INLINE void igl::copyleft::cgal::assign_scalar ( const CGAL::Simple_cartesian< mpq_class >::FT &  cgal,
double &  d 
)
113{
114 const auto interval = CGAL::to_interval(cgal);
115 d = interval.first;
116 do {
117 const double next = nextafter(d, interval.second);
118 if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
119 d = next;
120 } while (d < interval.second);
121}

◆ assign_scalar() [9/12]

IGL_INLINE void igl::copyleft::cgal::assign_scalar ( const CGAL::Simple_cartesian< mpq_class >::FT &  cgal,
float &  d 
)
126{
127 const auto interval = CGAL::to_interval(cgal);
128 d = interval.first;
129 do {
130 const float next = nextafter(d, float(interval.second));
131 if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
132 d = next;
133 } while (d < float(interval.second));
134}

◆ assign_scalar() [10/12]

IGL_INLINE void igl::copyleft::cgal::assign_scalar ( const double &  c,
double &  d 
)
50{
51 d = c;
52}

◆ assign_scalar() [11/12]

IGL_INLINE void igl::copyleft::cgal::assign_scalar ( const float &  c,
double &  d 
)
64{
65 d = c;
66}

◆ assign_scalar() [12/12]

IGL_INLINE void igl::copyleft::cgal::assign_scalar ( const float &  c,
float &  d 
)
57{
58 d = c;
59}

◆ cell_adjacency()

template<typename DerivedC >
IGL_INLINE void igl::copyleft::cgal::cell_adjacency ( const Eigen::PlainObjectBase< DerivedC > &  per_patch_cells,
const size_t  num_cells,
std::vector< std::set< std::tuple< typename DerivedC::Scalar, bool, size_t > > > &  adjacency_list 
)
17 {
18
19 const size_t num_patches = per_patch_cells.rows();
20 adjacency_list.resize(num_cells);
21 for (size_t i=0; i<num_patches; i++) {
22 const int positive_cell = per_patch_cells(i,0);
23 const int negative_cell = per_patch_cells(i,1);
24 adjacency_list[positive_cell].emplace(negative_cell, false, i);
25 adjacency_list[negative_cell].emplace(positive_cell, true, i);
26 }
27}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index rows() const
Definition PlainObjectBase.h:151
IGL_INLINE void adjacency_list(const Eigen::PlainObjectBase< Index > &F, std::vector< std::vector< IndexVector > > &A, bool sorted=false)
Definition adjacency_list.cpp:14

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

Referenced by propagate_winding_numbers(), and relabel_small_immersed_cells().

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

◆ closest_facet() [1/3]

template<typename DerivedV , typename DerivedF , typename DerivedI , typename DerivedP , typename uE2EType , typename DerivedEMAP , typename Kernel , typename DerivedR , typename DerivedS >
IGL_INLINE void igl::copyleft::cgal::closest_facet ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedI > &  I,
const Eigen::PlainObjectBase< DerivedP > &  P,
const std::vector< std::vector< uE2EType > > &  uE2E,
const Eigen::PlainObjectBase< DerivedEMAP > &  EMAP,
const std::vector< std::vector< size_t > > &  VF,
const std::vector< std::vector< size_t > > &  VFi,
const CGAL::AABB_tree< CGAL::AABB_traits< Kernel, CGAL::AABB_triangle_primitive< Kernel, typename std::vector< typename Kernel::Triangle_3 >::iterator > > > &  tree,
const std::vector< typename Kernel::Triangle_3 > &  triangles,
const std::vector< bool > &  in_I,
Eigen::PlainObjectBase< DerivedR > &  R,
Eigen::PlainObjectBase< DerivedS > &  S 
)
96{
97 typedef typename Kernel::Point_3 Point_3;
98 typedef typename Kernel::Plane_3 Plane_3;
99 typedef typename Kernel::Segment_3 Segment_3;
100 typedef typename Kernel::Triangle_3 Triangle;
101 typedef typename std::vector<Triangle>::iterator Iterator;
102 typedef typename CGAL::AABB_triangle_primitive<Kernel, Iterator> Primitive;
103 typedef typename CGAL::AABB_traits<Kernel, Primitive> AABB_triangle_traits;
104 typedef typename CGAL::AABB_tree<AABB_triangle_traits> Tree;
105
106 const size_t num_faces = I.rows();
107 if (F.rows() <= 0 || I.rows() <= 0) {
108 throw std::runtime_error(
109 "Closest facet cannot be computed on empty mesh.");
110 }
111
112 auto on_the_positive_side = [&](size_t fid, const Point_3& p) -> bool
113 {
114 const auto& f = F.row(fid).eval();
115 Point_3 v0(V(f[0], 0), V(f[0], 1), V(f[0], 2));
116 Point_3 v1(V(f[1], 0), V(f[1], 1), V(f[1], 2));
117 Point_3 v2(V(f[2], 0), V(f[2], 1), V(f[2], 2));
118 auto ori = CGAL::orientation(v0, v1, v2, p);
119 switch (ori) {
120 case CGAL::POSITIVE:
121 return true;
122 case CGAL::NEGATIVE:
123 return false;
124 case CGAL::COPLANAR:
125 // Warning:
126 // This can only happen if fid contains a boundary edge.
127 // Categorized this ambiguous case as negative side.
128 return false;
129 default:
130 throw std::runtime_error("Unknown CGAL state.");
131 }
132 return false;
133 };
134
135 auto get_orientation = [&](size_t fid, size_t s, size_t d) -> bool
136 {
137 const auto& f = F.row(fid);
138 if ((size_t)f[0] == s && (size_t)f[1] == d) return false;
139 else if ((size_t)f[1] == s && (size_t)f[2] == d) return false;
140 else if ((size_t)f[2] == s && (size_t)f[0] == d) return false;
141 else if ((size_t)f[0] == d && (size_t)f[1] == s) return true;
142 else if ((size_t)f[1] == d && (size_t)f[2] == s) return true;
143 else if ((size_t)f[2] == d && (size_t)f[0] == s) return true;
144 else {
145 throw std::runtime_error(
146 "Cannot compute orientation due to incorrect connectivity");
147 return false;
148 }
149 };
150 auto index_to_signed_index = [&](size_t index, bool ori) -> int{
151 return (index+1) * (ori? 1:-1);
152 };
153 //auto signed_index_to_index = [&](int signed_index) -> size_t {
154 // return abs(signed_index) - 1;
155 //};
156
157 enum ElementType { VERTEX, EDGE, FACE };
158 auto determine_element_type = [&](const Point_3& p, const size_t fid,
159 size_t& element_index) -> ElementType {
160 const auto& tri = triangles[fid];
161 const Point_3 p0 = tri[0];
162 const Point_3 p1 = tri[1];
163 const Point_3 p2 = tri[2];
164
165 if (p == p0) { element_index = 0; return VERTEX; }
166 if (p == p1) { element_index = 1; return VERTEX; }
167 if (p == p2) { element_index = 2; return VERTEX; }
168 if (CGAL::collinear(p0, p1, p)) { element_index = 2; return EDGE; }
169 if (CGAL::collinear(p1, p2, p)) { element_index = 0; return EDGE; }
170 if (CGAL::collinear(p2, p0, p)) { element_index = 1; return EDGE; }
171
172 element_index = 0;
173 return FACE;
174 };
175
176 auto process_edge_case = [&](
177 size_t query_idx,
178 const size_t s, const size_t d,
179 size_t preferred_facet,
180 bool& orientation) -> size_t
181 {
182 Point_3 query_point(
183 P(query_idx, 0),
184 P(query_idx, 1),
185 P(query_idx, 2));
186
187 size_t corner_idx = std::numeric_limits<size_t>::max();
188 if ((s == F(preferred_facet, 0) && d == F(preferred_facet, 1)) ||
189 (s == F(preferred_facet, 1) && d == F(preferred_facet, 0)))
190 {
191 corner_idx = 2;
192 } else if ((s == F(preferred_facet, 0) && d == F(preferred_facet, 2)) ||
193 (s == F(preferred_facet, 2) && d == F(preferred_facet, 0)))
194 {
195 corner_idx = 1;
196 } else if ((s == F(preferred_facet, 1) && d == F(preferred_facet, 2)) ||
197 (s == F(preferred_facet, 2) && d == F(preferred_facet, 1)))
198 {
199 corner_idx = 0;
200 } else
201 {
202 std::cerr << "s: " << s << "\t d:" << d << std::endl;
203 std::cerr << F.row(preferred_facet) << std::endl;
204 throw std::runtime_error(
205 "Invalid connectivity, edge does not belong to facet");
206 }
207
208 auto ueid = EMAP(preferred_facet + corner_idx * F.rows());
209 auto eids = uE2E[ueid];
210 std::vector<size_t> intersected_face_indices;
211 for (auto eid : eids)
212 {
213 const size_t fid = eid % F.rows();
214 if (in_I[fid])
215 {
216 intersected_face_indices.push_back(fid);
217 }
218 }
219
220 const size_t num_intersected_faces = intersected_face_indices.size();
221 std::vector<int> intersected_face_signed_indices(num_intersected_faces);
222 std::transform(
223 intersected_face_indices.begin(),
224 intersected_face_indices.end(),
225 intersected_face_signed_indices.begin(),
226 [&](size_t index) {
227 return index_to_signed_index(
228 index, get_orientation(index, s,d));
229 });
230
231 assert(num_intersected_faces >= 1);
232 if (num_intersected_faces == 1)
233 {
234 // The edge must be a boundary edge. Thus, the orientation can be
235 // simply determined by checking if the query point is on the
236 // positive side of the facet.
237 const size_t fid = intersected_face_indices[0];
238 orientation = on_the_positive_side(fid, query_point);
239 return fid;
240 }
241
242 Eigen::VectorXi order;
243 DerivedP pivot = P.row(query_idx).eval();
245 intersected_face_signed_indices,
246 pivot, order);
247
248 // Although first and last are equivalent, make the choice based on
249 // preferred_facet.
250 const size_t first = order[0];
251 const size_t last = order[num_intersected_faces-1];
252 if (intersected_face_indices[first] == preferred_facet) {
253 orientation = intersected_face_signed_indices[first] < 0;
254 return intersected_face_indices[first];
255 } else if (intersected_face_indices[last] == preferred_facet) {
256 orientation = intersected_face_signed_indices[last] > 0;
257 return intersected_face_indices[last];
258 } else {
259 orientation = intersected_face_signed_indices[order[0]] < 0;
260 return intersected_face_indices[order[0]];
261 }
262 };
263
264 auto process_face_case = [&](
265 const size_t query_idx, const Point_3& closest_point,
266 const size_t fid, bool& orientation) -> size_t {
267 const auto& f = F.row(I(fid, 0));
268 return process_edge_case(query_idx, f[0], f[1], I(fid, 0), orientation);
269 };
270
271 // Given that the closest point to query point P(query_idx,:) on (V,F(I,:))
272 // is the vertex at V(s,:) which is incident at least on triangle
273 // F(preferred_facet,:), determine a facet incident on V(s,:) that is
274 // _exposed_ to the query point and determine whether that facet is facing
275 // _toward_ or _away_ from the query point.
276 //
277 // Inputs:
278 // query_idx index into P of query point
279 // s index into V of closest point at vertex
280 // preferred_facet facet incident on s
281 // Outputs:
282 // orientation whether returned face is facing toward or away from
283 // query (parity unclear)
284 // Returns face guaranteed to be "exposed" to P(query_idx,:)
285 auto process_vertex_case = [&](
286 const size_t query_idx,
287 size_t s,
288 size_t preferred_facet,
289 bool& orientation) -> size_t
290 {
291 const Point_3 query_point(
292 P(query_idx, 0), P(query_idx, 1), P(query_idx, 2));
293 const Point_3 closest_point(V(s, 0), V(s, 1), V(s, 2));
294 std::vector<size_t> adj_faces;
295 std::vector<size_t> adj_face_corners;
296 {
297 // Gather adj faces to s within I.
298 const auto& all_adj_faces = VF[s];
299 const auto& all_adj_face_corners = VFi[s];
300 const size_t num_all_adj_faces = all_adj_faces.size();
301 for (size_t i=0; i<num_all_adj_faces; i++)
302 {
303 const size_t fid = all_adj_faces[i];
304 // Shouldn't this always be true if I is a full connected component?
305 if (in_I[fid])
306 {
307 adj_faces.push_back(fid);
308 adj_face_corners.push_back(all_adj_face_corners[i]);
309 }
310 }
311 }
312 const size_t num_adj_faces = adj_faces.size();
313 assert(num_adj_faces > 0);
314
315 std::set<size_t> adj_vertices_set;
316 std::unordered_multimap<size_t, size_t> v2f;
317 for (size_t i=0; i<num_adj_faces; i++)
318 {
319 const size_t fid = adj_faces[i];
320 const size_t cid = adj_face_corners[i];
321 const auto& f = F.row(adj_faces[i]);
322 const size_t next = f[(cid+1)%3];
323 const size_t prev = f[(cid+2)%3];
324 adj_vertices_set.insert(next);
325 adj_vertices_set.insert(prev);
326 v2f.insert({{next, fid}, {prev, fid}});
327 }
328 const size_t num_adj_vertices = adj_vertices_set.size();
329 std::vector<size_t> adj_vertices(num_adj_vertices);
330 std::copy(adj_vertices_set.begin(), adj_vertices_set.end(),
331 adj_vertices.begin());
332
333 std::vector<Point_3> adj_points;
334 for (size_t vid : adj_vertices)
335 {
336 adj_points.emplace_back(V(vid,0), V(vid,1), V(vid,2));
337 }
338
339 // A plane is on the exterior if all adj_points lies on or to
340 // one side of the plane.
341 auto is_on_exterior = [&](const Plane_3& separator) -> bool{
342 size_t positive=0;
343 size_t negative=0;
344 size_t coplanar=0;
345 for (const auto& point : adj_points) {
346 switch(separator.oriented_side(point)) {
347 case CGAL::ON_POSITIVE_SIDE:
348 positive++;
349 break;
350 case CGAL::ON_NEGATIVE_SIDE:
351 negative++;
352 break;
353 case CGAL::ON_ORIENTED_BOUNDARY:
354 coplanar++;
355 break;
356 default:
357 throw "Unknown plane-point orientation";
358 }
359 }
360 auto query_orientation = separator.oriented_side(query_point);
361 if (query_orientation == CGAL::ON_ORIENTED_BOUNDARY &&
362 (positive == 0 && negative == 0)) {
363 // All adj vertices and query point are coplanar.
364 // In this case, all separators are equally valid.
365 return true;
366 } else {
367 bool r = (positive == 0 && query_orientation == CGAL::POSITIVE)
368 || (negative == 0 && query_orientation == CGAL::NEGATIVE);
369 return r;
370 }
371 };
372
373 size_t d = std::numeric_limits<size_t>::max();
374 for (size_t i=0; i<num_adj_vertices; i++) {
375 const size_t vi = adj_vertices[i];
376 for (size_t j=i+1; j<num_adj_vertices; j++) {
377 Plane_3 separator(closest_point, adj_points[i], adj_points[j]);
378 if (separator.is_degenerate()) {
379 continue;
380 }
381 if (is_on_exterior(separator)) {
382 if (!CGAL::collinear(
383 query_point, adj_points[i], closest_point)) {
384 d = vi;
385 break;
386 } else {
387 d = adj_vertices[j];
388 assert(!CGAL::collinear(
389 query_point, adj_points[j], closest_point));
390 break;
391 }
392 }
393 }
394 }
395 if (d == std::numeric_limits<size_t>::max()) {
396 Eigen::MatrixXd tmp_vertices(V.rows(), V.cols());
397 for (size_t i=0; i<V.rows(); i++) {
398 for (size_t j=0; j<V.cols(); j++) {
399 tmp_vertices(i,j) = CGAL::to_double(V(i,j));
400 }
401 }
402 Eigen::MatrixXi tmp_faces(adj_faces.size(), 3);
403 for (size_t i=0; i<adj_faces.size(); i++) {
404 tmp_faces.row(i) = F.row(adj_faces[i]);
405 }
406 //igl::writePLY("debug.ply", tmp_vertices, tmp_faces, false);
407 throw std::runtime_error("Invalid vertex neighborhood");
408 }
409 const auto itr = v2f.equal_range(d);
410 assert(itr.first != itr.second);
411
412 return process_edge_case(query_idx, s, d, itr.first->second, orientation);
413 };
414
415 const size_t num_queries = P.rows();
416 R.resize(num_queries, 1);
417 S.resize(num_queries, 1);
418 for (size_t i=0; i<num_queries; i++) {
419 const Point_3 query(P(i,0), P(i,1), P(i,2));
420 auto projection = tree.closest_point_and_primitive(query);
421 const Point_3 closest_point = projection.first;
422 size_t fid = projection.second - triangles.begin();
423 bool fid_ori = false;
424
425 // Gether all facets sharing the closest point.
426 typename std::vector<typename Tree::Primitive_id> intersected_faces;
427 tree.all_intersected_primitives(Segment_3(closest_point, query),
428 std::back_inserter(intersected_faces));
429 const size_t num_intersected_faces = intersected_faces.size();
430 std::vector<size_t> intersected_face_indices(num_intersected_faces);
431 std::transform(intersected_faces.begin(),
432 intersected_faces.end(),
433 intersected_face_indices.begin(),
434 [&](const typename Tree::Primitive_id& itr) -> size_t
435 { return I(itr-triangles.begin(), 0); });
436
437 size_t element_index;
438 auto element_type = determine_element_type(closest_point, fid,
439 element_index);
440 switch(element_type) {
441 case VERTEX:
442 {
443 const auto& f = F.row(I(fid, 0));
444 const size_t s = f[element_index];
445 fid = process_vertex_case(i, s, I(fid, 0), fid_ori);
446 }
447 break;
448 case EDGE:
449 {
450 const auto& f = F.row(I(fid, 0));
451 const size_t s = f[(element_index+1)%3];
452 const size_t d = f[(element_index+2)%3];
453 fid = process_edge_case(i, s, d, I(fid, 0), fid_ori);
454 }
455 break;
456 case FACE:
457 {
458 fid = process_face_case(i, closest_point, fid, fid_ori);
459 }
460 break;
461 default:
462 throw std::runtime_error("Unknown element type.");
463 }
464
465
466 R(i,0) = fid;
467 S(i,0) = fid_ori;
468 }
469}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index cols() const
Definition PlainObjectBase.h:153
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
Definition PlainObjectBase.h:279
@ F
Definition libslic3r.h:102
Kernel::Plane_3 Plane_3
Definition points_inside_component.cpp:34
Kernel::Point_3 Point_3
Definition points_inside_component.cpp:31
IGL_INLINE void order_facets_around_edge(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, size_t s, size_t d, const std::vector< int > &adj_faces, Eigen::PlainObjectBase< DerivedI > &order, bool debug=false)
@ VERTEX
Definition exact_geodesic.cpp:328
@ FACE
Definition exact_geodesic.cpp:330
@ EDGE
Definition exact_geodesic.cpp:329

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

+ Here is the call graph for this function:

◆ closest_facet() [2/3]

template<typename DerivedV , typename DerivedF , typename DerivedI , typename DerivedP , typename uE2EType , typename DerivedEMAP , typename DerivedR , typename DerivedS >
IGL_INLINE void igl::copyleft::cgal::closest_facet ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedI > &  I,
const Eigen::PlainObjectBase< DerivedP > &  P,
const std::vector< std::vector< uE2EType > > &  uE2E,
const Eigen::PlainObjectBase< DerivedEMAP > &  EMAP,
Eigen::PlainObjectBase< DerivedR > &  R,
Eigen::PlainObjectBase< DerivedS > &  S 
)
39{
40
41 typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
42 typedef Kernel::Point_3 Point_3;
43 typedef Kernel::Plane_3 Plane_3;
44 typedef Kernel::Segment_3 Segment_3;
45 typedef Kernel::Triangle_3 Triangle;
46 typedef std::vector<Triangle>::iterator Iterator;
47 typedef CGAL::AABB_triangle_primitive<Kernel, Iterator> Primitive;
48 typedef CGAL::AABB_traits<Kernel, Primitive> AABB_triangle_traits;
49 typedef CGAL::AABB_tree<AABB_triangle_traits> Tree;
50
51 if (F.rows() <= 0 || I.rows() <= 0) {
52 throw std::runtime_error(
53 "Closest facet cannot be computed on empty mesh.");
54 }
55
56 std::vector<std::vector<size_t> > VF, VFi;
57 igl::vertex_triangle_adjacency(V.rows(), F, VF, VFi);
58 std::vector<bool> in_I;
59 std::vector<Triangle> triangles;
60 Tree tree;
61 submesh_aabb_tree(V,F,I,tree,triangles,in_I);
62
63 return closest_facet(
64 V,F,I,P,uE2E,EMAP,VF,VFi,tree,triangles,in_I,R,S);
65}
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
CGAL::Exact_predicates_inexact_constructions_kernel Kernel
Definition point_areas.cpp:16

References closest_facet(), Eigen::PlainObjectBase< Derived >::rows(), submesh_aabb_tree(), and igl::vertex_triangle_adjacency().

Referenced by closest_facet(), closest_facet(), and extract_cells().

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

◆ closest_facet() [3/3]

template<typename DerivedV , typename DerivedF , typename DerivedP , typename uE2EType , typename DerivedEMAP , typename DerivedR , typename DerivedS >
IGL_INLINE void igl::copyleft::cgal::closest_facet ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedP > &  P,
const std::vector< std::vector< uE2EType > > &  uE2E,
const Eigen::PlainObjectBase< DerivedEMAP > &  EMAP,
Eigen::PlainObjectBase< DerivedR > &  R,
Eigen::PlainObjectBase< DerivedS > &  S 
)
486 {
487 const size_t num_faces = F.rows();
488 Eigen::VectorXi I = igl::LinSpaced<Eigen::VectorXi>(num_faces, 0, num_faces-1);
489 igl::copyleft::cgal::closest_facet(V, F, I, P, uE2E, EMAP, R, S);
490}
IGL_INLINE void closest_facet(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedI > &I, const Eigen::PlainObjectBase< DerivedP > &P, const std::vector< std::vector< uE2EType > > &uE2E, const Eigen::PlainObjectBase< DerivedEMAP > &EMAP, Eigen::PlainObjectBase< DerivedR > &R, Eigen::PlainObjectBase< DerivedS > &S)
Definition closest_facet.cpp:30

References closest_facet().

+ Here is the call graph for this function:

◆ complex_to_mesh()

template<typename Tr , typename DerivedV , typename DerivedF >
IGL_INLINE bool igl::copyleft::cgal::complex_to_mesh ( const CGAL::Complex_2_in_triangulation_3< Tr > &  c2t3,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F 
)
23{
24 using namespace Eigen;
25 // CGAL/IO/Complex_2_in_triangulation_3_file_writer.h
26 using CGAL::Surface_mesher::number_of_facets_on_surface;
27
28 typedef typename CGAL::Complex_2_in_triangulation_3<Tr> C2t3;
29 typedef typename Tr::Finite_facets_iterator Finite_facets_iterator;
30 typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator;
31 typedef typename Tr::Facet Facet;
32 typedef typename Tr::Edge Edge;
33 typedef typename Tr::Vertex_handle Vertex_handle;
34
35 // Header.
36 const Tr& tr = c2t3.triangulation();
37
38 bool success = true;
39
40 const int n = tr.number_of_vertices();
41 const int m = c2t3.number_of_facets();
42
43 assert(m == number_of_facets_on_surface(tr));
44
45 // Finite vertices coordinates.
46 std::map<Vertex_handle, int> v2i;
47 V.resize(n,3);
48 {
49 int v = 0;
50 for(Finite_vertices_iterator vit = tr.finite_vertices_begin();
51 vit != tr.finite_vertices_end();
52 ++vit)
53 {
54 V(v,0) = vit->point().x();
55 V(v,1) = vit->point().y();
56 V(v,2) = vit->point().z();
57 v2i[vit] = v++;
58 }
59 }
60
61 {
62 Finite_facets_iterator fit = tr.finite_facets_begin();
63 std::set<Facet> oriented_set;
64 std::stack<Facet> stack;
65
66 while ((int)oriented_set.size() != m)
67 {
68 while ( fit->first->is_facet_on_surface(fit->second) == false ||
69 oriented_set.find(*fit) != oriented_set.end() ||
70 oriented_set.find(c2t3.opposite_facet(*fit)) !=
71 oriented_set.end() )
72 {
73 ++fit;
74 }
75 oriented_set.insert(*fit);
76 stack.push(*fit);
77 while(! stack.empty() )
78 {
79 Facet f = stack.top();
80 stack.pop();
81 for(int ih = 0 ; ih < 3 ; ++ih)
82 {
83 const int i1 = tr.vertex_triple_index(f.second, tr. cw(ih));
84 const int i2 = tr.vertex_triple_index(f.second, tr.ccw(ih));
85
86 const typename C2t3::Face_status face_status
87 = c2t3.face_status(Edge(f.first, i1, i2));
88 if(face_status == C2t3::REGULAR)
89 {
90 Facet fn = c2t3.neighbor(f, ih);
91 if (oriented_set.find(fn) == oriented_set.end())
92 {
93 if(oriented_set.find(c2t3.opposite_facet(fn)) == oriented_set.end())
94 {
95 oriented_set.insert(fn);
96 stack.push(fn);
97 }else {
98 success = false; // non-orientable
99 }
100 }
101 }else if(face_status != C2t3::BOUNDARY)
102 {
103 success = false; // non manifold, thus non-orientable
104 }
105 } // end "for each neighbor of f"
106 } // end "stack non empty"
107 } // end "oriented_set not full"
108
109 F.resize(m,3);
110 int f = 0;
111 for(typename std::set<Facet>::const_iterator fit =
112 oriented_set.begin();
113 fit != oriented_set.end();
114 ++fit)
115 {
116 const typename Tr::Cell_handle cell = fit->first;
117 const int& index = fit->second;
118 const int index1 = v2i[cell->vertex(tr.vertex_triple_index(index, 0))];
119 const int index2 = v2i[cell->vertex(tr.vertex_triple_index(index, 1))];
120 const int index3 = v2i[cell->vertex(tr.vertex_triple_index(index, 2))];
121 // This order is flipped
122 F(f,0) = index1;
123 F(f,1) = index2;
124 F(f,2) = index3;
125 f++;
126 }
127 assert(f == m);
128 } // end if(facets must be oriented)
129
130 // This CGAL code seems to randomly assign the global orientation
131 // Flip based on the signed volume.
132 Eigen::Vector3d cen;
133 double vol;
134 igl::centroid(V,F,cen,vol);
135 if(vol < 0)
136 {
137 // Flip
138 F = F.rowwise().reverse().eval();
139 }
140
141 // CGAL code somehow can end up with unreferenced vertices
142 {
143 VectorXi _1;
144 remove_unreferenced( MatrixXd(V), MatrixXi(F), V,F,_1);
145 }
146
147 return success;
148}
Definition LDLT.h:16
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 centroid(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< Derivedc > &c, Derivedvol &vol)
Definition centroid.cpp:16

References igl::centroid(), igl::remove_unreferenced(), and Eigen::PlainObjectBase< Derived >::resize().

Referenced by signed_distance_isosurface().

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

◆ component_inside_component() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedI >
IGL_INLINE bool igl::copyleft::cgal::component_inside_component ( const Eigen::PlainObjectBase< DerivedV > &  V1,
const Eigen::PlainObjectBase< DerivedF > &  F1,
const Eigen::PlainObjectBase< DerivedI > &  I1,
const Eigen::PlainObjectBase< DerivedV > &  V2,
const Eigen::PlainObjectBase< DerivedF > &  F2,
const Eigen::PlainObjectBase< DerivedI > &  I2 
)
31 {
32 if (F1.rows() <= 0 || I1.rows() <= 0 || F2.rows() <= 0 || I2.rows() <= 0) {
33 throw "Component inside test cannot be done on empty component!";
34 }
35
36 const Eigen::Vector3i& f = F1.row(I1(0, 0));
38 (V1(f[0],0) + V1(f[1],0) + V1(f[2],0))/3.0,
39 (V1(f[0],1) + V1(f[1],1) + V1(f[2],1))/3.0,
40 (V1(f[0],2) + V1(f[1],2) + V1(f[2],2))/3.0);
41 Eigen::VectorXi inside;
42 igl::copyleft::cgal::points_inside_component(V2, F2, I2, query, inside);
43 assert(inside.size() == 1);
44 return inside[0];
45}
IGL_INLINE void points_inside_component(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedI > &I, const Eigen::PlainObjectBase< DerivedP > &P, Eigen::PlainObjectBase< DerivedB > &inside)
Definition points_inside_component.cpp:250

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

Referenced by component_inside_component().

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

◆ component_inside_component() [2/2]

template<typename DerivedV , typename DerivedF >
IGL_INLINE bool igl::copyleft::cgal::component_inside_component ( const Eigen::PlainObjectBase< DerivedV > &  V1,
const Eigen::PlainObjectBase< DerivedF > &  F1,
const Eigen::PlainObjectBase< DerivedV > &  V2,
const Eigen::PlainObjectBase< DerivedF > &  F2 
)
52 {
53 if (F1.rows() <= 0 || F2.rows() <= 0) {
54 throw "Component inside test cannot be done on empty component!";
55 }
56 Eigen::VectorXi I1(F1.rows()), I2(F2.rows());
57 I1 = igl::LinSpaced<Eigen::VectorXi>(F1.rows(), 0, F1.rows()-1);
58 I2 = igl::LinSpaced<Eigen::VectorXi>(F2.rows(), 0, F2.rows()-1);
59 return igl::copyleft::cgal::component_inside_component(V1, F1, I1, V2, F2, I2);
60}
IGL_INLINE bool component_inside_component(const Eigen::PlainObjectBase< DerivedV > &V1, const Eigen::PlainObjectBase< DerivedF > &F1, const Eigen::PlainObjectBase< DerivedI > &I1, const Eigen::PlainObjectBase< DerivedV > &V2, const Eigen::PlainObjectBase< DerivedF > &F2, const Eigen::PlainObjectBase< DerivedI > &I2)
Definition component_inside_component.cpp:25

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

+ Here is the call graph for this function:

◆ convex_hull() [1/2]

template<typename DerivedV , typename DerivedF >
IGL_INLINE void igl::copyleft::cgal::convex_hull ( const Eigen::MatrixBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F 
)
49{
52 convex_hull(V,W,G);
53 // This is a lazy way to reindex into the original mesh
55 Eigen::VectorXi J;
56 igl::ismember_rows(W,V,I,J);
57 assert(I.all() && "Should find all W in V");
58 F.resizeLike(G);
59 for(int f = 0;f<G.rows();f++)
60 {
61 for(int c = 0;c<3;c++)
62 {
63 F(f,c) = J(G(f,c));
64 }
65 }
66}
IGL_INLINE void convex_hull(const Eigen::MatrixBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedW > &W, Eigen::PlainObjectBase< DerivedG > &G)
Definition convex_hull.cpp:21
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 convex_hull(), igl::ismember_rows(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ convex_hull() [2/2]

template<typename DerivedV , typename DerivedW , typename DerivedG >
IGL_INLINE void igl::copyleft::cgal::convex_hull ( const Eigen::MatrixBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedW > &  W,
Eigen::PlainObjectBase< DerivedG > &  G 
)
25{
26 typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
27 typedef K::Point_3 Point_3;
28 //typedef CGAL::Delaunay_triangulation_3<K> Delaunay;
29 //typedef Delaunay::Vertex_handle Vertex_handle;
30 //typedef CGAL::Surface_mesh<Point_3> Surface_mesh;
31 typedef CGAL::Polyhedron_3<K> Polyhedron_3;
32 std::vector<Point_3> points(V.rows());
33 for(int i = 0;i<V.rows();i++)
34 {
35 points[i] = Point_3(V(i,0),V(i,1),V(i,2));
36 }
37 Polyhedron_3 poly;
38 CGAL::convex_hull_3(points.begin(),points.end(),poly);
39 assert(poly.is_pure_triangle() && "Assuming CGAL outputs a triangle mesh");
40 polyhedron_to_mesh(poly,W,G);
41}

References polyhedron_to_mesh().

Referenced by convex_hull(), and wire_mesh().

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

◆ delaunay_triangulation()

template<typename DerivedV , typename DerivedF >
IGL_INLINE void igl::copyleft::cgal::delaunay_triangulation ( const Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F 
)
21{
22 typedef typename DerivedV::Scalar Scalar;
23 igl::delaunay_triangulation(V, orient2D<Scalar>, incircle<Scalar>, F);
24 // This function really exists to test our igl::delaunay_triangulation
25 //
26 // It's currently much faster to call cgal's native Delaunay routine
27 //
28//#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
29//#include <CGAL/Delaunay_triangulation_2.h>
30//#include <CGAL/Triangulation_vertex_base_with_info_2.h>
31//#include <vector>
32// const auto delaunay =
33// [&](const Eigen::MatrixXd & V,Eigen::MatrixXi & F)
34// {
35// typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
36// typedef CGAL::Triangulation_vertex_base_with_info_2<unsigned int, Kernel> Vb;
37// typedef CGAL::Triangulation_data_structure_2<Vb> Tds;
38// typedef CGAL::Delaunay_triangulation_2<Kernel, Tds> Delaunay;
39// typedef Kernel::Point_2 Point;
40// std::vector< std::pair<Point,unsigned> > points(V.rows());
41// for(int i = 0;i<V.rows();i++)
42// {
43// points[i] = std::make_pair(Point(V(i,0),V(i,1)),i);
44// }
45// Delaunay triangulation;
46// triangulation.insert(points.begin(),points.end());
47// F.resize(triangulation.number_of_faces(),3);
48// {
49// int j = 0;
50// for(Delaunay::Finite_faces_iterator fit = triangulation.finite_faces_begin();
51// fit != triangulation.finite_faces_end(); ++fit)
52// {
53// Delaunay::Face_handle face = fit;
54// F(j,0) = face->vertex(0)->info();
55// F(j,1) = face->vertex(1)->info();
56// F(j,2) = face->vertex(2)->info();
57// j++;
58// }
59// }
60// };
61}
IGL_INLINE void delaunay_triangulation(const Eigen::PlainObjectBase< DerivedV > &V, Orient2D orient2D, InCircle incircle, Eigen::PlainObjectBase< DerivedF > &F)
Definition delaunay_triangulation.cpp:22

References igl::delaunay_triangulation().

Referenced by remesh_intersections().

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

◆ extract_cells() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedP , typename DerivedE , typename DeriveduE , typename uE2EType , typename DerivedEMAP , typename DerivedC >
IGL_INLINE size_t igl::copyleft::cgal::extract_cells ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedP > &  P,
const Eigen::PlainObjectBase< DerivedE > &  E,
const Eigen::PlainObjectBase< DeriveduE > &  uE,
const std::vector< std::vector< uE2EType > > &  uE2E,
const Eigen::PlainObjectBase< DerivedEMAP > &  EMAP,
Eigen::PlainObjectBase< DerivedC > &  cells 
)
85{
86 // Trivial base case
87 if(P.size() == 0)
88 {
89 assert(F.size() == 0);
90 cells.resize(0,2);
91 return 0;
92 }
93
94 typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
95 typedef Kernel::Point_3 Point_3;
96 typedef Kernel::Plane_3 Plane_3;
97 typedef Kernel::Segment_3 Segment_3;
98 typedef Kernel::Triangle_3 Triangle;
99 typedef std::vector<Triangle>::iterator Iterator;
100 typedef CGAL::AABB_triangle_primitive<Kernel, Iterator> Primitive;
101 typedef CGAL::AABB_traits<Kernel, Primitive> AABB_triangle_traits;
102 typedef CGAL::AABB_tree<AABB_triangle_traits> Tree;
103
104#ifdef EXTRACT_CELLS_DEBUG
105 const auto & tictoc = []() -> double
106 {
107 static double t_start = igl::get_seconds();
108 double diff = igl::get_seconds()-t_start;
109 t_start += diff;
110 return diff;
111 };
112 const auto log_time = [&](const std::string& label) -> void {
113 std::cout << "extract_cells." << label << ": "
114 << tictoc() << std::endl;
115 };
116 tictoc();
117#else
118 // no-op
119 const auto log_time = [](const std::string){};
120#endif
121 const size_t num_faces = F.rows();
122 typedef typename DerivedF::Scalar Index;
123 assert(P.size() > 0);
124 const size_t num_patches = P.maxCoeff()+1;
125
126 // Extract all cells...
127 DerivedC raw_cells;
128 const size_t num_raw_cells =
129 extract_cells_single_component(V,F,P,uE,uE2E,EMAP,raw_cells);
130 log_time("extract_single_component_cells");
131
132 // Compute triangle-triangle adjacency data-structure
133 std::vector<std::vector<std::vector<Index > > > TT,_1;
134 igl::triangle_triangle_adjacency(E, EMAP, uE2E, false, TT, _1);
135 log_time("compute_face_adjacency");
136
137 // Compute connected components of the mesh
138 Eigen::VectorXi C, counts;
139 igl::facet_components(TT, C, counts);
140 log_time("form_components");
141
142 const size_t num_components = counts.size();
143 // components[c] --> list of face indices into F of faces in component c
144 std::vector<std::vector<size_t> > components(num_components);
145 // Loop over all faces
146 for (size_t i=0; i<num_faces; i++)
147 {
148 components[C[i]].push_back(i);
149 }
150 // Convert vector lists to Eigen lists...
151 // and precompute data-structures for each component
152 std::vector<std::vector<size_t> > VF,VFi;
153 igl::vertex_triangle_adjacency(V.rows(), F, VF, VFi);
154 std::vector<Eigen::VectorXi> Is(num_components);
155 std::vector<
156 CGAL::AABB_tree<
157 CGAL::AABB_traits<
158 Kernel,
159 CGAL::AABB_triangle_primitive<
160 Kernel, std::vector<
161 Kernel::Triangle_3 >::iterator > > > > trees(num_components);
162 std::vector< std::vector<Kernel::Triangle_3 > >
163 triangle_lists(num_components);
164 std::vector<std::vector<bool> > in_Is(num_components);
165
166 // Find outer facets, their orientations and cells for each component
167 Eigen::VectorXi outer_facets(num_components);
168 Eigen::VectorXi outer_facet_orientation(num_components);
169 Eigen::VectorXi outer_cells(num_components);
170 for (size_t i=0; i<num_components; i++)
171 {
172 Is[i].resize(components[i].size());
173 std::copy(components[i].begin(), components[i].end(),Is[i].data());
174 bool flipped;
175 igl::copyleft::cgal::outer_facet(V, F, Is[i], outer_facets[i], flipped);
176 outer_facet_orientation[i] = flipped?1:0;
177 outer_cells[i] = raw_cells(P[outer_facets[i]], outer_facet_orientation[i]);
178 }
179#ifdef EXTRACT_CELLS_DEBUG
180 log_time("outer_facet_per_component");
181#endif
182
183 // Compute barycenter of a triangle in mesh (V,F)
184 //
185 // Inputs:
186 // fid index into F
187 // Returns row-vector of barycenter coordinates
188 const auto get_triangle_center = [&V,&F](const size_t fid)
189 {
190 return ((V.row(F(fid,0))+V.row(F(fid,1))+V.row(F(fid,2)))/3.0).eval();
191 };
192 std::vector<std::vector<size_t> > nested_cells(num_raw_cells);
193 std::vector<std::vector<size_t> > ambient_cells(num_raw_cells);
194 std::vector<std::vector<size_t> > ambient_comps(num_components);
195 // Only bother if there's more than one component
196 if(num_components > 1)
197 {
198 // construct bounding boxes for each component
199 DerivedV bbox_min(num_components, 3);
200 DerivedV bbox_max(num_components, 3);
201 // Assuming our mesh (in exact numbers) fits in the range of double.
202 bbox_min.setConstant(std::numeric_limits<double>::max());
203 bbox_max.setConstant(std::numeric_limits<double>::min());
204 // Loop over faces
205 for (size_t i=0; i<num_faces; i++)
206 {
207 // component of this face
208 const auto comp_id = C[i];
209 const auto& f = F.row(i);
210 for (size_t j=0; j<3; j++)
211 {
212 for(size_t d=0;d<3;d++)
213 {
214 bbox_min(comp_id,d) = std::min(bbox_min(comp_id,d), V(f[j],d));
215 bbox_max(comp_id,d) = std::max(bbox_max(comp_id,d), V(f[j],d));
216 }
217 }
218 }
219 // Return true if box of component ci intersects that of cj
220 const auto bbox_intersects = [&bbox_max,&bbox_min](size_t ci, size_t cj)
221 {
222 return !(
223 bbox_max(ci,0) < bbox_min(cj,0) ||
224 bbox_max(ci,1) < bbox_min(cj,1) ||
225 bbox_max(ci,2) < bbox_min(cj,2) ||
226 bbox_max(cj,0) < bbox_min(ci,0) ||
227 bbox_max(cj,1) < bbox_min(ci,1) ||
228 bbox_max(cj,2) < bbox_min(ci,2));
229 };
230
231 // Loop over components. This section is O(m²)
232 for (size_t i=0; i<num_components; i++)
233 {
234 // List of components that could overlap with component i
235 std::vector<size_t> candidate_comps;
236 candidate_comps.reserve(num_components);
237 // Loop over components
238 for (size_t j=0; j<num_components; j++)
239 {
240 if (i == j) continue;
241 if (bbox_intersects(i,j)) candidate_comps.push_back(j);
242 }
243
244 const size_t num_candidate_comps = candidate_comps.size();
245 if (num_candidate_comps == 0) continue;
246
247 // Build aabb tree for this component.
248 submesh_aabb_tree(V,F,Is[i],trees[i],triangle_lists[i],in_Is[i]);
249
250 // Get query points on each candidate component: barycenter of
251 // outer-facet
252 DerivedV queries(num_candidate_comps, 3);
253 for (size_t j=0; j<num_candidate_comps; j++)
254 {
255 const size_t index = candidate_comps[j];
256 queries.row(j) = get_triangle_center(outer_facets[index]);
257 }
258
259 // Gather closest facets in ith component to each query point and their
260 // orientations
261 const auto& I = Is[i];
262 const auto& tree = trees[i];
263 const auto& in_I = in_Is[i];
264 const auto& triangles = triangle_lists[i];
265
266 Eigen::VectorXi closest_facets, closest_facet_orientations;
268 V,
269 F,
270 I,
271 queries,
272 uE2E,
273 EMAP,
274 VF,
275 VFi,
276 tree,
277 triangles,
278 in_I,
279 closest_facets,
280 closest_facet_orientations);
281 // Loop over all candidates
282 for (size_t j=0; j<num_candidate_comps; j++)
283 {
284 const size_t index = candidate_comps[j];
285 const size_t closest_patch = P[closest_facets[j]];
286 const size_t closest_patch_side = closest_facet_orientations[j] ? 0:1;
287 // The cell id of the closest patch
288 const size_t ambient_cell =
289 raw_cells(closest_patch,closest_patch_side);
290 if (ambient_cell != (size_t)outer_cells[i])
291 {
292 // ---> component index inside component i, because the cell of the
293 // closest facet on i to component index is **not** the same as the
294 // "outer cell" of component i: component index is **not** outside of
295 // component i (therefore it's inside).
296 nested_cells[ambient_cell].push_back(outer_cells[index]);
297 ambient_cells[outer_cells[index]].push_back(ambient_cell);
298 ambient_comps[index].push_back(i);
299 }
300 }
301 }
302 }
303
304#ifdef EXTRACT_CELLS_DEBUG
305 log_time("nested_relationship");
306#endif
307
308 const size_t INVALID = std::numeric_limits<size_t>::max();
309 const size_t INFINITE_CELL = num_raw_cells;
310 std::vector<size_t> embedded_cells(num_raw_cells, INVALID);
311 for (size_t i=0; i<num_components; i++) {
312 const size_t outer_cell = outer_cells[i];
313 const auto& ambient_comps_i = ambient_comps[i];
314 const auto& ambient_cells_i = ambient_cells[outer_cell];
315 const size_t num_ambient_comps = ambient_comps_i.size();
316 assert(num_ambient_comps == ambient_cells_i.size());
317 if (num_ambient_comps > 0) {
318 size_t embedded_comp = INVALID;
319 size_t embedded_cell = INVALID;
320 for (size_t j=0; j<num_ambient_comps; j++) {
321 if (ambient_comps[ambient_comps_i[j]].size() ==
322 num_ambient_comps-1) {
323 embedded_comp = ambient_comps_i[j];
324 embedded_cell = ambient_cells_i[j];
325 break;
326 }
327 }
328 assert(embedded_comp != INVALID);
329 assert(embedded_cell != INVALID);
330 embedded_cells[outer_cell] = embedded_cell;
331 } else {
332 embedded_cells[outer_cell] = INFINITE_CELL;
333 }
334 }
335 for (size_t i=0; i<num_patches; i++) {
336 if (embedded_cells[raw_cells(i,0)] != INVALID) {
337 raw_cells(i,0) = embedded_cells[raw_cells(i, 0)];
338 }
339 if (embedded_cells[raw_cells(i,1)] != INVALID) {
340 raw_cells(i,1) = embedded_cells[raw_cells(i, 1)];
341 }
342 }
343
344 size_t count = 0;
345 std::vector<size_t> mapped_indices(num_raw_cells+1, INVALID);
346 // Always map infinite cell to index 0.
347 mapped_indices[INFINITE_CELL] = count;
348 count++;
349
350 for (size_t i=0; i<num_patches; i++) {
351 const size_t old_positive_cell_id = raw_cells(i, 0);
352 const size_t old_negative_cell_id = raw_cells(i, 1);
353 size_t positive_cell_id, negative_cell_id;
354 if (mapped_indices[old_positive_cell_id] == INVALID) {
355 mapped_indices[old_positive_cell_id] = count;
356 positive_cell_id = count;
357 count++;
358 } else {
359 positive_cell_id = mapped_indices[old_positive_cell_id];
360 }
361 if (mapped_indices[old_negative_cell_id] == INVALID) {
362 mapped_indices[old_negative_cell_id] = count;
363 negative_cell_id = count;
364 count++;
365 } else {
366 negative_cell_id = mapped_indices[old_negative_cell_id];
367 }
368 raw_cells(i, 0) = positive_cell_id;
369 raw_cells(i, 1) = negative_cell_id;
370 }
371 cells = raw_cells;
372#ifdef EXTRACT_CELLS_DEBUG
373 log_time("finalize");
374#endif
375 return count;
376}
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:33
constexpr auto size(const C &c) -> decltype(c.size())
Definition span.hpp:183
constexpr auto data(C &c) -> decltype(c.data())
Definition span.hpp:195
IGL_INLINE size_t extract_cells_single_component(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DeriveduE > &uE, const std::vector< std::vector< uE2EType > > &uE2E, const Eigen::PlainObjectBase< DerivedEMAP > &EMAP, Eigen::PlainObjectBase< DerivedC > &cells)
Definition extract_cells.cpp:386
IGL_INLINE void submesh_aabb_tree(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedI > &I, CGAL::AABB_tree< CGAL::AABB_traits< Kernel, CGAL::AABB_triangle_primitive< Kernel, typename std::vector< typename Kernel::Triangle_3 >::iterator > > > &tree, std::vector< typename Kernel::Triangle_3 > &triangles, std::vector< bool > &in_I)
Definition submesh_aabb_tree.cpp:16
IGL_INLINE void outer_facet(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedI > &I, IndexType &f, bool &flipped)
Definition outer_facet.cpp:21
IGL_INLINE void count(const Eigen::SparseMatrix< XType > &X, const int dim, Eigen::SparseVector< SType > &S)
Definition count.cpp:12
IGL_INLINE void components(const Eigen::SparseMatrix< AScalar > &A, Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< Derivedcounts > &counts)
Definition components.cpp:14
IGL_INLINE double get_seconds()
Definition get_seconds.cpp:10
IGL_INLINE void facet_components(const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedC > &C)
Definition facet_components.cpp:13
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
S::iterator begin(S &sh, const PathTag &)
Definition geometry_traits.hpp:614
S::iterator end(S &sh, const PathTag &)
Definition geometry_traits.hpp:620

References closest_facet(), igl::components(), igl::count(), extract_cells_single_component(), igl::facet_components(), igl::get_seconds(), outer_facet(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), submesh_aabb_tree(), igl::triangle_triangle_adjacency(), and igl::vertex_triangle_adjacency().

+ Here is the call graph for this function:

◆ extract_cells() [2/2]

template<typename DerivedV , typename DerivedF , typename DerivedC >
IGL_INLINE size_t igl::copyleft::cgal::extract_cells ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedC > &  cells 
)
43{
44 const size_t num_faces = F.rows();
45 // Construct edge adjacency
46 Eigen::MatrixXi E, uE;
47 Eigen::VectorXi EMAP;
48 std::vector<std::vector<size_t> > uE2E;
49 igl::unique_edge_map(F, E, uE, EMAP, uE2E);
50 // Cluster into manifold patches
51 Eigen::VectorXi P;
52 igl::extract_manifold_patches(F, EMAP, uE2E, P);
53 // Extract cells
54 DerivedC per_patch_cells;
55 const size_t num_cells =
56 igl::copyleft::cgal::extract_cells(V,F,P,E,uE,uE2E,EMAP,per_patch_cells);
57 // Distribute per-patch cell information to each face
58 cells.resize(num_faces, 2);
59 for (size_t i=0; i<num_faces; i++)
60 {
61 cells.row(i) = per_patch_cells.row(P[i]);
62 }
63 return num_cells;
64}
IGL_INLINE size_t extract_cells(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedC > &cells)
Definition extract_cells.cpp:39
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 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_cells(), igl::extract_manifold_patches(), Eigen::PlainObjectBase< Derived >::resize(), and igl::unique_edge_map().

Referenced by extract_cells(), mesh_boolean(), outer_hull(), and propagate_winding_numbers().

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

◆ extract_cells_single_component()

template<typename DerivedV , typename DerivedF , typename DerivedP , typename DeriveduE , typename uE2EType , typename DerivedEMAP , typename DerivedC >
IGL_INLINE size_t igl::copyleft::cgal::extract_cells_single_component ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedP > &  P,
const Eigen::PlainObjectBase< DeriveduE > &  uE,
const std::vector< std::vector< uE2EType > > &  uE2E,
const Eigen::PlainObjectBase< DerivedEMAP > &  EMAP,
Eigen::PlainObjectBase< DerivedC > &  cells 
)
394{
395 const size_t num_faces = F.rows();
396 // Input:
397 // index index into #F*3 list of undirect edges
398 // Returns index into face
399 const auto edge_index_to_face_index = [&num_faces](size_t index)
400 {
401 return index % num_faces;
402 };
403 // Determine if a face (containing undirected edge {s,d} is consistently
404 // oriented with directed edge {s,d} (or otherwise it is with {d,s})
405 //
406 // Inputs:
407 // fid face index into F
408 // s source index of edge
409 // d destination index of edge
410 // Returns true if face F(fid,:) is consistent with {s,d}
411 const auto is_consistent =
412 [&F](const size_t fid, const size_t s, const size_t d) -> bool
413 {
414 if ((size_t)F(fid, 0) == s && (size_t)F(fid, 1) == d) return false;
415 if ((size_t)F(fid, 1) == s && (size_t)F(fid, 2) == d) return false;
416 if ((size_t)F(fid, 2) == s && (size_t)F(fid, 0) == d) return false;
417
418 if ((size_t)F(fid, 0) == d && (size_t)F(fid, 1) == s) return true;
419 if ((size_t)F(fid, 1) == d && (size_t)F(fid, 2) == s) return true;
420 if ((size_t)F(fid, 2) == d && (size_t)F(fid, 0) == s) return true;
421 throw "Invalid face!";
422 return false;
423 };
424
425 const size_t num_unique_edges = uE.rows();
426 const size_t num_patches = P.maxCoeff() + 1;
427
428 // Build patch-patch adjacency list.
429 std::vector<std::map<size_t, size_t> > patch_adj(num_patches);
430 for (size_t i=0; i<num_unique_edges; i++) {
431 const size_t s = uE(i,0);
432 const size_t d = uE(i,1);
433 const auto adj_faces = uE2E[i];
434 const size_t num_adj_faces = adj_faces.size();
435 if (num_adj_faces > 2) {
436 for (size_t j=0; j<num_adj_faces; j++) {
437 const size_t patch_j = P[edge_index_to_face_index(adj_faces[j])];
438 for (size_t k=j+1; k<num_adj_faces; k++) {
439 const size_t patch_k = P[edge_index_to_face_index(adj_faces[k])];
440 if (patch_adj[patch_j].find(patch_k) == patch_adj[patch_j].end()) {
441 patch_adj[patch_j].insert({patch_k, i});
442 }
443 if (patch_adj[patch_k].find(patch_j) == patch_adj[patch_k].end()) {
444 patch_adj[patch_k].insert({patch_j, i});
445 }
446 }
447 }
448 }
449 }
450
451
452 const int INVALID = std::numeric_limits<int>::max();
453 std::vector<size_t> cell_labels(num_patches * 2);
454 for (size_t i=0; i<num_patches; i++) cell_labels[i] = i;
455 std::vector<std::set<size_t> > equivalent_cells(num_patches*2);
456 std::vector<bool> processed(num_unique_edges, false);
457
458 size_t label_count=0;
459 for (size_t i=0; i<num_patches; i++) {
460 for (const auto& entry : patch_adj[i]) {
461 const size_t neighbor_patch = entry.first;
462 const size_t uei = entry.second;
463 if (processed[uei]) continue;
464 processed[uei] = true;
465
466 const auto& adj_faces = uE2E[uei];
467 const size_t num_adj_faces = adj_faces.size();
468 assert(num_adj_faces > 2);
469
470 const size_t s = uE(uei,0);
471 const size_t d = uE(uei,1);
472
473 std::vector<int> signed_adj_faces;
474 for (auto ej : adj_faces)
475 {
476 const size_t fid = edge_index_to_face_index(ej);
477 bool cons = is_consistent(fid, s, d);
478 signed_adj_faces.push_back((fid+1)*(cons ? 1:-1));
479 }
480 {
481 // Sort adjacent faces cyclically around {s,d}
482 Eigen::VectorXi order;
483 // order[f] will reveal the order of face f in signed_adj_faces
484 order_facets_around_edge(V, F, s, d, signed_adj_faces, order);
485 for (size_t j=0; j<num_adj_faces; j++) {
486 const size_t curr_idx = j;
487 const size_t next_idx = (j+1)%num_adj_faces;
488 const size_t curr_patch_idx =
489 P[edge_index_to_face_index(adj_faces[order[curr_idx]])];
490 const size_t next_patch_idx =
491 P[edge_index_to_face_index(adj_faces[order[next_idx]])];
492 const bool curr_cons = signed_adj_faces[order[curr_idx]] > 0;
493 const bool next_cons = signed_adj_faces[order[next_idx]] > 0;
494 const size_t curr_cell_idx = curr_patch_idx*2 + (curr_cons?0:1);
495 const size_t next_cell_idx = next_patch_idx*2 + (next_cons?1:0);
496 equivalent_cells[curr_cell_idx].insert(next_cell_idx);
497 equivalent_cells[next_cell_idx].insert(curr_cell_idx);
498 }
499 }
500 }
501 }
502
503 size_t count=0;
504 cells.resize(num_patches, 2);
505 cells.setConstant(INVALID);
506 const auto extract_equivalent_cells = [&](size_t i) {
507 if (cells(i/2, i%2) != INVALID) return;
508 std::queue<size_t> Q;
509 Q.push(i);
510 cells(i/2, i%2) = count;
511 while (!Q.empty()) {
512 const size_t index = Q.front();
513 Q.pop();
514 for (const auto j : equivalent_cells[index]) {
515 if (cells(j/2, j%2) == INVALID) {
516 cells(j/2, j%2) = count;
517 Q.push(j);
518 }
519 }
520 }
521 count++;
522 };
523 for (size_t i=0; i<num_patches; i++) {
524 extract_equivalent_cells(i*2);
525 extract_equivalent_cells(i*2+1);
526 }
527
528 assert((cells.array() != INVALID).all());
529 return count;
530}
EIGEN_DEVICE_FUNC Derived & setConstant(Index size, const Scalar &val)
Definition CwiseNullaryOp.h:341
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 igl::count(), igl::find(), order_facets_around_edge(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), and Eigen::PlainObjectBase< Derived >::setConstant().

Referenced by extract_cells().

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

◆ extract_feature() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedE >
IGL_INLINE void igl::copyleft::cgal::extract_feature ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const double  tol,
const Eigen::PlainObjectBase< DerivedE > &  E,
const Eigen::PlainObjectBase< DerivedE > &  uE,
const std::vector< std::vector< typename DerivedE::Scalar > > &  uE2E,
Eigen::PlainObjectBase< DerivedE > &  feature_edges 
)
44 {
45
46 assert(V.cols() == 3);
47 assert(F.cols() == 3);
48 using Scalar = typename DerivedV::Scalar;
49 using IndexType = typename DerivedE::Scalar;
50 using Vertex = Eigen::Matrix<Scalar, 3, 1>;
51 using Kernel = typename CGAL::Exact_predicates_exact_constructions_kernel;
52 using Point = typename Kernel::Point_3;
53
54 const size_t num_unique_edges = uE.rows();
55 const size_t num_faces = F.rows();
56 // NOTE: CGAL's definition of dihedral angle measures the angle between two
57 // facets instead of facet normals.
58 const double cos_tol = cos(igl::PI - tol);
59 std::vector<size_t> result; // Indices into uE
60
61 auto is_non_manifold = [&uE2E](size_t ei) -> bool {
62 return uE2E[ei].size() > 2;
63 };
64
65 auto is_boundary = [&uE2E](size_t ei) -> bool {
66 return uE2E[ei].size() == 1;
67 };
68
69 auto opposite_vertex = [&uE, &F](size_t ei, size_t fi) -> IndexType {
70 const size_t v0 = uE(ei, 0);
71 const size_t v1 = uE(ei, 1);
72 for (size_t i=0; i<3; i++) {
73 const size_t v = F(fi, i);
74 if (v != v0 && v != v1) { return v; }
75 }
76 throw "Input face must be topologically degenerate!";
77 };
78
79 auto is_feature = [&V, &F, &uE, &uE2E, &opposite_vertex, num_faces](
80 size_t ei, double cos_tol) -> bool {
81 auto adj_faces = uE2E[ei];
82 assert(adj_faces.size() == 2);
83 const Vertex v0 = V.row(uE(ei, 0));
84 const Vertex v1 = V.row(uE(ei, 1));
85 const Vertex v2 = V.row(opposite_vertex(ei, adj_faces[0] % num_faces));
86 const Vertex v3 = V.row(opposite_vertex(ei, adj_faces[1] % num_faces));
87 const Point p0(v0[0], v0[1], v0[2]);
88 const Point p1(v1[0], v1[1], v1[2]);
89 const Point p2(v2[0], v2[1], v2[2]);
90 const Point p3(v3[0], v3[1], v3[2]);
91 const auto ori = CGAL::orientation(p0, p1, p2, p3);
92 switch (ori) {
93 case CGAL::POSITIVE:
94 return CGAL::compare_dihedral_angle(p0, p1, p2, p3, cos_tol) ==
95 CGAL::SMALLER;
96 case CGAL::NEGATIVE:
97 return CGAL::compare_dihedral_angle(p0, p1, p3, p2, cos_tol) ==
98 CGAL::SMALLER;
99 case CGAL::COPLANAR:
100 if (!CGAL::collinear(p0, p1, p2) && !CGAL::collinear(p0, p1, p3)) {
101 return CGAL::compare_dihedral_angle(p0, p1, p2, p3, cos_tol) ==
102 CGAL::SMALLER;
103 } else {
104 throw "Dihedral angle (and feature edge) is not well defined for"
105 " degenerate triangles!";
106 }
107 default:
108 throw "Unknown CGAL orientation";
109 }
110 };
111
112 for (size_t i=0; i<num_unique_edges; i++) {
113 if (is_boundary(i) || is_non_manifold(i) || is_feature(i, cos_tol)) {
114 result.push_back(i);
115 }
116 }
117
118 const size_t num_feature_edges = result.size();
119 feature_edges.resize(num_feature_edges, 2);
120 for (size_t i=0; i<num_feature_edges; i++) {
121 feature_edges.row(i) = uE.row(result[i]);
122 }
123}
EIGEN_DEVICE_FUNC const CosReturnType cos() const
Definition ArrayCwiseUnaryOps.h:202
const double PI
Definition PI.h:16
Kernel::Point_2 Point
Definition point_areas.cpp:20

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

+ Here is the call graph for this function:

◆ extract_feature() [2/2]

template<typename DerivedV , typename DerivedF , typename DerivedE >
IGL_INLINE void igl::copyleft::cgal::extract_feature ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const double  tol,
Eigen::PlainObjectBase< DerivedE > &  feature_edges 
)
22 {
23
24 using IndexType = typename DerivedE::Scalar;
25 DerivedE E, uE;
26 Eigen::VectorXi EMAP;
27 std::vector<std::vector<IndexType> > uE2E;
28 igl::unique_edge_map(F, E, uE, EMAP, uE2E);
29
30 igl::copyleft::cgal::extract_feature(V, F, tol, E, uE, uE2E, feature_edges);
31}
IGL_INLINE void extract_feature(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const double tol, Eigen::PlainObjectBase< DerivedE > &feature_edges)
Definition extract_feature.cpp:18

References extract_feature(), and igl::unique_edge_map().

Referenced by extract_feature().

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

◆ fast_winding_number() [1/2]

template<typename DerivedP , typename DerivedN , typename DerivedQ , typename BetaType , typename DerivedWN >
IGL_INLINE void igl::copyleft::cgal::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 
)
19 {
20 typedef typename DerivedWN::Scalar real;
22 RealMatrix;
23
24 std::vector<std::vector<int> > point_indices;
28 Eigen::MatrixXi I;
30
31 octree(P,point_indices,CH,CN,W);
32 knn(P,21,point_indices,CH,CN,W,I);
33 point_areas(P,I,N,A);
34
38
39 igl::fast_winding_number(P,N,A,point_indices,CH,
40 expansion_order,CM,R,EC);
41 igl::fast_winding_number(P,N,A,point_indices,CH,
42 CM,R,EC,Q,beta,WN);
43 }
EIGEN_DEVICE_FUNC RealReturnType real() const
Definition CommonCwiseUnaryOps.h:86
IGL_INLINE void point_areas(const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedI > &I, const Eigen::MatrixBase< DerivedN > &N, Eigen::PlainObjectBase< DerivedA > &A)
Definition point_areas.cpp:28
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)
Definition knn.cpp:11
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)
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 igl::fast_winding_number(), igl::knn(), igl::octree(), point_areas(), and real().

Referenced by fast_winding_number().

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

◆ fast_winding_number() [2/2]

template<typename DerivedP , typename DerivedN , typename DerivedQ , typename DerivedWN >
IGL_INLINE void igl::copyleft::cgal::fast_winding_number ( const Eigen::MatrixBase< DerivedP > &  P,
const Eigen::MatrixBase< DerivedN > &  N,
const Eigen::MatrixBase< DerivedQ > &  Q,
Eigen::PlainObjectBase< DerivedWN > &  WN 
)
52 {
53 fast_winding_number(P,N,Q,2,2.0,WN);
54 }
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)
Definition fast_winding_number.cpp:13

References fast_winding_number().

+ Here is the call graph for this function:

◆ half_space_box() [1/3]

template<typename DerivedV >
IGL_INLINE void igl::copyleft::cgal::half_space_box ( const CGAL::Plane_3< CGAL::Epeck > &  P,
const Eigen::MatrixBase< DerivedV > &  V,
Eigen::Matrix< CGAL::Epeck::FT, 8, 3 > &  BV,
Eigen::Matrix< int, 12, 3 > &  BF 
)
12{
13 typedef CGAL::Plane_3<CGAL::Epeck> Plane;
14 typedef CGAL::Point_3<CGAL::Epeck> Point;
15 typedef CGAL::Vector_3<CGAL::Epeck> Vector;
16 typedef CGAL::Epeck::FT EScalar;
18 for(int v = 0;v<V.rows();v++) for(int c = 0;c<V.cols();c++) avg(c) += V(v,c);
19 avg /= V.rows();
20
21 Point o3(avg(0),avg(1),avg(2));
22 Point o2 = P.projection(o3);
23 Vector u;
24 EScalar max_sqrd = -1;
25 for(int v = 0;v<V.rows();v++)
26 {
27 Vector v2 = P.projection(Point(V(v,0),V(v,1),V(v,2))) - o2;
28 const EScalar sqrd = v2.squared_length();
29 if(max_sqrd<0 || sqrd < max_sqrd)
30 {
31 u = v2;
32 max_sqrd = sqrd;
33 }
34 }
35 // L1 bbd
36 const EScalar bbd =
37 (EScalar(V.col(0).maxCoeff())- EScalar(V.col(0).minCoeff())) +
38 (EScalar(V.col(1).maxCoeff())- EScalar(V.col(1).minCoeff())) +
39 (EScalar(V.col(2).maxCoeff())- EScalar(V.col(2).minCoeff()));
40 Vector n = P.orthogonal_vector();
41 // now we have a center o2 and a vector u to the farthest point on the plane
42 std::vector<Point> vBV;vBV.reserve(8);
43 Vector v = CGAL::cross_product(u,n);
44 // Scale u,v,n to be longer than bbd
45 const auto & longer_than = [](const EScalar min_sqr, Vector & x)
46 {
47 assert(x.squared_length() > 0);
48 while(x.squared_length() < min_sqr)
49 {
50 x = 2.*x;
51 }
52 };
53 longer_than(bbd*bbd,u);
54 longer_than(bbd*bbd,v);
55 longer_than(bbd*bbd,n);
56 vBV.emplace_back( o2 + u + v);
57 vBV.emplace_back( o2 - u + v);
58 vBV.emplace_back( o2 - u - v);
59 vBV.emplace_back( o2 + u - v);
60 vBV.emplace_back( o2 + u + v - n);
61 vBV.emplace_back( o2 - u + v - n);
62 vBV.emplace_back( o2 - u - v - n);
63 vBV.emplace_back( o2 + u - v - n);
64 BV.resize(8,3);
65 for(int b = 0;b<8;b++)
66 {
67 igl::copyleft::cgal::assign_scalar(vBV[b].x(),BV(b,0));
68 igl::copyleft::cgal::assign_scalar(vBV[b].y(),BV(b,1));
69 igl::copyleft::cgal::assign_scalar(vBV[b].z(),BV(b,2));
70 }
71 BF.resize(12,3);
72 BF<<
73 1,0,2,
74 2,0,3,
75 4,5,6,
76 4,6,7,
77 0,1,4,
78 4,1,5,
79 1,2,5,
80 5,2,6,
81 2,3,6,
82 6,3,7,
83 3,0,7,
84 7,0,4;
85}
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
const Scalar & y
Definition MathFunctions.h:552
TCoord< P > x(const P &p)
Definition geometry_traits.hpp:297

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

Referenced by half_space_box(), half_space_box(), and intersect_with_half_space().

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

◆ half_space_box() [2/3]

template<typename Derivedequ , typename DerivedV >
IGL_INLINE void igl::copyleft::cgal::half_space_box ( const Eigen::MatrixBase< Derivedequ > &  equ,
const Eigen::MatrixBase< DerivedV > &  V,
Eigen::Matrix< CGAL::Epeck::FT, 8, 3 > &  BV,
Eigen::Matrix< int, 12, 3 > &  BF 
)
108{
109 typedef CGAL::Plane_3<CGAL::Epeck> Plane;
110 Plane P(equ(0),equ(1),equ(2),equ(3));
111 return half_space_box(P,V,BV,BF);
112}
IGL_INLINE void half_space_box(const CGAL::Plane_3< CGAL::Epeck > &P, const Eigen::MatrixBase< DerivedV > &V, Eigen::Matrix< CGAL::Epeck::FT, 8, 3 > &BV, Eigen::Matrix< int, 12, 3 > &BF)
Definition half_space_box.cpp:7

References half_space_box().

+ Here is the call graph for this function:

◆ half_space_box() [3/3]

template<typename Derivedp , typename Derivedn , typename DerivedV >
IGL_INLINE void igl::copyleft::cgal::half_space_box ( const Eigen::MatrixBase< Derivedp > &  p,
const Eigen::MatrixBase< Derivedn > &  n,
const Eigen::MatrixBase< DerivedV > &  V,
Eigen::Matrix< CGAL::Epeck::FT, 8, 3 > &  BV,
Eigen::Matrix< int, 12, 3 > &  BF 
)
94{
95 typedef CGAL::Plane_3<CGAL::Epeck> Plane;
96 typedef CGAL::Point_3<CGAL::Epeck> Point;
97 typedef CGAL::Vector_3<CGAL::Epeck> Vector;
98 Plane P(Point(p(0),p(1),p(2)),Vector(n(0),n(1),n(2)));
99 return half_space_box(P,V,BV,BF);
100}

References half_space_box().

+ Here is the call graph for this function:

◆ hausdorff()

template<typename DerivedV , typename Kernel , typename Scalar >
IGL_INLINE void igl::copyleft::cgal::hausdorff ( const Eigen::MatrixBase< DerivedV > &  V,
const CGAL::AABB_tree< CGAL::AABB_traits< Kernel, CGAL::AABB_triangle_primitive< Kernel, typename std::vector< CGAL::Triangle_3< Kernel > >::iterator > > > &  treeB,
const std::vector< CGAL::Triangle_3< Kernel > > &  TB,
Scalar &  l,
Scalar &  u 
)
21{
22 // Not sure why using `auto` here doesn't work with the `hausdorff` function
23 // parameter but explicitly naming the type does...
24 const std::function<double(const double &,const double &,const double &)>
25 dist_to_B = [&treeB](
26 const double & x, const double & y, const double & z)->double
27 {
28 CGAL::Point_3<Kernel> query(x,y,z);
29 typename CGAL::AABB_tree<
30 CGAL::AABB_traits<Kernel,
31 CGAL::AABB_triangle_primitive<Kernel,
32 typename std::vector<CGAL::Triangle_3<Kernel> >::iterator
33 >
34 >
35 >::Point_and_primitive_id pp = treeB.closest_point_and_primitive(query);
36 return std::sqrt((query-pp.first).squared_length());
37 };
38 return igl::hausdorff(V,dist_to_B,l,u);
39}
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)
Definition hausdorff.cpp:17

References igl::hausdorff().

+ Here is the call graph for this function:

◆ incircle()

template<typename Scalar >
IGL_INLINE short igl::copyleft::cgal::incircle ( const Scalar  pa[2],
const Scalar  pb[2],
const Scalar  pc[2],
const Scalar  pd[2] 
)
19{
20 typedef CGAL::Exact_predicates_exact_constructions_kernel Epeck;
21 typedef CGAL::Exact_predicates_inexact_constructions_kernel Epick;
22 typedef typename std::conditional<std::is_same<Scalar, Epeck::FT>::value,
23 Epeck, Epick>::type Kernel;
24
25 switch(CGAL::side_of_oriented_circle(
26 typename Kernel::Point_2(pa[0], pa[1]),
27 typename Kernel::Point_2(pb[0], pb[1]),
28 typename Kernel::Point_2(pc[0], pc[1]),
29 typename Kernel::Point_2(pd[0], pd[1]))) {
30 case CGAL::ON_POSITIVE_SIDE:
31 return 1;
32 case CGAL::ON_NEGATIVE_SIDE:
33 return -1;
34 case CGAL::ON_ORIENTED_BOUNDARY:
35 return 0;
36 default:
37 throw "Invalid incircle result";
38 }
39}

◆ insert_into_cdt()

template<typename Kernel >
IGL_INLINE void igl::copyleft::cgal::insert_into_cdt ( const CGAL::Object &  obj,
const CGAL::Plane_3< Kernel > &  P,
CGAL::Constrained_triangulation_plus_2< CGAL::Constrained_Delaunay_triangulation_2< Kernel, CGAL::Triangulation_data_structure_2< CGAL::Triangulation_vertex_base_2< Kernel >, CGAL::Constrained_triangulation_face_base_2< Kernel > >, CGAL::Exact_intersections_tag > > &  cdt 
)
28{
29 typedef CGAL::Point_3<Kernel> Point_3;
30 typedef CGAL::Segment_3<Kernel> Segment_3;
31 typedef CGAL::Triangle_3<Kernel> Triangle_3;
32
33 if(const Segment_3 *iseg = CGAL::object_cast<Segment_3 >(&obj))
34 {
35 // Add segment constraint
36 cdt.insert_constraint( P.to_2d(iseg->vertex(0)),P.to_2d(iseg->vertex(1)));
37 }else if(const Point_3 *ipoint = CGAL::object_cast<Point_3 >(&obj))
38 {
39 // Add point
40 cdt.insert(P.to_2d(*ipoint));
41 } else if(const Triangle_3 *itri = CGAL::object_cast<Triangle_3 >(&obj))
42 {
43 // Add 3 segment constraints
44 cdt.insert_constraint( P.to_2d(itri->vertex(0)),P.to_2d(itri->vertex(1)));
45 cdt.insert_constraint( P.to_2d(itri->vertex(1)),P.to_2d(itri->vertex(2)));
46 cdt.insert_constraint( P.to_2d(itri->vertex(2)),P.to_2d(itri->vertex(0)));
47 } else if(const std::vector<Point_3 > *polyp =
48 CGAL::object_cast< std::vector<Point_3 > >(&obj))
49 {
50 const std::vector<Point_3 > & poly = *polyp;
51 const size_t m = poly.size();
52 assert(m>=2);
53 for(size_t p = 0;p<m;p++)
54 {
55 const size_t np = (p+1)%m;
56 cdt.insert_constraint(P.to_2d(poly[p]),P.to_2d(poly[np]));
57 }
58 }else {
59 throw std::runtime_error("Unknown intersection object!");
60 }
61}

Referenced by projected_cdt().

+ Here is the caller graph for this function:

◆ insphere()

template<typename Scalar >
IGL_INLINE short igl::copyleft::cgal::insphere ( const Scalar  pa[3],
const Scalar  pb[3],
const Scalar  pc[3],
const Scalar  pd[3],
const Scalar  pe[3] 
)
20{
21 typedef CGAL::Exact_predicates_exact_constructions_kernel Epeck;
22 typedef CGAL::Exact_predicates_inexact_constructions_kernel Epick;
23 typedef typename std::conditional<std::is_same<Scalar, Epeck::FT>::value,
24 Epeck, Epick>::type Kernel;
25
26 switch(CGAL::side_of_oriented_sphere(
27 typename Kernel::Point_3(pa[0], pa[1], pa[2]),
28 typename Kernel::Point_3(pb[0], pb[1], pb[2]),
29 typename Kernel::Point_3(pc[0], pc[1], pc[2]),
30 typename Kernel::Point_3(pd[0], pd[1], pd[2]),
31 typename Kernel::Point_3(pe[0], pe[1], pe[2]))) {
32 case CGAL::ON_POSITIVE_SIDE:
33 return 1;
34 case CGAL::ON_NEGATIVE_SIDE:
35 return -1;
36 case CGAL::ON_ORIENTED_BOUNDARY:
37 return 0;
38 default:
39 throw "Invalid incircle result";
40 }
41}

◆ intersect_other() [1/2]

IGL_INLINE bool igl::copyleft::cgal::intersect_other ( const Eigen::MatrixXd &  VA,
const Eigen::MatrixXi &  FA,
const Eigen::MatrixXd &  VB,
const Eigen::MatrixXi &  FB,
const bool  first_only,
Eigen::MatrixXi &  IF 
)
276{
277 Eigen::MatrixXd VVAB;
278 Eigen::MatrixXi FFAB;
279 Eigen::VectorXi JAB,IMAB;
280 return intersect_other(
281 VA,FA,VB,FB,{true,first_only},IF,VVAB,FFAB,JAB,IMAB);
282}
IGL_INLINE bool intersect_other(const Eigen::PlainObjectBase< DerivedVA > &VA, const Eigen::PlainObjectBase< DerivedFA > &FA, const Eigen::PlainObjectBase< DerivedVB > &VB, const Eigen::PlainObjectBase< DerivedFB > &FB, const RemeshSelfIntersectionsParam &params, Eigen::PlainObjectBase< DerivedIF > &IF, Eigen::PlainObjectBase< DerivedVVAB > &VVAB, Eigen::PlainObjectBase< DerivedFFAB > &FFAB, Eigen::PlainObjectBase< DerivedJAB > &JAB, Eigen::PlainObjectBase< DerivedIMAB > &IMAB)
Definition intersect_other.cpp:246

References intersect_other().

+ Here is the call graph for this function:

◆ intersect_other() [2/2]

template<typename DerivedVA , typename DerivedFA , typename DerivedVB , typename DerivedFB , typename DerivedIF , typename DerivedVVAB , typename DerivedFFAB , typename DerivedJAB , typename DerivedIMAB >
IGL_INLINE bool igl::copyleft::cgal::intersect_other ( const Eigen::PlainObjectBase< DerivedVA > &  VA,
const Eigen::PlainObjectBase< DerivedFA > &  FA,
const Eigen::PlainObjectBase< DerivedVB > &  VB,
const Eigen::PlainObjectBase< DerivedFB > &  FB,
const RemeshSelfIntersectionsParam params,
Eigen::PlainObjectBase< DerivedIF > &  IF,
Eigen::PlainObjectBase< DerivedVVAB > &  VVAB,
Eigen::PlainObjectBase< DerivedFFAB > &  FFAB,
Eigen::PlainObjectBase< DerivedJAB > &  JAB,
Eigen::PlainObjectBase< DerivedIMAB > &  IMAB 
)
257{
258 if(params.detect_only)
259 {
260 return intersect_other_helper<CGAL::Epick>
261 (VA,FA,VB,FB,params,IF,VVAB,FFAB,JAB,IMAB);
262 }else
263 {
264 return intersect_other_helper<CGAL::Epeck>
265 (VA,FA,VB,FB,params,IF,VVAB,FFAB,JAB,IMAB);
266 }
267}
bool detect_only
Definition RemeshSelfIntersectionsParam.h:21

References igl::copyleft::cgal::RemeshSelfIntersectionsParam::detect_only.

Referenced by intersect_other(), and trim_with_solid().

+ Here is the caller graph for this function:

◆ intersect_other_helper()

template<typename Kernel , typename DerivedVA , typename DerivedFA , typename DerivedVB , typename DerivedFB , typename DerivedIF , typename DerivedVVAB , typename DerivedFFAB , typename DerivedJAB , typename DerivedIMAB >
static IGL_INLINE bool igl::copyleft::cgal::intersect_other_helper ( const Eigen::PlainObjectBase< DerivedVA > &  VA,
const Eigen::PlainObjectBase< DerivedFA > &  FA,
const Eigen::PlainObjectBase< DerivedVB > &  VB,
const Eigen::PlainObjectBase< DerivedFB > &  FB,
const RemeshSelfIntersectionsParam params,
Eigen::PlainObjectBase< DerivedIF > &  IF,
Eigen::PlainObjectBase< DerivedVVAB > &  VVAB,
Eigen::PlainObjectBase< DerivedFFAB > &  FFAB,
Eigen::PlainObjectBase< DerivedJAB > &  JAB,
Eigen::PlainObjectBase< DerivedIMAB > &  IMAB 
)
static
78 {
79
80 using namespace std;
81 using namespace Eigen;
82
83 typedef typename DerivedFA::Index Index;
84 // 3D Primitives
85 typedef CGAL::Point_3<Kernel> Point_3;
86 typedef CGAL::Segment_3<Kernel> Segment_3;
87 typedef CGAL::Triangle_3<Kernel> Triangle_3;
88 typedef CGAL::Plane_3<Kernel> Plane_3;
89 typedef CGAL::Tetrahedron_3<Kernel> Tetrahedron_3;
90 // 2D Primitives
91 typedef CGAL::Point_2<Kernel> Point_2;
92 typedef CGAL::Segment_2<Kernel> Segment_2;
93 typedef CGAL::Triangle_2<Kernel> Triangle_2;
94 // 2D Constrained Delaunay Triangulation types
95 typedef CGAL::Triangulation_vertex_base_2<Kernel> TVB_2;
96 typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTAB_2;
97 typedef CGAL::Triangulation_data_structure_2<TVB_2,CTAB_2> TDS_2;
98 typedef CGAL::Exact_intersections_tag Itag;
99 // Axis-align boxes for all-pairs self-intersection detection
100 typedef std::vector<Triangle_3> Triangles;
101 typedef typename Triangles::iterator TrianglesIterator;
102 typedef typename Triangles::const_iterator TrianglesConstIterator;
103 typedef
104 CGAL::Box_intersection_d::Box_with_handle_d<double,3,TrianglesIterator>
105 Box;
106 typedef
107 std::map<Index,std::vector<std::pair<Index,CGAL::Object> > >
108 OffendingMap;
109 typedef std::map<std::pair<Index,Index>,std::vector<Index> > EdgeMap;
110 typedef std::pair<Index,Index> EMK;
111
112 Triangles TA,TB;
113 // Compute and process self intersections
116 // http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Box_intersection_d/Chapter_main.html#Section_63.5
117 // Create the corresponding vector of bounding boxes
118 std::vector<Box> A_boxes,B_boxes;
119 const auto box_up = [](Triangles & T, std::vector<Box> & boxes) -> void
120 {
121 boxes.reserve(T.size());
122 for (
123 TrianglesIterator tit = T.begin();
124 tit != T.end();
125 ++tit)
126 {
127 boxes.push_back(Box(tit->bbox(), tit));
128 }
129 };
130 box_up(TA,A_boxes);
131 box_up(TB,B_boxes);
132 OffendingMap offendingA,offendingB;
133 //EdgeMap edge2facesA,edge2facesB;
134
135 std::list<int> lIF;
136 const auto cb = [&](const Box &a, const Box &b) -> void
137 {
138 using namespace std;
139 // index in F and T
140 int fa = a.handle()-TA.begin();
141 int fb = b.handle()-TB.begin();
142 const Triangle_3 & A = *a.handle();
143 const Triangle_3 & B = *b.handle();
144 if(CGAL::do_intersect(A,B))
145 {
146 // There was an intersection
147 lIF.push_back(fa);
148 lIF.push_back(fb);
149 if(params.first_only)
150 {
152 }
153 if(!params.detect_only)
154 {
155 CGAL::Object result = CGAL::intersection(A,B);
156
157 push_result(FA,fa,fb,result,offendingA);
158 push_result(FB,fb,fa,result,offendingB);
159 }
160 }
161 };
162 try{
163 CGAL::box_intersection_d(
164 A_boxes.begin(), A_boxes.end(),
165 B_boxes.begin(), B_boxes.end(),
166 cb);
167 }catch(int e)
168 {
169 // Rethrow if not FIRST_HIT_EXCEPTION
171 {
172 throw e;
173 }
174 // Otherwise just fall through
175 }
176
177 // Convert lIF to Eigen matrix
178 assert(lIF.size()%2 == 0);
179 IF.resize(lIF.size()/2,2);
180 {
181 int i=0;
182 for(
183 list<int>::const_iterator ifit = lIF.begin();
184 ifit!=lIF.end();
185 )
186 {
187 IF(i,0) = (*ifit);
188 ifit++;
189 IF(i,1) = (*ifit);
190 ifit++;
191 i++;
192 }
193 }
194 if(!params.detect_only)
195 {
196 // Obsolete, now remesh_intersections expects a single mesh
197 // remesh_intersections(VA,FA,TA,offendingA,VVA,FFA,JA,IMA);
198 // remesh_intersections(VB,FB,TB,offendingB,VVB,FFB,JB,IMB);
199 // Combine mesh and offending maps
200 DerivedVA VAB(VA.rows()+VB.rows(),3);
201 VAB<<VA,VB;
202 DerivedFA FAB(FA.rows()+FB.rows(),3);
203 FAB<<FA,(FB.array()+VA.rows());
204 Triangles TAB;
205 TAB.reserve(TA.size()+TB.size());
206 TAB.insert(TAB.end(),TA.begin(),TA.end());
207 TAB.insert(TAB.end(),TB.begin(),TB.end());
208 OffendingMap offending;
209 //offending.reserve(offendingA.size() + offendingB.size());
210 for (const auto itr : offendingA)
211 {
212 // Remap offenders in FB to FAB
213 auto offenders = itr.second;
214 for(auto & offender : offenders)
215 {
216 offender.first += FA.rows();
217 }
218 offending[itr.first] = offenders;
219 }
220 for (const auto itr : offendingB)
221 {
222 // Store offenders for FB according to place in FAB
223 offending[FA.rows() + itr.first] = itr.second;
224 }
225
227 VAB,FAB,TAB,offending,params.stitch_all,VVAB,FFAB,JAB,IMAB);
228 }
229
230 return IF.rows() > 0;
231 }
#define IGL_FIRST_HIT_EXCEPTION
Definition intersect_other.cpp:16
IGL_INLINE void remesh_intersections(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const std::vector< CGAL::Triangle_3< Kernel > > &T, const std::map< typename DerivedF::Index, std::vector< std::pair< typename DerivedF::Index, CGAL::Object > > > &offending, bool stitch_all, Eigen::PlainObjectBase< DerivedVV > &VV, Eigen::PlainObjectBase< DerivedFF > &FF, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::PlainObjectBase< DerivedIM > &IM)
Definition remesh_intersections.cpp:58
IGL_INLINE void mesh_to_cgal_triangle_list(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, std::vector< CGAL::Triangle_3< Kernel > > &T)
Definition mesh_to_cgal_triangle_list.cpp:17
STL namespace.
bool stitch_all
Definition RemeshSelfIntersectionsParam.h:23
bool first_only
Definition RemeshSelfIntersectionsParam.h:22

References igl::copyleft::cgal::RemeshSelfIntersectionsParam::detect_only, igl::copyleft::cgal::RemeshSelfIntersectionsParam::first_only, IGL_FIRST_HIT_EXCEPTION, mesh_to_cgal_triangle_list(), push_result(), remesh_intersections(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), and igl::copyleft::cgal::RemeshSelfIntersectionsParam::stitch_all.

+ Here is the call graph for this function:

◆ intersect_with_half_space() [1/3]

template<typename DerivedV , typename DerivedF , typename DerivedVC , typename DerivedFC , typename DerivedJ >
IGL_INLINE bool igl::copyleft::cgal::intersect_with_half_space ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const CGAL::Plane_3< CGAL::Epeck > &  P,
Eigen::PlainObjectBase< DerivedVC > &  VC,
Eigen::PlainObjectBase< DerivedFC > &  FC,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
62{
65 half_space_box(P,V,BV,BF);
66 // Disturbingly, (BV,BF) must be first argument
67 const bool ret = mesh_boolean(BV,BF,V,F,MESH_BOOLEAN_TYPE_INTERSECT,VC,FC,J);
68 // But now J is wrong...
69 std::for_each(
70 J.data(),
71 J.data()+J.size(),
72 [&BF,&F](typename DerivedJ::Scalar & j)
73 {j = (j<BF.rows()?F.rows()+j:j-BF.rows());}
74 );
75 return ret;
76}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar * data() const
Definition PlainObjectBase.h:255
IGL_INLINE bool mesh_boolean(const Eigen::MatrixBase< DerivedVA > &VA, const Eigen::MatrixBase< DerivedFA > &FA, const Eigen::MatrixBase< DerivedVB > &VB, const Eigen::MatrixBase< DerivedFB > &FB, const MeshBooleanType &type, Eigen::PlainObjectBase< DerivedVC > &VC, Eigen::PlainObjectBase< DerivedFC > &FC, Eigen::PlainObjectBase< DerivedJ > &J)
Definition mesh_boolean.cpp:43

References Eigen::PlainObjectBase< Derived >::data(), half_space_box(), mesh_boolean(), and igl::MESH_BOOLEAN_TYPE_INTERSECT.

+ Here is the call graph for this function:

◆ intersect_with_half_space() [2/3]

template<typename DerivedV , typename DerivedF , typename Derivedequ , typename DerivedVC , typename DerivedFC , typename DerivedJ >
IGL_INLINE bool igl::copyleft::cgal::intersect_with_half_space ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< Derivedequ > &  equ,
Eigen::PlainObjectBase< DerivedVC > &  VC,
Eigen::PlainObjectBase< DerivedFC > &  FC,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
43{
44 typedef CGAL::Plane_3<CGAL::Epeck> Plane;
45 Plane P(equ(0),equ(1),equ(2),equ(3));
46 return intersect_with_half_space(V,F,P,VC,FC,J);
47}
IGL_INLINE bool intersect_with_half_space(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< Derivedp > &p, const Eigen::MatrixBase< Derivedn > &n, Eigen::PlainObjectBase< DerivedVC > &VC, Eigen::PlainObjectBase< DerivedFC > &FC, Eigen::PlainObjectBase< DerivedJ > &J)
Definition intersect_with_half_space.cpp:13

References intersect_with_half_space().

+ Here is the call graph for this function:

◆ intersect_with_half_space() [3/3]

template<typename DerivedV , typename DerivedF , typename Derivedp , typename Derivedn , typename DerivedVC , typename DerivedFC , typename DerivedJ >
IGL_INLINE bool igl::copyleft::cgal::intersect_with_half_space ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const Eigen::MatrixBase< Derivedp > &  p,
const Eigen::MatrixBase< Derivedn > &  n,
Eigen::PlainObjectBase< DerivedVC > &  VC,
Eigen::PlainObjectBase< DerivedFC > &  FC,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
21{
22 typedef CGAL::Plane_3<CGAL::Epeck> Plane;
23 typedef CGAL::Point_3<CGAL::Epeck> Point;
24 typedef CGAL::Vector_3<CGAL::Epeck> Vector;
25 Plane P(Point(p(0),p(1),p(2)),Vector(n(0),n(1),n(2)));
26 return intersect_with_half_space(V,F,P,VC,FC,J);
27}

References intersect_with_half_space().

Referenced by intersect_with_half_space(), and intersect_with_half_space().

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

◆ lexicographic_triangulation()

template<typename DerivedP , typename DerivedF >
IGL_INLINE void igl::copyleft::cgal::lexicographic_triangulation ( const Eigen::PlainObjectBase< DerivedP > &  P,
Eigen::PlainObjectBase< DerivedF > &  F 
)
21{
22 typedef typename DerivedP::Scalar Scalar;
23 igl::lexicographic_triangulation(P, orient2D<Scalar>, F);
24}
IGL_INLINE void lexicographic_triangulation(const Eigen::PlainObjectBase< DerivedP > &P, Orient2D orient2D, Eigen::PlainObjectBase< DerivedF > &F)
Definition lexicographic_triangulation.cpp:21

References igl::lexicographic_triangulation().

+ Here is the call graph for this function:

◆ mesh_boolean() [1/7]

template<typename DerivedVA , typename DerivedFA , typename DerivedVB , typename DerivedFB , typename DerivedVC , typename DerivedFC >
IGL_INLINE bool igl::copyleft::cgal::mesh_boolean ( const Eigen::MatrixBase< DerivedVA > &  VA,
const Eigen::MatrixBase< DerivedFA > &  FA,
const Eigen::MatrixBase< DerivedVB > &  VB,
const Eigen::MatrixBase< DerivedFB > &  FB,
const MeshBooleanType type,
Eigen::PlainObjectBase< DerivedVC > &  VC,
Eigen::PlainObjectBase< DerivedFC > &  FC 
)

References mesh_boolean().

+ Here is the call graph for this function:

◆ mesh_boolean() [2/7]

template<typename DerivedVA , typename DerivedFA , typename DerivedVB , typename DerivedFB , typename DerivedVC , typename DerivedFC , typename DerivedJ >
IGL_INLINE bool igl::copyleft::cgal::mesh_boolean ( const Eigen::MatrixBase< DerivedVA > &  VA,
const Eigen::MatrixBase< DerivedFA > &  FA,
const Eigen::MatrixBase< DerivedVB > &  VB,
const Eigen::MatrixBase< DerivedFB > &  FB,
const MeshBooleanType type,
Eigen::PlainObjectBase< DerivedVC > &  VC,
Eigen::PlainObjectBase< DerivedFC > &  FC,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
52{
53 std::function<int(const int, const int)> keep;
54 std::function<int(const Eigen::Matrix<int,1,Eigen::Dynamic>) > wind_num_op;
55 mesh_boolean_type_to_funcs(type,wind_num_op,keep);
56 return mesh_boolean(VA,FA,VB,FB,wind_num_op,keep,VC,FC,J);
57}
IGL_INLINE void mesh_boolean_type_to_funcs(const MeshBooleanType &type, std::function< int(const Eigen::Matrix< int, 1, Eigen::Dynamic >) > &wind_num_op, std::function< int(const int, const int)> &keep)
Definition mesh_boolean_type_to_funcs.cpp:4

References mesh_boolean(), and mesh_boolean_type_to_funcs().

Referenced by igl::copyleft::cgal::CSGTree::CSGTree(), intersect_with_half_space(), mesh_boolean(), mesh_boolean(), mesh_boolean(), mesh_boolean(), mesh_boolean(), mesh_boolean(), minkowski_sum(), minkowski_sum(), Slic3r::MeshBoolean::minus(), Slic3r::MeshBoolean::self_union(), and wire_mesh().

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

◆ mesh_boolean() [3/7]

template<typename DerivedVA , typename DerivedFA , typename DerivedVB , typename DerivedFB , typename DerivedVC , typename DerivedFC , typename DerivedJ >
IGL_INLINE bool igl::copyleft::cgal::mesh_boolean ( const Eigen::MatrixBase< DerivedVA > &  VA,
const Eigen::MatrixBase< DerivedFA > &  FA,
const Eigen::MatrixBase< DerivedVB > &  VB,
const Eigen::MatrixBase< DerivedFB > &  FB,
const std::function< int(const Eigen::Matrix< int, 1, Eigen::Dynamic >) > &  wind_num_op,
const std::function< int(const int, const int)> &  keep,
Eigen::PlainObjectBase< DerivedVC > &  VC,
Eigen::PlainObjectBase< DerivedFC > &  FC,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
98{
99 // Generate combined mesh (VA,FA,VB,FB) -> (V,F)
100 Eigen::Matrix<size_t,2,1> sizes(FA.rows(),FB.rows());
101 // TODO: This is a precision template **bug** that results in failure to
102 // compile. If DerivedVA::Scalar is double and DerivedVB::Scalar is
103 // CGAL::Epeck::FT then the following assignment will not compile. This
104 // implies that VA must have the trumping precision (and a valid assignment
105 // operator from VB's type).
107 DerivedFC FF(FA.rows() + FB.rows(), 3);
108 // Can't use comma initializer
109 for(int a = 0;a<VA.rows();a++)
110 {
111 for(int d = 0;d<3;d++) VV(a,d) = VA(a,d);
112 }
113 for(int b = 0;b<VB.rows();b++)
114 {
115 for(int d = 0;d<3;d++) VV(VA.rows()+b,d) = VB(b,d);
116 }
117 FF.block(0, 0, FA.rows(), 3) = FA;
118 // Eigen struggles to assign nothing to nothing and will assert if FB is empty
119 if(FB.rows() > 0)
120 {
121 FF.block(FA.rows(), 0, FB.rows(), 3) = FB.array() + VA.rows();
122 }
123 return mesh_boolean(VV,FF,sizes,wind_num_op,keep,VC,FC,J);
124}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ArrayWrapper< Derived > array()
Definition MatrixBase.h:317

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

+ Here is the call graph for this function:

◆ mesh_boolean() [4/7]

template<typename DerivedVA , typename DerivedFA , typename DerivedVB , typename DerivedFB , typename DerivedVC , typename DerivedFC , typename DerivedJ >
IGL_INLINE bool igl::copyleft::cgal::mesh_boolean ( const Eigen::MatrixBase< DerivedVA > &  VA,
const Eigen::MatrixBase< DerivedFA > &  FA,
const Eigen::MatrixBase< DerivedVB > &  VB,
const Eigen::MatrixBase< DerivedFB > &  FB,
const std::string &  type_str,
Eigen::PlainObjectBase< DerivedVC > &  VC,
Eigen::PlainObjectBase< DerivedFC > &  FC,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
75{
76 return mesh_boolean(
77 VA,FA,VB,FB,string_to_mesh_boolean_type(type_str),VC,FC,J);
78}
IGL_INLINE bool string_to_mesh_boolean_type(const std::string &s, MeshBooleanType &type)
Definition string_to_mesh_boolean_type.cpp:6

References mesh_boolean(), and string_to_mesh_boolean_type().

+ Here is the call graph for this function:

◆ mesh_boolean() [5/7]

template<typename DerivedVV , typename DerivedFF , typename Derivedsizes , typename DerivedVC , typename DerivedFC , typename DerivedJ >
IGL_INLINE bool igl::copyleft::cgal::mesh_boolean ( const Eigen::MatrixBase< DerivedVV > &  VV,
const Eigen::MatrixBase< DerivedFF > &  FF,
const Eigen::MatrixBase< Derivedsizes > &  sizes,
const std::function< int(const Eigen::Matrix< int, 1, Eigen::Dynamic >) > &  wind_num_op,
const std::function< int(const int, const int)> &  keep,
Eigen::PlainObjectBase< DerivedVC > &  VC,
Eigen::PlainObjectBase< DerivedFC > &  FC,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
188{
189#ifdef MESH_BOOLEAN_TIMING
190 const auto & tictoc = []() -> double
191 {
192 static double t_start = igl::get_seconds();
193 double diff = igl::get_seconds()-t_start;
194 t_start += diff;
195 return diff;
196 };
197 const auto log_time = [&](const std::string& label) -> void {
198 std::cout << "mesh_boolean." << label << ": "
199 << tictoc() << std::endl;
200 };
201 tictoc();
202#endif
203 typedef typename DerivedVC::Scalar Scalar;
204 typedef CGAL::Epeck Kernel;
205 typedef Kernel::FT ExactScalar;
208 typedef Eigen::Matrix<
209 ExactScalar,
212 DerivedVC::IsRowMajor> MatrixXES;
213 MatrixXES V;
214 DerivedFC F;
215 VectorXJ CJ;
216 {
217 Eigen::VectorXi I;
219 params.stitch_all = true;
220 MatrixXES Vr;
221 DerivedFC Fr;
222 Eigen::MatrixXi IF;
224 VV, FF, params, Vr, Fr, IF, CJ, I);
225 assert(I.size() == Vr.rows());
226 // Merge coinciding vertices into non-manifold vertices.
227 std::for_each(Fr.data(), Fr.data()+Fr.size(),
228 [&I](typename DerivedFC::Scalar& a) { a=I[a]; });
229 // Remove unreferenced vertices.
230 Eigen::VectorXi UIM;
231 igl::remove_unreferenced(Vr, Fr, V, F, UIM);
232 }
233#ifdef MESH_BOOLEAN_TIMING
234 log_time("resolve_self_intersection");
235#endif
236
237 // Compute edges of (F) --> (E,uE,EMAP,uE2E)
238 Eigen::MatrixXi E, uE;
239 Eigen::VectorXi EMAP;
240 std::vector<std::vector<size_t> > uE2E;
241 igl::unique_edge_map(F, E, uE, EMAP, uE2E);
242
243 // Compute patches (F,EMAP,uE2E) --> (P)
244 Eigen::VectorXi P;
245 const size_t num_patches = igl::extract_manifold_patches(F, EMAP, uE2E, P);
246#ifdef MESH_BOOLEAN_TIMING
247 log_time("patch_extraction");
248#endif
249
250 // Compute cells (V,F,P,E,uE,EMAP) -> (per_patch_cells)
251 Eigen::MatrixXi per_patch_cells;
252 const size_t num_cells =
254 V, F, P, E, uE, uE2E, EMAP, per_patch_cells);
255#ifdef MESH_BOOLEAN_TIMING
256 log_time("cell_extraction");
257#endif
258
259 // Compute winding numbers on each side of each facet.
260 const size_t num_faces = F.rows();
261 // W(f,:) --> [w1out,w1in,w2out,w2in, ... wnout,wnint] winding numbers above
262 // and below each face w.r.t. each input mesh, so that W(f,2*i) is the
263 // winding number above face f w.r.t. input i, and W(f,2*i+1) is the winding
264 // number below face f w.r.t. input i.
265 Eigen::MatrixXi W;
266 // labels(f) = i means that face f comes from mesh i
267 Eigen::VectorXi labels(num_faces);
268 // cumulative sizes
269 Derivedsizes cumsizes;
270 igl::cumsum(sizes,1,cumsizes);
271 const size_t num_inputs = sizes.size();
272 std::transform(
273 CJ.data(),
274 CJ.data()+CJ.size(),
275 labels.data(),
276 // Determine which input mesh birth face i comes from
277 [&num_inputs,&cumsizes](int i)->int
278 {
279 for(int k = 0;k<num_inputs;k++)
280 {
281 if(i<cumsizes(k)) return k;
282 }
283 assert(false && "Birth parent index out of range");
284 return -1;
285 });
286 bool valid = true;
287 if (num_faces > 0)
288 {
289 valid = valid &
291 V, F, uE, uE2E, num_patches, P, num_cells, per_patch_cells, labels, W);
292 } else
293 {
294 W.resize(0, 2*num_inputs);
295 }
296 assert((size_t)W.rows() == num_faces);
297 // If W doesn't have enough columns, pad with zeros
298 if (W.cols() <= 2*num_inputs)
299 {
300 const int old_ncols = W.cols();
301 W.conservativeResize(num_faces,2*num_inputs);
302 W.rightCols(2*num_inputs-old_ncols).setConstant(0);
303 }
304 assert((size_t)W.cols() == 2*num_inputs);
305#ifdef MESH_BOOLEAN_TIMING
306 log_time("propagate_input_winding_number");
307#endif
308
309 // Compute resulting winding number.
310 Eigen::MatrixXi Wr(num_faces, 2);
311 for (size_t i=0; i<num_faces; i++)
312 {
313 // Winding number vectors above and below
314 Eigen::RowVectorXi w_out(1,num_inputs), w_in(1,num_inputs);
315 for(size_t k =0;k<num_inputs;k++)
316 {
317 w_out(k) = W(i,2*k+0);
318 w_in(k) = W(i,2*k+1);
319 }
320 Wr(i,0) = wind_num_op(w_out);
321 Wr(i,1) = wind_num_op(w_in);
322 }
323#ifdef MESH_BOOLEAN_TIMING
324 log_time("compute_output_winding_number");
325#endif
326
327#ifdef SMALL_CELL_REMOVAL
329 V, F, num_patches, P, num_cells, per_patch_cells, 1e-3, Wr);
330#endif
331
332 // Extract boundary separating inside from outside.
333 auto index_to_signed_index = [&](size_t i, bool ori) -> int
334 {
335 return (i+1)*(ori?1:-1);
336 };
337 //auto signed_index_to_index = [&](int i) -> size_t {
338 // return abs(i) - 1;
339 //};
340 std::vector<int> selected;
341 for(size_t i=0; i<num_faces; i++)
342 {
343 auto should_keep = keep(Wr(i,0), Wr(i,1));
344 if (should_keep > 0)
345 {
346 selected.push_back(index_to_signed_index(i, true));
347 } else if (should_keep < 0)
348 {
349 selected.push_back(index_to_signed_index(i, false));
350 }
351 }
352
353 const size_t num_selected = selected.size();
354 DerivedFC kept_faces(num_selected, 3);
355 DerivedJ kept_face_indices(num_selected, 1);
356 for (size_t i=0; i<num_selected; i++)
357 {
358 size_t idx = abs(selected[i]) - 1;
359 if (selected[i] > 0)
360 {
361 kept_faces.row(i) = F.row(idx);
362 } else
363 {
364 kept_faces.row(i) = F.row(idx).reverse();
365 }
366 kept_face_indices(i, 0) = CJ[idx];
367 }
368#ifdef MESH_BOOLEAN_TIMING
369 log_time("extract_output");
370#endif
371
372 // Finally, remove duplicated faces and unreferenced vertices.
373 {
374 DerivedFC G;
375 DerivedJ JJ;
376 igl::resolve_duplicated_faces(kept_faces, G, JJ);
377 igl::slice(kept_face_indices, JJ, 1, J);
378
379#ifdef DOUBLE_CHECK_EXACT_OUTPUT
380 {
381 // Sanity check on exact output.
383 params.detect_only = true;
384 params.first_only = true;
385 MatrixXES dummy_VV;
386 DerivedFC dummy_FF, dummy_IF;
387 Eigen::VectorXi dummy_J, dummy_IM;
389 Kernel,
390 MatrixXES, DerivedFC,
391 MatrixXES, DerivedFC,
392 DerivedFC,
393 Eigen::VectorXi,
394 Eigen::VectorXi
395 > checker(V, G, params,
396 dummy_VV, dummy_FF, dummy_IF, dummy_J, dummy_IM);
397 if (checker.count != 0)
398 {
399 throw "Self-intersection not fully resolved.";
400 }
401 }
402#endif
403
404 MatrixX3S Vs;
405 assign(V,Vs);
406 Eigen::VectorXi newIM;
407 igl::remove_unreferenced(Vs,G,VC,FC,newIM);
408 }
409#ifdef MESH_BOOLEAN_TIMING
410 log_time("clean_up");
411#endif
412 return valid;
413}
Definition SelfIntersectMesh.h:50
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half abs(const half &a)
Definition Half.h:445
const int Dynamic
Definition Constants.h:21
IGL_INLINE void relabel_small_immersed_cells(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const size_t num_patches, const Eigen::PlainObjectBase< DerivedP > &P, const size_t num_cells, const Eigen::PlainObjectBase< DerivedC > &C, const FT vol_threashold, Eigen::PlainObjectBase< DerivedW > &W)
Definition relabel_small_immersed_cells.cpp:24
IGL_INLINE void remesh_self_intersections(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const RemeshSelfIntersectionsParam &params, Eigen::PlainObjectBase< DerivedVV > &VV, Eigen::PlainObjectBase< DerivedFF > &FF, Eigen::PlainObjectBase< DerivedIF > &IF, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::PlainObjectBase< DerivedIM > &IM)
Definition remesh_self_intersections.cpp:22
IGL_INLINE bool propagate_winding_numbers(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedL > &labels, Eigen::PlainObjectBase< DerivedW > &W)
Definition propagate_winding_numbers.cpp:39
IGL_INLINE void resolve_duplicated_faces(const Eigen::PlainObjectBase< DerivedF1 > &F1, Eigen::PlainObjectBase< DerivedF2 > &F2, Eigen::PlainObjectBase< DerivedJ > &J)
Definition resolve_duplicated_faces.cpp:19
IGL_INLINE void cumsum(const Eigen::MatrixBase< DerivedX > &X, const int dim, Eigen::PlainObjectBase< DerivedY > &Y)
Definition cumsum.cpp:13
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
Definition RemeshSelfIntersectionsParam.h:20

References igl::cumsum(), Eigen::Dynamic, extract_cells(), igl::extract_manifold_patches(), igl::get_seconds(), remesh_self_intersections(), igl::remove_unreferenced(), igl::copyleft::cgal::RemeshSelfIntersectionsParam::stitch_all, and igl::unique_edge_map().

+ Here is the call graph for this function:

◆ mesh_boolean() [6/7]

template<typename DerivedV , typename DerivedF , typename DerivedVC , typename DerivedFC , typename DerivedJ >
IGL_INLINE bool igl::copyleft::cgal::mesh_boolean ( const std::vector< DerivedV > &  Vlist,
const std::vector< DerivedF > &  Flist,
const MeshBooleanType type,
Eigen::PlainObjectBase< DerivedVC > &  VC,
Eigen::PlainObjectBase< DerivedFC > &  FC,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
161{
162 DerivedV VV;
163 DerivedF FF;
165 igl::combine(Vlist,Flist,VV,FF,Vsizes,Fsizes);
166 std::function<int(const int, const int)> keep;
167 std::function<int(const Eigen::Matrix<int,1,Eigen::Dynamic>) > wind_num_op;
168 mesh_boolean_type_to_funcs(type,wind_num_op,keep);
169 return mesh_boolean(VV,FF,Fsizes,wind_num_op,keep,VC,FC,J);
170}
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 igl::combine(), mesh_boolean(), and mesh_boolean_type_to_funcs().

+ Here is the call graph for this function:

◆ mesh_boolean() [7/7]

template<typename DerivedV , typename DerivedF , typename DerivedVC , typename DerivedFC , typename DerivedJ >
IGL_INLINE bool igl::copyleft::cgal::mesh_boolean ( const std::vector< DerivedV > &  Vlist,
const std::vector< DerivedF > &  Flist,
const std::function< int(const Eigen::Matrix< int, 1, Eigen::Dynamic >) > &  wind_num_op,
const std::function< int(const int, const int)> &  keep,
Eigen::PlainObjectBase< DerivedVC > &  VC,
Eigen::PlainObjectBase< DerivedFC > &  FC,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
140{
141 DerivedV VV;
142 DerivedF FF;
144 igl::combine(Vlist,Flist,VV,FF,Vsizes,Fsizes);
145 return mesh_boolean(VV,FF,Fsizes,wind_num_op,keep,VC,FC,J);
146}

References igl::combine(), and mesh_boolean().

+ Here is the call graph for this function:

◆ mesh_boolean_type_to_funcs()

IGL_INLINE void igl::copyleft::cgal::mesh_boolean_type_to_funcs ( const MeshBooleanType type,
std::function< int(const Eigen::Matrix< int, 1, Eigen::Dynamic >) > &  wind_num_op,
std::function< int(const int, const int)> &  keep 
)
8{
9 switch (type)
10 {
12 wind_num_op = BinaryUnion();
13 keep = KeepInside();
14 return;
16 wind_num_op = BinaryIntersect();
17 keep = KeepInside();
18 return;
20 wind_num_op = BinaryMinus();
21 keep = KeepInside();
22 return;
24 wind_num_op = BinaryXor();
25 keep = KeepInside();
26 return;
28 wind_num_op = BinaryResolve();
29 keep = KeepAll();
30 return;
31 default:
32 assert(false && "Unsupported boolean type.");
33 return;
34 }
35}
Definition BinaryWindingNumberOperations.h:153
Definition BinaryWindingNumberOperations.h:142
@ 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

References igl::MESH_BOOLEAN_TYPE_INTERSECT, igl::MESH_BOOLEAN_TYPE_MINUS, igl::MESH_BOOLEAN_TYPE_RESOLVE, igl::MESH_BOOLEAN_TYPE_UNION, and igl::MESH_BOOLEAN_TYPE_XOR.

Referenced by mesh_boolean(), and mesh_boolean().

+ Here is the caller graph for this function:

◆ mesh_to_cgal_triangle_list()

template<typename DerivedV , typename DerivedF , typename Kernel >
IGL_INLINE void igl::copyleft::cgal::mesh_to_cgal_triangle_list ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
std::vector< CGAL::Triangle_3< Kernel > > &  T 
)
21{
22 typedef CGAL::Point_3<Kernel> Point_3;
23 typedef CGAL::Triangle_3<Kernel> Triangle_3;
24 // Must be 3D
25 assert(V.cols() == 3);
26 // **Copy** to convert to output type (this is especially/only needed if the
27 // input type DerivedV::Scalar is CGAL::Epeck
29 typename Kernel::FT,
30 DerivedV::RowsAtCompileTime,
31 DerivedV::ColsAtCompileTime>
32 KV(V.rows(),V.cols());
33 assign(V,KV);
34 // Must be triangles
35 assert(F.cols() == 3);
36 T.reserve(F.rows());
37 // Loop over faces
38 for(int f = 0;f<(int)F.rows();f++)
39 {
40 T.push_back(
41 Triangle_3(
42 Point_3( KV(F(f,0),0), KV(F(f,0),1), KV(F(f,0),2)),
43 Point_3( KV(F(f,1),0), KV(F(f,1),1), KV(F(f,1),2)),
44 Point_3( KV(F(f,2),0), KV(F(f,2),1), KV(F(f,2),2))));
45 }
46}

References assign().

Referenced by igl::copyleft::cgal::SelfIntersectMesh< Kernel, DerivedV, DerivedF, DerivedVV, DerivedFF, DerivedIF, DerivedJ, DerivedIM >::SelfIntersectMesh(), intersect_other_helper(), and point_mesh_squared_distance_precompute().

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

◆ mesh_to_polyhedron()

template<typename Polyhedron >
IGL_INLINE bool igl::copyleft::cgal::mesh_to_polyhedron ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
Polyhedron &  poly 
)
18{
19 typedef typename Polyhedron::HalfedgeDS HalfedgeDS;
20 // Postcondition: hds is a valid polyhedral surface.
21 CGAL::Polyhedron_incremental_builder_3<HalfedgeDS> B(poly.hds());
22 B.begin_surface(V.rows(),F.rows());
23 typedef typename HalfedgeDS::Vertex Vertex;
24 typedef typename Vertex::Point Point;
25 assert(V.cols() == 3 && "V must be #V by 3");
26 for(int v = 0;v<V.rows();v++)
27 {
28 B.add_vertex(Point(V(v,0),V(v,1),V(v,2)));
29 }
30 assert(F.cols() == 3 && "F must be #F by 3");
31 for(int f=0;f<F.rows();f++)
32 {
33 B.begin_facet();
34 for(int c = 0;c<3;c++)
35 {
36 B.add_vertex_to_facet(F(f,c));
37 }
38 B.end_facet();
39 }
40 if(B.error())
41 {
42 B.rollback();
43 return false;
44 }
45 B.end_surface();
46 return poly.is_valid();
47}

◆ minkowski_sum() [1/3]

template<typename DerivedVA , typename DerivedFA , typename sType , int sCols, int sOptions, typename dType , int dCols, int dOptions, typename DerivedW , typename DerivedG , typename DerivedJ >
IGL_INLINE void igl::copyleft::cgal::minkowski_sum ( const Eigen::MatrixBase< DerivedVA > &  VA,
const Eigen::MatrixBase< DerivedFA > &  FA,
const Eigen::Matrix< sType, 1, sCols, sOptions > &  s,
const Eigen::Matrix< dType, 1, dCols, dOptions > &  d,
const bool  resolve_overlaps,
Eigen::PlainObjectBase< DerivedW > &  W,
Eigen::PlainObjectBase< DerivedG > &  G,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
166{
167 using namespace Eigen;
168 using namespace std;
169 assert(s.cols() == 3 && "s should be a 3d point");
170 assert(d.cols() == 3 && "d should be a 3d point");
171 // silly base case
172 if(FA.size() == 0)
173 {
174 W.resize(0,3);
175 G.resize(0,3);
176 return;
177 }
178 const int dim = VA.cols();
179 assert(dim == 3 && "dim must be 3D");
180 assert(s.size() == 3 && "s must be 3D point");
181 assert(d.size() == 3 && "d must be 3D point");
182 // segment vector
183 const CGAL::Vector_3<CGAL::Epeck> v(d(0)-s(0),d(1)-s(1),d(2)-s(2));
184 // number of vertices
185 const int n = VA.rows();
186 // duplicate vertices at s and d, we'll remove unreferernced later
187 W.resize(2*n,dim);
188 for(int i = 0;i<n;i++)
189 {
190 for(int j = 0;j<dim;j++)
191 {
192 W (i,j) = VA(i,j) + s(j);
193 W(i+n,j) = VA(i,j) + d(j);
194 }
195 }
196 // number of faces
197 const int m = FA.rows();
200 // Nevermind, actually P = !N
201 Matrix<bool,Dynamic,1> P(m,1),N(m,1);
202 // loop over faces
203 int mp = 0,mn = 0;
204 for(int f = 0;f<m;f++)
205 {
206 const CGAL::Plane_3<CGAL::Epeck> plane(
207 CGAL::Point_3<CGAL::Epeck>(VA(FA(f,0),0),VA(FA(f,0),1),VA(FA(f,0),2)),
208 CGAL::Point_3<CGAL::Epeck>(VA(FA(f,1),0),VA(FA(f,1),1),VA(FA(f,1),2)),
209 CGAL::Point_3<CGAL::Epeck>(VA(FA(f,2),0),VA(FA(f,2),1),VA(FA(f,2),2)));
210 const auto normal = plane.orthogonal_vector();
211 const auto dt = normal * v;
212 if(dt > 0)
213 {
214 P(f) = true;
215 N(f) = false;
216 mp++;
217 }else
218 //}else if(dt < 0)
219 {
220 P(f) = false;
221 N(f) = true;
222 mn++;
223 //}else
224 //{
225 // P(f) = false;
226 // N(f) = false;
227 }
228 }
229
232 MatrixXI GT(mp+mn,3);
233 GT<< slice_mask(FA,N,1), slice_mask((FA.array()+n).eval(),P,1);
234 // J indexes FA for parts at s and m+FA for parts at d
235 J.derived() = igl::LinSpaced<DerivedJ >(m,0,m-1);
236 DerivedJ JT(mp+mn);
237 JT << slice_mask(J,P,1), slice_mask(J,N,1);
238 JT.block(mp,0,mn,1).array()+=m;
239
240 // Original non-co-planar faces with positively oriented reversed
241 MatrixXI BA(mp+mn,3);
242 BA << slice_mask(FA,P,1).rowwise().reverse(), slice_mask(FA,N,1);
243 // Quads along **all** sides
244 MatrixXI GQ((mp+mn)*3,4);
245 GQ<<
246 BA.col(1), BA.col(0), BA.col(0).array()+n, BA.col(1).array()+n,
247 BA.col(2), BA.col(1), BA.col(1).array()+n, BA.col(2).array()+n,
248 BA.col(0), BA.col(2), BA.col(2).array()+n, BA.col(0).array()+n;
249
250 MatrixXI uGQ;
251 VectorXI S,sI,sJ;
252 // Inputs:
253 // F #F by d list of polygons
254 // Outputs:
255 // S #uF list of signed incidences for each unique face
256 // uF #uF by d list of unique faces
257 // I #uF index vector so that uF = sort(F,2)(I,:)
258 // J #F index vector so that sort(F,2) = uF(J,:)
259 [](
260 const MatrixXI & F,
261 VectorXI & S,
262 MatrixXI & uF,
263 VectorXI & I,
264 VectorXI & J)
265 {
266 const int m = F.rows();
267 const int d = F.cols();
268 MatrixXI sF = F;
269 const auto MN = sF.rowwise().minCoeff().eval();
270 // rotate until smallest index is first
271 for(int p = 0;p<d;p++)
272 {
273 for(int f = 0;f<m;f++)
274 {
275 if(sF(f,0) != MN(f))
276 {
277 for(int r = 0;r<d-1;r++)
278 {
279 std::swap(sF(f,r),sF(f,r+1));
280 }
281 }
282 }
283 }
284 // swap orienation so that last index is greater than first
285 for(int f = 0;f<m;f++)
286 {
287 if(sF(f,d-1) < sF(f,1))
288 {
289 sF.block(f,1,1,d-1) = sF.block(f,1,1,d-1).reverse().eval();
290 }
291 }
293 {
294 VectorXI P = igl::LinSpaced<VectorXI >(d,0,d-1);
295 for(int p = 0;p<d;p++)
296 {
297 for(int f = 0;f<m;f++)
298 {
299 bool all = true;
300 for(int r = 0;r<d;r++)
301 {
302 all = all && (sF(f,P(r)) == F(f,r));
303 }
304 M(f) = M(f) || all;
305 }
306 for(int r = 0;r<d-1;r++)
307 {
308 std::swap(P(r),P(r+1));
309 }
310 }
311 }
312 unique_rows(sF,uF,I,J);
313 S = VectorXI::Zero(uF.rows(),1);
314 assert(m == J.rows());
315 for(int f = 0;f<m;f++)
316 {
317 S(J(f)) += M(f) ? 1 : -1;
318 }
319 }(MatrixXI(GQ),S,uGQ,sI,sJ);
320 assert(S.rows() == uGQ.rows());
321 const int nq = (S.array().abs()==2).count();
322 GQ.resize(nq,4);
323 {
324 int k = 0;
325 for(int q = 0;q<uGQ.rows();q++)
326 {
327 switch(S(q))
328 {
329 case -2:
330 GQ.row(k++) = uGQ.row(q).reverse().eval();
331 break;
332 case 2:
333 GQ.row(k++) = uGQ.row(q);
334 break;
335 default:
336 // do not add
337 break;
338 }
339 }
340 assert(nq == k);
341 }
342
343 G.resize(GT.rows()+2*GQ.rows(),3);
344 G<<
345 GT,
346 GQ.col(0), GQ.col(1), GQ.col(2),
347 GQ.col(0), GQ.col(2), GQ.col(3);
348 J.resize(JT.rows()+2*GQ.rows(),1);
349 J<<JT,DerivedJ::Constant(2*GQ.rows(),1,2*m+1);
350 if(resolve_overlaps)
351 {
354 DerivedW(W),DerivedG(G),
356 MESH_BOOLEAN_TYPE_UNION,
357 W,G,SJ);
358 J.derived() = slice(DerivedJ(J),SJ,1);
359 }
360}
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
IGL_INLINE void all(const Eigen::SparseMatrix< AType > &A, const int dim, Eigen::PlainObjectBase< DerivedB > &B)
Definition all.cpp:13
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
#define GT(x, y)
Definition priorityq.c:88

References igl::all(), Eigen::MatrixBase< Derived >::array(), Eigen::PlainObjectBase< Derived >::cols(), igl::count(), GT, mesh_boolean(), igl::MESH_BOOLEAN_TYPE_UNION, Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), igl::slice(), igl::slice_mask(), and igl::unique_rows().

+ Here is the call graph for this function:

◆ minkowski_sum() [2/3]

template<typename DerivedVA , typename DerivedFA , typename sType , int sCols, int sOptions, typename dType , int dCols, int dOptions, typename DerivedW , typename DerivedG , typename DerivedJ >
IGL_INLINE void igl::copyleft::cgal::minkowski_sum ( const Eigen::MatrixBase< DerivedVA > &  VA,
const Eigen::MatrixBase< DerivedFA > &  FA,
const Eigen::Matrix< sType, 1, sCols, sOptions > &  s,
const Eigen::Matrix< dType, 1, dCols, dOptions > &  d,
Eigen::PlainObjectBase< DerivedW > &  W,
Eigen::PlainObjectBase< DerivedG > &  G,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
378{
379 return minkowski_sum(VA,FA,s,d,true,W,G,J);
380}
IGL_INLINE void minkowski_sum(const Eigen::MatrixBase< DerivedVA > &VA, const Eigen::MatrixBase< DerivedFA > &FA, const Eigen::MatrixBase< DerivedVB > &VB, const Eigen::MatrixBase< DerivedFB > &FB, const bool resolve_overlaps, Eigen::PlainObjectBase< DerivedW > &W, Eigen::PlainObjectBase< DerivedG > &G, Eigen::PlainObjectBase< DerivedJ > &J)
Definition minkowski_sum.cpp:31

References minkowski_sum().

+ Here is the call graph for this function:

◆ minkowski_sum() [3/3]

template<typename DerivedVA , typename DerivedFA , typename DerivedVB , typename DerivedFB , typename DerivedW , typename DerivedG , typename DerivedJ >
IGL_INLINE void igl::copyleft::cgal::minkowski_sum ( const Eigen::MatrixBase< DerivedVA > &  VA,
const Eigen::MatrixBase< DerivedFA > &  FA,
const Eigen::MatrixBase< DerivedVB > &  VB,
const Eigen::MatrixBase< DerivedFB > &  FB,
const bool  resolve_overlaps,
Eigen::PlainObjectBase< DerivedW > &  W,
Eigen::PlainObjectBase< DerivedG > &  G,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
40{
41 using namespace std;
42 using namespace Eigen;
43 assert(FA.cols() == 3 && "FA must contain a closed triangle mesh");
44 assert(FB.cols() <= FA.cols() &&
45 "FB must contain lower diemnsional simplices than FA");
46 const auto tictoc = []()->double
47 {
48 static double t_start;
49 double now = igl::get_seconds();
50 double interval = now-t_start;
51 t_start = now;
52 return interval;
53 };
54 tictoc();
56 edges(FB,EB);
58 if(FB.cols() == 3)
59 {
60 edges(FA,EA);
61 }
62 // number of copies of A along edges of B
63 const int n_ab = EB.rows();
64 // number of copies of B along edges of A
65 const int n_ba = EA.rows();
66
67 vector<DerivedW> vW(n_ab + n_ba);
68 vector<DerivedG> vG(n_ab + n_ba);
69 vector<DerivedJ> vJ(n_ab + n_ba);
70 vector<int> offsets(n_ab + n_ba + 1);
71 offsets[0] = 0;
72 // sweep A along edges of B
73 for(int e = 0;e<n_ab;e++)
74 {
76 minkowski_sum(
77 VA,
78 FA,
79 VB.row(EB(e,0)).eval(),
80 VB.row(EB(e,1)).eval(),
81 false,
82 vW[e],
83 vG[e],
84 eJ);
85 assert(vG[e].rows() == eJ.rows());
86 assert(eJ.cols() == 1);
87 vJ[e].resize(vG[e].rows(),2);
88 vJ[e].col(0) = eJ;
89 vJ[e].col(1).setConstant(e);
90 offsets[e+1] = offsets[e] + vW[e].rows();
91 }
92 // sweep B along edges of A
93 for(int e = 0;e<n_ba;e++)
94 {
96 const int ee = n_ab+e;
97 minkowski_sum(
98 VB,
99 FB,
100 VA.row(EA(e,0)).eval(),
101 VA.row(EA(e,1)).eval(),
102 false,
103 vW[ee],
104 vG[ee],
105 eJ);
106 vJ[ee].resize(vG[ee].rows(),2);
107 vJ[ee].col(0) = eJ.array() + (FA.rows()+1);
108 vJ[ee].col(1).setConstant(ee);
109 offsets[ee+1] = offsets[ee] + vW[ee].rows();
110 }
111 // Combine meshes
112 int n=0,m=0;
113 for_each(vW.begin(),vW.end(),[&n](const DerivedW & w){n+=w.rows();});
114 for_each(vG.begin(),vG.end(),[&m](const DerivedG & g){m+=g.rows();});
115 assert(n == offsets.back());
116
117 W.resize(n,3);
118 G.resize(m,3);
119 J.resize(m,2);
120 {
121 int m_off = 0,n_off = 0;
122 for(int i = 0;i<vG.size();i++)
123 {
124 W.block(n_off,0,vW[i].rows(),3) = vW[i];
125 G.block(m_off,0,vG[i].rows(),3) = vG[i].array()+offsets[i];
126 J.block(m_off,0,vJ[i].rows(),2) = vJ[i];
127 n_off += vW[i].rows();
128 m_off += vG[i].rows();
129 }
130 assert(n == n_off);
131 assert(m == m_off);
132 }
133 if(resolve_overlaps)
134 {
137 DerivedW(W),
138 DerivedG(G),
141 MESH_BOOLEAN_TYPE_UNION,
142 W,
143 G,
144 SJ);
145 slice(DerivedJ(J),SJ,1,J);
146 }
147}
void for_each(const Eigen::SparseMatrix< AType > &A, const Func &func)
Definition for_each.h:31
IGL_INLINE void edges(const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedE > &E)
Definition edges.cpp:13
size_t rows(const T &raster)
Definition MarchingSquares.hpp:55

References Eigen::PlainObjectBase< Derived >::cols(), igl::edges(), igl::for_each(), igl::get_seconds(), mesh_boolean(), igl::MESH_BOOLEAN_TYPE_UNION, minkowski_sum(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), Eigen::PlainObjectBase< Derived >::setConstant(), and igl::slice().

Referenced by minkowski_sum(), and minkowski_sum().

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

◆ order_facets_around_edge() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedI >
IGL_INLINE void igl::copyleft::cgal::order_facets_around_edge ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
size_t  s,
size_t  d,
const std::vector< int > &  adj_faces,
const Eigen::PlainObjectBase< DerivedV > &  pivot_point,
Eigen::PlainObjectBase< DerivedI > &  order 
)
290{
291 assert(V.cols() == 3);
292 assert(F.cols() == 3);
293 assert(pivot_point.cols() == 3);
294 auto signed_index_to_index = [&](int signed_idx)
295 {
296 return abs(signed_idx) -1;
297 };
298 auto get_opposite_vertex_index = [&](size_t fid) -> typename DerivedF::Scalar
299 {
300 typedef typename DerivedF::Scalar Index;
301 if (F(fid, 0) != (Index)s && F(fid, 0) != (Index)d) return F(fid, 0);
302 if (F(fid, 1) != (Index)s && F(fid, 1) != (Index)d) return F(fid, 1);
303 if (F(fid, 2) != (Index)s && F(fid, 2) != (Index)d) return F(fid, 2);
304 assert(false);
305 // avoid warning
306 return -1;
307 };
308
309 {
310 // Check if s, d and pivot are collinear.
311 typedef CGAL::Exact_predicates_exact_constructions_kernel K;
312 K::Point_3 ps(V(s,0), V(s,1), V(s,2));
313 K::Point_3 pd(V(d,0), V(d,1), V(d,2));
314 K::Point_3 pp(pivot_point(0,0), pivot_point(0,1), pivot_point(0,2));
315 if (CGAL::collinear(ps, pd, pp)) {
316 throw std::runtime_error(
317 "Pivot point is collinear with the outer edge!");
318 }
319 }
320
321 const size_t N = adj_faces.size();
322 const size_t num_faces = N + 1; // N adj faces + 1 pivot face
323
324 // Because face indices are used for tie breaking, the original face indices
325 // in the new faces array must be ascending.
326 auto comp = [&](int i, int j)
327 {
328 return signed_index_to_index(adj_faces[i]) <
329 signed_index_to_index(adj_faces[j]);
330 };
331 std::vector<size_t> adj_order(N);
332 for (size_t i=0; i<N; i++) adj_order[i] = i;
333 std::sort(adj_order.begin(), adj_order.end(), comp);
334
335 DerivedV vertices(num_faces + 2, 3);
336 for (size_t i=0; i<N; i++)
337 {
338 const size_t fid = signed_index_to_index(adj_faces[adj_order[i]]);
339 vertices.row(i) = V.row(get_opposite_vertex_index(fid));
340 }
341 vertices.row(N ) = pivot_point;
342 vertices.row(N+1) = V.row(s);
343 vertices.row(N+2) = V.row(d);
344
345 DerivedF faces(num_faces, 3);
346 for (size_t i=0; i<N; i++)
347 {
348 if (adj_faces[adj_order[i]] < 0)
349 {
350 faces(i,0) = N+1; // s
351 faces(i,1) = N+2; // d
352 faces(i,2) = i ;
353 } else
354 {
355 faces(i,0) = N+2; // d
356 faces(i,1) = N+1; // s
357 faces(i,2) = i ;
358 }
359 }
360 // Last face is the pivot face.
361 faces(N, 0) = N+1;
362 faces(N, 1) = N+2;
363 faces(N, 2) = N;
364
365 std::vector<int> adj_faces_with_pivot(num_faces);
366 for (size_t i=0; i<num_faces; i++)
367 {
368 if ((size_t)faces(i,0) == N+1 && (size_t)faces(i,1) == N+2)
369 {
370 adj_faces_with_pivot[i] = int(i+1) * -1;
371 } else
372 {
373 adj_faces_with_pivot[i] = int(i+1);
374 }
375 }
376
377 DerivedI order_with_pivot;
379 vertices, faces, N+1, N+2, adj_faces_with_pivot, order_with_pivot);
380
381 assert((size_t)order_with_pivot.size() == num_faces);
382 order.resize(N);
383 size_t pivot_index = num_faces + 1;
384 for (size_t i=0; i<num_faces; i++)
385 {
386 if ((size_t)order_with_pivot[i] == N)
387 {
388 pivot_index = i;
389 break;
390 }
391 }
392 assert(pivot_index < num_faces);
393
394 for (size_t i=0; i<N; i++)
395 {
396 order[i] = adj_order[order_with_pivot[(pivot_index+i+1)%num_faces]];
397 }
398}

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

+ Here is the call graph for this function:

◆ order_facets_around_edge() [2/2]

template<typename DerivedV , typename DerivedF , typename DerivedI >
IGL_INLINE void igl::copyleft::cgal::order_facets_around_edge ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
size_t  s,
size_t  d,
const std::vector< int > &  adj_faces,
Eigen::PlainObjectBase< DerivedI > &  order,
bool  debug = false 
)

Referenced by closest_facet(), igl::copyleft::cgal::points_inside_component_helper::determine_point_edge_orientation(), extract_cells_single_component(), order_facets_around_edge(), order_facets_around_edges(), and outer_facet().

+ Here is the caller graph for this function:

◆ order_facets_around_edges() [1/3]

template<typename DerivedV , typename DerivedF , typename DerivedN , typename DeriveduE , typename uE2EType , typename uE2oEType , typename uE2CType >
IGL_INLINE std::enable_if<!std::is_same< typenameDerivedV::Scalar, typenameCGAL::Exact_predicates_exact_constructions_kernel::FT >::value, void >::type igl::copyleft::cgal::order_facets_around_edges ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedN > &  N,
const Eigen::PlainObjectBase< DeriveduE > &  uE,
const std::vector< std::vector< uE2EType > > &  uE2E,
std::vector< std::vector< uE2oEType > > &  uE2oE,
std::vector< std::vector< uE2CType > > &  uE2C 
)
33 {
34
36 const typename DerivedV::Scalar EPS = 1e-12;
37 const size_t num_faces = F.rows();
38 const size_t num_undirected_edges = uE.rows();
39
40 auto edge_index_to_face_index = [&](size_t ei) { return ei % num_faces; };
41 auto edge_index_to_corner_index = [&](size_t ei) { return ei / num_faces; };
42
43 uE2oE.resize(num_undirected_edges);
44 uE2C.resize(num_undirected_edges);
45
46 for(size_t ui = 0;ui<num_undirected_edges;ui++)
47 {
48 const auto& adj_edges = uE2E[ui];
49 const size_t edge_valance = adj_edges.size();
50 assert(edge_valance > 0);
51
52 const auto ref_edge = adj_edges[0];
53 const auto ref_face = edge_index_to_face_index(ref_edge);
54 Vector3F ref_normal = N.row(ref_face);
55
56 const auto ref_corner_o = edge_index_to_corner_index(ref_edge);
57 const auto ref_corner_s = (ref_corner_o+1)%3;
58 const auto ref_corner_d = (ref_corner_o+2)%3;
59
60 const typename DerivedF::Scalar o = F(ref_face, ref_corner_o);
61 const typename DerivedF::Scalar s = F(ref_face, ref_corner_s);
62 const typename DerivedF::Scalar d = F(ref_face, ref_corner_d);
63
64 Vector3F edge = V.row(d) - V.row(s);
65 auto edge_len = edge.norm();
66 bool degenerated = edge_len < EPS;
67 if (degenerated) {
68 if (edge_valance <= 2) {
69 // There is only one way to order 2 or less faces.
70 edge.setZero();
71 } else {
72 edge.setZero();
74 normals(edge_valance, 3);
75 for (size_t fei=0; fei<edge_valance; fei++) {
76 const auto fe = adj_edges[fei];
77 const auto f = edge_index_to_face_index(fe);
78 normals.row(fei) = N.row(f);
79 }
80 for (size_t i=0; i<edge_valance; i++) {
81 size_t j = (i+1) % edge_valance;
82 Vector3F ni = normals.row(i);
83 Vector3F nj = normals.row(j);
84 edge = ni.cross(nj);
85 edge_len = edge.norm();
86 if (edge_len >= EPS) {
87 edge.normalize();
88 break;
89 }
90 }
91
92 // Ensure edge direction are consistent with reference face.
93 Vector3F in_face_vec = V.row(o) - V.row(s);
94 if (edge.cross(in_face_vec).dot(ref_normal) < 0) {
95 edge *= -1;
96 }
97
98 if (edge.norm() < EPS) {
99 std::cerr << "=====================================" << std::endl;
100 std::cerr << " ui: " << ui << std::endl;
101 std::cerr << "edge: " << ref_edge << std::endl;
102 std::cerr << "face: " << ref_face << std::endl;
103 std::cerr << " vs: " << V.row(s) << std::endl;
104 std::cerr << " vd: " << V.row(d) << std::endl;
105 std::cerr << "adj face normals: " << std::endl;
106 std::cerr << normals << std::endl;
107 std::cerr << "Very degenerated case detected:" << std::endl;
108 std::cerr << "Near zero edge surrounded by "
109 << edge_valance << " neearly colinear faces" <<
110 std::endl;
111 std::cerr << "=====================================" << std::endl;
112 }
113 }
114 } else {
115 edge.normalize();
116 }
117
118 Eigen::MatrixXd angle_data(edge_valance, 3);
119 std::vector<bool> cons(edge_valance);
120
121 for (size_t fei=0; fei<edge_valance; fei++) {
122 const auto fe = adj_edges[fei];
123 const auto f = edge_index_to_face_index(fe);
124 const auto c = edge_index_to_corner_index(fe);
125 cons[fei] = (d == F(f, (c+1)%3));
126 assert( cons[fei] || (d == F(f,(c+2)%3)));
127 assert(!cons[fei] || (s == F(f,(c+2)%3)));
128 assert(!cons[fei] || (d == F(f,(c+1)%3)));
129 Vector3F n = N.row(f);
130 angle_data(fei, 0) = ref_normal.cross(n).dot(edge);
131 angle_data(fei, 1) = ref_normal.dot(n);
132 if (cons[fei]) {
133 angle_data(fei, 0) *= -1;
134 angle_data(fei, 1) *= -1;
135 }
136 angle_data(fei, 0) *= -1; // Sort clockwise.
137 angle_data(fei, 2) = (cons[fei]?1.:-1.)*(f+1);
138 }
139
140 Eigen::VectorXi order;
141 igl::sort_angles(angle_data, order);
142
143 auto& ordered_edges = uE2oE[ui];
144 auto& consistency = uE2C[ui];
145
146 ordered_edges.resize(edge_valance);
147 consistency.resize(edge_valance);
148 for (size_t fei=0; fei<edge_valance; fei++) {
149 ordered_edges[fei] = adj_edges[order[fei]];
150 consistency[fei] = cons[order[fei]];
151 }
152 }
153}
Eigen::MatrixXd normals(Ex ex_policy, const PointSet &points, const AABBMesh &mesh, double eps, std::function< void()> thr, const std::vector< unsigned > &pt_indices)
Definition MeshNormals.cpp:116
IGL_INLINE S_type EPS()
IGL_INLINE void sort_angles(const Eigen::PlainObjectBase< DerivedM > &M, Eigen::PlainObjectBase< DerivedR > &R)
Definition sort_angles.cpp:13

References igl::EPS(), Eigen::PlainObjectBase< Derived >::rows(), and igl::sort_angles().

Referenced by outer_hull_legacy().

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

◆ order_facets_around_edges() [2/3]

template<typename DerivedV , typename DerivedF , typename DerivedN , typename DeriveduE , typename uE2EType , typename uE2oEType , typename uE2CType >
IGL_INLINE std::enable_if< std::is_same< typenameDerivedV::Scalar, typenameCGAL::Exact_predicates_exact_constructions_kernel::FT >::value, void >::type igl::copyleft::cgal::order_facets_around_edges ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedN > &  N,
const Eigen::PlainObjectBase< DeriveduE > &  uE,
const std::vector< std::vector< uE2EType > > &  uE2E,
std::vector< std::vector< uE2oEType > > &  uE2oE,
std::vector< std::vector< uE2CType > > &  uE2C 
)
173 {
174
177 const typename DerivedV::Scalar EPS = 1e-12;
178 const size_t num_faces = F.rows();
179 const size_t num_undirected_edges = uE.rows();
180
181 auto edge_index_to_face_index = [&](size_t ei) { return ei % num_faces; };
182 auto edge_index_to_corner_index = [&](size_t ei) { return ei / num_faces; };
183
184 uE2oE.resize(num_undirected_edges);
185 uE2C.resize(num_undirected_edges);
186
187 for(size_t ui = 0;ui<num_undirected_edges;ui++)
188 {
189 const auto& adj_edges = uE2E[ui];
190 const size_t edge_valance = adj_edges.size();
191 assert(edge_valance > 0);
192
193 const auto ref_edge = adj_edges[0];
194 const auto ref_face = edge_index_to_face_index(ref_edge);
195 Vector3F ref_normal = N.row(ref_face);
196
197 const auto ref_corner_o = edge_index_to_corner_index(ref_edge);
198 const auto ref_corner_s = (ref_corner_o+1)%3;
199 const auto ref_corner_d = (ref_corner_o+2)%3;
200
201 const typename DerivedF::Scalar o = F(ref_face, ref_corner_o);
202 const typename DerivedF::Scalar s = F(ref_face, ref_corner_s);
203 const typename DerivedF::Scalar d = F(ref_face, ref_corner_d);
204
205 Vector3E exact_edge = V.row(d) - V.row(s);
206 exact_edge.array() /= exact_edge.squaredNorm();
207 Vector3F edge(
208 CGAL::to_double(exact_edge[0]),
209 CGAL::to_double(exact_edge[1]),
210 CGAL::to_double(exact_edge[2]));
211 edge.normalize();
212
213 Eigen::MatrixXd angle_data(edge_valance, 3);
214 std::vector<bool> cons(edge_valance);
215
216 for (size_t fei=0; fei<edge_valance; fei++) {
217 const auto fe = adj_edges[fei];
218 const auto f = edge_index_to_face_index(fe);
219 const auto c = edge_index_to_corner_index(fe);
220 cons[fei] = (d == F(f, (c+1)%3));
221 assert( cons[fei] || (d == F(f,(c+2)%3)));
222 assert(!cons[fei] || (s == F(f,(c+2)%3)));
223 assert(!cons[fei] || (d == F(f,(c+1)%3)));
224 Vector3F n = N.row(f);
225 angle_data(fei, 0) = ref_normal.cross(n).dot(edge);
226 angle_data(fei, 1) = ref_normal.dot(n);
227 if (cons[fei]) {
228 angle_data(fei, 0) *= -1;
229 angle_data(fei, 1) *= -1;
230 }
231 angle_data(fei, 0) *= -1; // Sort clockwise.
232 angle_data(fei, 2) = (cons[fei]?1.:-1.)*(f+1);
233 }
234
235 Eigen::VectorXi order;
236 igl::sort_angles(angle_data, order);
237
238 auto& ordered_edges = uE2oE[ui];
239 auto& consistency = uE2C[ui];
240
241 ordered_edges.resize(edge_valance);
242 consistency.resize(edge_valance);
243 for (size_t fei=0; fei<edge_valance; fei++) {
244 ordered_edges[fei] = adj_edges[order[fei]];
245 consistency[fei] = cons[order[fei]];
246 }
247 }
248}

References igl::EPS(), Eigen::PlainObjectBase< Derived >::rows(), and igl::sort_angles().

+ Here is the call graph for this function:

◆ order_facets_around_edges() [3/3]

template<typename DerivedV , typename DerivedF , typename DeriveduE , typename uE2EType , typename uE2oEType , typename uE2CType >
IGL_INLINE void igl::copyleft::cgal::order_facets_around_edges ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DeriveduE > &  uE,
const std::vector< std::vector< uE2EType > > &  uE2E,
std::vector< std::vector< uE2oEType > > &  uE2oE,
std::vector< std::vector< uE2CType > > &  uE2C 
)
263 {
264
265 //typedef Eigen::Matrix<typename DerivedV::Scalar, 3, 1> Vector3E;
266 const size_t num_faces = F.rows();
267 const size_t num_undirected_edges = uE.rows();
268
269 auto edge_index_to_face_index = [&](size_t ei) { return ei % num_faces; };
270 auto edge_index_to_corner_index = [&](size_t ei) { return ei / num_faces; };
271
272 uE2oE.resize(num_undirected_edges);
273 uE2C.resize(num_undirected_edges);
274
275 for(size_t ui = 0;ui<num_undirected_edges;ui++)
276 {
277 const auto& adj_edges = uE2E[ui];
278 const size_t edge_valance = adj_edges.size();
279 assert(edge_valance > 0);
280
281 const auto ref_edge = adj_edges[0];
282 const auto ref_face = edge_index_to_face_index(ref_edge);
283
284 const auto ref_corner_o = edge_index_to_corner_index(ref_edge);
285 const auto ref_corner_s = (ref_corner_o+1)%3;
286 const auto ref_corner_d = (ref_corner_o+2)%3;
287
288 //const typename DerivedF::Scalar o = F(ref_face, ref_corner_o);
289 const typename DerivedF::Scalar s = F(ref_face, ref_corner_s);
290 const typename DerivedF::Scalar d = F(ref_face, ref_corner_d);
291
292 std::vector<bool> cons(edge_valance);
293 std::vector<int> adj_faces(edge_valance);
294 for (size_t fei=0; fei<edge_valance; fei++) {
295 const auto fe = adj_edges[fei];
296 const auto f = edge_index_to_face_index(fe);
297 const auto c = edge_index_to_corner_index(fe);
298 cons[fei] = (d == F(f, (c+1)%3));
299 adj_faces[fei] = (f+1) * (cons[fei] ? 1:-1);
300
301 assert( cons[fei] || (d == F(f,(c+2)%3)));
302 assert(!cons[fei] || (s == F(f,(c+2)%3)));
303 assert(!cons[fei] || (d == F(f,(c+1)%3)));
304 }
305
306 Eigen::VectorXi order;
307 order_facets_around_edge(V, F, s, d, adj_faces, order);
308 assert((size_t)order.size() == edge_valance);
309
310 auto& ordered_edges = uE2oE[ui];
311 auto& consistency = uE2C[ui];
312
313 ordered_edges.resize(edge_valance);
314 consistency.resize(edge_valance);
315 for (size_t fei=0; fei<edge_valance; fei++) {
316 ordered_edges[fei] = adj_edges[order[fei]];
317 consistency[fei] = cons[order[fei]];
318 }
319 }
320}

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

+ Here is the call graph for this function:

◆ orient2D()

template<typename Scalar >
IGL_INLINE short igl::copyleft::cgal::orient2D ( const Scalar  pa[2],
const Scalar  pb[2],
const Scalar  pc[2] 
)
18{
19 typedef CGAL::Exact_predicates_exact_constructions_kernel Epeck;
20 typedef CGAL::Exact_predicates_inexact_constructions_kernel Epick;
21 typedef typename std::conditional<std::is_same<Scalar, Epeck::FT>::value,
22 Epeck, Epick>::type Kernel;
23
24 switch(CGAL::orientation(
25 typename Kernel::Point_2(pa[0], pa[1]),
26 typename Kernel::Point_2(pb[0], pb[1]),
27 typename Kernel::Point_2(pc[0], pc[1]))) {
28 case CGAL::LEFT_TURN:
29 return 1;
30 case CGAL::RIGHT_TURN:
31 return -1;
32 case CGAL::COLLINEAR:
33 return 0;
34 default:
35 throw "Invalid orientation";
36 }
37}

◆ orient3D()

template<typename Scalar >
IGL_INLINE short igl::copyleft::cgal::orient3D ( const Scalar  pa[3],
const Scalar  pb[3],
const Scalar  pc[3],
const Scalar  pd[3] 
)
19{
20 typedef CGAL::Exact_predicates_exact_constructions_kernel Epeck;
21 typedef CGAL::Exact_predicates_inexact_constructions_kernel Epick;
22 typedef typename std::conditional<std::is_same<Scalar, Epeck::FT>::value,
23 Epeck, Epick>::type Kernel;
24
25 switch(CGAL::orientation(
26 typename Kernel::Point_3(pa[0], pa[1], pa[2]),
27 typename Kernel::Point_3(pb[0], pb[1], pb[2]),
28 typename Kernel::Point_3(pc[0], pc[1], pc[2]),
29 typename Kernel::Point_3(pd[0], pd[1], pd[2]))) {
30 case CGAL::POSITIVE:
31 return 1;
32 case CGAL::NEGATIVE:
33 return -1;
34 case CGAL::COPLANAR:
35 return 0;
36 default:
37 throw "Invalid orientation";
38 }
39}

◆ outer_edge()

template<typename DerivedV , typename DerivedF , typename DerivedI , typename IndexType , typename DerivedA >
IGL_INLINE void igl::copyleft::cgal::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) -> void {
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}
typename Traits< remove_cvref_t< L > >::Scalar Scalar
Definition Line.hpp:36
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)
Definition outer_element.cpp:19

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

Referenced by outer_facet(), and outer_facet().

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

◆ outer_facet() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedI , typename IndexType >
IGL_INLINE void igl::copyleft::cgal::outer_facet ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedI > &  I,
IndexType &  f,
bool &  flipped 
)
26 {
27
28 // Algorithm:
29 //
30 // 1. Find an outer edge (s, d).
31 //
32 // 2. Order adjacent facets around this edge. Because the edge is an
33 // outer edge, there exists a plane passing through it such that all its
34 // adjacent facets lie on the same side. The implementation of
35 // order_facets_around_edge() will find a natural start facet such that
36 // The first and last facets according to this order are on the outside.
37 //
38 // 3. Because the vertex s is an outer vertex by construction (see
39 // implemnetation of outer_edge()). The first adjacent facet is facing
40 // outside (i.e. flipped=false) if it has positive X normal component.
41 // If it has zero normal component, it is facing outside if it contains
42 // directed edge (s, d).
43
44 //typedef typename DerivedV::Scalar Scalar;
45 typedef typename DerivedV::Index Index;
46
47 Index s,d;
49 outer_edge(V, F, I, s, d, incident_faces);
50 assert(incident_faces.size() > 0);
51
52 auto convert_to_signed_index = [&](size_t fid) -> int{
53 if ((F(fid, 0) == s && F(fid, 1) == d) ||
54 (F(fid, 1) == s && F(fid, 2) == d) ||
55 (F(fid, 2) == s && F(fid, 0) == d) ) {
56 return int(fid+1) * -1;
57 } else {
58 return int(fid+1);
59 }
60 };
61
62 auto signed_index_to_index = [&](int signed_id) -> size_t {
63 return size_t(abs(signed_id) - 1);
64 };
65
66 std::vector<int> adj_faces(incident_faces.size());
67 std::transform(incident_faces.data(),
68 incident_faces.data() + incident_faces.size(),
69 adj_faces.begin(),
70 convert_to_signed_index);
71
72 DerivedV pivot_point = V.row(s);
73 pivot_point(0, 0) += 1.0;
74
75 Eigen::VectorXi order;
76 order_facets_around_edge(V, F, s, d, adj_faces, pivot_point, order);
77
78 f = signed_index_to_index(adj_faces[order[0]]);
79 flipped = adj_faces[order[0]] > 0;
80}
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)
Definition outer_element.cpp:88

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

Referenced by extract_cells(), outer_hull_legacy(), and propagate_winding_numbers().

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

◆ outer_facet() [2/2]

template<typename DerivedV , typename DerivedF , typename DerivedN , typename DerivedI , typename IndexType >
IGL_INLINE void igl::copyleft::cgal::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 
)
97 {
98 // Algorithm:
99 // Find an outer edge.
100 // Find the incident facet with the largest absolute X normal component.
101 // If there is a tie, keep the one with positive X component.
102 // If there is still a tie, pick the face with the larger signed index
103 // (flipped face has negative index).
104 typedef typename DerivedV::Scalar Scalar;
105 typedef typename DerivedV::Index Index;
106 const size_t INVALID = std::numeric_limits<size_t>::max();
107
108 Index v1,v2;
110 outer_edge(V, F, I, v1, v2, incident_faces);
111 assert(incident_faces.size() > 0);
112
113 auto generic_fabs = [&](const Scalar& val) -> const Scalar {
114 if (val >= 0) return val;
115 else return -val;
116 };
117
118 Scalar max_nx = 0;
119 size_t outer_fid = INVALID;
120 const size_t num_incident_faces = incident_faces.size();
121 for (size_t i=0; i<num_incident_faces; i++)
122 {
123 const auto& fid = incident_faces(i);
124 const Scalar nx = N(fid, 0);
125 if (outer_fid == INVALID) {
126 max_nx = nx;
127 outer_fid = fid;
128 } else {
129 if (generic_fabs(nx) > generic_fabs(max_nx)) {
130 max_nx = nx;
131 outer_fid = fid;
132 } else if (nx == -max_nx && nx > 0) {
133 max_nx = nx;
134 outer_fid = fid;
135 } else if (nx == max_nx) {
136 if ((max_nx >= 0 && outer_fid < fid) ||
137 (max_nx < 0 && outer_fid > fid)) {
138 max_nx = nx;
139 outer_fid = fid;
140 }
141 }
142 }
143 }
144
145 assert(outer_fid != INVALID);
146 f = outer_fid;
147 flipped = max_nx < 0;
148}

References outer_edge().

+ Here is the call graph for this function:

◆ outer_hull()

template<typename DerivedV , typename DerivedF , typename DerivedHV , typename DerivedHF , typename DerivedJ , typename Derivedflip >
IGL_INLINE void igl::copyleft::cgal::outer_hull ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedHV > &  HV,
Eigen::PlainObjectBase< DerivedHF > &  HF,
Eigen::PlainObjectBase< DerivedJ > &  J,
Eigen::PlainObjectBase< Derivedflip > &  flip 
)
34{
35 // Exact types
36 typedef CGAL::Epeck Kernel;
37 typedef Kernel::FT ExactScalar;
38 typedef
40 ExactScalar,
43 DerivedHV::IsRowMajor>
44 MatrixXES;
45 // Remesh self-intersections
46 MatrixXES Vr;
47 DerivedHF Fr;
48 DerivedJ Jr;
49 {
51 params.stitch_all = true;
52 Eigen::VectorXi I;
53 Eigen::MatrixXi IF;
54 remesh_self_intersections(V, F, params, Vr, Fr, IF, Jr, I);
55 // Merge coinciding vertices into non-manifold vertices.
56 std::for_each(Fr.data(), Fr.data()+Fr.size(),
57 [&I](typename DerivedHF::Scalar& a) { a=I[a]; });
58 // Remove unreferenced vertices.
59 Eigen::VectorXi UIM;
60 remove_unreferenced(MatrixXES(Vr),DerivedHF(Fr), Vr, Fr, UIM);
61 }
62 // Extract cells for each face
63 Eigen::MatrixXi C;
64 extract_cells(Vr,Fr,C);
65 // Extract faces on ambient cell
66 int num_outer = 0;
67 for(int i = 0;i<C.rows();i++)
68 {
69 num_outer += ( C(i,0) == 0 || C(i,1) == 0 ) ? 1 : 0;
70 }
71 HF.resize(num_outer,3);
72 J.resize(num_outer,1);
73 flip.resize(num_outer,1);
74 {
75 int h = 0;
76 for(int i = 0;i<C.rows();i++)
77 {
78 if(C(i,0)==0)
79 {
80 HF.row(h) = Fr.row(i);
81 J(h) = Jr(i);
82 flip(h) = false;
83 h++;
84 }else if(C(i,1) == 0)
85 {
86 HF.row(h) = Fr.row(i).reverse();
87 J(h) = Jr(i);
88 flip(h) = true;
89 h++;
90 }
91 }
92 assert(h == num_outer);
93 }
94 // Remove unreferenced vertices and re-index faces
95 {
96 // Cast to output type
97 DerivedHV Vr_cast;
98 assign(Vr,Vr_cast);
99 Eigen::VectorXi I;
100 remove_unreferenced(Vr_cast,DerivedHF(HF),HV,HF,I);
101 }
102}

References assign(), Eigen::Dynamic, extract_cells(), remesh_self_intersections(), igl::remove_unreferenced(), Eigen::PlainObjectBase< Derived >::resize(), and igl::copyleft::cgal::RemeshSelfIntersectionsParam::stitch_all.

+ Here is the call graph for this function:

◆ outer_hull_legacy()

template<typename DerivedV , typename DerivedF , typename DerivedG , typename DerivedJ , typename Derivedflip >
IGL_INLINE void igl::copyleft::cgal::outer_hull_legacy ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedG > &  G,
Eigen::PlainObjectBase< DerivedJ > &  J,
Eigen::PlainObjectBase< Derivedflip > &  flip 
)
136{
137#ifdef IGL_OUTER_HULL_DEBUG
138 std::cerr << "Extracting outer hull" << std::endl;
139#endif
140 using namespace Eigen;
141 using namespace std;
142 typedef typename DerivedF::Index Index;
145 //typedef Matrix<typename DerivedF::Scalar,Dynamic,DerivedF::ColsAtCompileTime> MatrixXF;
148 const Index m = F.rows();
149
150 // UNUSED:
151 //const auto & duplicate_simplex = [&F](const int f, const int g)->bool
152 //{
153 // return
154 // (F(f,0) == F(g,0) && F(f,1) == F(g,1) && F(f,2) == F(g,2)) ||
155 // (F(f,1) == F(g,0) && F(f,2) == F(g,1) && F(f,0) == F(g,2)) ||
156 // (F(f,2) == F(g,0) && F(f,0) == F(g,1) && F(f,1) == F(g,2)) ||
157 // (F(f,0) == F(g,2) && F(f,1) == F(g,1) && F(f,2) == F(g,0)) ||
158 // (F(f,1) == F(g,2) && F(f,2) == F(g,1) && F(f,0) == F(g,0)) ||
159 // (F(f,2) == F(g,2) && F(f,0) == F(g,1) && F(f,1) == F(g,0));
160 //};
161
162#ifdef IGL_OUTER_HULL_DEBUG
163 cout<<"outer hull..."<<endl;
164#endif
165
166#ifdef IGL_OUTER_HULL_DEBUG
167 cout<<"edge map..."<<endl;
168#endif
171 //typedef Matrix<typename DerivedV::Scalar, 3, 1> Vector3F;
172 MatrixX2I E,uE;
173 VectorXI EMAP;
174 vector<vector<typename DerivedF::Index> > uE2E;
175 unique_edge_map(F,E,uE,EMAP,uE2E);
176#ifdef IGL_OUTER_HULL_DEBUG
177 for (size_t ui=0; ui<uE.rows(); ui++) {
178 std::cout << ui << ": " << uE2E[ui].size() << " -- (";
179 for (size_t i=0; i<uE2E[ui].size(); i++) {
180 std::cout << uE2E[ui][i] << ", ";
181 }
182 std::cout << ")" << std::endl;
183 }
184#endif
185
186 std::vector<std::vector<typename DerivedF::Index> > uE2oE;
187 std::vector<std::vector<bool> > uE2C;
188 order_facets_around_edges(V, F, uE, uE2E, uE2oE, uE2C);
189 uE2E = uE2oE;
190 VectorXI diIM(3*m);
191 for (auto ue : uE2E) {
192 for (size_t i=0; i<ue.size(); i++) {
193 auto fe = ue[i];
194 diIM[fe] = i;
195 }
196 }
197
198 vector<vector<vector<Index > > > TT,_1;
199 triangle_triangle_adjacency(E,EMAP,uE2E,false,TT,_1);
200 VectorXI counts;
201#ifdef IGL_OUTER_HULL_DEBUG
202 cout<<"facet components..."<<endl;
203#endif
204 facet_components(TT,C,counts);
205 assert(C.maxCoeff()+1 == counts.rows());
206 const size_t ncc = counts.rows();
207 G.resize(0,F.cols());
208 J.resize(0,1);
209 flip.setConstant(m,1,false);
210
211#ifdef IGL_OUTER_HULL_DEBUG
212 cout<<"reindex..."<<endl;
213#endif
214 // H contains list of faces on outer hull;
215 vector<bool> FH(m,false);
216 vector<bool> EH(3*m,false);
217 vector<MatrixXG> vG(ncc);
218 vector<MatrixXJ> vJ(ncc);
219 vector<MatrixXJ> vIM(ncc);
220 //size_t face_count = 0;
221 for(size_t id = 0;id<ncc;id++)
222 {
223 vIM[id].resize(counts[id],1);
224 }
225 // current index into each IM
226 vector<size_t> g(ncc,0);
227 // place order of each face in its respective component
228 for(Index f = 0;f<m;f++)
229 {
230 vIM[C(f)](g[C(f)]++) = f;
231 }
232
233#ifdef IGL_OUTER_HULL_DEBUG
234 cout<<"barycenters..."<<endl;
235#endif
236 // assumes that "resolve" has handled any coplanar cases correctly and nearly
237 // coplanar cases can be sorted based on barycenter.
238 MatrixXV BC;
239 barycenter(V,F,BC);
240
241#ifdef IGL_OUTER_HULL_DEBUG
242 cout<<"loop over CCs (="<<ncc<<")..."<<endl;
243#endif
244 for(Index id = 0;id<(Index)ncc;id++)
245 {
246 auto & IM = vIM[id];
247 // starting face that's guaranteed to be on the outer hull and in this
248 // component
249 int f;
250 bool f_flip;
251#ifdef IGL_OUTER_HULL_DEBUG
252 cout<<"outer facet..."<<endl;
253#endif
254 igl::copyleft::cgal::outer_facet(V,F,IM,f,f_flip);
255#ifdef IGL_OUTER_HULL_DEBUG
256 cout<<"outer facet: "<<f<<endl;
257 //cout << V.row(F(f, 0)) << std::endl;
258 //cout << V.row(F(f, 1)) << std::endl;
259 //cout << V.row(F(f, 2)) << std::endl;
260#endif
261 int FHcount = 1;
262 FH[f] = true;
263 // Q contains list of face edges to continue traversing upong
264 queue<int> Q;
265 Q.push(f+0*m);
266 Q.push(f+1*m);
267 Q.push(f+2*m);
268 flip(f) = f_flip;
269 //std::cout << "face " << face_count++ << ": " << f << std::endl;
270 //std::cout << "f " << F.row(f).array()+1 << std::endl;
271 //cout<<"flip("<<f<<") = "<<(flip(f)?"true":"false")<<endl;
272#ifdef IGL_OUTER_HULL_DEBUG
273 cout<<"BFS..."<<endl;
274#endif
275 while(!Q.empty())
276 {
277 // face-edge
278 const int e = Q.front();
279 Q.pop();
280 // face
281 const int f = e%m;
282 // corner
283 const int c = e/m;
284#ifdef IGL_OUTER_HULL_DEBUG
285 std::cout << "edge: " << e << ", ue: " << EMAP(e) << std::endl;
286 std::cout << "face: " << f << std::endl;
287 std::cout << "corner: " << c << std::endl;
288 std::cout << "consistent: " << uE2C[EMAP(e)][diIM[e]] << std::endl;
289#endif
290 // Should never see edge again...
291 if(EH[e] == true)
292 {
293 continue;
294 }
295 EH[e] = true;
296 // source of edge according to f
297 const int fs = flip(f)?F(f,(c+2)%3):F(f,(c+1)%3);
298 // destination of edge according to f
299 const int fd = flip(f)?F(f,(c+1)%3):F(f,(c+2)%3);
300 // edge valence
301 const size_t val = uE2E[EMAP(e)].size();
302#ifdef IGL_OUTER_HULL_DEBUG
303 //std::cout << "vd: " << V.row(fd) << std::endl;
304 //std::cout << "vs: " << V.row(fs) << std::endl;
305 //std::cout << "edge: " << V.row(fd) - V.row(fs) << std::endl;
306 for (size_t i=0; i<val; i++) {
307 if (i == diIM(e)) {
308 std::cout << "* ";
309 } else {
310 std::cout << " ";
311 }
312 std::cout << i << ": "
313 << " (e: " << uE2E[EMAP(e)][i] << ", f: "
314 << uE2E[EMAP(e)][i] % m * (uE2C[EMAP(e)][i] ? 1:-1) << ")" << std::endl;
315 }
316#endif
317
318 // is edge consistent with edge of face used for sorting
319 const int e_cons = (uE2C[EMAP(e)][diIM(e)] ? 1: -1);
320 int nfei = -1;
321 // Loop once around trying to find suitable next face
322 for(size_t step = 1; step<val+2;step++)
323 {
324 const int nfei_new = (diIM(e) + 2*val + e_cons*step*(flip(f)?-1:1))%val;
325 const int nf = uE2E[EMAP(e)][nfei_new] % m;
326 {
327#ifdef IGL_OUTER_HULL_DEBUG
328 //cout<<"Next facet: "<<(f+1)<<" --> "<<(nf+1)<<", |"<<
329 // di[EMAP(e)][diIM(e)]<<" - "<<di[EMAP(e)][nfei_new]<<"| = "<<
330 // abs(di[EMAP(e)][diIM(e)] - di[EMAP(e)][nfei_new])
331 // <<endl;
332#endif
333
334
335
336 // Only use this face if not already seen
337 if(!FH[nf])
338 {
339 nfei = nfei_new;
340 //} else {
341 // std::cout << "skipping face " << nfei_new << " because it is seen before"
342 // << std::endl;
343 }
344 break;
345 //} else {
346 // std::cout << di[EMAP(e)][diIM(e)].transpose() << std::endl;
347 // std::cout << di[EMAP(e)][diIM(nfei_new)].transpose() << std::endl;
348 // std::cout << "skipping face " << nfei_new << " with identical dihedral angle"
349 // << std::endl;
350 }
351//#ifdef IGL_OUTER_HULL_DEBUG
352// cout<<"Skipping co-planar facet: "<<(f+1)<<" --> "<<(nf+1)<<endl;
353//#endif
354 }
355
356 int max_ne = -1;
357 if(nfei >= 0)
358 {
359 max_ne = uE2E[EMAP(e)][nfei];
360 }
361
362 if(max_ne>=0)
363 {
364 // face of neighbor
365 const int nf = max_ne%m;
366#ifdef IGL_OUTER_HULL_DEBUG
367 if(!FH[nf])
368 {
369 // first time seeing face
370 cout<<(f+1)<<" --> "<<(nf+1)<<endl;
371 }
372#endif
373 FH[nf] = true;
374 //std::cout << "face " << face_count++ << ": " << nf << std::endl;
375 //std::cout << "f " << F.row(nf).array()+1 << std::endl;
376 FHcount++;
377 // corner of neighbor
378 const int nc = max_ne/m;
379 const int nd = F(nf,(nc+2)%3);
380 const bool cons = (flip(f)?fd:fs) == nd;
381 flip(nf) = (cons ? flip(f) : !flip(f));
382 //cout<<"flip("<<nf<<") = "<<(flip(nf)?"true":"false")<<endl;
383 const int ne1 = nf+((nc+1)%3)*m;
384 const int ne2 = nf+((nc+2)%3)*m;
385 if(!EH[ne1])
386 {
387 Q.push(ne1);
388 }
389 if(!EH[ne2])
390 {
391 Q.push(ne2);
392 }
393 }
394 }
395
396 {
397 vG[id].resize(FHcount,3);
398 vJ[id].resize(FHcount,1);
399 //nG += FHcount;
400 size_t h = 0;
401 assert(counts(id) == IM.rows());
402 for(int i = 0;i<counts(id);i++)
403 {
404 const size_t f = IM(i);
405 //if(f_flip)
406 //{
407 // flip(f) = !flip(f);
408 //}
409 if(FH[f])
410 {
411 vG[id].row(h) = (flip(f)?F.row(f).reverse().eval():F.row(f));
412 vJ[id](h,0) = f;
413 h++;
414 }
415 }
416 assert((int)h == FHcount);
417 }
418 }
419
420 // Is A inside B? Assuming A and B are consistently oriented but closed and
421 // non-intersecting.
422 const auto & has_overlapping_bbox = [](
424 const MatrixXG & A,
425 const MatrixXG & B)->bool
426 {
427 const auto & bounding_box = [](
429 const MatrixXG & F)->
430 DerivedV
431 {
432 DerivedV BB(2,3);
433 BB<<
434 1e26,1e26,1e26,
435 -1e26,-1e26,-1e26;
436 const size_t m = F.rows();
437 for(size_t f = 0;f<m;f++)
438 {
439 for(size_t c = 0;c<3;c++)
440 {
441 const auto & vfc = V.row(F(f,c)).eval();
442 BB(0,0) = std::min(BB(0,0), vfc(0,0));
443 BB(0,1) = std::min(BB(0,1), vfc(0,1));
444 BB(0,2) = std::min(BB(0,2), vfc(0,2));
445 BB(1,0) = std::max(BB(1,0), vfc(0,0));
446 BB(1,1) = std::max(BB(1,1), vfc(0,1));
447 BB(1,2) = std::max(BB(1,2), vfc(0,2));
448 }
449 }
450 return BB;
451 };
452 // A lot of the time we're dealing with unrelated, distant components: cull
453 // them.
454 DerivedV ABB = bounding_box(V,A);
455 DerivedV BBB = bounding_box(V,B);
456 if( (BBB.row(0)-ABB.row(1)).maxCoeff()>0 ||
457 (ABB.row(0)-BBB.row(1)).maxCoeff()>0 )
458 {
459 // bounding boxes do not overlap
460 return false;
461 } else {
462 return true;
463 }
464 };
465
466 // Reject components which are completely inside other components
467 vector<bool> keep(ncc,true);
468 size_t nG = 0;
469 // This is O( ncc * ncc * m)
470 for(size_t id = 0;id<ncc;id++)
471 {
472 if (!keep[id]) continue;
473 std::vector<size_t> unresolved;
474 for(size_t oid = 0;oid<ncc;oid++)
475 {
476 if(id == oid || !keep[oid])
477 {
478 continue;
479 }
480 if (has_overlapping_bbox(V, vG[id], vG[oid])) {
481 unresolved.push_back(oid);
482 }
483 }
484 const size_t num_unresolved_components = unresolved.size();
485 DerivedV query_points(num_unresolved_components, 3);
486 for (size_t i=0; i<num_unresolved_components; i++) {
487 const size_t oid = unresolved[i];
488 DerivedF f = vG[oid].row(0);
489 query_points(i,0) = (V(f(0,0), 0) + V(f(0,1), 0) + V(f(0,2), 0))/3.0;
490 query_points(i,1) = (V(f(0,0), 1) + V(f(0,1), 1) + V(f(0,2), 1))/3.0;
491 query_points(i,2) = (V(f(0,0), 2) + V(f(0,1), 2) + V(f(0,2), 2))/3.0;
492 }
493 Eigen::VectorXi inside;
494 igl::copyleft::cgal::points_inside_component(V, vG[id], query_points, inside);
495 assert((size_t)inside.size() == num_unresolved_components);
496 for (size_t i=0; i<num_unresolved_components; i++) {
497 if (inside(i, 0)) {
498 const size_t oid = unresolved[i];
499 keep[oid] = false;
500 }
501 }
502 }
503 for (size_t id = 0; id<ncc; id++) {
504 if (keep[id]) {
505 nG += vJ[id].rows();
506 }
507 }
508
509 // collect G and J across components
510 G.resize(nG,3);
511 J.resize(nG,1);
512 {
513 size_t off = 0;
514 for(Index id = 0;id<(Index)ncc;id++)
515 {
516 if(keep[id])
517 {
518 assert(vG[id].rows() == vJ[id].rows());
519 G.block(off,0,vG[id].rows(),vG[id].cols()) = vG[id];
520 J.block(off,0,vJ[id].rows(),vJ[id].cols()) = vJ[id];
521 off += vG[id].rows();
522 }
523 }
524 }
525}
Definition PlainObjectBase.h:100
bool inside(const Polygons &polygons, const Point &p)
Definition Utils.hpp:15
IGL_INLINE void bounding_box(const Eigen::MatrixBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedBV > &BV, Eigen::PlainObjectBase< DerivedBF > &BF)
Definition bounding_box.cpp:12
IGL_INLINE void barycenter(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedBC > &BC)
Definition barycenter.cpp:14
Coord step(const Coord &crd, Dir d)
Definition MarchingSquares.hpp:137
size_t cols(const T &raster)
Definition MarchingSquares.hpp:60

References igl::barycenter(), igl::bounding_box(), igl::facet_components(), order_facets_around_edges(), outer_facet(), points_inside_component(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), Eigen::PlainObjectBase< Derived >::setConstant(), igl::triangle_triangle_adjacency(), and igl::unique_edge_map().

Referenced by peel_outer_hull_layers().

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

◆ outer_vertex()

template<typename DerivedV , typename DerivedF , typename DerivedI , typename IndexType , typename DerivedA >
IGL_INLINE void igl::copyleft::cgal::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().

Referenced by outer_edge().

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

◆ peel_outer_hull_layers()

template<typename DerivedV , typename DerivedF , typename DerivedI , typename Derivedflip >
IGL_INLINE size_t igl::copyleft::cgal::peel_outer_hull_layers ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedI > &  I,
Eigen::PlainObjectBase< Derivedflip > &  flip 
)
30{
31 using namespace Eigen;
32 using namespace std;
33 typedef typename DerivedF::Index Index;
35 typedef Matrix<Index,Dynamic,1> MatrixXI;
37 const Index m = F.rows();
38#ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
39 cout<<"peel outer hull layers..."<<endl;
40#endif
41#ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
42 cout<<"calling outer hull..."<<endl;
43 writePLY(STR("peel-outer-hull-input.ply"),V,F);
44#endif
45
46#ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
47 cout<<"resize output ..."<<endl;
48#endif
49 // keep track of iteration parity and whether flipped in hull
50 MatrixXF Fr = F;
51 I.resize(m,1);
52 flip.resize(m,1);
53 // Keep track of index map
54 MatrixXI IM = igl::LinSpaced<MatrixXI >(m,0,m-1);
55 // This is O(n * layers)
56 MatrixXI P(m,1);
57 Index iter = 0;
58 while(Fr.size() > 0)
59 {
60 assert(Fr.rows() == IM.rows());
61 // Compute outer hull of current Fr
62 MatrixXF Fo;
63 MatrixXI Jo;
64 MatrixXflip flipr;
65#ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
66 {
67 cout<<"calling outer hull..." << iter <<endl;
68 std::stringstream ss;
69 ss << "outer_hull_" << iter << ".ply";
70 Eigen::MatrixXd vertices(V.rows(), V.cols());
71 std::transform(V.data(), V.data() + V.rows()*V.cols(),
72 vertices.data(),
73 [](typename DerivedV::Scalar val)
74 {return CGAL::to_double(val); });
75 writePLY(ss.str(), vertices, Fr);
76 }
77#endif
78 outer_hull_legacy(V,Fr,Fo,Jo,flipr);
79#ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
80 writePLY(STR("outer-hull-output-"<<iter<<".ply"),V,Fo);
81 cout<<"reindex, flip..."<<endl;
82#endif
83 assert(Fo.rows() != 0);
84 assert(Fo.rows() == Jo.rows());
85 // all faces in Fo of Fr
86 vector<bool> in_outer(Fr.rows(),false);
87 for(Index g = 0;g<Jo.rows();g++)
88 {
89 I(IM(Jo(g))) = iter;
90 P(IM(Jo(g))) = iter;
91 in_outer[Jo(g)] = true;
92 flip(IM(Jo(g))) = flipr(Jo(g));
93 }
94 // Fr = Fr - Fo
95 // update IM
96 MatrixXF prev_Fr = Fr;
97 MatrixXI prev_IM = IM;
98 Fr.resize(prev_Fr.rows() - Fo.rows(),F.cols());
99 IM.resize(Fr.rows());
100 {
101 Index g = 0;
102 for(Index f = 0;f<prev_Fr.rows();f++)
103 {
104 if(!in_outer[f])
105 {
106 Fr.row(g) = prev_Fr.row(f);
107 IM(g) = prev_IM(f);
108 g++;
109 }
110 }
111 }
112 iter++;
113 }
114 return iter;
115}
#define STR(X)
Definition STR.h:17
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

References Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::data(), outer_hull_legacy(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), STR, and igl::writePLY().

+ Here is the call graph for this function:

◆ peel_winding_number_layers()

template<typename DerivedV , typename DerivedF , typename DerivedW >
IGL_INLINE size_t igl::copyleft::cgal::peel_winding_number_layers ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedW > &  W 
)
14 {
15 const size_t num_faces = F.rows();
16 Eigen::VectorXi labels(num_faces);
17 labels.setZero();
18
19 Eigen::MatrixXi winding_numbers;
20 igl::copyleft::cgal::propagate_winding_numbers(V, F, labels, winding_numbers);
21 assert(winding_numbers.rows() == num_faces);
22 assert(winding_numbers.cols() == 2);
23
24 int min_w = winding_numbers.minCoeff();
25 int max_w = winding_numbers.maxCoeff();
26 assert(max_w > min_w);
27
28 W.resize(num_faces, 1);
29 for (size_t i=0; i<num_faces; i++) {
30 W(i, 0) = winding_numbers(i, 1);
31 }
32 return max_w - min_w;
33}

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

+ Here is the call graph for this function:

◆ piecewise_constant_winding_number()

template<typename DerivedV , typename DerivedF >
IGL_INLINE bool igl::copyleft::cgal::piecewise_constant_winding_number ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F 
)
18{
24 // resolve intersections
25 remesh_self_intersections(V,F,{false,false,true},VV,FF,IF,J,IM);
27}
IGL_INLINE bool piecewise_constant_winding_number(const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DeriveduE > &uE, const std::vector< std::vector< uE2EType > > &uE2E)
Definition piecewise_constant_winding_number.cpp:16

References igl::piecewise_constant_winding_number(), and remesh_self_intersections().

+ Here is the call graph for this function:

◆ point_areas() [1/2]

template<typename DerivedP , typename DerivedI , typename DerivedN , typename DerivedA >
IGL_INLINE void igl::copyleft::cgal::point_areas ( const Eigen::MatrixBase< DerivedP > &  P,
const Eigen::MatrixBase< DerivedI > &  I,
const Eigen::MatrixBase< DerivedN > &  N,
Eigen::PlainObjectBase< DerivedA > &  A 
)
33 {
34 Eigen::MatrixXd T;
35 point_areas(P,I,N,A,T);
36 }

References point_areas().

Referenced by fast_winding_number(), and point_areas().

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

◆ point_areas() [2/2]

template<typename DerivedP , typename DerivedI , typename DerivedN , typename DerivedA , typename DerivedT >
IGL_INLINE void igl::copyleft::cgal::point_areas ( const Eigen::MatrixBase< DerivedP > &  P,
const Eigen::MatrixBase< DerivedI > &  I,
const Eigen::MatrixBase< DerivedN > &  N,
Eigen::PlainObjectBase< DerivedA > &  A,
Eigen::PlainObjectBase< DerivedT > &  T 
)
47 {
48 typedef typename DerivedP::Scalar real;
49 typedef typename DerivedN::Scalar scalarN;
50 typedef typename DerivedA::Scalar scalarA;
51 typedef Eigen::Matrix<real,1,3> RowVec3;
52 typedef Eigen::Matrix<real,1,2> RowVec2;
53
56 typedef Eigen::Matrix<typename DerivedN::Scalar,
58 typedef Eigen::Matrix<typename DerivedI::Scalar,
60
61
62
63 const int n = P.rows();
64
65 assert(P.cols() == 3 && "P must have exactly 3 columns");
66 assert(P.rows() == N.rows()
67 && "P and N must have the same number of rows");
68 assert(P.rows() == I.rows()
69 && "P and I must have the same number of rows");
70
71 A.setZero(n,1);
72 T.setZero(n,3);
73 igl::parallel_for(P.rows(),[&](int i)
74 {
75 MatrixI neighbor_index = I.row(i);
76 MatrixP neighbors;
77 igl::slice(P,neighbor_index,1,neighbors);
78 if(N.rows() && neighbors.rows() > 1){
79 MatrixN neighbor_normals;
80 igl::slice(N,neighbor_index,1,neighbor_normals);
81 Eigen::Matrix<scalarN,1,3> poi_normal = neighbor_normals.row(0);
82 Eigen::Matrix<scalarN,Eigen::Dynamic,1> dotprod =
83 poi_normal(0)*neighbor_normals.col(0)
84 + poi_normal(1)*neighbor_normals.col(1)
85 + poi_normal(2)*neighbor_normals.col(2);
86 Eigen::Array<bool,Eigen::Dynamic,1> keep = dotprod.array() > 0;
87 igl::slice_mask(Eigen::MatrixXd(neighbors),keep,1,neighbors);
88 }
89 if(neighbors.rows() <= 2){
90 A(i) = 0;
91 } else {
92 //subtract the mean from neighbors, then take svd,
93 //the scores will be U*S. This is our pca plane fitting
94 RowVec3 mean = neighbors.colwise().mean();
95 MatrixP mean_centered = neighbors.rowwise() - mean;
96 Eigen::JacobiSVD<MatrixP> svd(mean_centered,
97 Eigen::ComputeThinU | Eigen::ComputeThinV);
98 MatrixP scores = svd.matrixU() * svd.singularValues().asDiagonal();
99
100 T.row(i) = svd.matrixV().col(2).transpose();
101 if(T.row(i).dot(N.row(i)) < 0){
102 T.row(i) *= -1;
103 }
104
105 MatrixP plane;
106 igl::slice(scores,igl::colon<int>(0,scores.rows()-1),
107 igl::colon<int>(0,1),plane);
108
109 std::vector< std::pair<Point,unsigned> > points;
110 //This is where we obtain a delaunay triangulation of the points
111 for(unsigned iter = 0; iter < plane.rows(); iter++){
112 points.push_back( std::make_pair(
113 Point(plane(iter,0),plane(iter,1)), iter ) );
114 }
115 Delaunay triangulation;
116 triangulation.insert(points.begin(),points.end());
117 Eigen::MatrixXi F(triangulation.number_of_faces(),3);
118 int f_row = 0;
119 for(Delaunay::Finite_faces_iterator fit =
120 triangulation.finite_faces_begin();
121 fit != triangulation.finite_faces_end(); ++fit) {
122 Delaunay::Face_handle face = fit;
123 F.row(f_row) = Eigen::RowVector3i((int)face->vertex(0)->info(),
124 (int)face->vertex(1)->info(),
125 (int)face->vertex(2)->info());
126 f_row++;
127 }
128
129 //Here we calculate the voronoi area of the point
130 scalarA area_accumulator = 0;
131 for(int f = 0; f < F.rows(); f++){
132 int X = -1;
133 for(int face_iter = 0; face_iter < 3; face_iter++){
134 if(F(f,face_iter) == 0){
135 X = face_iter;
136 }
137 }
138 if(X >= 0){
139 //Triangle XYZ with X being the point we want the area of
140 int Y = (X+1)%3;
141 int Z = (X+2)%3;
142 scalarA x = (plane.row(F(f,Y))-plane.row(F(f,Z))).norm();
143 scalarA y = (plane.row(F(f,X))-plane.row(F(f,Z))).norm();
144 scalarA z = (plane.row(F(f,Y))-plane.row(F(f,X))).norm();
145 scalarA cosX = (z*z + y*y - x*x)/(2*y*z);
146 scalarA cosY = (z*z + x*x - y*y)/(2*x*z);
147 scalarA cosZ = (x*x + y*y - z*z)/(2*y*x);
148 Eigen::Matrix<scalarA,1,3> barycentric;
149 barycentric << x*cosX, y*cosY, z*cosZ;
150 barycentric /= (barycentric(0)+barycentric(1)+barycentric(2));
151
152 //TODO: to make numerically stable, reorder so that x≥y≥z:
153 scalarA full_area = 0.25*std::sqrt(
154 (x+(y+z))*(z-(x-y))*(z+(x-y))*(x+(y-z)));
155 Eigen::Matrix<scalarA,1,3> partial_area =
156 barycentric * full_area;
157 if(cosX < 0){
158 area_accumulator += 0.5*full_area;
159 } else if (cosY < 0 || cosZ < 0){
160 area_accumulator += 0.25*full_area;
161 } else {
162 area_accumulator += (partial_area(1) + partial_area(2))/2;
163 }
164 }
165 }
166
167 if(std::isfinite(area_accumulator)){
168 A(i) = area_accumulator;
169 } else {
170 A(i) = 0;
171 }
172 }
173 },1000);
174 }
EIGEN_DEVICE_FUNC Derived & setZero(Index size)
Definition CwiseNullaryOp.h:515
@ Y
Definition libslic3r.h:99
@ Z
Definition libslic3r.h:100
@ X
Definition libslic3r.h:98
bool parallel_for(const Index loop_size, const FunctionType &func, const size_t min_parallel=0)
Definition parallel_for.h:99
CGAL::Delaunay_triangulation_2< Kernel, Tds > Delaunay
Definition point_areas.cpp:19

References Eigen::Dynamic, igl::parallel_for(), real(), Eigen::PlainObjectBase< Derived >::setZero(), and igl::slice().

+ Here is the call graph for this function:

◆ point_mesh_squared_distance() [1/2]

template<typename Kernel , typename DerivedP , typename DerivedsqrD , typename DerivedI , typename DerivedC >
IGL_INLINE void igl::copyleft::cgal::point_mesh_squared_distance ( const Eigen::PlainObjectBase< DerivedP > &  P,
const CGAL::AABB_tree< CGAL::AABB_traits< Kernel, CGAL::AABB_triangle_primitive< Kernel, typename std::vector< CGAL::Triangle_3< Kernel > >::iterator > > > &  tree,
const std::vector< CGAL::Triangle_3< Kernel > > &  T,
Eigen::PlainObjectBase< DerivedsqrD > &  sqrD,
Eigen::PlainObjectBase< DerivedI > &  I,
Eigen::PlainObjectBase< DerivedC > &  C 
)
107{
108 typedef CGAL::Triangle_3<Kernel> Triangle_3;
109 typedef typename std::vector<Triangle_3>::iterator Iterator;
110 typedef CGAL::AABB_triangle_primitive<Kernel, Iterator> Primitive;
111 typedef CGAL::AABB_traits<Kernel, Primitive> AABB_triangle_traits;
112 typedef CGAL::AABB_tree<AABB_triangle_traits> Tree;
113 typedef typename Tree::Point_and_primitive_id Point_and_primitive_id;
114 typedef CGAL::Point_3<Kernel> Point_3;
115 assert(P.cols() == 3);
116 const int n = P.rows();
117 sqrD.resize(n,1);
118 I.resize(n,1);
119 C.resize(n,P.cols());
120 for(int p = 0;p < n;p++)
121 {
122 Point_3 query(P(p,0),P(p,1),P(p,2));
123 // Find closest point and primitive id
124 Point_and_primitive_id pp = tree.closest_point_and_primitive(query);
125 Point_3 closest_point = pp.first;
126 assign_scalar(closest_point[0],C(p,0));
127 assign_scalar(closest_point[1],C(p,1));
128 assign_scalar(closest_point[2],C(p,2));
129 assign_scalar((closest_point-query).squared_length(),sqrD(p));
130 I(p) = pp.second - T.begin();
131 }
132}

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

+ Here is the call graph for this function:

◆ point_mesh_squared_distance() [2/2]

template<typename Kernel , typename DerivedP , typename DerivedV , typename DerivedF , typename DerivedsqrD , typename DerivedI , typename DerivedC >
IGL_INLINE void igl::copyleft::cgal::point_mesh_squared_distance ( const Eigen::PlainObjectBase< DerivedP > &  P,
const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedsqrD > &  sqrD,
Eigen::PlainObjectBase< DerivedI > &  I,
Eigen::PlainObjectBase< DerivedC > &  C 
)
27{
28 using namespace std;
29 typedef CGAL::Triangle_3<Kernel> Triangle_3;
30 typedef typename std::vector<Triangle_3>::iterator Iterator;
31 typedef CGAL::AABB_triangle_primitive<Kernel, Iterator> Primitive;
32 typedef CGAL::AABB_traits<Kernel, Primitive> AABB_triangle_traits;
33 typedef CGAL::AABB_tree<AABB_triangle_traits> Tree;
34 Tree tree;
35 vector<Triangle_3> T;
37 return point_mesh_squared_distance(P,tree,T,sqrD,I,C);
38}
IGL_INLINE void point_mesh_squared_distance(const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedsqrD > &sqrD, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedC > &C)
Definition point_mesh_squared_distance.cpp:20
IGL_INLINE void point_mesh_squared_distance_precompute(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, CGAL::AABB_tree< CGAL::AABB_traits< Kernel, CGAL::AABB_triangle_primitive< Kernel, typename std::vector< CGAL::Triangle_3< Kernel > >::iterator > > > &tree, std::vector< CGAL::Triangle_3< Kernel > > &T)
Definition point_mesh_squared_distance.cpp:41

References point_mesh_squared_distance(), and point_mesh_squared_distance_precompute().

Referenced by point_mesh_squared_distance().

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

◆ point_mesh_squared_distance_precompute()

template<typename Kernel , typename DerivedV , typename DerivedF >
IGL_INLINE void igl::copyleft::cgal::point_mesh_squared_distance_precompute ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
CGAL::AABB_tree< CGAL::AABB_traits< Kernel, CGAL::AABB_triangle_primitive< Kernel, typename std::vector< CGAL::Triangle_3< Kernel > >::iterator > > > &  tree,
std::vector< CGAL::Triangle_3< Kernel > > &  T 
)
52{
53 using namespace std;
54
55 typedef CGAL::Triangle_3<Kernel> Triangle_3;
56 typedef CGAL::Point_3<Kernel> Point_3;
57 typedef typename std::vector<Triangle_3>::iterator Iterator;
58 typedef CGAL::AABB_triangle_primitive<Kernel, Iterator> Primitive;
59 typedef CGAL::AABB_traits<Kernel, Primitive> AABB_triangle_traits;
60 typedef CGAL::AABB_tree<AABB_triangle_traits> Tree;
61
62 // Must be 3D
63 assert(V.cols() == 3);
64 // Must be triangles
65 assert(F.cols() == 3);
66
67 // WTF ALERT!!!!
68 //
69 // There's a bug in clang probably or at least in cgal. Without calling this
70 // line (I guess invoking some compilation from <vector>), clang will vomit
71 // errors inside CGAL.
72 //
73 // http://stackoverflow.com/questions/27748442/is-clangs-c11-support-reliable
74 T.reserve(0);
75
76 // Make list of cgal triangles
78 tree.clear();
79 tree.insert(T.begin(),T.end());
80 tree.accelerate_distance_queries();
81 // accelerate_distance_queries doesn't seem actually to do _all_ of the
82 // precomputation. the tree (despite being const) will still do more
83 // precomputation and reorganizing on the first call of `closest_point` or
84 // `closest_point_and_primitive`. Therefore, call it once here.
85 tree.closest_point_and_primitive(Point_3(0,0,0));
86}

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

Referenced by point_mesh_squared_distance().

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

◆ point_segment_squared_distance()

template<typename Kernel >
IGL_INLINE void igl::copyleft::cgal::point_segment_squared_distance ( const CGAL::Point_3< Kernel > &  P1,
const CGAL::Segment_3< Kernel > &  S2,
CGAL::Point_3< Kernel > &  P2,
typename Kernel::FT &  d 
)
16{
17 if(S2.is_degenerate())
18 {
19 P2 = S2.source();
20 d = (P1-P2).squared_length();
21 return;
22 }
23 // http://stackoverflow.com/a/1501725/148668
24 const auto sqr_len = S2.squared_length();
25 assert(sqr_len != 0);
26 const auto & V = S2.source();
27 const auto & W = S2.target();
28 const auto t = (P1-V).dot(W-V)/sqr_len;
29 if(t<0)
30 {
31 P2 = V;
32 }else if(t>1)
33 {
34 P2 = W;
35 }else
36 {
37 P2 = V + t*(W-V);
38 }
39 d = (P1-P2).squared_length();
40}
IGL_INLINE double dot(const double *a, const double *b)
Definition dot.cpp:11

References igl::dot().

Referenced by segment_segment_squared_distance().

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

◆ point_solid_signed_squared_distance()

template<typename DerivedQ , typename DerivedVB , typename DerivedFB , typename DerivedD >
IGL_INLINE void igl::copyleft::cgal::point_solid_signed_squared_distance ( const Eigen::PlainObjectBase< DerivedQ > &  Q,
const Eigen::PlainObjectBase< DerivedVB > &  VB,
const Eigen::PlainObjectBase< DerivedFB > &  FB,
Eigen::PlainObjectBase< DerivedD > &  D 
)
26{
27 // compute unsigned distances
28 Eigen::VectorXi I;
29 DerivedVB C;
30 point_mesh_squared_distance<CGAL::Epeck>(Q,VB,FB,D,I,C);
31 // Collect queries that have non-zero distance
33 // Compute sign for non-zero distance queries
34 DerivedQ QNZ;
35 slice_mask(Q,NZ,1,QNZ);
38 // Apply sign to distances
39 DerivedD S = DerivedD::Zero(Q.rows(),1);
40 {
41 int k = 0;
42 for(int q = 0;q<Q.rows();q++)
43 {
44 if(NZ(q))
45 {
46 D(q) *= DNZ(k++) ? -1. : 1.;
47 }
48 }
49 }
50}
General-purpose arrays with easy API for coefficient-wise operations.
Definition Array.h:47

References points_inside_component(), Eigen::PlainObjectBase< Derived >::rows(), and igl::slice_mask().

Referenced by trim_with_solid().

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

◆ point_triangle_squared_distance()

template<typename Kernel >
IGL_INLINE void igl::copyleft::cgal::point_triangle_squared_distance ( const CGAL::Point_3< Kernel > &  P1,
const CGAL::Triangle_3< Kernel > &  T2,
CGAL::Point_3< Kernel > &  P2,
typename Kernel::FT &  d 
)

◆ points_inside_component() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedI , typename DerivedP , typename DerivedB >
IGL_INLINE void igl::copyleft::cgal::points_inside_component ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedI > &  I,
const Eigen::PlainObjectBase< DerivedP > &  P,
Eigen::PlainObjectBase< DerivedB > &  inside 
)
255 {
257 if (F.rows() <= 0 || I.rows() <= 0) {
258 throw "Inside check cannot be done on empty facet component.";
259 }
260
261 const size_t num_faces = I.rows();
262 std::vector<Triangle> triangles;
263 for (size_t i=0; i<num_faces; i++) {
264 const Eigen::Vector3i f = F.row(I(i, 0));
265 triangles.emplace_back(
266 Point_3(V(f[0], 0), V(f[0], 1), V(f[0], 2)),
267 Point_3(V(f[1], 0), V(f[1], 1), V(f[1], 2)),
268 Point_3(V(f[2], 0), V(f[2], 1), V(f[2], 2)));
269 if (triangles.back().is_degenerate()) {
270 throw "Input facet components contains degenerated triangles";
271 }
272 }
273 Tree tree(triangles.begin(), triangles.end());
274 tree.accelerate_distance_queries();
275
276 enum ElementType { VERTEX, EDGE, FACE };
277 auto determine_element_type = [&](
278 size_t fid, const Point_3& p, size_t& element_index) -> ElementType{
279 const Eigen::Vector3i f = F.row(I(fid, 0));
280 const Point_3 p0(V(f[0], 0), V(f[0], 1), V(f[0], 2));
281 const Point_3 p1(V(f[1], 0), V(f[1], 1), V(f[1], 2));
282 const Point_3 p2(V(f[2], 0), V(f[2], 1), V(f[2], 2));
283
284 if (p == p0) { element_index = 0; return VERTEX; }
285 if (p == p1) { element_index = 1; return VERTEX; }
286 if (p == p2) { element_index = 2; return VERTEX; }
287 if (CGAL::collinear(p0, p1, p)) { element_index = 2; return EDGE; }
288 if (CGAL::collinear(p1, p2, p)) { element_index = 0; return EDGE; }
289 if (CGAL::collinear(p2, p0, p)) { element_index = 1; return EDGE; }
290
291 element_index = 0;
292 return FACE;
293 };
294
295 const size_t num_queries = P.rows();
296 inside.resize(num_queries, 1);
297 for (size_t i=0; i<num_queries; i++) {
298 const Point_3 query(P(i,0), P(i,1), P(i,2));
299 auto projection = tree.closest_point_and_primitive(query);
300 auto closest_point = projection.first;
301 size_t fid = projection.second - triangles.begin();
302
303 size_t element_index;
304 switch (determine_element_type(fid, closest_point, element_index)) {
305 case VERTEX:
306 {
307 const size_t s = F(I(fid, 0), element_index);
309 V, F, I, query, s);
310 }
311 break;
312 case EDGE:
313 {
314 const size_t s = F(I(fid, 0), (element_index+1)%3);
315 const size_t d = F(I(fid, 0), (element_index+2)%3);
317 V, F, I, query, s, d);
318 }
319 break;
320 case FACE:
321 inside(i,0) = determine_point_face_orientation(V, F, I, query, fid);
322 break;
323 default:
324 throw "Unknown closest element type!";
325 }
326 }
327}
Definition points_inside_component.cpp:28
bool determine_point_face_orientation(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedI > &I, const Point_3 &query, size_t fid)
Definition points_inside_component.cpp:225
bool determine_point_vertex_orientation(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedI > &I, const Point_3 &query, size_t s)
Definition points_inside_component.cpp:156
CGAL::AABB_tree< AABB_triangle_traits > Tree
Definition points_inside_component.cpp:38
bool determine_point_edge_orientation(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedI > &I, const Point_3 &query, size_t s, size_t d)
Definition points_inside_component.cpp:91

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

Referenced by component_inside_component(), outer_hull_legacy(), point_solid_signed_squared_distance(), and points_inside_component().

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

◆ points_inside_component() [2/2]

template<typename DerivedV , typename DerivedF , typename DerivedP , typename DerivedB >
IGL_INLINE void igl::copyleft::cgal::points_inside_component ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedP > &  P,
Eigen::PlainObjectBase< DerivedB > &  inside 
)
335 {
336 Eigen::VectorXi I = igl::LinSpaced<Eigen::VectorXi>(F.rows(), 0, F.rows()-1);
338}

References points_inside_component().

+ Here is the call graph for this function:

◆ polyhedron_to_mesh()

template<typename Polyhedron , typename DerivedV , typename DerivedF >
IGL_INLINE void igl::copyleft::cgal::polyhedron_to_mesh ( const Polyhedron &  poly,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F 
)
19{
20 using namespace std;
21 V.resize(poly.size_of_vertices(),3);
22 F.resize(poly.size_of_facets(),3);
23 typedef typename Polyhedron::Vertex_const_iterator Vertex_iterator;
24 std::map<Vertex_iterator,size_t> vertex_to_index;
25 {
26 size_t v = 0;
27 for(
28 typename Polyhedron::Vertex_const_iterator p = poly.vertices_begin();
29 p != poly.vertices_end();
30 p++)
31 {
32 V(v,0) = p->point().x();
33 V(v,1) = p->point().y();
34 V(v,2) = p->point().z();
35 vertex_to_index[p] = v;
36 v++;
37 }
38 }
39 {
40 size_t f = 0;
41 for(
42 typename Polyhedron::Facet_const_iterator facet = poly.facets_begin();
43 facet != poly.facets_end();
44 ++facet)
45 {
46 typename Polyhedron::Halfedge_around_facet_const_circulator he =
47 facet->facet_begin();
48 // Facets in polyhedral surfaces are at least triangles.
49 assert(CGAL::circulator_size(he) == 3 && "Facets should be triangles");
50 size_t c = 0;
51 do {
53 // F(f,c) = std::distance(poly.vertices_begin(), he->vertex());
54 F(f,c) = vertex_to_index[he->vertex()];
55 c++;
56 } while ( ++he != facet->facet_begin());
57 f++;
58 }
59 }
60}

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

Referenced by convex_hull().

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

◆ projected_cdt() [1/2]

template<typename Kernel , typename DerivedV , typename DerivedF >
IGL_INLINE void igl::copyleft::cgal::projected_cdt ( const std::vector< CGAL::Object > &  objects,
const CGAL::Plane_3< Kernel > &  P,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F 
)
56{
57 std::vector<CGAL::Point_3<Kernel> > vertices;
58 std::vector<std::vector<typename DerivedF::Scalar> > faces;
59 projected_cdt(objects,P,vertices,faces);
60 V.resize(vertices.size(),3);
61 for(int v = 0;v<vertices.size();v++)
62 {
63 for(int d = 0;d<3;d++)
64 {
65 assign_scalar(vertices[v][d], V(v,d));
66 }
67 }
68 list_to_matrix(faces,F);
69}
IGL_INLINE void projected_cdt(const std::vector< CGAL::Object > &objects, const CGAL::Plane_3< Kernel > &P, std::vector< CGAL::Point_3< Kernel > > &vertices, std::vector< std::vector< Index > > &faces)
Definition projected_cdt.cpp:13
IGL_INLINE bool list_to_matrix(const std::vector< std::vector< T > > &V, Eigen::PlainObjectBase< Derived > &M)
Definition list_to_matrix.cpp:19

References assign_scalar(), igl::list_to_matrix(), projected_cdt(), and Eigen::PlainObjectBase< Derived >::resize().

+ Here is the call graph for this function:

◆ projected_cdt() [2/2]

template<typename Kernel , typename Index >
IGL_INLINE void igl::copyleft::cgal::projected_cdt ( const std::vector< CGAL::Object > &  objects,
const CGAL::Plane_3< Kernel > &  P,
std::vector< CGAL::Point_3< Kernel > > &  vertices,
std::vector< std::vector< Index > > &  faces 
)
18{
19 typedef CGAL::Triangulation_vertex_base_2<Kernel> TVB_2;
20 typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTFB_2;
21 typedef CGAL::Triangulation_data_structure_2<TVB_2,CTFB_2> TDS_2;
22 typedef CGAL::Exact_intersections_tag Itag;
23 typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS_2,Itag> CDT_2;
24 typedef CGAL::Constrained_triangulation_plus_2<CDT_2> CDT_plus_2;
25 CDT_plus_2 cdt;
26 for(const auto & obj : objects) insert_into_cdt(obj,P,cdt);
27 // Read off vertices of the cdt, remembering index
28 std::map<typename CDT_plus_2::Vertex_handle,Index> v2i;
29 size_t count=0;
30 for (
31 auto itr = cdt.finite_vertices_begin();
32 itr != cdt.finite_vertices_end();
33 itr++)
34 {
35 vertices.push_back(P.to_3d(itr->point()));
36 v2i[itr] = count;
37 count++;
38 }
39 // Read off faces and store index triples
40 for (
41 auto itr = cdt.finite_faces_begin();
42 itr != cdt.finite_faces_end();
43 itr++)
44 {
45 faces.push_back(
46 { v2i[itr->vertex(0)], v2i[itr->vertex(1)], v2i[itr->vertex(2)] });
47 }
48}
IGL_INLINE void insert_into_cdt(const CGAL::Object &obj, const CGAL::Plane_3< Kernel > &P, CGAL::Constrained_triangulation_plus_2< CGAL::Constrained_Delaunay_triangulation_2< Kernel, CGAL::Triangulation_data_structure_2< CGAL::Triangulation_vertex_base_2< Kernel >, CGAL::Constrained_triangulation_face_base_2< Kernel > >, CGAL::Exact_intersections_tag > > &cdt)
Definition insert_into_cdt.cpp:14

References igl::count(), and insert_into_cdt().

Referenced by projected_cdt(), and remesh_intersections().

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

◆ projected_delaunay()

template<typename Kernel >
IGL_INLINE void igl::copyleft::cgal::projected_delaunay ( const CGAL::Triangle_3< Kernel > &  A,
const std::vector< CGAL::Object > &  A_objects_3,
CGAL::Constrained_triangulation_plus_2< CGAL::Constrained_Delaunay_triangulation_2< Kernel, CGAL::Triangulation_data_structure_2< CGAL::Triangulation_vertex_base_2< Kernel >, CGAL::Constrained_triangulation_face_base_2< Kernel > >, CGAL::Exact_intersections_tag > > &  cdt 
)
28{
29 using namespace std;
30 // 3D Primitives
31 typedef CGAL::Point_3<Kernel> Point_3;
32 typedef CGAL::Segment_3<Kernel> Segment_3;
33 typedef CGAL::Triangle_3<Kernel> Triangle_3;
34 typedef CGAL::Plane_3<Kernel> Plane_3;
35 //typedef CGAL::Tetrahedron_3<Kernel> Tetrahedron_3;
36 typedef CGAL::Point_2<Kernel> Point_2;
37 //typedef CGAL::Segment_2<Kernel> Segment_2;
38 //typedef CGAL::Triangle_2<Kernel> Triangle_2;
39 typedef CGAL::Triangulation_vertex_base_2<Kernel> TVB_2;
40 typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTFB_2;
41 typedef CGAL::Triangulation_data_structure_2<TVB_2,CTFB_2> TDS_2;
42 typedef CGAL::Exact_intersections_tag Itag;
43 typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS_2,Itag>
44 CDT_2;
45 typedef CGAL::Constrained_triangulation_plus_2<CDT_2> CDT_plus_2;
46
47 // http://www.cgal.org/Manual/3.2/doc_html/cgal_manual/Triangulation_2/Chapter_main.html#Section_2D_Triangulations_Constrained_Plus
48 // Plane of triangle A
49 Plane_3 P(A.vertex(0),A.vertex(1),A.vertex(2));
50 // Insert triangle into vertices
51 typename CDT_plus_2::Vertex_handle corners[3];
52 typedef size_t Index;
53 for(Index i = 0;i<3;i++)
54 {
55 const Point_3 & p3 = A.vertex(i);
56 const Point_2 & p2 = P.to_2d(p3);
57 typename CDT_plus_2::Vertex_handle corner = cdt.insert(p2);
58 corners[i] = corner;
59 }
60 // Insert triangle edges as constraints
61 for(Index i = 0;i<3;i++)
62 {
63 cdt.insert_constraint( corners[(i+1)%3], corners[(i+2)%3]);
64 }
65 // Insert constraints for intersection objects
66 for( const auto & obj : A_objects_3)
67 {
68 if(const Segment_3 *iseg = CGAL::object_cast<Segment_3 >(&obj))
69 {
70 // Add segment constraint
71 cdt.insert_constraint(P.to_2d(iseg->vertex(0)),P.to_2d(iseg->vertex(1)));
72 }else if(const Point_3 *ipoint = CGAL::object_cast<Point_3 >(&obj))
73 {
74 // Add point
75 cdt.insert(P.to_2d(*ipoint));
76 } else if(const Triangle_3 *itri = CGAL::object_cast<Triangle_3 >(&obj))
77 {
78 // Add 3 segment constraints
79 cdt.insert_constraint(P.to_2d(itri->vertex(0)),P.to_2d(itri->vertex(1)));
80 cdt.insert_constraint(P.to_2d(itri->vertex(1)),P.to_2d(itri->vertex(2)));
81 cdt.insert_constraint(P.to_2d(itri->vertex(2)),P.to_2d(itri->vertex(0)));
82 } else if(const std::vector<Point_3 > *polyp =
83 CGAL::object_cast< std::vector<Point_3 > >(&obj))
84 {
85 //cerr<<REDRUM("Poly...")<<endl;
86 const std::vector<Point_3 > & poly = *polyp;
87 const Index m = poly.size();
88 assert(m>=2);
89 for(Index p = 0;p<m;p++)
90 {
91 const Index np = (p+1)%m;
92 cdt.insert_constraint(P.to_2d(poly[p]),P.to_2d(poly[np]));
93 }
94 }else
95 {
96 cerr<<REDRUM("What is this object?!")<<endl;
97 assert(false);
98 }
99 }
100}
#define REDRUM(X)
Definition REDRUM.h:40
IGL_INLINE bool cdt(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const CDTParam &param, Eigen::PlainObjectBase< DerivedTV > &TV, Eigen::PlainObjectBase< DerivedTT > &TT, Eigen::PlainObjectBase< DerivedTF > &TF)
Definition cdt.cpp:18

References REDRUM.

◆ propagate_winding_numbers() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedL , typename DerivedW >
IGL_INLINE bool igl::copyleft::cgal::propagate_winding_numbers ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedL > &  labels,
Eigen::PlainObjectBase< DerivedW > &  W 
)
44{
45#ifdef PROPAGATE_WINDING_NUMBER_TIMING
46 const auto & tictoc = []() -> double
47 {
48 static double t_start = igl::get_seconds();
49 double diff = igl::get_seconds()-t_start;
50 t_start += diff;
51 return diff;
52 };
53 const auto log_time = [&](const std::string& label) -> void {
54 std::cout << "propagate_winding_num." << label << ": "
55 << tictoc() << std::endl;
56 };
57 tictoc();
58#endif
59
60 Eigen::MatrixXi E, uE;
61 Eigen::VectorXi EMAP;
62 std::vector<std::vector<size_t> > uE2E;
63 igl::unique_edge_map(F, E, uE, EMAP, uE2E);
64
65 Eigen::VectorXi P;
66 const size_t num_patches = igl::extract_manifold_patches(F, EMAP, uE2E, P);
67
68 DerivedW per_patch_cells;
69 const size_t num_cells =
71 V, F, P, E, uE, uE2E, EMAP, per_patch_cells);
72#ifdef PROPAGATE_WINDING_NUMBER_TIMING
73 log_time("cell_extraction");
74#endif
75
76 return propagate_winding_numbers(V, F,
77 uE, uE2E,
78 num_patches, P,
79 num_cells, per_patch_cells,
80 labels, W);
81}

References extract_cells(), igl::extract_manifold_patches(), igl::get_seconds(), propagate_winding_numbers(), and igl::unique_edge_map().

Referenced by peel_winding_number_layers(), and propagate_winding_numbers().

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

◆ propagate_winding_numbers() [2/2]

template<typename DerivedV , typename DerivedF , typename DeriveduE , typename uE2EType , typename DerivedP , typename DerivedC , typename DerivedL , typename DerivedW >
IGL_INLINE bool igl::copyleft::cgal::propagate_winding_numbers ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DeriveduE > &  uE,
const std::vector< std::vector< uE2EType > > &  uE2E,
const size_t  num_patches,
const Eigen::PlainObjectBase< DerivedP > &  P,
const size_t  num_cells,
const Eigen::PlainObjectBase< DerivedC > &  C,
const Eigen::PlainObjectBase< DerivedL > &  labels,
Eigen::PlainObjectBase< DerivedW > &  W 
)
104{
105#ifdef PROPAGATE_WINDING_NUMBER_TIMING
106 const auto & tictoc = []() -> double
107 {
108 static double t_start = igl::get_seconds();
109 double diff = igl::get_seconds()-t_start;
110 t_start += diff;
111 return diff;
112 };
113 const auto log_time = [&](const std::string& label) -> void {
114 std::cout << "propagate_winding_num." << label << ": "
115 << tictoc() << std::endl;
116 };
117 tictoc();
118#endif
119
120 bool valid = true;
121 // https://github.com/libigl/libigl/issues/674
123 {
124 assert(false && "Input mesh is not PWN");
125 std::cerr << "Input mesh is not PWN!" << std::endl;
126 valid = false;
127 }
128
129 const size_t num_faces = F.rows();
130 typedef std::tuple<typename DerivedC::Scalar, bool, size_t> CellConnection;
131 std::vector<std::set<CellConnection> > cell_adj;
132 igl::copyleft::cgal::cell_adjacency(C, num_cells, cell_adj);
133#ifdef PROPAGATE_WINDING_NUMBER_TIMING
134 log_time("cell_connectivity");
135#endif
136
137 auto save_cell = [&](const std::string& filename, size_t cell_id) -> void{
138 std::vector<size_t> faces;
139 for (size_t i=0; i<num_patches; i++) {
140 if ((C.row(i).array() == cell_id).any()) {
141 for (size_t j=0; j<num_faces; j++) {
142 if ((size_t)P[j] == i) {
143 faces.push_back(j);
144 }
145 }
146 }
147 }
148 Eigen::MatrixXi cell_faces(faces.size(), 3);
149 for (size_t i=0; i<faces.size(); i++) {
150 cell_faces.row(i) = F.row(faces[i]);
151 }
152 Eigen::MatrixXd vertices;
153 assign(V,vertices);
154 writePLY(filename, vertices, cell_faces);
155 };
156
157#ifndef NDEBUG
158 {
159 // Check for odd cycle.
160 Eigen::VectorXi cell_labels(num_cells);
161 cell_labels.setZero();
162 Eigen::VectorXi parents(num_cells);
163 parents.setConstant(-1);
164 auto trace_parents = [&](size_t idx) -> std::list<size_t> {
165 std::list<size_t> path;
166 path.push_back(idx);
167 while ((size_t)parents[path.back()] != path.back()) {
168 path.push_back(parents[path.back()]);
169 }
170 return path;
171 };
172 for (size_t i=0; i<num_cells; i++) {
173 if (cell_labels[i] == 0) {
174 cell_labels[i] = 1;
175 std::queue<size_t> Q;
176 Q.push(i);
177 parents[i] = i;
178 while (!Q.empty()) {
179 size_t curr_idx = Q.front();
180 Q.pop();
181 int curr_label = cell_labels[curr_idx];
182 for (const auto& neighbor : cell_adj[curr_idx]) {
183 if (cell_labels[std::get<0>(neighbor)] == 0)
184 {
185 cell_labels[std::get<0>(neighbor)] = curr_label * -1;
186 Q.push(std::get<0>(neighbor));
187 parents[std::get<0>(neighbor)] = curr_idx;
188 } else
189 {
190 if (cell_labels[std::get<0>(neighbor)] != curr_label * -1)
191 {
192 std::cerr << "Odd cell cycle detected!" << std::endl;
193 auto path = trace_parents(curr_idx);
194 path.reverse();
195 auto path2 = trace_parents(std::get<0>(neighbor));
196 path.insert(path.end(), path2.begin(), path2.end());
197 for (auto cell_id : path)
198 {
199 std::cout << cell_id << " ";
200 std::stringstream filename;
201 filename << "cell_" << cell_id << ".ply";
202 save_cell(filename.str(), cell_id);
203 }
204 std::cout << std::endl;
205 valid = false;
206 }
207 // Do not fail when odd cycle is detected because the resulting
208 // integer winding number field, although inconsistent, may still
209 // be used if the problem region is local and embedded within a
210 // valid volume.
211 //assert(cell_labels[std::get<0>(neighbor)] == curr_label * -1);
212 }
213 }
214 }
215 }
216 }
217#ifdef PROPAGATE_WINDING_NUMBER_TIMING
218 log_time("odd_cycle_check");
219#endif
220 }
221#endif
222
223 size_t outer_facet;
224 bool flipped;
225 Eigen::VectorXi I = igl::LinSpaced<Eigen::VectorXi>(num_faces, 0, num_faces-1);
226 igl::copyleft::cgal::outer_facet(V, F, I, outer_facet, flipped);
227#ifdef PROPAGATE_WINDING_NUMBER_TIMING
228 log_time("outer_facet");
229#endif
230
231 const size_t outer_patch = P[outer_facet];
232 const size_t infinity_cell = C(outer_patch, flipped?1:0);
233
234 Eigen::VectorXi patch_labels(num_patches);
235 const int INVALID = std::numeric_limits<int>::max();
236 patch_labels.setConstant(INVALID);
237 for (size_t i=0; i<num_faces; i++) {
238 if (patch_labels[P[i]] == INVALID) {
239 patch_labels[P[i]] = labels[i];
240 } else {
241 assert(patch_labels[P[i]] == labels[i]);
242 }
243 }
244 assert((patch_labels.array() != INVALID).all());
245 const size_t num_labels = patch_labels.maxCoeff()+1;
246
247 Eigen::MatrixXi per_cell_W(num_cells, num_labels);
248 per_cell_W.setConstant(INVALID);
249 per_cell_W.row(infinity_cell).setZero();
250 std::queue<size_t> Q;
251 Q.push(infinity_cell);
252 while (!Q.empty()) {
253 size_t curr_cell = Q.front();
254 Q.pop();
255 for (const auto& neighbor : cell_adj[curr_cell]) {
256 size_t neighbor_cell, patch_idx;
257 bool direction;
258 std::tie(neighbor_cell, direction, patch_idx) = neighbor;
259 if ((per_cell_W.row(neighbor_cell).array() == INVALID).any()) {
260 per_cell_W.row(neighbor_cell) = per_cell_W.row(curr_cell);
261 for (size_t i=0; i<num_labels; i++) {
262 int inc = (patch_labels[patch_idx] == (int)i) ?
263 (direction ? -1:1) :0;
264 per_cell_W(neighbor_cell, i) =
265 per_cell_W(curr_cell, i) + inc;
266 }
267 Q.push(neighbor_cell);
268 } else {
269#ifndef NDEBUG
270 // Checking for winding number consistency.
271 // This check would inevitably fail for meshes that contain open
272 // boundary or non-orientable. However, the inconsistent winding number
273 // field would still be useful in some cases such as when problem region
274 // is local and embedded within the volume. This, unfortunately, is the
275 // best we can do because the problem of computing integer winding
276 // number is ill-defined for open and non-orientable surfaces.
277 for (size_t i=0; i<num_labels; i++) {
278 if ((int)i == patch_labels[patch_idx]) {
279 int inc = direction ? -1:1;
280 //assert(per_cell_W(neighbor_cell, i) ==
281 // per_cell_W(curr_cell, i) + inc);
282 } else {
283 //assert(per_cell_W(neighbor_cell, i) ==
284 // per_cell_W(curr_cell, i));
285 }
286 }
287#endif
288 }
289 }
290 }
291#ifdef PROPAGATE_WINDING_NUMBER_TIMING
292 log_time("propagate_winding_number");
293#endif
294
295 W.resize(num_faces, num_labels*2);
296 for (size_t i=0; i<num_faces; i++)
297 {
298 const size_t patch = P[i];
299 const size_t positive_cell = C(patch, 0);
300 const size_t negative_cell = C(patch, 1);
301 for (size_t j=0; j<num_labels; j++) {
302 W(i,j*2 ) = per_cell_W(positive_cell, j);
303 W(i,j*2+1) = per_cell_W(negative_cell, j);
304 }
305 }
306#ifdef PROPAGATE_WINDING_NUMBER_TIMING
307 log_time("store_result");
308#endif
309 return valid;
310}
IGL_INLINE void cell_adjacency(const Eigen::PlainObjectBase< DerivedC > &per_patch_cells, const size_t num_cells, std::vector< std::set< std::tuple< typename DerivedC::Scalar, bool, size_t > > > &adjacency_list)
Definition cell_adjacency.cpp:13

References assign(), cell_adjacency(), igl::get_seconds(), outer_facet(), igl::piecewise_constant_winding_number(), Eigen::PlainObjectBase< Derived >::resize(), and igl::writePLY().

+ Here is the call graph for this function:

◆ push_result()

template<typename DerivedF >
static IGL_INLINE void igl::copyleft::cgal::push_result ( const Eigen::PlainObjectBase< DerivedF > &  F,
const int  f,
const int  f_other,
const CGAL::Object &  result,
std::map< typename DerivedF::Index, std::vector< std::pair< typename DerivedF::Index, CGAL::Object > > > &  offending 
)
static
39 {
40 typedef typename DerivedF::Index Index;
41 typedef std::pair<Index,Index> EMK;
42 if(offending.count(f) == 0)
43 {
44 // first time marking, initialize with new id and empty list
45 offending[f] = {};
46 for(Index e = 0; e<3;e++)
47 {
48 // append face to edge's list
49 Index i = F(f,(e+1)%3) < F(f,(e+2)%3) ? F(f,(e+1)%3) : F(f,(e+2)%3);
50 Index j = F(f,(e+1)%3) < F(f,(e+2)%3) ? F(f,(e+2)%3) : F(f,(e+1)%3);
51 //edge2faces[EMK(i,j)].push_back(f);
52 }
53 }
54 offending[f].push_back({f_other,result});
55 }

Referenced by intersect_other_helper().

+ Here is the caller graph for this function:

◆ read_triangle_mesh()

template<typename DerivedV , typename DerivedF >
IGL_INLINE bool igl::copyleft::cgal::read_triangle_mesh ( const std::string  str,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F 
)
18{
19 Eigen::MatrixXd Vd;
20 bool ret = igl::read_triangle_mesh(str,Vd,F);
21 if(ret)
22 {
23 assign(Vd,V);
24 }
25 return ret;
26}
IGL_INLINE bool read_triangle_mesh(const std::string str, std::vector< std::vector< Scalar > > &V, std::vector< std::vector< Index > > &F)
Definition read_triangle_mesh.cpp:26

References assign(), and igl::read_triangle_mesh().

+ Here is the call graph for this function:

◆ relabel_small_immersed_cells()

template<typename DerivedV , typename DerivedF , typename DerivedP , typename DerivedC , typename FT , typename DerivedW >
IGL_INLINE void igl::copyleft::cgal::relabel_small_immersed_cells ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const size_t  num_patches,
const Eigen::PlainObjectBase< DerivedP > &  P,
const size_t  num_cells,
const Eigen::PlainObjectBase< DerivedC > &  C,
const FT  vol_threashold,
Eigen::PlainObjectBase< DerivedW > &  W 
)
33{
34 const size_t num_vertices = V.rows();
35 const size_t num_faces = F.rows();
36 typedef std::tuple<typename DerivedC::Scalar, bool, size_t> CellConnection;
37 std::vector<std::set<CellConnection> > cell_adj;
38 igl::copyleft::cgal::cell_adjacency(C, num_cells, cell_adj);
39
40 Eigen::MatrixXd VV;
41 assign(V,VV);
42
43 auto compute_cell_volume = [&](size_t cell_id) {
44 std::vector<short> is_involved(num_patches, 0);
45 for (size_t i=0; i<num_patches; i++) {
46 if (C(i,0) == cell_id) {
47 // cell is on positive side of patch i.
48 is_involved[i] = 1;
49 }
50 if (C(i,1) == cell_id) {
51 // cell is on negative side of patch i.
52 is_involved[i] = -1;
53 }
54 }
55
56 std::vector<size_t> involved_positive_faces;
57 std::vector<size_t> involved_negative_faces;
58 for (size_t i=0; i<num_faces; i++) {
59 switch (is_involved[P[i]]) {
60 case 1:
61 involved_negative_faces.push_back(i);
62 break;
63 case -1:
64 involved_positive_faces.push_back(i);
65 break;
66 }
67 }
68
69 const size_t num_positive_faces = involved_positive_faces.size();
70 const size_t num_negative_faces = involved_negative_faces.size();
71 DerivedF selected_faces(num_positive_faces + num_negative_faces, 3);
72 for (size_t i=0; i<num_positive_faces; i++) {
73 selected_faces.row(i) = F.row(involved_positive_faces[i]);
74 }
75 for (size_t i=0; i<num_negative_faces; i++) {
76 selected_faces.row(num_positive_faces+i) =
77 F.row(involved_negative_faces[i]).reverse();
78 }
79
80 Eigen::VectorXd c(3);
81 double vol;
82 igl::centroid(VV, selected_faces, c, vol);
83 return vol;
84 };
85
86 std::vector<typename DerivedV::Scalar> cell_volumes(num_cells);
87 for (size_t i=0; i<num_cells; i++) {
88 cell_volumes[i] = compute_cell_volume(i);
89 }
90
91 std::vector<typename DerivedW::Scalar> cell_values(num_cells);
92 for (size_t i=0; i<num_faces; i++) {
93 cell_values[C(P[i], 0)] = W(i, 0);
94 cell_values[C(P[i], 1)] = W(i, 1);
95 }
96
97 for (size_t i=1; i<num_cells; i++) {
98 std::cout << cell_volumes[i] << std::endl;
99 if (cell_volumes[i] >= vol_threashold) continue;
100 std::set<typename DerivedW::Scalar> neighbor_values;
101 const auto neighbors = cell_adj[i];
102 for (const auto& entry : neighbors) {
103 const auto& j = std::get<0>(entry);
104 neighbor_values.insert(cell_values[j]);
105 }
106 // If cell i is immersed, assign its value to be the immersed value.
107 if (neighbor_values.size() == 1) {
108 cell_values[i] = *neighbor_values.begin();
109 }
110 }
111
112 for (size_t i=0; i<num_faces; i++) {
113 W(i,0) = cell_values[C(P[i], 0)];
114 W(i,1) = cell_values[C(P[i], 1)];
115 }
116}

References assign(), cell_adjacency(), igl::centroid(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ remesh_intersections() [1/2]

template<typename DerivedV , typename DerivedF , typename Kernel , typename DerivedVV , typename DerivedFF , typename DerivedJ , typename DerivedIM >
IGL_INLINE void igl::copyleft::cgal::remesh_intersections ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const std::vector< CGAL::Triangle_3< Kernel > > &  T,
const std::map< typename DerivedF::Index, std::vector< std::pair< typename DerivedF::Index, CGAL::Object > > > &  offending,
bool  stitch_all,
Eigen::PlainObjectBase< DerivedVV > &  VV,
Eigen::PlainObjectBase< DerivedFF > &  FF,
Eigen::PlainObjectBase< DerivedJ > &  J,
Eigen::PlainObjectBase< DerivedIM > &  IM 
)
71{
72
73#ifdef REMESH_INTERSECTIONS_TIMING
74 const auto & tictoc = []() -> double
75 {
76 static double t_start = igl::get_seconds();
77 double diff = igl::get_seconds()-t_start;
78 t_start += diff;
79 return diff;
80 };
81 const auto log_time = [&](const std::string& label) -> void {
82 std::cout << "remesh_intersections." << label << ": "
83 << tictoc() << std::endl;
84 };
85 tictoc();
86#endif
87
88 typedef CGAL::Point_3<Kernel> Point_3;
89 typedef CGAL::Segment_3<Kernel> Segment_3;
90 typedef CGAL::Plane_3<Kernel> Plane_3;
91 typedef CGAL::Triangulation_vertex_base_2<Kernel> TVB_2;
92 typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTFB_2;
93 typedef CGAL::Triangulation_data_structure_2<TVB_2,CTFB_2> TDS_2;
94 typedef CGAL::Exact_intersections_tag Itag;
95 typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS_2,Itag>
96 CDT_2;
97 typedef CGAL::Constrained_triangulation_plus_2<CDT_2> CDT_plus_2;
98
99 typedef typename DerivedF::Index Index;
100 typedef std::pair<Index, Index> Edge;
101 struct EdgeHash {
102 size_t operator()(const Edge& e) const {
103 return (e.first * 805306457) ^ (e.second * 201326611);
104 }
105 };
106 typedef std::unordered_map<Edge, std::vector<Index>, EdgeHash > EdgeMap;
107
108 const size_t num_faces = F.rows();
109 const size_t num_base_vertices = V.rows();
110 assert(num_faces == T.size());
111
112 std::vector<bool> is_offending(num_faces, false);
113 for (const auto itr : offending)
114 {
115 const auto& fid = itr.first;
116 is_offending[fid] = true;
117 }
118
119 // Cluster overlaps so that co-planar clusters are resolved only once
120 std::unordered_map<Index, std::vector<Index> > intersecting_and_coplanar;
121 for (const auto itr : offending)
122 {
123 const auto& fi = itr.first;
124 const auto P = T[fi].supporting_plane();
125 assert(!P.is_degenerate());
126 for (const auto jtr : itr.second)
127 {
128 const auto& fj = jtr.first;
129 const auto& tj = T[fj];
130 if (P.has_on(tj[0]) && P.has_on(tj[1]) && P.has_on(tj[2]))
131 {
132 auto loc = intersecting_and_coplanar.find(fi);
133 if (loc == intersecting_and_coplanar.end())
134 {
135 intersecting_and_coplanar[fi] = {fj};
136 } else
137 {
138 loc->second.push_back(fj);
139 }
140 }
141 }
142 }
143#ifdef REMESH_INTERSECTIONS_TIMING
144 log_time("overlap_analysis");
145#endif
146
147 std::vector<std::vector<Index> > resolved_faces;
148 std::vector<Index> source_faces;
149 std::vector<Point_3> new_vertices;
150 EdgeMap edge_vertices;
151 // face_vertices: Given a face Index, find vertices inside the face
152 std::unordered_map<Index, std::vector<Index>> face_vertices;
153
154 // Run constraint Delaunay triangulation on the plane.
155 //
156 // Inputs:
157 // P plane to triangulate upone
158 // involved_faces #F list of indices into triangle of involved faces
159 // Outputs:
160 // vertices #V list of vertex positions of output triangulation
161 // faces #F list of face indices into vertices of output triangulation
162 //
163 auto delaunay_triangulation = [&offending, &T](
164 const Plane_3& P,
165 const std::vector<Index>& involved_faces,
166 std::vector<Point_3>& vertices,
167 std::vector<std::vector<Index> >& faces) -> void
168 {
169 std::vector<CGAL::Object> objects;
170
171 CDT_plus_2 cdt;
172 // insert each face into a common cdt
173 for (const auto& fid : involved_faces)
174 {
175 const auto itr = offending.find(fid);
176 const auto& triangle = T[fid];
177 objects.push_back(CGAL::make_object(triangle));
178 if (itr == offending.end())
179 {
180 continue;
181 }
182 for (const auto& index_obj : itr->second)
183 {
184 //const auto& ofid = index_obj.first;
185 const auto& obj = index_obj.second;
186 objects.push_back(obj);
187 }
188 }
189 projected_cdt(objects,P,vertices,faces);
190 };
191
192 // Given p on triangle indexed by ori_f, add point to list of vertices return index of p.
193 //
194 // Input:
195 // p point to search for
196 // ori_f index of triangle p is corner of
197 // Returns global index of vertex (dependent on whether stitch_all flag is
198 // set)
199 //
200 auto find_or_append_point = [&](
201 const Point_3& p,
202 const size_t ori_f) -> Index
203 {
204 if (stitch_all)
205 {
206 // No need to check if p shared by multiple triangles because all shared
207 // vertices would be merged later on.
208 const size_t index = num_base_vertices + new_vertices.size();
209 new_vertices.push_back(p);
210 return index;
211 } else
212 {
213 // Stitching triangles according to input connectivity.
214 // This step is potentially costly.
215 const auto& triangle = T[ori_f];
216 const auto& f = F.row(ori_f).eval();
217
218 // Check if p is one of the triangle corners.
219 for (size_t i=0; i<3; i++)
220 {
221 if (p == triangle[i]) return f[i];
222 }
223
224 // Check if p is on one of the edges.
225 for (size_t i=0; i<3; i++) {
226 const Point_3 curr_corner = triangle[i];
227 const Point_3 next_corner = triangle[(i+1)%3];
228 const Segment_3 edge(curr_corner, next_corner);
229 if (edge.has_on(p)) {
230 const Index curr = f[i];
231 const Index next = f[(i+1)%3];
232 Edge key;
233 key.first = curr<next?curr:next;
234 key.second = curr<next?next:curr;
235 auto itr = edge_vertices.find(key);
236 if (itr == edge_vertices.end()) {
237 const Index index =
238 num_base_vertices + new_vertices.size();
239 edge_vertices.insert({key, {index}});
240 new_vertices.push_back(p);
241 return index;
242 } else {
243 for (const auto vid : itr->second) {
244 if (p == new_vertices[vid - num_base_vertices]) {
245 return vid;
246 }
247 }
248 const size_t index = num_base_vertices + new_vertices.size();
249 new_vertices.push_back(p);
250 itr->second.push_back(index);
251 return index;
252 }
253 }
254 }
255
256 // p must be in the middle of the triangle.
257 auto & existing_face_vertices = face_vertices[ori_f];
258 for(const auto vid : existing_face_vertices) {
259 if (p == new_vertices[vid - num_base_vertices]) {
260 return vid;
261 }
262 }
263 const size_t index = num_base_vertices + new_vertices.size();
264 new_vertices.push_back(p);
265 existing_face_vertices.push_back(index);
266 return index;
267 }
268 };
269
270 // Determine the vertex indices for each corner of each output triangle.
271 //
272 // Inputs:
273 // vertices #V list of vertices of cdt
274 // faces #F list of list of face indices into vertices of cdt
275 // involved_faces list of involved faces on the plane of cdt
276 // Side effects:
277 // - add faces to resolved_faces
278 // - add corresponding original face to source_faces
279 // -
280 auto post_triangulation_process = [&](
281 const std::vector<Point_3>& vertices,
282 const std::vector<std::vector<Index> >& faces,
283 const std::vector<Index>& involved_faces) -> void
284 {
285 assert(involved_faces.size() > 0);
286 // for all faces of the cdt
287 for (const auto& f : faces)
288 {
289 const Point_3& v0 = vertices[f[0]];
290 const Point_3& v1 = vertices[f[1]];
291 const Point_3& v2 = vertices[f[2]];
292 Point_3 center(
293 (v0[0] + v1[0] + v2[0]) / 3.0,
294 (v0[1] + v1[1] + v2[1]) / 3.0,
295 (v0[2] + v1[2] + v2[2]) / 3.0);
296 if (involved_faces.size() == 1)
297 {
298 // If only there is only one involved face, all sub-triangles must
299 // belong to it and have the correct orientation.
300 const auto& ori_f = involved_faces[0];
301 std::vector<Index> corners(3);
302 corners[0] = find_or_append_point(v0, ori_f);
303 corners[1] = find_or_append_point(v1, ori_f);
304 corners[2] = find_or_append_point(v2, ori_f);
305 resolved_faces.emplace_back(corners);
306 source_faces.push_back(ori_f);
307 } else
308 {
309 for (const auto& ori_f : involved_faces)
310 {
311 const auto& triangle = T[ori_f];
312 const Plane_3 P = triangle.supporting_plane();
313 if (triangle.has_on(center)) {
314 std::vector<Index> corners(3);
315 corners[0] = find_or_append_point(v0, ori_f);
316 corners[1] = find_or_append_point(v1, ori_f);
317 corners[2] = find_or_append_point(v2, ori_f);
318 if (CGAL::orientation(
319 P.to_2d(v0), P.to_2d(v1), P.to_2d(v2))
320 == CGAL::RIGHT_TURN) {
321 std::swap(corners[0], corners[1]);
322 }
323 resolved_faces.emplace_back(corners);
324 source_faces.push_back(ori_f);
325 }
326 }
327 }
328 }
329 };
330
331 // Process un-touched faces.
332 for (size_t i=0; i<num_faces; i++)
333 {
334 if (!is_offending[i] && !T[i].is_degenerate())
335 {
336 resolved_faces.push_back( { F(i,0), F(i,1), F(i,2) } );
337 source_faces.push_back(i);
338 }
339 }
340
341 // Process self-intersecting faces.
342 std::vector<bool> processed(num_faces, false);
343 std::vector<std::pair<Plane_3, std::vector<Index> > > cdt_inputs;
344 for (const auto itr : offending)
345 {
346 const auto fid = itr.first;
347 if (processed[fid]) continue;
348 processed[fid] = true;
349
350 const auto loc = intersecting_and_coplanar.find(fid);
351 std::vector<Index> involved_faces;
352 if (loc == intersecting_and_coplanar.end())
353 {
354 involved_faces.push_back(fid);
355 } else
356 {
357 std::queue<Index> Q;
358 Q.push(fid);
359 while (!Q.empty())
360 {
361 const auto index = Q.front();
362 involved_faces.push_back(index);
363 Q.pop();
364
365 const auto overlapping_faces = intersecting_and_coplanar.find(index);
366 assert(overlapping_faces != intersecting_and_coplanar.end());
367
368 for (const auto other_index : overlapping_faces->second)
369 {
370 if (processed[other_index]) continue;
371 processed[other_index] = true;
372 Q.push(other_index);
373 }
374 }
375 }
376
377 Plane_3 P = T[fid].supporting_plane();
378 cdt_inputs.emplace_back(P, involved_faces);
379 }
380#ifdef REMESH_INTERSECTIONS_TIMING
381 log_time("preprocess");
382#endif
383
384 const size_t num_cdts = cdt_inputs.size();
385 std::vector<std::vector<Point_3> > cdt_vertices(num_cdts);
386 std::vector<std::vector<std::vector<Index> > > cdt_faces(num_cdts);
387
393 //igl::parallel_for(num_cdts,[&](int i)
394 for (size_t i=0; i<num_cdts; i++)
395 {
396 auto& vertices = cdt_vertices[i];
397 auto& faces = cdt_faces[i];
398 const auto& P = cdt_inputs[i].first;
399 const auto& involved_faces = cdt_inputs[i].second;
400 delaunay_triangulation(P, involved_faces, vertices, faces);
401 }
402 //,1000);
403#ifdef REMESH_INTERSECTIONS_TIMING
404 log_time("cdt");
405#endif
406
407 for (size_t i=0; i<num_cdts; i++)
408 {
409 const auto& vertices = cdt_vertices[i];
410 const auto& faces = cdt_faces[i];
411 const auto& involved_faces = cdt_inputs[i].second;
412 post_triangulation_process(vertices, faces, involved_faces);
413 }
414#ifdef REMESH_INTERSECTIONS_TIMING
415 log_time("stitching");
416#endif
417
418 // Output resolved mesh.
419 const size_t num_out_vertices = new_vertices.size() + num_base_vertices;
420 VV.resize(num_out_vertices, 3);
421 for (size_t i=0; i<num_base_vertices; i++)
422 {
423 assign_scalar(V(i,0), VV(i,0));
424 assign_scalar(V(i,1), VV(i,1));
425 assign_scalar(V(i,2), VV(i,2));
426 }
427
428 for (size_t i=num_base_vertices; i<num_out_vertices; i++)
429 {
430 assign_scalar(new_vertices[i-num_base_vertices][0], VV(i,0));
431 assign_scalar(new_vertices[i-num_base_vertices][1], VV(i,1));
432 assign_scalar(new_vertices[i-num_base_vertices][2], VV(i,2));
433 }
434
435 const size_t num_out_faces = resolved_faces.size();
436 FF.resize(num_out_faces, 3);
437 for (size_t i=0; i<num_out_faces; i++)
438 {
439 FF(i,0) = resolved_faces[i][0];
440 FF(i,1) = resolved_faces[i][1];
441 FF(i,2) = resolved_faces[i][2];
442 }
443
444 J.resize(num_out_faces);
445 std::copy(source_faces.begin(), source_faces.end(), J.data());
446
447 // Extract unique vertex indices.
448 const size_t VV_size = VV.rows();
449 IM.resize(VV_size,1);
450
451 DerivedVV unique_vv;
452 Eigen::VectorXi unique_to_vv, vv_to_unique;
453 // This is not stable... So even if offending is empty V != VV in
454 // general...
455 igl::unique_rows(VV, unique_vv, unique_to_vv, vv_to_unique);
456 if(stitch_all)
457 {
458 // Merge all vertices having the same coordinates into a single vertex
459 // and set IM to identity map.
460 VV = unique_vv;
461 std::transform(FF.data(), FF.data() + FF.rows()*FF.cols(),
462 FF.data(), [&vv_to_unique](const typename DerivedFF::Scalar& a)
463 { return vv_to_unique[a]; });
464 IM.resize(unique_vv.rows());
465 // Have to use << instead of = because Eigen's PlainObjectBase is annoying
466 IM << igl::LinSpaced<
468 >(unique_vv.rows(), 0, unique_vv.rows()-1);
469 }else
470 {
471 // Vertices with the same coordinates would be represented by one vertex.
472 // The IM value of a vertex is the index of the representative vertex.
473 for (Index v=0; v<(Index)VV_size; v++) {
474 IM(v) = unique_to_vv[vv_to_unique[v]];
475 }
476 }
477
478#ifdef REMESH_INTERSECTIONS_TIMING
479 log_time("store_results");
480#endif
481}
IGL_INLINE void delaunay_triangulation(const Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F)
Definition delaunay_triangulation.cpp:18
Derived LinSpaced(typename Derived::Index size, const typename Derived::Scalar &low, const typename Derived::Scalar &high)
Definition LinSpaced.h:44
Definition marching_cubes.cpp:49
std::size_t operator()(const EdgeKey &key) const
Definition marching_cubes.cpp:50

References assign_scalar(), Eigen::PlainObjectBase< Derived >::cols(), Eigen::PlainObjectBase< Derived >::data(), delaunay_triangulation(), igl::get_seconds(), igl::LinSpaced(), EdgeHash::operator()(), projected_cdt(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), and igl::unique_rows().

Referenced by igl::copyleft::cgal::SelfIntersectMesh< Kernel, DerivedV, DerivedF, DerivedVV, DerivedFF, DerivedIF, DerivedJ, DerivedIM >::SelfIntersectMesh(), intersect_other_helper(), and remesh_intersections().

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

◆ remesh_intersections() [2/2]

template<typename DerivedV , typename DerivedF , typename Kernel , typename DerivedVV , typename DerivedFF , typename DerivedJ , typename DerivedIM >
IGL_INLINE void igl::copyleft::cgal::remesh_intersections ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const std::vector< CGAL::Triangle_3< Kernel > > &  T,
const std::map< typename DerivedF::Index, std::vector< std::pair< typename DerivedF::Index, CGAL::Object > > > &  offending,
Eigen::PlainObjectBase< DerivedVV > &  VV,
Eigen::PlainObjectBase< DerivedFF > &  FF,
Eigen::PlainObjectBase< DerivedJ > &  J,
Eigen::PlainObjectBase< DerivedIM > &  IM 
)
45{
46 // by default, no stitching
47 igl::copyleft::cgal::remesh_intersections(V,F,T,offending,false,VV,FF,J,IM);
48}

References remesh_intersections().

+ Here is the call graph for this function:

◆ remesh_self_intersections()

template<typename DerivedV , typename DerivedF , typename DerivedVV , typename DerivedFF , typename DerivedIF , typename DerivedJ , typename DerivedIM >
IGL_INLINE void igl::copyleft::cgal::remesh_self_intersections ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const RemeshSelfIntersectionsParam params,
Eigen::PlainObjectBase< DerivedVV > &  VV,
Eigen::PlainObjectBase< DerivedFF > &  FF,
Eigen::PlainObjectBase< DerivedIF > &  IF,
Eigen::PlainObjectBase< DerivedJ > &  J,
Eigen::PlainObjectBase< DerivedIM > &  IM 
)
31{
32 using namespace std;
33 if(params.detect_only)
34 {
37
38//#ifdef __APPLE__
39//#define IGL_THROW_FPE 11
40// const auto & throw_fpe = [](int e)
41// {
42// throw "IGL_THROW_FPE";
43// };
44// signal(SIGFPE,throw_fpe);
45//#endif
46
47 typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
48 typedef
50 Kernel,
51 DerivedV,
52 DerivedF,
53 DerivedVV,
54 DerivedFF,
55 DerivedIF,
56 DerivedJ,
57 DerivedIM>
58 SelfIntersectMeshK;
59 SelfIntersectMeshK SIM(V,F,params,VV,FF,IF,J,IM);
60
61//#ifdef __APPLE__
62// signal(SIGFPE,SIG_DFL);
63//#endif
64
65 }else
66 {
67 typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
68 typedef
69 SelfIntersectMesh<
70 Kernel,
71 DerivedV,
72 DerivedF,
73 DerivedVV,
74 DerivedFF,
75 DerivedIF,
76 DerivedJ,
77 DerivedIM>
78 SelfIntersectMeshK;
79 SelfIntersectMeshK SIM(V,F,params,VV,FF,IF,J,IM);
80 }
81}

References igl::copyleft::cgal::RemeshSelfIntersectionsParam::detect_only.

Referenced by mesh_boolean(), outer_hull(), and piecewise_constant_winding_number().

+ Here is the caller graph for this function:

◆ resolve_intersections()

template<typename DerivedV , typename DerivedE , typename DerivedVI , typename DerivedEI , typename DerivedJ , typename DerivedIM >
IGL_INLINE void igl::copyleft::cgal::resolve_intersections ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedE > &  E,
Eigen::PlainObjectBase< DerivedVI > &  VI,
Eigen::PlainObjectBase< DerivedEI > &  EI,
Eigen::PlainObjectBase< DerivedJ > &  J,
Eigen::PlainObjectBase< DerivedIM > &  IM 
)
33{
34 using namespace Eigen;
35 using namespace igl;
36 using namespace std;
37 // Exact scalar type
38 typedef CGAL::Epeck K;
39 typedef K::FT EScalar;
40 typedef CGAL::Segment_2<K> Segment_2;
41 typedef CGAL::Point_2<K> Point_2;
42 typedef Matrix<EScalar,Dynamic,Dynamic> MatrixXE;
43
44 // Convert vertex positions to exact kernel
45 MatrixXE VE(V.rows(),V.cols());
46 for(int i = 0;i<V.rows();i++)
47 {
48 for(int j = 0;j<V.cols();j++)
49 {
50 VE(i,j) = V(i,j);
51 }
52 }
53
54 const int m = E.rows();
55 // resolve all intersections: silly O(n²) implementation
56 std::vector<std::vector<Point_2> > steiner(m);
57 for(int i = 0;i<m;i++)
58 {
59 Segment_2 si(row_to_point<K>(VE,E(i,0)),row_to_point<K>(VE,E(i,1)));
60 steiner[i].push_back(si.vertex(0));
61 steiner[i].push_back(si.vertex(1));
62 for(int j = i+1;j<m;j++)
63 {
64 Segment_2 sj(row_to_point<K>(VE,E(j,0)),row_to_point<K>(VE,E(j,1)));
65 // do they intersect?
66 if(CGAL::do_intersect(si,sj))
67 {
68 CGAL::Object result = CGAL::intersection(si,sj);
69 if(const Point_2 * p = CGAL::object_cast<Point_2 >(&result))
70 {
71 steiner[i].push_back(*p);
72 steiner[j].push_back(*p);
73 // add intersection point
74 }else if(const Segment_2 * s = CGAL::object_cast<Segment_2 >(&result))
75 {
76 // add both endpoints
77 steiner[i].push_back(s->vertex(0));
78 steiner[j].push_back(s->vertex(0));
79 steiner[i].push_back(s->vertex(1));
80 steiner[j].push_back(s->vertex(1));
81 }else
82 {
83 assert(false && "Unknown intersection type");
84 }
85 }
86 }
87 }
88
89 subdivide_segments(V,E,steiner,VI,EI,J,IM);
90}
IGL_INLINE void subdivide_segments(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedE > &E, const std::vector< std::vector< CGAL::Point_2< Kernel > > > &steiner, Eigen::PlainObjectBase< DerivedVI > &VI, Eigen::PlainObjectBase< DerivedEI > &EI, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::PlainObjectBase< DerivedIM > &IM)
Definition subdivide_segments.cpp:27
Definition AABB.cpp:1014

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

Referenced by snap_rounding().

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

◆ row_to_point()

template<typename Kernel , typename DerivedV >
IGL_INLINE CGAL::Point_2< Kernel > igl::copyleft::cgal::row_to_point ( const Eigen::PlainObjectBase< DerivedV > &  V,
const typename DerivedV::Index &  i 
)
16{
17 return CGAL::Point_2<Kernel>(V(i,0),V(i,1));
18}

◆ segment_segment_squared_distance()

template<typename Kernel >
IGL_INLINE bool igl::copyleft::cgal::segment_segment_squared_distance ( const CGAL::Segment_3< Kernel > &  S1,
const CGAL::Segment_3< Kernel > &  S2,
CGAL::Point_3< Kernel > &  P1,
CGAL::Point_3< Kernel > &  P2,
typename Kernel::FT &  d 
)
19{
20 typedef CGAL::Point_3<Kernel> Point_3;
21 typedef CGAL::Vector_3<Kernel> Vector_3;
22 typedef typename Kernel::FT EScalar;
23 if(S1.is_degenerate())
24 {
25 // All points on S1 are the same
26 P1 = S1.source();
28 return true;
29 }else if(S2.is_degenerate())
30 {
31 assert(!S1.is_degenerate());
32 // All points on S2 are the same
33 P2 = S2.source();
34 point_segment_squared_distance(P2,S1,P1,dst);
35 return true;
36 }
37
38 assert(!S1.is_degenerate());
39 assert(!S2.is_degenerate());
40
41 Vector_3 u = S1.target() - S1.source();
42 Vector_3 v = S2.target() - S2.source();
43 Vector_3 w = S1.source() - S2.source();
44
45 const auto a = u.dot(u); // always >= 0
46 const auto b = u.dot(v);
47 const auto c = v.dot(v); // always >= 0
48 const auto d = u.dot(w);
49 const auto e = v.dot(w);
50 const auto D = a*c - b*b; // always >= 0
51 assert(D>=0);
52 const auto sc=D, sN=D, sD = D; // sc = sN / sD, default sD = D >= 0
53 const auto tc=D, tN=D, tD = D; // tc = tN / tD, default tD = D >= 0
54
55 bool parallel = false;
56 // compute the line parameters of the two closest points
57 if (D==0)
58 {
59 // the lines are almost parallel
60 parallel = true;
61 sN = 0.0; // force using source point on segment S1
62 sD = 1.0; // to prevent possible division by 0.0 later
63 tN = e;
64 tD = c;
65 } else
66 {
67 // get the closest points on the infinite lines
68 sN = (b*e - c*d);
69 tN = (a*e - b*d);
70 if (sN < 0.0)
71 {
72 // sc < 0 => the s=0 edge is visible
73 sN = 0.0;
74 tN = e;
75 tD = c;
76 } else if (sN > sD)
77 { // sc > 1 => the s=1 edge is visible
78 sN = sD;
79 tN = e + b;
80 tD = c;
81 }
82 }
83
84 if (tN < 0.0)
85 {
86 // tc < 0 => the t=0 edge is visible
87 tN = 0.0;
88 // recompute sc for this edge
89 if (-d < 0.0)
90 {
91 sN = 0.0;
92 }else if (-d > a)
93 {
94 sN = sD;
95 }else
96 {
97 sN = -d;
98 sD = a;
99 }
100 }else if (tN > tD)
101 {
102 // tc > 1 => the t=1 edge is visible
103 tN = tD;
104 // recompute sc for this edge
105 if ((-d + b) < 0.0)
106 {
107 sN = 0;
108 }else if ((-d + b) > a)
109 {
110 sN = sD;
111 }else
112 {
113 sN = (-d + b);
114 sD = a;
115 }
116 }
117 // finally do the division to get sc and tc
118 sc = (abs(sN) == 0 ? 0.0 : sN / sD);
119 tc = (abs(tN) == 0 ? 0.0 : tN / tD);
120
121 // get the difference of the two closest points
122 P1 = S1.source() + sc*(S1.target()-S1.source());
123 P2 = S2.source() + sc*(S2.target()-S2.source());
124 Vector_3 dP = w + (sc * u) - (tc * v); // = S1(sc) - S2(tc)
125 assert(dP == (P1-P2));
126
127 dst = dP.squared_length(); // return the closest distance
128 return parallel;
129}
Kernel::Vector_3 Vector_3
Definition points_inside_component.cpp:32
IGL_INLINE void point_segment_squared_distance(const CGAL::Point_3< Kernel > &P1, const CGAL::Segment_3< Kernel > &S2, CGAL::Point_3< Kernel > &P2, typename Kernel::FT &d)
Definition point_segment_squared_distance.cpp:11

References point_segment_squared_distance().

Referenced by triangle_triangle_squared_distance().

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

◆ signed_distance_isosurface()

IGL_INLINE bool igl::copyleft::cgal::signed_distance_isosurface ( const Eigen::MatrixXd &  IV,
const Eigen::MatrixXi &  IF,
const double  level,
const double  angle_bound,
const double  radius_bound,
const double  distance_bound,
const SignedDistanceType  sign_type,
Eigen::MatrixXd &  V,
Eigen::MatrixXi &  F 
)
40{
41 using namespace std;
42 using namespace Eigen;
43
44 // default triangulation for Surface_mesher
45 typedef CGAL::Surface_mesh_default_triangulation_3 Tr;
46 // c2t3
47 typedef CGAL::Complex_2_in_triangulation_3<Tr> C2t3;
48 typedef Tr::Geom_traits GT;//Kernel
49 typedef GT::Sphere_3 Sphere_3;
50 typedef GT::Point_3 Point_3;
51 typedef GT::FT FT;
52 typedef std::function<FT (Point_3)> Function;
53 typedef CGAL::Implicit_surface_3<GT, Function> Surface_3;
54
56 tree.init(IV,IF);
57
58 Eigen::MatrixXd FN,VN,EN;
59 Eigen::MatrixXi E;
60 Eigen::VectorXi EMAP;
62 switch(sign_type)
63 {
64 default:
65 assert(false && "Unknown SignedDistanceType");
67 // do nothing
68 break;
71 hier.set_mesh(IV,IF);
72 hier.grow();
73 break;
75 // "Signed Distance Computation Using the Angle Weighted Pseudonormal"
76 // [Bærentzen & Aanæs 2005]
77 per_face_normals(IV,IF,FN);
78 per_vertex_normals(IV,IF,PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE,FN,VN);
80 IV,IF,PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM,FN,EN,E,EMAP);
81 break;
82 }
83
84 Tr tr; // 3D-Delaunay triangulation
85 C2t3 c2t3 (tr); // 2D-complex in 3D-Delaunay triangulation
86 // defining the surface
87 const auto & IVmax = IV.colwise().maxCoeff();
88 const auto & IVmin = IV.colwise().minCoeff();
89 const double bbd = (IVmax-IVmin).norm();
90 const double r = bbd/2.;
91 const auto & IVmid = 0.5*(IVmax + IVmin);
92 // Supposedly the implict needs to evaluate to <0 at cmid...
93 // http://doc.cgal.org/latest/Surface_mesher/classCGAL_1_1Implicit__surface__3.html
94 Point_3 cmid(IVmid(0),IVmid(1),IVmid(2));
95 Function fun;
96 switch(sign_type)
97 {
98 default:
99 assert(false && "Unknown SignedDistanceType");
101 fun =
102 [&tree,&IV,&IF,&level](const Point_3 & q) -> FT
103 {
104 int i;
105 RowVector3d c;
106 const double sd = tree.squared_distance(
107 IV,IF,RowVector3d(q.x(),q.y(),q.z()),i,c);
108 return sd-level;
109 };
112 fun =
113 [&tree,&IV,&IF,&hier,&level](const Point_3 & q) -> FT
114 {
115 const double sd = signed_distance_winding_number(
116 tree,IV,IF,hier,Vector3d(q.x(),q.y(),q.z()));
117 return sd-level;
118 };
119 break;
120 case SIGNED_DISTANCE_TYPE_PSEUDONORMAL:
121 fun = [&tree,&IV,&IF,&FN,&VN,&EN,&EMAP,&level](const Point_3 & q) -> FT
122 {
123 const double sd =
125 tree,IV,IF,FN,VN,EN,EMAP,RowVector3d(q.x(),q.y(),q.z()));
126 return sd- level;
127 };
128 break;
129 }
130 Sphere_3 bounding_sphere(cmid, (r+level)*(r+level));
131 Surface_3 surface(fun,bounding_sphere);
132 CGAL::Surface_mesh_default_criteria_3<Tr>
133 criteria(angle_bound,radius_bound,distance_bound);
134 // meshing surface
135 CGAL::make_surface_mesh(c2t3, surface, criteria, CGAL::Manifold_tag());
136 // complex to (V,F)
138}
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
Definition WindingNumberAABB.h:24
virtual void grow()
Definition WindingNumberAABB.h:130
void set_mesh(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F)
Definition WindingNumberAABB.h:81
IGL_INLINE bool complex_to_mesh(const CGAL::Complex_2_in_triangulation_3< Tr > &c2t3, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F)
Definition complex_to_mesh.cpp:19
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
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
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
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
@ 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
@ SIGNED_DISTANCE_TYPE_PSEUDONORMAL
Definition signed_distance.h:21
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 complex_to_mesh(), igl::WindingNumberAABB< Point, DerivedV, DerivedF >::grow(), GT, igl::AABB< DerivedV, DIM >::init(), igl::per_edge_normals(), igl::PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM, igl::per_face_normals(), igl::per_vertex_normals(), igl::PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE, igl::WindingNumberAABB< Point, DerivedV, DerivedF >::set_mesh(), igl::signed_distance_pseudonormal(), igl::SIGNED_DISTANCE_TYPE_DEFAULT, igl::SIGNED_DISTANCE_TYPE_PSEUDONORMAL, igl::SIGNED_DISTANCE_TYPE_UNSIGNED, igl::SIGNED_DISTANCE_TYPE_WINDING_NUMBER, igl::signed_distance_winding_number(), and igl::AABB< DerivedV, DIM >::squared_distance().

+ Here is the call graph for this function:

◆ snap_rounding()

template<typename DerivedV , typename DerivedE , typename DerivedVI , typename DerivedEI , typename DerivedJ >
IGL_INLINE void igl::copyleft::cgal::snap_rounding ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedE > &  E,
Eigen::PlainObjectBase< DerivedVI > &  VI,
Eigen::PlainObjectBase< DerivedEI > &  EI,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
31{
32 using namespace Eigen;
33 using namespace igl;
34 using namespace igl::copyleft::cgal;
35 using namespace std;
36 // Exact scalar type
37 typedef CGAL::Epeck Kernel;
38 typedef Kernel::FT EScalar;
39 typedef CGAL::Segment_2<Kernel> Segment_2;
40 typedef CGAL::Point_2<Kernel> Point_2;
41 typedef CGAL::Vector_2<Kernel> Vector_2;
42 typedef Matrix<EScalar,Dynamic,Dynamic> MatrixXE;
43 // Convert vertex positions to exact kernel
44
45 MatrixXE VE;
46 {
47 VectorXi IM;
48 resolve_intersections(V,E,VE,EI,J,IM);
50 EI.data(),
51 EI.data()+EI.size(),
52 [&IM](typename DerivedEI::Scalar& i){i=IM(i);});
53 VectorXi _;
54 remove_unreferenced( MatrixXE(VE), DerivedEI(EI), VE,EI,_);
55 }
56
57 // find all hot pixels
59 //const RowVector2i SW(
60 // round(VE.col(0).minCoeff()),
61 // round(VE.col(1).minCoeff()));
62 //const RowVector2i NE(
63 // round(VE.col(0).maxCoeff()),
64 // round(VE.col(1).maxCoeff()));
65
66 // https://github.com/CGAL/cgal/issues/548
67 // Round an exact scalar to the nearest integer. A priori can't just round
68 // double. Suppose e=0.5+ε but double(e)<0.5
69 //
70 // Inputs:
71 // e exact number
72 // Outputs:
73 // i closest integer
74 const auto & round = [](const EScalar & e)->int
75 {
76 const double d = CGAL::to_double(e);
77 // get an integer that's near the closest int
78 int i = std::round(d);
79 EScalar di_sqr = CGAL::square((e-EScalar(i)));
80 const auto & search = [&i,&di_sqr,&e](const int dir)
81 {
82 while(true)
83 {
84 const int j = i+dir;
85 const EScalar dj_sqr = CGAL::square((e-EScalar(j)));
86 if(dj_sqr < di_sqr)
87 {
88 i = j;
89 di_sqr = dj_sqr;
90 }else
91 {
92 break;
93 }
94 }
95 };
96 // Try to increase/decrease int
97 search(1);
98 search(-1);
99 return i;
100 };
101 vector<Point_2> hot;
102 for(int i = 0;i<VE.rows();i++)
103 {
104 hot.emplace_back(round(VE(i,0)),round(VE(i,1)));
105 }
106 {
107 std::vector<size_t> _1,_2;
108 igl::unique(vector<Point_2>(hot),hot,_1,_2);
109 }
110
111 // find all segments intersecting hot pixels
112 // split edge at closest point to hot pixel center
113 vector<vector<Point_2>> steiner(EI.rows());
114 // initialize each segment with endpoints
115 for(int i = 0;i<EI.rows();i++)
116 {
117 steiner[i].emplace_back(VE(EI(i,0),0),VE(EI(i,0),1));
118 steiner[i].emplace_back(VE(EI(i,1),0),VE(EI(i,1),1));
119 }
120 // silly O(n²) implementation
121 for(const Point_2 & h : hot)
122 {
123 // North, East, South, West
124 Segment_2 wall[4] =
125 {
126 {h+Vector_2(-0.5, 0.5),h+Vector_2( 0.5, 0.5)},
127 {h+Vector_2( 0.5, 0.5),h+Vector_2( 0.5,-0.5)},
128 {h+Vector_2( 0.5,-0.5),h+Vector_2(-0.5,-0.5)},
129 {h+Vector_2(-0.5,-0.5),h+Vector_2(-0.5, 0.5)}
130 };
131 // consider all segments
132 for(int i = 0;i<EI.rows();i++)
133 {
134 // endpoints
135 const Point_2 s(VE(EI(i,0),0),VE(EI(i,0),1));
136 const Point_2 d(VE(EI(i,1),0),VE(EI(i,1),1));
137 // if either end-point is in h's pixel then ignore
138 const Point_2 rs(round(s.x()),round(s.y()));
139 const Point_2 rd(round(d.x()),round(d.y()));
140 if(h == rs || h == rd)
141 {
142 continue;
143 }
144 // otherwise check for intersections with walls consider all walls
145 const Segment_2 si(s,d);
146 vector<Point_2> hits;
147 for(int j = 0;j<4;j++)
148 {
149 const Segment_2 & sj = wall[j];
150 if(CGAL::do_intersect(si,sj))
151 {
152 CGAL::Object result = CGAL::intersection(si,sj);
153 if(const Point_2 * p = CGAL::object_cast<Point_2 >(&result))
154 {
155 hits.push_back(*p);
156 }else if(const Segment_2 * s = CGAL::object_cast<Segment_2 >(&result))
157 {
158 // add both endpoints
159 hits.push_back(s->vertex(0));
160 hits.push_back(s->vertex(1));
161 }
162 }
163 }
164 if(hits.size() == 0)
165 {
166 continue;
167 }
168 // centroid of hits
169 Vector_2 cen(0,0);
170 for(const Point_2 & hit : hits)
171 {
172 cen = Vector_2(cen.x()+hit.x(), cen.y()+hit.y());
173 }
174 cen = Vector_2(cen.x()/EScalar(hits.size()),cen.y()/EScalar(hits.size()));
175 const Point_2 rcen(round(cen.x()),round(cen.y()));
176 // after all of that, don't add as a steiner unless it's going to round
177 // to h
178 if(rcen == h)
179 {
180 steiner[i].emplace_back(cen.x(),cen.y());
181 }
182 }
183 }
184 {
185 DerivedJ prevJ = J;
186 VectorXi IM;
187 subdivide_segments(MatrixXE(VE),MatrixXi(EI),steiner,VE,EI,J,IM);
188 for_each(J.data(),J.data()+J.size(),[&prevJ](typename DerivedJ::Scalar & j){j=prevJ(j);});
189 for_each(
190 EI.data(),
191 EI.data()+EI.size(),
192 [&IM](typename DerivedEI::Scalar& i){i=IM(i);});
193 VectorXi _;
194 remove_unreferenced( MatrixXE(VE), DerivedEI(EI), VE,EI,_);
195 }
196
197
198 VI.resizeLike(VE);
199 for(int i = 0;i<VE.rows();i++)
200 {
201 for(int j = 0;j<VE.cols();j++)
202 {
203 VI(i,j) = round(CGAL::to_double(VE(i,j)));
204 }
205 }
206}
EIGEN_DEVICE_FUNC const RoundReturnType round() const
Definition ArrayCwiseUnaryOps.h:374
#define _(msgid)
Definition getopt.c:87
Definition assign.h:19
IGL_INLINE void resolve_intersections(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedE > &E, Eigen::PlainObjectBase< DerivedVI > &VI, Eigen::PlainObjectBase< DerivedEI > &EI, Eigen::PlainObjectBase< DerivedJ > &J, Eigen::PlainObjectBase< DerivedIM > &IM)
Definition resolve_intersections.cpp:26
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
CGAL::SM_Edge_index EI
Definition CutSurface.cpp:77
CGAL::SM_Vertex_index VI
Definition CutSurface.cpp:75

References _, Eigen::PlainObjectBase< Derived >::data(), igl::for_each(), igl::remove_unreferenced(), resolve_intersections(), round(), subdivide_segments(), and igl::unique().

+ Here is the call graph for this function:

◆ string_to_mesh_boolean_type() [1/2]

IGL_INLINE igl::MeshBooleanType igl::copyleft::cgal::string_to_mesh_boolean_type ( const std::string &  s)
45{
46 MeshBooleanType type;
47#ifndef NDEBUG
48 const bool ret =
49#endif
51 assert(ret && "Unknown MeshBooleanType name");
52 return type;
53}
MeshBooleanType
Definition MeshBooleanType.h:13

References string_to_mesh_boolean_type().

+ Here is the call graph for this function:

◆ string_to_mesh_boolean_type() [2/2]

IGL_INLINE bool igl::copyleft::cgal::string_to_mesh_boolean_type ( const std::string &  s,
MeshBooleanType type 
)
9{
10 using namespace std;
11 string eff_s = s;
12 transform(eff_s.begin(), eff_s.end(), eff_s.begin(), ::tolower);
13 const auto & find_any =
14 [](const vector<string> & haystack, const string & needle)->bool
15 {
16 return find(haystack.begin(), haystack.end(), needle) != haystack.end();
17 };
18 if(find_any({"union","unite","u","∪"},eff_s))
19 {
21 }else if(find_any({"intersect","intersection","i","∩"},eff_s))
22 {
24 }else if(
25 find_any(
26 {"minus","subtract","difference","relative complement","m","\\"},eff_s))
27 {
29 }else if(find_any({"xor","symmetric difference","x","∆"},eff_s))
30 {
32 }else if(find_any({"resolve"},eff_s))
33 {
35 }else
36 {
37 return false;
38 }
39 return true;
40}

References igl::find(), igl::MESH_BOOLEAN_TYPE_INTERSECT, igl::MESH_BOOLEAN_TYPE_MINUS, igl::MESH_BOOLEAN_TYPE_RESOLVE, igl::MESH_BOOLEAN_TYPE_UNION, and igl::MESH_BOOLEAN_TYPE_XOR.

Referenced by mesh_boolean(), and string_to_mesh_boolean_type().

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

◆ subdivide_segments()

template<typename DerivedV , typename DerivedE , typename Kernel , typename DerivedVI , typename DerivedEI , typename DerivedJ , typename DerivedIM >
IGL_INLINE void igl::copyleft::cgal::subdivide_segments ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedE > &  E,
const std::vector< std::vector< CGAL::Point_2< Kernel > > > &  steiner,
Eigen::PlainObjectBase< DerivedVI > &  VI,
Eigen::PlainObjectBase< DerivedEI > &  EI,
Eigen::PlainObjectBase< DerivedJ > &  J,
Eigen::PlainObjectBase< DerivedIM > &  IM 
)
35{
36 using namespace Eigen;
37 using namespace igl;
38 using namespace std;
39
40 // Exact scalar type
41 typedef Kernel K;
42 typedef typename Kernel::FT EScalar;
43 typedef CGAL::Segment_2<Kernel> Segment_2;
44 typedef CGAL::Point_2<Kernel> Point_2;
45 typedef Matrix<EScalar,Dynamic,Dynamic> MatrixXE;
46
47 // non-const copy
48 std::vector<std::vector<CGAL::Point_2<Kernel> > > steiner = _steiner;
49
50 // Convert vertex positions to exact kernel
51 MatrixXE VE(V.rows(),V.cols());
52 for(int i = 0;i<V.rows();i++)
53 {
54 for(int j = 0;j<V.cols();j++)
55 {
56 VE(i,j) = V(i,j);
57 }
58 }
59
60 // number of original vertices
61 const int n = V.rows();
62 // number of original segments
63 const int m = E.rows();
64 // now steiner contains lists of points (unsorted) for each edge. Sort them
65 // and count total number of vertices and edges
66 int ni = 0;
67 int mi = 0;
68 // new steiner points
69 std::vector<Point_2> S;
70 std::vector<std::vector<typename DerivedE::Scalar> > vEI;
71 std::vector<typename DerivedJ::Scalar> vJ;
72 for(int i = 0;i<m;i++)
73 {
74 {
75 const Point_2 s = row_to_point<K>(VE,E(i,0));
76 std::sort(
77 steiner[i].begin(),
78 steiner[i].end(),
79 [&s](const Point_2 & A, const Point_2 & B)->bool
80 {
81 return (A-s).squared_length() < (B-s).squared_length();
82 });
83 }
84 // remove duplicates
85 steiner[i].erase(
86 std::unique(steiner[i].begin(), steiner[i].end()),
87 steiner[i].end());
88 {
89 int s = E(i,0);
90 // legs to each steiner in order
91 for(int j = 1;j<steiner[i].size()-1;j++)
92 {
93 int d = n+S.size();
94 S.push_back(steiner[i][j]);
95 vEI.push_back({s,d});
96 vJ.push_back(i);
97 s = d;
98 }
99 // don't forget last (which might only) leg
100 vEI.push_back({s,E(i,1)});
101 vJ.push_back(i);
102 }
103 }
104 // potentially unnecessary copying ...
105 VI.resize(n+S.size(),2);
106 for(int i = 0;i<V.rows();i++)
107 {
108 for(int j = 0;j<V.cols();j++)
109 {
110 assign_scalar(V(i,j),VI(i,j));
111 }
112 }
113 for(int i = 0;i<S.size();i++)
114 {
115 assign_scalar(S[i].x(),VI(n+i,0));
116 assign_scalar(S[i].y(),VI(n+i,1));
117 }
118 list_to_matrix(vEI,EI);
119 list_to_matrix(vJ,J);
120 {
121 // Find unique mapping
122 std::vector<Point_2> vVES,_1;
123 for(int i = 0;i<n;i++)
124 {
125 vVES.push_back(row_to_point<K>(VE,i));
126 }
127 vVES.insert(vVES.end(),S.begin(),S.end());
128 std::vector<size_t> vA,vIM;
129 igl::unique(vVES,_1,vA,vIM);
130 // Push indices back into vVES
131 for_each(vIM.data(),vIM.data()+vIM.size(),[&vA](size_t & i){i=vA[i];});
132 list_to_matrix(vIM,IM);
133 }
134}
@ E
Definition libslic3r.h:101

References assign_scalar(), Eigen::PlainObjectBase< Derived >::cols(), igl::for_each(), igl::list_to_matrix(), Eigen::PlainObjectBase< Derived >::rows(), and igl::unique().

Referenced by resolve_intersections(), and snap_rounding().

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

◆ submesh_aabb_tree()

template<typename DerivedV , typename DerivedF , typename DerivedI , typename Kernel >
IGL_INLINE void igl::copyleft::cgal::submesh_aabb_tree ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedI > &  I,
CGAL::AABB_tree< CGAL::AABB_traits< Kernel, CGAL::AABB_triangle_primitive< Kernel, typename std::vector< typename Kernel::Triangle_3 >::iterator > > > &  tree,
std::vector< typename Kernel::Triangle_3 > &  triangles,
std::vector< bool > &  in_I 
)
28{
29 in_I.resize(F.rows(), false);
30 const size_t num_faces = I.rows();
31 for (size_t i=0; i<num_faces; i++)
32 {
33 const Eigen::Vector3i f = F.row(I(i, 0));
34 in_I[I(i,0)] = true;
35 triangles.emplace_back(
36 typename Kernel::Point_3(V(f[0], 0), V(f[0], 1), V(f[0], 2)),
37 typename Kernel::Point_3(V(f[1], 0), V(f[1], 1), V(f[1], 2)),
38 typename Kernel::Point_3(V(f[2], 0), V(f[2], 1), V(f[2], 2)));
39#ifndef NDEBUG
40 if (triangles.back().is_degenerate())
41 {
42 throw std::runtime_error(
43 "Input facet components contains degenerated triangles");
44 }
45#endif
46 }
47 tree.insert(triangles.begin(), triangles.end());
48 tree.accelerate_distance_queries();
49}

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

Referenced by closest_facet(), and extract_cells().

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

◆ triangle_triangle_squared_distance()

template<typename Kernel >
IGL_INLINE bool igl::copyleft::cgal::triangle_triangle_squared_distance ( const CGAL::Triangle_3< Kernel > &  T1,
const CGAL::Triangle_3< Kernel > &  T2,
CGAL::Point_3< Kernel > &  P1,
CGAL::Point_3< Kernel > &  P2,
typename Kernel::FT &  d 
)
21{
22 typedef CGAL::Point_3<Kernel> Point_3;
23 typedef CGAL::Vector_3<Kernel> Vector_3;
24 typedef CGAL::Triangle_3<Kernel> Triangle_3;
25 typedef CGAL::Segment_3<Kernel> Segment_3;
26 typedef typename Kernel::FT EScalar;
27 assert(!T1.is_degenerate());
28 assert(!T2.is_degenerate());
29
30 bool unique = true;
31 if(CGAL::do_intersect(T1,T2))
32 {
33 // intersecting triangles have zero (squared) distance
34 CGAL::Object result = CGAL::intersection(T1,T2);
35 // Some point on the intersection result
36 CGAL::Point_3<Kernel> Q;
37 if(const Point_3 * p = CGAL::object_cast<Point_3 >(&result))
38 {
39 Q = *p;
40 }else if(const Segment_3 * s = CGAL::object_cast<Segment_3 >(&result))
41 {
42 unique = false;
43 Q = s->source();
44 }else if(const Triangle_3 *itri = CGAL::object_cast<Triangle_3 >(&result))
45 {
46 Q = s->vertex(0);
47 unique = false;
48 }else if(const std::vector<Point_3 > *polyp =
49 CGAL::object_cast< std::vector<Point_3 > >(&result))
50 {
51 assert(polyp->size() > 0 && "intersection poly should not be empty");
52 Q = polyp[0];
53 unique = false;
54 }else
55 {
56 assert(false && "Unknown intersection result");
57 }
58 P1 = Q;
59 P2 = Q;
60 d = 0;
61 return unique;
62 }
63 // triangles do not intersect: the points of closest approach must be on the
64 // boundary of one of the triangles
65 d = std::numeric_limits<double>::infinity();
66 const auto & vertices_face = [&unique](
67 const Triangle_3 & T1,
68 const Triangle_3 & T2,
69 Point_3 & P1,
70 Point_3 & P2,
71 EScalar & d)
72 {
73 for(int i = 0;i<3;i++)
74 {
75 const Point_3 vi = T1.vertex(i);
76 Point_3 P2i;
77 EScalar di;
79 if(di<d)
80 {
81 d = di;
82 P1 = vi;
83 P2 = P2i;
84 unique = true;
85 }else if(d == di)
86 {
87 // edge of T1 floating parallel above T2
88 unique = false;
89 }
90 }
91 };
92 vertices_face(T1,T2,P1,P2,d);
93 vertices_face(T2,T1,P1,P2,d);
94 for(int i = 0;i<3;i++)
95 {
96 const Segment_3 s1( T1.vertex(i+1), T1.vertex(i+2));
97 for(int j = 0;j<3;j++)
98 {
99 const Segment_3 s2( T2.vertex(i+1), T2.vertex(i+2));
100 Point_3 P1ij;
101 Point_3 P2ij;
102 EScalar dij;
103 bool uniqueij = segment_segment_squared_distance(s1,s2,P1ij,P2ij,dij);
104 if(dij < d)
105 {
106 P1 = P1ij;
107 P2 = P2ij;
108 d = dij;
109 unique = uniqueij;
110 }
111 }
112 }
113 return unique;
114}
IGL_INLINE bool segment_segment_squared_distance(const CGAL::Segment_3< Kernel > &S1, const CGAL::Segment_3< Kernel > &S2, CGAL::Point_3< Kernel > &P1, CGAL::Point_3< Kernel > &P2, typename Kernel::FT &d)
Definition segment_segment_squared_distance.cpp:13
IGL_INLINE void point_triangle_squared_distance(const CGAL::Point_3< Kernel > &P1, const CGAL::Triangle_3< Kernel > &T2, CGAL::Point_3< Kernel > &P2, typename Kernel::FT &d)
Definition point_triangle_squared_distance.cpp:11

References point_triangle_squared_distance(), segment_segment_squared_distance(), and igl::unique().

+ Here is the call graph for this function:

◆ trim_with_solid()

template<typename DerivedVA , typename DerivedFA , typename DerivedVB , typename DerivedFB , typename DerivedV , typename DerivedF , typename DerivedD , typename DerivedJ >
IGL_INLINE void igl::copyleft::cgal::trim_with_solid ( const Eigen::PlainObjectBase< DerivedVA > &  VA,
const Eigen::PlainObjectBase< DerivedFA > &  FA,
const Eigen::PlainObjectBase< DerivedVB > &  VB,
const Eigen::PlainObjectBase< DerivedFB > &  FB,
Eigen::PlainObjectBase< DerivedV > &  Vd,
Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedD > &  D,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
40{
41 // resolve intersections using exact representation
44 typedef Eigen::Matrix<CGAL::Epeck::FT,1,3> RowVector3E;
45 MatrixX3E V;
46 Eigen::MatrixXi _1;
47 Eigen::VectorXi _2;
48 // Intersect A and B meshes and stitch together new faces
50 VA,FA,VB,FB,{false,false,true},_1,V,F,J,_2);
51 // Partition result into manifold patches
52 Eigen::VectorXi P;
53 const size_t num_patches = igl::extract_manifold_patches(F,P);
54 // only keep faces from A
56 igl::slice_mask(Eigen::MatrixXi(F),A,1,F);
57 igl::slice_mask(Eigen::VectorXi(P),A,1,P);
58 igl::slice_mask(Eigen::VectorXi(J),A,1,J);
59 // Aggregate representative query points for each patch
60 std::vector<bool> flag(num_patches);
61 std::vector<std::vector<CGAL::Epeck::FT> > vQ;
62 Eigen::VectorXi P2Q(num_patches);
63 for(int f = 0;f<P.rows();f++)
64 {
65 const auto p = P(f);
66 // if not yet processed this patch
67 if(!flag[p])
68 {
69 P2Q(p) = vQ.size();
70 std::vector<CGAL::Epeck::FT> q = {
71 (V(F(f,0),0)+ V(F(f,1),0)+ V(F(f,2),0))/3.,
72 (V(F(f,0),1)+ V(F(f,1),1)+ V(F(f,2),1))/3.,
73 (V(F(f,0),2)+ V(F(f,1),2)+ V(F(f,2),2))/3.};
74 vQ.emplace_back(q);
75 flag[p] = true;
76 }
77 }
78 MatrixX3E Q;
80 VectorXE SP;
83 // distribute flag to all faces
84 D.resize(F.rows());
85 for(int f = 0;f<F.rows();f++)
86 {
87 D(f) = DP(P2Q(P(f)));
88 }
89 Eigen::VectorXi _;
90 igl::remove_unreferenced(MatrixX3E(V),DerivedF(F),V,F,_);
91 assign(V,Vd);
92}
IGL_INLINE void point_solid_signed_squared_distance(const Eigen::PlainObjectBase< DerivedQ > &Q, const Eigen::PlainObjectBase< DerivedVB > &VB, const Eigen::PlainObjectBase< DerivedFB > &FB, Eigen::PlainObjectBase< DerivedD > &D)
Definition point_solid_signed_squared_distance.cpp:21

References _, assign(), igl::extract_manifold_patches(), intersect_other(), igl::list_to_matrix(), point_solid_signed_squared_distance(), igl::remove_unreferenced(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), and igl::slice_mask().

+ Here is the call graph for this function:

◆ wire_mesh() [1/2]

template<typename DerivedWV , typename DerivedWE , typename DerivedV , typename DerivedF , typename DerivedJ >
IGL_INLINE void igl::copyleft::cgal::wire_mesh ( const Eigen::MatrixBase< DerivedWV > &  WV,
const Eigen::MatrixBase< DerivedWE > &  WE,
const double  th,
const int  poly_size,
const bool  solid,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
26{
27
28 typedef typename DerivedWV::Scalar Scalar;
29 // Canonical polygon to place at each endpoint
31 MatrixX3S PV(poly_size,3);
32 for(int p =0;p<PV.rows();p++)
33 {
34 const Scalar phi = (Scalar(p)/Scalar(PV.rows()))*2.*igl::PI;
35 PV(p,0) = 0.5*cos(phi);
36 PV(p,1) = 0.5*sin(phi);
37 PV(p,2) = 0;
38 }
39
40 V.resize(WV.rows() + PV.rows() * 2 * WE.rows(),3);
41 V.topLeftCorner(WV.rows(),3) = WV;
42 // Signed adjacency list
43 std::vector<std::vector<std::pair<int,int> > > A(WV.rows());
44 // Inputs:
45 // e index of edge
46 // c index of endpoint [0,1]
47 // p index of polygon vertex
48 // Returns index of corresponding vertex in V
49 const auto index =
50 [&PV,&WV](const int e, const int c, const int p)->int
51 {
52 return WV.rows() + e*2*PV.rows() + PV.rows()*c + p;
53 };
54 const auto unindex =
55 [&PV,&WV](int v, int & e, int & c, int & p)
56 {
57 assert(v>=WV.rows());
58 v = v-WV.rows();
59 e = v/(2*PV.rows());
60 v = v-e*(2*PV.rows());
61 c = v/(PV.rows());
62 v = v-c*(PV.rows());
63 p = v;
64 };
65 // loop over all edges
66 for(int e = 0;e<WE.rows();e++)
67 {
68 // Fill in adjacency list as we go
69 A[WE(e,0)].emplace_back(e,0);
70 A[WE(e,1)].emplace_back(e,1);
71 typedef Eigen::Matrix<Scalar,1,3> RowVector3S;
72 const RowVector3S ev = WV.row(WE(e,1))-WV.row(WE(e,0));
73 const Scalar len = ev.norm();
74 // Unit edge vector
75 const RowVector3S uv = ev.normalized();
77 q = q.FromTwoVectors(RowVector3S(0,0,1),uv);
78 // loop over polygon vertices
79 for(int p = 0;p<PV.rows();p++)
80 {
81 RowVector3S qp = q*(PV.row(p)*th);
82 // loop over endpoints
83 for(int c = 0;c<2;c++)
84 {
85 // Direction moving along edge vector
86 const Scalar dir = c==0?1:-1;
87 // Amount (distance) to move along edge vector
88 // Start with factor of thickness;
89 // Max out amount at 1/3 of edge length so that there's always some
90 // amount of edge
91 Scalar dist = std::min(1.*th,len/3.0);
92 // Move to endpoint, offset by amount
93 V.row(index(e,c,p)) =
94 qp+WV.row(WE(e,c)) + dist*dir*uv;
95 }
96 }
97 }
98
99 std::vector<std::vector<typename DerivedF::Index> > vF;
100 std::vector<int> vJ;
101 const auto append_hull =
102 [&V,&vF,&vJ,&unindex,&WV](const Eigen::VectorXi & I, const int j)
103 {
104 MatrixX3S Vv;
105 igl::slice(V,I,1,Vv);
106 Eigen::MatrixXi Fv;
107 convex_hull(Vv,Fv);
108 for(int f = 0;f<Fv.rows();f++)
109 {
110 const Eigen::Array<int,1,3> face(I(Fv(f,0)), I(Fv(f,1)), I(Fv(f,2)));
111 //const bool on_vertex = (face<WV.rows()).any();
112 //if(!on_vertex)
113 //{
114 // // This correctly prunes fcaes on the "caps" of convex hulls around
115 // // edges, but for convex hulls around vertices this will only work if
116 // // the incoming edges are not overlapping.
117 // //
118 // // Q: For convex hulls around vertices, is the correct thing to do:
119 // // check if all corners of face lie *on or _outside_* of plane of "cap"?
120 // //
121 // // H: Maybe, but if there's an intersection then the boundary of the
122 // // incoming convex hulls around edges is still not going to match up
123 // // with the boundary on the convex hull around the vertices.
124 // //
125 // // Might have to bite the bullet and always call self-union.
126 // bool all_same = true;
127 // int e0,c0,p0;
128 // unindex(face(0),e0,c0,p0);
129 // for(int i = 1;i<3;i++)
130 // {
131 // int ei,ci,pi;
132 // unindex(face(i),ei,ci,pi);
133 // all_same = all_same && (e0==ei && c0==ci);
134 // }
135 // if(all_same)
136 // {
137 // // don't add this face
138 // continue;
139 // }
140 //}
141 vF.push_back( { face(0),face(1),face(2)});
142 vJ.push_back(j);
143 }
144 };
145 // loop over each vertex
146 for(int v = 0;v<WV.rows();v++)
147 {
148 // Gather together this vertex and the polygon vertices of all incident
149 // edges
150 Eigen::VectorXi I(1+A[v].size()*PV.rows());
151 // This vertex
152 I(0) = v;
153 for(int n = 0;n<A[v].size();n++)
154 {
155 for(int p = 0;p<PV.rows();p++)
156 {
157 const int e = A[v][n].first;
158 const int c = A[v][n].second;
159 I(1+n*PV.rows()+p) = index(e,c,p);
160 }
161 }
162 append_hull(I,v);
163 }
164 // loop over each edge
165 for(int e = 0;e<WE.rows();e++)
166 {
167 // Gether together polygon vertices of both endpoints
168 Eigen::VectorXi I(PV.rows()*2);
169 for(int c = 0;c<2;c++)
170 {
171 for(int p = 0;p<PV.rows();p++)
172 {
173 I(c*PV.rows()+p) = index(e,c,p);
174 }
175 }
176 append_hull(I,WV.rows()+e);
177 }
178
179 list_to_matrix(vF,F);
180 if(solid)
181 {
182 // Self-union to clean up
184 Eigen::MatrixXd(V),Eigen::MatrixXi(F),Eigen::MatrixXd(),Eigen::MatrixXi(),
185 "union",
186 V,F,J);
187 for(int j=0;j<J.size();j++) J(j) = vJ[J(j)];
188 }else
189 {
190 list_to_matrix(vJ,J);
191 }
192}
EIGEN_DEVICE_FUNC const SinReturnType sin() const
Definition ArrayCwiseUnaryOps.h:220
static EIGEN_DEVICE_FUNC Quaternion FromTwoVectors(const MatrixBase< Derived1 > &a, const MatrixBase< Derived2 > &b)
The quaternion class used to represent 3D orientations and rotations.
Definition Quaternion.h:233

References convex_hull(), cos(), Eigen::Quaternion< _Scalar, _Options >::FromTwoVectors(), igl::list_to_matrix(), mesh_boolean(), igl::PI, Eigen::PlainObjectBase< Derived >::resize(), sin(), and igl::slice().

Referenced by wire_mesh().

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

◆ wire_mesh() [2/2]

template<typename DerivedWV , typename DerivedWE , typename DerivedV , typename DerivedF , typename DerivedJ >
IGL_INLINE void igl::copyleft::cgal::wire_mesh ( const Eigen::MatrixBase< DerivedWV > &  WV,
const Eigen::MatrixBase< DerivedWE > &  WE,
const double  th,
const int  poly_size,
Eigen::PlainObjectBase< DerivedV > &  V,
Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedJ > &  J 
)
208{
209 return wire_mesh(WV,WE,th,poly_size,true,V,F,J);
210}
IGL_INLINE void wire_mesh(const Eigen::MatrixBase< DerivedWV > &WV, const Eigen::MatrixBase< DerivedWE > &WE, const double th, const int poly_size, const bool solid, Eigen::PlainObjectBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedJ > &J)
Definition wire_mesh.cpp:17

References wire_mesh().

+ Here is the call graph for this function: