1 // Copyright (c) 2017-2021, Lawrence Livermore National Security, LLC and
2 // other Axom Project Developers. See the top-level LICENSE file for details.
3 //
4 // SPDX-License-Identifier: (BSD-3-Clause)
5 
6 #include "gtest/gtest.h"
7 
8 #include "axom/slic/interface/slic.hpp"
9 
10 #include "axom/primal/geometry/Point.hpp"
11 #include "axom/mint/mesh/UnstructuredMesh.hpp"
12 #include "axom/quest/MeshTester.hpp"
13 #include "quest_test_utilities.hpp"
14 
15 namespace
16 {
17 static const int DIM = 3;
18 static const double EPS = 1e-6;
19 
20 typedef axom::mint::UnstructuredMesh<axom::mint::SINGLE_SHAPE> UMesh;
21 typedef axom::primal::Point<double, 3> Point3;
22 
23 /*! Insert a vertex with coordinates (x,y,z) into \a mesh  */
insertVertex(UMesh * mesh,double x,double y,double z)24 void insertVertex(UMesh* mesh, double x, double y, double z)
25 {
26   mesh->appendNode(x, y, z);
27 }
28 
29 /*! Insert a triangle with vertex indices (v1,v2,v3) into \a mesh  */
insertTriangle(UMesh * mesh,int v1,int v2,int v3)30 void insertTriangle(UMesh* mesh, int v1, int v2, int v3)
31 {
32   axom::IndexType indices[3] = {v1, v2, v3};
33   mesh->appendCell(indices);
34 }
35 
36 }  // namespace
37 
38 //------------------------------------------------------------------------------
TEST(quest_vertex_weld,emptyMesh)39 TEST(quest_vertex_weld, emptyMesh)
40 {
41   SLIC_INFO("*** Tests welding function on an empty triangle mesh");
42 
43   UMesh* mesh = new UMesh(DIM, axom::mint::TRIANGLE);
44 
45   EXPECT_EQ(0, mesh->getNumberOfNodes());
46   EXPECT_EQ(0, mesh->getNumberOfCells());
47 
48   axom::quest::weldTriMeshVertices(&mesh, EPS);
49 
50   EXPECT_EQ(0, mesh->getNumberOfNodes());
51   EXPECT_EQ(0, mesh->getNumberOfCells());
52 
53   delete mesh;
54   mesh = nullptr;
55 }
56 
57 //------------------------------------------------------------------------------
TEST(quest_vertex_weld,onlyVertices)58 TEST(quest_vertex_weld, onlyVertices)
59 {
60   SLIC_INFO("*** Tests welding function on a triangle mesh"
61             << " with vertices but no triangles.");
62 
63   UMesh* mesh = new UMesh(DIM, axom::mint::TRIANGLE);
64   insertVertex(mesh, 1, 0, 0);
65   insertVertex(mesh, 1, 1, 0);
66   insertVertex(mesh, 1, 1, 1);
67 
68   EXPECT_EQ(3, mesh->getNumberOfNodes());
69   EXPECT_EQ(0, mesh->getNumberOfCells());
70 
71   axom::quest::weldTriMeshVertices(&mesh, EPS);
72 
73   EXPECT_EQ(3, mesh->getNumberOfNodes());
74   EXPECT_EQ(0, mesh->getNumberOfCells());
75 
76   delete mesh;
77   mesh = nullptr;
78 }
79 
80 //------------------------------------------------------------------------------
TEST(quest_vertex_weld,oneTriangle)81 TEST(quest_vertex_weld, oneTriangle)
82 {
83   SLIC_INFO("*** Tests welding function on a triangle mesh with one triangle.");
84 
85   UMesh* mesh = new UMesh(DIM, axom::mint::TRIANGLE);
86   insertVertex(mesh, 1, 0, 0);
87   insertVertex(mesh, 1, 1, 0);
88   insertVertex(mesh, 1, 1, 1);
89 
90   EXPECT_EQ(3, mesh->getNumberOfNodes());
91 
92   insertTriangle(mesh, 0, 1, 2);
93   EXPECT_EQ(1, mesh->getNumberOfCells());
94 
95   axom::quest::weldTriMeshVertices(&mesh, EPS);
96 
97   EXPECT_EQ(3, mesh->getNumberOfNodes());
98   EXPECT_EQ(1, mesh->getNumberOfCells());
99 
100   delete mesh;
101   mesh = nullptr;
102 }
103 
104 //------------------------------------------------------------------------------
TEST(quest_vertex_weld,degenerateTriangle)105 TEST(quest_vertex_weld, degenerateTriangle)
106 {
107   SLIC_INFO(
108     "*** Tests welding function on a triangle mesh degenerate triangles.");
109 
110   UMesh* mesh = new UMesh(DIM, axom::mint::TRIANGLE);
111   insertVertex(mesh, 1, 0, 0);
112   insertVertex(mesh, 1, 1, 0);
113   insertVertex(mesh, 1, 1, 1);
114   insertVertex(mesh, 1.01, 1.01, 1.01);  // should be welded
115 
116   EXPECT_EQ(4, mesh->getNumberOfNodes());
117 
118   insertTriangle(mesh, 0, 1, 2);
119   insertTriangle(mesh, 0, 1, 1);  // degenerate: only two distinct vertices
120   insertTriangle(mesh, 1, 1, 1);  // degenerate: one one distinct vertex
121   insertTriangle(mesh, 1, 2, 3);  // degenerate: verts 2 and 3 should be welded
122   EXPECT_EQ(4, mesh->getNumberOfCells());
123 
124   const double eps = .1;
125   axom::quest::weldTriMeshVertices(&mesh, eps);
126 
127   EXPECT_EQ(3, mesh->getNumberOfNodes());
128   EXPECT_EQ(1, mesh->getNumberOfCells());
129 
130   delete mesh;
131   mesh = nullptr;
132 }
133 
134 //------------------------------------------------------------------------------
TEST(quest_vertex_weld,vertexAdjacentTrianglePair)135 TEST(quest_vertex_weld, vertexAdjacentTrianglePair)
136 {
137   SLIC_INFO("*** Tests welding function on a triangle mesh"
138             << " with two triangles adjacent along a vertex.");
139 
140   UMesh* mesh = new UMesh(DIM, axom::mint::TRIANGLE);
141   insertVertex(mesh, 1, 0, 0);
142   insertVertex(mesh, 1, 1, 0);
143   insertVertex(mesh, 1, 1, 1);
144 
145   insertVertex(mesh, 0, 1, 0);
146   insertVertex(mesh, 0, 1, 1);
147   insertVertex(mesh, 1, 1, 1);  // Duplicate
148 
149   EXPECT_EQ(6, mesh->getNumberOfNodes());
150 
151   insertTriangle(mesh, 0, 1, 2);
152   insertTriangle(mesh, 3, 4, 5);
153   EXPECT_EQ(2, mesh->getNumberOfCells());
154 
155   axom::quest::weldTriMeshVertices(&mesh, EPS);
156 
157   // Duplicated vertices should have been removed
158   EXPECT_EQ(5, mesh->getNumberOfNodes());
159   EXPECT_EQ(2, mesh->getNumberOfCells());
160 
161   delete mesh;
162   mesh = nullptr;
163 }
164 
165 //------------------------------------------------------------------------------
TEST(quest_vertex_weld,edgeAdjacentTrianglePair)166 TEST(quest_vertex_weld, edgeAdjacentTrianglePair)
167 {
168   SLIC_INFO("*** Tests welding function on a triangle mesh"
169             << " with two triangles adjacent along an edge.");
170 
171   UMesh* mesh = new UMesh(DIM, axom::mint::TRIANGLE);
172   insertVertex(mesh, 1, 0, 0);
173   insertVertex(mesh, 1, 1, 0);
174   insertVertex(mesh, 1, 1, 1);
175 
176   insertVertex(mesh, 0, 1, 0);
177   insertVertex(mesh, 1, 1, 0);  // Duplicate
178   insertVertex(mesh, 1, 1, 1);  // Duplicate
179 
180   EXPECT_EQ(6, mesh->getNumberOfNodes());
181 
182   insertTriangle(mesh, 0, 1, 2);
183   insertTriangle(mesh, 3, 4, 5);
184   EXPECT_EQ(2, mesh->getNumberOfCells());
185 
186   axom::quest::weldTriMeshVertices(&mesh, EPS);
187 
188   // Duplicated vertices should have been removed
189   EXPECT_EQ(4, mesh->getNumberOfNodes());
190   EXPECT_EQ(2, mesh->getNumberOfCells());
191 
192   delete mesh;
193   mesh = nullptr;
194 }
195 
196 //------------------------------------------------------------------------------
TEST(quest_vertex_weld,fuzzWeld)197 TEST(quest_vertex_weld, fuzzWeld)
198 {
199   SLIC_INFO("*** Tests welding function on a triangle mesh"
200             << " with a pair of triangles adjacent along an edge"
201             << " whose vertices are welded");
202 
203   UMesh* mesh = new UMesh(DIM, axom::mint::TRIANGLE);
204   insertVertex(mesh, 1, 0, 0);
205   insertVertex(mesh, 1, 1, 0);
206   insertVertex(mesh, 1, 1, 1);
207   insertVertex(mesh, 0.99, 0.99, -0.01);  // should weld with 2nd vert
208   insertVertex(mesh, 1.01, 1.01, 1.01);   // should weld with 3rd vert
209   insertVertex(mesh, 0, 1, 0);
210 
211   EXPECT_EQ(6, mesh->getNumberOfNodes());
212 
213   insertTriangle(mesh, 0, 1, 2);
214   insertTriangle(mesh, 3, 4, 5);
215   EXPECT_EQ(2, mesh->getNumberOfCells());
216 
217   const double eps = .1;
218   axom::quest::weldTriMeshVertices(&mesh, eps);
219 
220   EXPECT_EQ(4, mesh->getNumberOfNodes());
221   EXPECT_EQ(2, mesh->getNumberOfCells());
222 
223   delete mesh;
224   mesh = nullptr;
225 }
226 
227 //------------------------------------------------------------------------------
TEST(quest_vertex_weld,disconnectedTrianglePair)228 TEST(quest_vertex_weld, disconnectedTrianglePair)
229 {
230   SLIC_INFO("*** Tests welding function on a triangle mesh"
231             << " with a pair of disconnected triangles.");
232 
233   UMesh* mesh = new UMesh(DIM, axom::mint::TRIANGLE);
234   insertVertex(mesh, 1, 0, 0);  // verts for first triangle
235   insertVertex(mesh, 1, 1, 0);
236   insertVertex(mesh, 1, 1, 1);
237   insertVertex(mesh, 0, -1, 0);  // verts for second triangle
238   insertVertex(mesh, -1, -1, 0);
239   insertVertex(mesh, -1, -1, -1);
240 
241   EXPECT_EQ(6, mesh->getNumberOfNodes());
242 
243   insertTriangle(mesh, 0, 1, 2);
244   insertTriangle(mesh, 3, 4, 5);
245   EXPECT_EQ(2, mesh->getNumberOfCells());
246 
247   axom::quest::weldTriMeshVertices(&mesh, EPS);
248 
249   // Duplicated vertices should have been removed
250   EXPECT_EQ(6, mesh->getNumberOfNodes());
251   EXPECT_EQ(2, mesh->getNumberOfCells());
252 
253   delete mesh;
254   mesh = nullptr;
255 }
256 
257 //------------------------------------------------------------------------------
TEST(quest_vertex_weld,indexedTetrahedron)258 TEST(quest_vertex_weld, indexedTetrahedron)
259 {
260   SLIC_INFO("*** Tests welding function on an indexed tetrahedron");
261 
262   // Get the tetrahedron mesh.  It is already an indexed mesh.
263   UMesh* mesh =
264     static_cast<UMesh*>(axom::quest::utilities::make_tetrahedron_mesh());
265 
266   const int NV = 4;
267   const int NT = 4;
268 
269   EXPECT_EQ(NV, mesh->getNumberOfNodes());
270   EXPECT_EQ(NT, mesh->getNumberOfCells());
271 
272   axom::quest::weldTriMeshVertices(&mesh, EPS);
273 
274   // welding shouldn't change anything on this mesh
275   EXPECT_EQ(NV, mesh->getNumberOfNodes());
276   EXPECT_EQ(NT, mesh->getNumberOfCells());
277 
278   delete mesh;
279   mesh = nullptr;
280 }
281 
282 //------------------------------------------------------------------------------
TEST(quest_vertex_weld,indexedOctahedron)283 TEST(quest_vertex_weld, indexedOctahedron)
284 {
285   SLIC_INFO("*** Tests welding function on an indexed octahedron");
286 
287   // Get the octahedron mesh.  It is already an indexed mesh.
288   UMesh* mesh =
289     static_cast<UMesh*>(axom::quest::utilities::make_octahedron_mesh());
290 
291   const int NV = 6;
292   const int NT = 8;
293 
294   EXPECT_EQ(NV, mesh->getNumberOfNodes());
295   EXPECT_EQ(NT, mesh->getNumberOfCells());
296 
297   axom::quest::weldTriMeshVertices(&mesh, EPS);
298 
299   // welding shouldn't change anything on this mesh
300   EXPECT_EQ(NV, mesh->getNumberOfNodes());
301   EXPECT_EQ(NT, mesh->getNumberOfCells());
302 
303   delete mesh;
304   mesh = nullptr;
305 }
306 
307 //----------------------------------------------------------------------
308 //----------------------------------------------------------------------
309 #include "axom/slic/core/SimpleLogger.hpp"
310 using axom::slic::SimpleLogger;
311 
main(int argc,char * argv[])312 int main(int argc, char* argv[])
313 {
314   int result = 0;
315 
316   ::testing::InitGoogleTest(&argc, argv);
317 
318   SimpleLogger logger;  // create & initialize test logger,
319 
320   // finalized when exiting main scope
321 
322   result = RUN_ALL_TESTS();
323 
324   return result;
325 }
326