1 #include <gtest/gtest.h> 2 #include <Unittests/unittests_common.hh> 4 #include <OpenMesh/Core/Mesh/SmartHandles.hh> 16 virtual void SetUp() {
32 std::vector<Mesh::VertexHandle> face_vhandles;
34 face_vhandles.clear();
35 face_vhandles.push_back(vhandle[0]);
36 face_vhandles.push_back(vhandle[1]);
37 face_vhandles.push_back(vhandle[3]);
38 mesh_.add_face(face_vhandles);
40 face_vhandles.clear();
41 face_vhandles.push_back(vhandle[1]);
42 face_vhandles.push_back(vhandle[2]);
43 face_vhandles.push_back(vhandle[3]);
44 mesh_.add_face(face_vhandles);
48 face_vhandles.clear();
49 face_vhandles.push_back(vhandle[7]);
50 face_vhandles.push_back(vhandle[6]);
51 face_vhandles.push_back(vhandle[5]);
52 mesh_.add_face(face_vhandles);
54 face_vhandles.clear();
55 face_vhandles.push_back(vhandle[7]);
56 face_vhandles.push_back(vhandle[5]);
57 face_vhandles.push_back(vhandle[4]);
58 mesh_.add_face(face_vhandles);
62 face_vhandles.clear();
63 face_vhandles.push_back(vhandle[1]);
64 face_vhandles.push_back(vhandle[0]);
65 face_vhandles.push_back(vhandle[4]);
66 mesh_.add_face(face_vhandles);
68 face_vhandles.clear();
69 face_vhandles.push_back(vhandle[1]);
70 face_vhandles.push_back(vhandle[4]);
71 face_vhandles.push_back(vhandle[5]);
72 mesh_.add_face(face_vhandles);
76 face_vhandles.clear();
77 face_vhandles.push_back(vhandle[2]);
78 face_vhandles.push_back(vhandle[1]);
79 face_vhandles.push_back(vhandle[5]);
80 mesh_.add_face(face_vhandles);
82 face_vhandles.clear();
83 face_vhandles.push_back(vhandle[2]);
84 face_vhandles.push_back(vhandle[5]);
85 face_vhandles.push_back(vhandle[6]);
86 mesh_.add_face(face_vhandles);
91 face_vhandles.clear();
92 face_vhandles.push_back(vhandle[3]);
93 face_vhandles.push_back(vhandle[2]);
94 face_vhandles.push_back(vhandle[6]);
95 mesh_.add_face(face_vhandles);
97 face_vhandles.clear();
98 face_vhandles.push_back(vhandle[3]);
99 face_vhandles.push_back(vhandle[6]);
100 face_vhandles.push_back(vhandle[7]);
101 mesh_.add_face(face_vhandles);
105 face_vhandles.clear();
106 face_vhandles.push_back(vhandle[0]);
107 face_vhandles.push_back(vhandle[3]);
108 face_vhandles.push_back(vhandle[7]);
109 mesh_.add_face(face_vhandles);
111 face_vhandles.clear();
112 face_vhandles.push_back(vhandle[0]);
113 face_vhandles.push_back(vhandle[7]);
114 face_vhandles.push_back(vhandle[4]);
115 mesh_.add_face(face_vhandles);
133 EXPECT_EQ(18u, mesh_.n_edges() ) <<
"Wrong number of Edges";
134 EXPECT_EQ(36u, mesh_.n_halfedges() ) <<
"Wrong number of HalfEdges";
135 EXPECT_EQ(8u, mesh_.n_vertices() ) <<
"Wrong number of vertices";
136 EXPECT_EQ(12u, mesh_.n_faces() ) <<
"Wrong number of faces";
140 virtual void TearDown() {
161 TEST_F(OpenMeshSmartHandles, SimpleNavigation)
163 for (
auto vh : mesh_.vertices())
165 EXPECT_EQ(mesh_.halfedge_handle(vh), vh.halfedge()) <<
"outgoing halfedge of vertex does not match";
168 for (
auto heh : mesh_.halfedges())
170 EXPECT_EQ(mesh_.next_halfedge_handle(heh), heh.next()) <<
"next halfedge of halfedge does not match";
171 EXPECT_EQ(mesh_.prev_halfedge_handle(heh), heh.prev()) <<
"prevt halfedge of halfedge does not match";
172 EXPECT_EQ(mesh_.opposite_halfedge_handle(heh), heh.opp()) <<
"opposite halfedge of halfedge does not match";
173 EXPECT_EQ(mesh_.to_vertex_handle(heh), heh.to()) <<
"to vertex handle of halfedge does not match";
174 EXPECT_EQ(mesh_.from_vertex_handle(heh), heh.from()) <<
"from vertex handle of halfedge does not match";
175 EXPECT_EQ(mesh_.face_handle(heh), heh.face()) <<
"face handle of halfedge does not match";
178 for (
auto eh : mesh_.edges())
180 EXPECT_EQ(mesh_.halfedge_handle(eh, 0), eh.h0()) <<
"halfedge 0 of edge does not match";
181 EXPECT_EQ(mesh_.halfedge_handle(eh, 1), eh.h1()) <<
"halfedge 1 of edge does not match";
182 EXPECT_EQ(mesh_.from_vertex_handle(mesh_.halfedge_handle(eh, 0)), eh.v0()) <<
"first vertex of edge does not match";
183 EXPECT_EQ(mesh_.to_vertex_handle (mesh_.halfedge_handle(eh, 0)), eh.v1()) <<
"second vertex of edge does not match";
186 for (
auto fh : mesh_.faces())
188 EXPECT_EQ(mesh_.halfedge_handle(fh), fh.halfedge()) <<
"halfedge of face does not match";
195 TEST_F(OpenMeshSmartHandles, SimpleRanges)
197 for (
auto vh : mesh_.vertices())
200 std::vector<OpenMesh::VertexHandle> handles0;
201 std::vector<OpenMesh::VertexHandle> handles1;
202 for (
auto h : mesh_.vv_range(vh))
203 handles0.push_back(h);
204 for (
auto h : vh.vertices())
205 handles1.push_back(h);
206 EXPECT_EQ(handles0, handles1) <<
"vertex range of vertex does not match";
209 std::vector<OpenMesh::HalfedgeHandle> handles0;
210 std::vector<OpenMesh::HalfedgeHandle> handles1;
211 for (
auto h : mesh_.voh_range(vh))
212 handles0.push_back(h);
213 for (
auto h : vh.outgoing_halfedges())
214 handles1.push_back(h);
215 EXPECT_EQ(handles0, handles1) <<
"outgoing halfedge range of vertex does not match";
218 std::vector<OpenMesh::HalfedgeHandle> handles0;
219 std::vector<OpenMesh::HalfedgeHandle> handles1;
220 for (
auto h : mesh_.vih_range(vh))
221 handles0.push_back(h);
222 for (
auto h : vh.incoming_halfedges())
223 handles1.push_back(h);
224 EXPECT_EQ(handles0, handles1) <<
"incoming halfedge range of vertex does not match";
227 std::vector<OpenMesh::EdgeHandle> handles0;
228 std::vector<OpenMesh::EdgeHandle> handles1;
229 for (
auto h : mesh_.ve_range(vh))
230 handles0.push_back(h);
231 for (
auto h : vh.edges())
232 handles1.push_back(h);
233 EXPECT_EQ(handles0, handles1) <<
"edge range of vertex does not match";
236 std::vector<OpenMesh::FaceHandle> handles0;
237 std::vector<OpenMesh::FaceHandle> handles1;
238 for (
auto h : mesh_.vf_range(vh))
239 handles0.push_back(h);
240 for (
auto h : vh.faces())
241 handles1.push_back(h);
242 EXPECT_EQ(handles0, handles1) <<
"face range of vertex does not match";
246 for (
auto fh : mesh_.faces())
249 std::vector<OpenMesh::VertexHandle> handles0;
250 std::vector<OpenMesh::VertexHandle> handles1;
251 for (
auto h : mesh_.fv_range(fh))
252 handles0.push_back(h);
253 for (
auto h : fh.vertices())
254 handles1.push_back(h);
255 EXPECT_EQ(handles0, handles1) <<
"vertex range of face does not match";
258 std::vector<OpenMesh::HalfedgeHandle> handles0;
259 std::vector<OpenMesh::HalfedgeHandle> handles1;
260 for (
auto h : mesh_.fh_range(fh))
261 handles0.push_back(h);
262 for (
auto h : fh.halfedges())
263 handles1.push_back(h);
264 EXPECT_EQ(handles0, handles1) <<
"halfedge range of face does not match";
267 std::vector<OpenMesh::EdgeHandle> handles0;
268 std::vector<OpenMesh::EdgeHandle> handles1;
269 for (
auto h : mesh_.fe_range(fh))
270 handles0.push_back(h);
271 for (
auto h : fh.edges())
272 handles1.push_back(h);
273 EXPECT_EQ(handles0, handles1) <<
"edge range of face does not match";
276 std::vector<OpenMesh::FaceHandle> handles0;
277 std::vector<OpenMesh::FaceHandle> handles1;
278 for (
auto h : mesh_.ff_range(fh))
279 handles0.push_back(h);
280 for (
auto h : fh.faces())
281 handles1.push_back(h);
282 EXPECT_EQ(handles0, handles1) <<
"face range of face does not match";
289 TEST_F(OpenMeshSmartHandles, RangesOfRanges)
291 for (
auto vh : mesh_.vertices())
294 std::vector<OpenMesh::VertexHandle> handles0;
295 std::vector<OpenMesh::VertexHandle> handles1;
296 for (
auto h : mesh_.vv_range(vh))
297 for (
auto h2 : mesh_.vv_range(h))
298 handles0.push_back(h2);
299 for (
auto h : vh.vertices())
300 for (
auto h2 : h.vertices())
301 handles1.push_back(h2);
302 EXPECT_EQ(handles0, handles1) <<
"vertex range of vertex range does not match";
305 std::vector<OpenMesh::HalfedgeHandle> handles0;
306 std::vector<OpenMesh::HalfedgeHandle> handles1;
307 for (
auto h : mesh_.vv_range(vh))
308 for (
auto h2 : mesh_.voh_range(h))
309 handles0.push_back(h2);
310 for (
auto h : vh.vertices())
311 for (
auto h2 : h.outgoing_halfedges())
312 handles1.push_back(h2);
313 EXPECT_EQ(handles0, handles1) <<
"outgoing halfedge range of vertex range does not match";
316 std::vector<OpenMesh::HalfedgeHandle> handles0;
317 std::vector<OpenMesh::HalfedgeHandle> handles1;
318 for (
auto h : mesh_.vv_range(vh))
319 for (
auto h2 : mesh_.vih_range(h))
320 handles0.push_back(h2);
321 for (
auto h : vh.vertices())
322 for (
auto h2 : h.incoming_halfedges())
323 handles1.push_back(h2);
324 EXPECT_EQ(handles0, handles1) <<
"incoming halfedge range of vertex range does not match";
327 std::vector<OpenMesh::EdgeHandle> handles0;
328 std::vector<OpenMesh::EdgeHandle> handles1;
329 for (
auto h : mesh_.vv_range(vh))
330 for (
auto h2 : mesh_.ve_range(h))
331 handles0.push_back(h2);
332 for (
auto h : vh.vertices())
333 for (
auto h2 : h.edges())
334 handles1.push_back(h2);
335 EXPECT_EQ(handles0, handles1) <<
"edge range of vertex range does not match";
338 std::vector<OpenMesh::FaceHandle> handles0;
339 std::vector<OpenMesh::FaceHandle> handles1;
340 for (
auto h : mesh_.vv_range(vh))
341 for (
auto h2 : mesh_.vf_range(h))
342 handles0.push_back(h2);
343 for (
auto h : vh.vertices())
344 for (
auto h2 : h.faces())
345 handles1.push_back(h2);
346 EXPECT_EQ(handles0, handles1) <<
"face range of vertex range does not match";
349 std::vector<OpenMesh::VertexHandle> handles0;
350 std::vector<OpenMesh::VertexHandle> handles1;
351 for (
auto h : mesh_.vf_range(vh))
352 for (
auto h2 : mesh_.fv_range(h))
353 handles0.push_back(h2);
354 for (
auto h : vh.faces())
355 for (
auto h2 : h.vertices())
356 handles1.push_back(h2);
357 EXPECT_EQ(handles0, handles1) <<
"vertex range of face range does not match";
360 std::vector<OpenMesh::HalfedgeHandle> handles0;
361 std::vector<OpenMesh::HalfedgeHandle> handles1;
362 for (
auto h : mesh_.vf_range(vh))
363 for (
auto h2 : mesh_.fh_range(h))
364 handles0.push_back(h2);
365 for (
auto h : vh.faces())
366 for (
auto h2 : h.halfedges())
367 handles1.push_back(h2);
368 EXPECT_EQ(handles0, handles1) <<
"vertex range of face range does not match";
371 std::vector<OpenMesh::FaceHandle> handles0;
372 std::vector<OpenMesh::FaceHandle> handles1;
373 for (
auto h : mesh_.vf_range(vh))
374 for (
auto h2 : mesh_.ff_range(h))
375 handles0.push_back(h2);
376 for (
auto h : vh.faces())
377 for (
auto h2 : h.faces())
378 handles1.push_back(h2);
379 EXPECT_EQ(handles0, handles1) <<
"vertex range of face range does not match";
387 TEST_F(OpenMeshSmartHandles, ComplicatedNavigtaion)
389 for (
auto vh : mesh_.vertices())
391 EXPECT_EQ(mesh_.next_halfedge_handle(
392 mesh_.opposite_halfedge_handle(
393 mesh_.halfedge_handle(vh))),
394 vh.out().opp().next());
395 EXPECT_EQ(mesh_.prev_halfedge_handle(
396 mesh_.prev_halfedge_handle(
397 mesh_.opposite_halfedge_handle(
398 mesh_.next_halfedge_handle(
399 mesh_.next_halfedge_handle(
400 mesh_.halfedge_handle(vh)))))),
401 vh.out().next().next().opp().prev().prev());
402 EXPECT_EQ(mesh_.face_handle(
403 mesh_.opposite_halfedge_handle(
404 mesh_.halfedge_handle(
406 mesh_.opposite_halfedge_handle(
407 mesh_.next_halfedge_handle(
408 mesh_.halfedge_handle(vh))))))),
409 vh.out().next().opp().face().halfedge().opp().face());
416 TEST_F(OpenMeshSmartHandles, Performance)
419 int n_tests = 300000;
421 int n_tests = 10000000;
424 auto t_before_old = std::chrono::high_resolution_clock::now();
426 std::vector<OpenMesh::HalfedgeHandle> halfedges0;
427 for (
int i = 0; i < n_tests; ++i)
429 for (
auto vh : mesh_.vertices())
431 auto heh = mesh_.prev_halfedge_handle(
432 mesh_.prev_halfedge_handle(
433 mesh_.opposite_halfedge_handle(
434 mesh_.next_halfedge_handle(
435 mesh_.next_halfedge_handle(
436 mesh_.halfedge_handle(vh))))));
438 halfedges0.push_back(heh);
442 auto t_after_old = std::chrono::high_resolution_clock::now();
444 std::vector<OpenMesh::HalfedgeHandle> halfedges1;
445 for (
int i = 0; i < n_tests; ++i)
447 for (
auto vh : mesh_.vertices())
449 auto heh = vh.out().next().next().opp().prev().prev();
451 halfedges1.push_back(heh);
455 auto t_after_new = std::chrono::high_resolution_clock::now();
457 std::cout <<
"Conventional navigation took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_after_old-t_before_old).count() <<
"ms" << std::endl;
458 std::cout <<
"SmartHandle navigation took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_after_new-t_after_old ).count() <<
"ms" << std::endl;
460 EXPECT_EQ(halfedges0, halfedges1) <<
"halfedges do not match";
467 TEST_F(OpenMeshSmartHandles, MixOldAndNew)
471 heh = mesh_.opposite_halfedge_handle(heh);
482 TEST_F(OpenMeshSmartHandles, ComparisionBetweenSmartHandleAndNormalHandles)
486 EXPECT_EQ(vh, svh) <<
"Vertex handle and smart vertex handle are different";
493 std::vector<OpenMesh::SmartVertexHandle> smart_vertices = mesh_.vertices().to_vector();
504 TEST(OpenMeshSmartHandlesNoFixture, AddingFacesPolyMesh)
510 std::vector<OpenMesh::SmartVertexHandle> vertices;
511 for (
int i = 0; i < 4; ++i)
514 auto fh = mesh.add_face(vertices);
516 for (
auto heh : fh.halfedges())
522 TEST(OpenMeshSmartHandlesNoFixture, AddingFacesTriMesh)
528 std::vector<OpenMesh::SmartVertexHandle> vertices;
529 for (
int i = 0; i < 4; ++i)
532 auto fh = mesh.add_face(vertices);
534 for (
auto heh : fh.halfedges())
540 TEST(OpenMeshSmartHandlesNoFixture, SplitTriMesh)
546 std::vector<OpenMesh::SmartVertexHandle> vertices;
547 for (
int i = 0; i < 3; ++i)
550 auto fh = mesh.add_face(vertices);
558 EXPECT_NE(vh.
idx(), vh2.
idx()) <<
"This was only intended to fix an unused variable warning but cool that it caugth an actual error now";
SmartEdgeHandle edge() const
Returns incident edge of halfedge.
int idx() const
Get the underlying index of this handle.
Kernel::Point Point
Coordinate type.
SmartHalfedgeHandle halfedge(unsigned int _i) const
Returns one of the two halfedges of the edge.
Handle for a vertex entity.
SmartVertexHandle add_vertex(const Point &_p)
Alias for new_vertex(const Point&).
SmartVertexHandle split(EdgeHandle _eh, const Point &_p)
Edge split (= 2-to-4 split)
Smart version of VertexHandle contains a pointer to the corresponding mesh and allows easier access t...
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.