CSGTree.h 5.3 KB

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