CSGTree.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #ifndef IGL_BOOLEAN_CSG_TREE_H
  9. #define IGL_BOOLEAN_CSG_TREE_H
  10. #include <igl/boolean/string_to_mesh_boolean_type.h>
  11. #include <igl/boolean/MeshBooleanType.h>
  12. #include <igl/boolean/mesh_boolean.h>
  13. #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
  14. #include <CGAL/number_utils.h>
  15. namespace igl
  16. {
  17. namespace boolean
  18. {
  19. // Class for defining and computing a constructive solid geometry result
  20. // out of a tree of boolean operations on "solid" triangle meshes.
  21. //
  22. template <typename DerivedF>
  23. class CSGTree
  24. {
  25. private:
  26. typedef CGAL::Epeck::FT ExactScalar;
  27. typedef Eigen::Matrix<ExactScalar,Eigen::Dynamic,3> MatrixX3E;
  28. typedef Eigen::PlainObjectBase<DerivedF> POBF;
  29. typedef Eigen::Matrix<typename DerivedF::Index,Eigen::Dynamic,1>
  30. VectorJ;
  31. // Resulting mesh
  32. MatrixX3E m_V;
  33. POBF m_F;
  34. VectorJ m_J;
  35. // Number of birth faces in A + those in B. I.e. sum of original "leaf"
  36. // faces involved in result.
  37. size_t m_number_of_birth_faces;
  38. public:
  39. CSGTree()
  40. {
  41. }
  42. //typedef Eigen::MatrixXd MatrixX3E;
  43. //typedef Eigen::MatrixXi POBF;
  44. // http://stackoverflow.com/a/3279550/148668
  45. CSGTree(const CSGTree & other)
  46. :
  47. // copy things
  48. m_V(other.m_V),
  49. m_F(other.m_F),
  50. m_J(other.m_J),
  51. m_number_of_birth_faces(other.m_number_of_birth_faces)
  52. {
  53. }
  54. // copy-swap idiom
  55. friend void swap(CSGTree& first, CSGTree& second)
  56. {
  57. using std::swap;
  58. // swap things
  59. swap(first.m_V,second.m_V);
  60. swap(first.m_F,second.m_F);
  61. swap(first.m_J,second.m_J);
  62. swap(first.m_number_of_birth_faces,second.m_number_of_birth_faces);
  63. }
  64. // Pass-by-value (aka copy)
  65. CSGTree& operator=(CSGTree other)
  66. {
  67. swap(*this,other);
  68. return *this;
  69. }
  70. CSGTree(CSGTree&& other):
  71. // initialize via default constructor
  72. CSGTree()
  73. {
  74. swap(*this,other);
  75. }
  76. // Construct and compute a boolean operation on existing CSGTree nodes.
  77. //
  78. // Inputs:
  79. // A Solid result of previous CSG operation (or identity, see below)
  80. // B Solid result of previous CSG operation (or identity, see below)
  81. // type type of mesh boolean to compute
  82. CSGTree(
  83. const CSGTree & A,
  84. const CSGTree & B,
  85. const MeshBooleanType & type)
  86. {
  87. // conduct boolean operation
  88. mesh_boolean(A.V(),A.F(),B.V(),B.F(),type,m_V,m_F,m_J);
  89. // reindex m_J
  90. std::for_each(m_J.data(),m_J.data()+m_J.size(),
  91. [&](typename VectorJ::Scalar & j)
  92. {
  93. if(j < A.F().rows())
  94. {
  95. j = A.J()(j);
  96. }else
  97. {
  98. assert(j<(A.F().rows()+B.F().rows()));
  99. j = A.number_of_birth_faces()+(B.J()(j-A.F().rows()));
  100. }
  101. });
  102. m_number_of_birth_faces =
  103. A.number_of_birth_faces() + B.number_of_birth_faces();
  104. }
  105. // Overload using string for type
  106. CSGTree(
  107. const CSGTree & A,
  108. const CSGTree & B,
  109. const std::string & s):
  110. CSGTree(A,B,string_to_mesh_boolean_type(s))
  111. {
  112. // do nothing (all done in constructor).
  113. }
  114. // "Leaf" node with identity operation on assumed "solid" mesh (V,F)
  115. //
  116. // Inputs:
  117. // V #V by 3 list of mesh vertices (in any precision, will be
  118. // converted to exact)
  119. // F #F by 3 list of mesh face indices into V
  120. template <typename DerivedV>
  121. CSGTree(const Eigen::PlainObjectBase<DerivedV> & V, const POBF & F)//:
  122. // Possible Eigen bug:
  123. // https://forum.kde.org/viewtopic.php?f=74&t=128414
  124. //m_V(V.template cast<ExactScalar>()),m_F(F)
  125. {
  126. m_V = V.template cast<ExactScalar>();
  127. m_F = F;
  128. // number of faces
  129. m_number_of_birth_faces = m_F.rows();
  130. // identity birth index
  131. m_J = VectorJ::LinSpaced(
  132. m_number_of_birth_faces,0,m_number_of_birth_faces-1);
  133. }
  134. // Returns reference to resulting mesh vertices m_V in exact scalar
  135. // representation
  136. const MatrixX3E & V() const
  137. {
  138. return m_V;
  139. }
  140. // Returns mesh vertices in the desired output type, casting when
  141. // appropriate to floating precision.
  142. template <typename DerivedV>
  143. Eigen::PlainObjectBase<DerivedV> cast_V() const
  144. {
  145. Eigen::PlainObjectBase<DerivedV> dV;
  146. dV.resize(m_V.rows(),m_V.cols());
  147. for(int i = 0;i<m_V.size();i++)
  148. {
  149. *(dV.data()+i) = CGAL::to_double((*(m_V.data()+i)));
  150. }
  151. return dV;
  152. }
  153. // Returns reference to resulting mesh faces m_F
  154. const POBF & F() const
  155. {
  156. return m_F;
  157. }
  158. // Returns reference to "birth parents" indices into [F1;F2;...;Fn]
  159. // where F1, ... , Fn are the face lists of the leaf ("original") input
  160. // meshes.
  161. const VectorJ & J() const
  162. {
  163. return m_J;
  164. }
  165. // The number of leaf faces = #F1 + #F2 + ... + #Fn
  166. const size_t & number_of_birth_faces() const
  167. {
  168. return m_number_of_birth_faces;
  169. }
  170. };
  171. }
  172. }
  173. #endif