CSGTree.h 6.5 KB

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