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