// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2015 Alec Jacobson // // This Source Code Form is subject to the terms of the Mozilla Public License // v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_COPYLEFT_CGAL_CSG_TREE_H #define IGL_COPYLEFT_CGAL_CSG_TREE_H #include "../../MeshBooleanType.h" #include "string_to_mesh_boolean_type.h" #include "mesh_boolean.h" #include #include namespace igl { namespace copyleft { namespace cgal { // Class for defining and computing a constructive solid geometry result // out of a tree of boolean operations on "solid" triangle meshes. // //template class CSGTree { public: typedef CGAL::Epeck::FT ExactScalar; //typedef Eigen::PlainObjectBase POBF; typedef Eigen::MatrixXi POBF; typedef POBF::Index FIndex; typedef Eigen::Matrix MatrixX3E; typedef Eigen::Matrix VectorJ; private: // Resulting mesh MatrixX3E m_V; POBF m_F; VectorJ m_J; // Number of birth faces in A + those in B. I.e. sum of original "leaf" // faces involved in result. size_t m_number_of_birth_faces; public: CSGTree() { } //typedef Eigen::MatrixXd MatrixX3E; //typedef Eigen::MatrixXi POBF; // http://stackoverflow.com/a/3279550/148668 CSGTree(const CSGTree & other) : // copy things m_V(other.m_V), // This is an issue if m_F is templated // https://forum.kde.org/viewtopic.php?f=74&t=128414 m_F(other.m_F), m_J(other.m_J), m_number_of_birth_faces(other.m_number_of_birth_faces) { } // copy-swap idiom friend void swap(CSGTree& first, CSGTree& second) { using std::swap; // swap things swap(first.m_V,second.m_V); // This is an issue if m_F is templated, similar to // https://forum.kde.org/viewtopic.php?f=74&t=128414 swap(first.m_F,second.m_F); swap(first.m_J,second.m_J); swap(first.m_number_of_birth_faces,second.m_number_of_birth_faces); } // Pass-by-value (aka copy) CSGTree& operator=(CSGTree other) { swap(*this,other); return *this; } CSGTree(CSGTree&& other): // initialize via default constructor CSGTree() { swap(*this,other); } // Construct and compute a boolean operation on existing CSGTree nodes. // // Inputs: // A Solid result of previous CSG operation (or identity, see below) // B Solid result of previous CSG operation (or identity, see below) // type type of mesh boolean to compute CSGTree( const CSGTree & A, const CSGTree & B, const MeshBooleanType & type) { // conduct boolean operation mesh_boolean(A.V(),A.F(),B.V(),B.F(),type,m_V,m_F,m_J); // reindex m_J std::for_each(m_J.data(),m_J.data()+m_J.size(), [&](typename VectorJ::Scalar & j) -> void { if(j < A.F().rows()) { j = A.J()(j); }else { assert(j<(A.F().rows()+B.F().rows())); j = A.number_of_birth_faces()+(B.J()(j-A.F().rows())); } }); m_number_of_birth_faces = A.number_of_birth_faces() + B.number_of_birth_faces(); } // Overload using string for type CSGTree( const CSGTree & A, const CSGTree & B, const std::string & s): CSGTree(A,B,string_to_mesh_boolean_type(s)) { // do nothing (all done in constructor). } // "Leaf" node with identity operation on assumed "solid" mesh (V,F) // // Inputs: // V #V by 3 list of mesh vertices (in any precision, will be // converted to exact) // F #F by 3 list of mesh face indices into V template CSGTree(const Eigen::PlainObjectBase & V, const POBF & F)//: // Possible Eigen bug: // https://forum.kde.org/viewtopic.php?f=74&t=128414 //m_V(V.template cast()),m_F(F) { m_V = V.template cast(); m_F = F; // number of faces m_number_of_birth_faces = m_F.rows(); // identity birth index m_J = VectorJ::LinSpaced( m_number_of_birth_faces,0,m_number_of_birth_faces-1); } // Returns reference to resulting mesh vertices m_V in exact scalar // representation const MatrixX3E & V() const { return m_V; } // Returns mesh vertices in the desired output type, casting when // appropriate to floating precision. template DerivedV cast_V() const { DerivedV dV; dV.resize(m_V.rows(),m_V.cols()); for(int i = 0;i