VEManifoldMesh.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2019.08.13
  7. #pragma once
  8. #include <Mathematics/Logger.h>
  9. #include <array>
  10. #include <map>
  11. #include <memory>
  12. namespace WwiseGTE
  13. {
  14. class VEManifoldMesh
  15. {
  16. public:
  17. // Vertex data types.
  18. class Vertex;
  19. typedef std::shared_ptr<Vertex>(*VCreator)(int);
  20. typedef std::map<int, std::shared_ptr<Vertex>> VMap;
  21. // Edge data types.
  22. class Edge;
  23. typedef std::shared_ptr<Edge>(*ECreator)(int, int);
  24. typedef std::map<std::pair<int, int>, std::shared_ptr<Edge>> EMap;
  25. // Vertex object.
  26. class Vertex
  27. {
  28. public:
  29. virtual ~Vertex() = default;
  30. Vertex(int v)
  31. :
  32. V(v)
  33. {
  34. }
  35. // The unique vertex index.
  36. int V;
  37. // The edges (if any) sharing the vertex.
  38. std::array<std::weak_ptr<Edge>, 2> E;
  39. };
  40. // Edge object.
  41. class Edge
  42. {
  43. public:
  44. virtual ~Edge() = default;
  45. Edge(int v0, int v1)
  46. :
  47. V{ v0, v1 }
  48. {
  49. }
  50. // Vertices, listed as a directed edge <V[0],V[1]>.
  51. std::array<int, 2> V;
  52. // Adjacent edges. E[i] points to edge sharing V[i].
  53. std::array<std::weak_ptr<Edge>, 2> E;
  54. };
  55. // Construction and destruction.
  56. virtual ~VEManifoldMesh() = default;
  57. VEManifoldMesh(VCreator vCreator = nullptr, ECreator eCreator = nullptr)
  58. :
  59. mVCreator(vCreator ? vCreator : CreateVertex),
  60. mECreator(eCreator ? eCreator : CreateEdge),
  61. mThrowOnNonmanifoldInsertion(true)
  62. {
  63. }
  64. // Member access.
  65. inline VMap const& GetVertices() const
  66. {
  67. return mVMap;
  68. }
  69. inline EMap const& GetEdges() const
  70. {
  71. return mEMap;
  72. }
  73. // If the insertion of an edge fails because the mesh would become
  74. // nonmanifold, the default behavior is to throw an exception. You
  75. // can disable this behavior and continue gracefully without an
  76. // exception.
  77. void ThrowOnNonmanifoldInsertion(bool doException)
  78. {
  79. mThrowOnNonmanifoldInsertion = doException;
  80. }
  81. // If <v0,v1> is not in the mesh, an Edge object is created and
  82. // returned; otherwise, <v0,v1> is in the mesh and nullptr is
  83. // returned. If the insertion leads to a nonmanifold mesh, the
  84. // call fails with a nullptr returned.
  85. std::shared_ptr<Edge> Insert(int v0, int v1)
  86. {
  87. std::pair<int, int> ekey(v0, v1);
  88. if (mEMap.find(ekey) != mEMap.end())
  89. {
  90. // The edge already exists. Return a null pointer as a
  91. // signal to the caller that the insertion failed.
  92. return nullptr;
  93. }
  94. // Add the new edge.
  95. std::shared_ptr<Edge> edge = mECreator(v0, v1);
  96. mEMap[ekey] = edge;
  97. // Add the vertices if they do not already exist.
  98. for (int i = 0; i < 2; ++i)
  99. {
  100. int v = edge->V[i];
  101. std::shared_ptr<Vertex> vertex;
  102. auto viter = mVMap.find(v);
  103. if (viter == mVMap.end())
  104. {
  105. // This is the first time the vertex is encountered.
  106. vertex = mVCreator(v);
  107. mVMap[v] = vertex;
  108. // Update the vertex.
  109. vertex->E[0] = edge;
  110. }
  111. else
  112. {
  113. // This is the second time the vertex is encountered.
  114. vertex = viter->second;
  115. LogAssert(vertex != nullptr, "Unexpected condition.");
  116. // Update the vertex.
  117. if (vertex->E[1].lock())
  118. {
  119. if (mThrowOnNonmanifoldInsertion)
  120. {
  121. LogError("The mesh must be manifold.");
  122. }
  123. else
  124. {
  125. return nullptr;
  126. }
  127. }
  128. vertex->E[1] = edge;
  129. // Update the adjacent edge.
  130. auto adjacent = vertex->E[0].lock();
  131. LogAssert(adjacent != nullptr, "Unexpected condition.");
  132. for (int j = 0; j < 2; ++j)
  133. {
  134. if (adjacent->V[j] == v)
  135. {
  136. adjacent->E[j] = edge;
  137. break;
  138. }
  139. }
  140. // Update the edge.
  141. edge->E[i] = adjacent;
  142. }
  143. }
  144. return edge;
  145. }
  146. // If <v0,v1> is in the mesh, it is removed and 'true' is returned;
  147. // otherwise, <v0,v1> is not in the mesh and 'false' is returned.
  148. bool Remove(int v0, int v1)
  149. {
  150. std::pair<int, int> ekey(v0, v1);
  151. auto eiter = mEMap.find(ekey);
  152. if (eiter == mEMap.end())
  153. {
  154. // The edge does not exist.
  155. return false;
  156. }
  157. // Get the edge.
  158. std::shared_ptr<Edge> edge = eiter->second;
  159. // Remove the vertices if necessary (when they are not shared).
  160. for (int i = 0; i < 2; ++i)
  161. {
  162. // Inform the vertices the edge is being deleted.
  163. auto viter = mVMap.find(edge->V[i]);
  164. LogAssert(viter != mVMap.end(), "Unexpected condition.");
  165. std::shared_ptr<Vertex> vertex = viter->second;
  166. LogAssert(vertex != nullptr, "Unexpected condition.");
  167. if (vertex->E[0].lock() == edge)
  168. {
  169. // One-edge vertices always have pointer at index zero.
  170. vertex->E[0] = vertex->E[1];
  171. vertex->E[1].reset();
  172. }
  173. else if (vertex->E[1].lock() == edge)
  174. {
  175. vertex->E[1].reset();
  176. }
  177. else
  178. {
  179. LogError("Unexpected condition.");
  180. }
  181. // Remove the vertex if you have the last reference to it.
  182. if (!vertex->E[0].lock() && !vertex->E[1].lock())
  183. {
  184. mVMap.erase(vertex->V);
  185. }
  186. // Inform adjacent edges the edge is being deleted.
  187. auto adjacent = edge->E[i].lock();
  188. if (adjacent)
  189. {
  190. for (int j = 0; j < 2; ++j)
  191. {
  192. if (adjacent->E[j].lock() == edge)
  193. {
  194. adjacent->E[j].reset();
  195. break;
  196. }
  197. }
  198. }
  199. }
  200. mEMap.erase(ekey);
  201. return true;
  202. }
  203. // A manifold mesh is closed if each vertex is shared twice.
  204. bool IsClosed() const
  205. {
  206. for (auto const& element : mVMap)
  207. {
  208. auto vertex = element.second;
  209. if (!vertex->E[0].lock() || !vertex->E[1].lock())
  210. {
  211. return false;
  212. }
  213. }
  214. return true;
  215. }
  216. protected:
  217. // The vertex data and default vertex creation.
  218. static std::shared_ptr<Vertex> CreateVertex(int v0)
  219. {
  220. return std::make_shared<Vertex>(v0);
  221. }
  222. VCreator mVCreator;
  223. VMap mVMap;
  224. // The edge data and default edge creation.
  225. static std::shared_ptr<Edge> CreateEdge(int v0, int v1)
  226. {
  227. return std::make_shared<Edge>(v0, v1);
  228. }
  229. ECreator mECreator;
  230. EMap mEMap;
  231. bool mThrowOnNonmanifoldInsertion; // default: true
  232. };
  233. }