BambuStudio/libigl/igl/copyleft/cgal/CSGTree.h

190 lines
6.4 KiB
C++

// This file is part of libigl, a simple c++ geometry processing library.
//
// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
//
// 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 <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/number_utils.h>
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 <typename DerivedF>
class CSGTree
{
public:
typedef CGAL::Epeck::FT ExactScalar;
//typedef Eigen::PlainObjectBase<DerivedF> POBF;
typedef Eigen::MatrixXi POBF;
typedef POBF::Index FIndex;
typedef Eigen::Matrix<ExactScalar,Eigen::Dynamic,3> MatrixX3E;
typedef Eigen::Matrix<FIndex,Eigen::Dynamic,1> 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 <typename DerivedV>
CSGTree(const Eigen::PlainObjectBase<DerivedV> & V, const POBF & F)//:
// Possible Eigen bug:
// https://forum.kde.org/viewtopic.php?f=74&t=128414
//m_V(V.template cast<ExactScalar>()),m_F(F)
{
m_V = V.template cast<ExactScalar>();
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 <typename DerivedV>
DerivedV cast_V() const
{
DerivedV dV;
dV.resize(m_V.rows(),m_V.cols());
for(int i = 0;i<m_V.rows();i++)
{
for(int j = 0;j<m_V.cols();j++)
{
dV(i,j) = CGAL::to_double(m_V(i,j));
}
}
return dV;
}
// Returns reference to resulting mesh faces m_F
const POBF & F() const
{
return m_F;
}
// Returns reference to "birth parents" indices into [F1;F2;...;Fn]
// where F1, ... , Fn are the face lists of the leaf ("original") input
// meshes.
const VectorJ & J() const
{
return m_J;
}
// The number of leaf faces = #F1 + #F2 + ... + #Fn
const size_t & number_of_birth_faces() const
{
return m_number_of_birth_faces;
}
};
}
}
}
#endif