1#include <gtest/gtest.h>
2#include <Unittests/unittests_common.hh>
4#include <OpenMesh/Core/Mesh/PolyConnectivity.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() {
161TEST_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), eh.halfedge()) <<
"halfedge of edge does not match";
181 EXPECT_EQ(mesh_.halfedge_handle(eh, 0), eh.halfedge(0)) <<
"halfedge 0 of edge does not match";
182 EXPECT_EQ(mesh_.halfedge_handle(eh, 1), eh.halfedge(1)) <<
"halfedge 1 of edge does not match";
183 EXPECT_EQ(mesh_.halfedge_handle(eh), eh.h()) <<
"halfedge of edge does not match";
184 EXPECT_EQ(mesh_.halfedge_handle(eh, 0), eh.h0()) <<
"halfedge 0 of edge does not match";
185 EXPECT_EQ(mesh_.halfedge_handle(eh, 1), eh.h1()) <<
"halfedge 1 of edge does not match";
186 EXPECT_EQ(mesh_.from_vertex_handle(mesh_.halfedge_handle(eh, 0)), eh.v0()) <<
"first vertex of edge does not match";
187 EXPECT_EQ(mesh_.to_vertex_handle (mesh_.halfedge_handle(eh, 0)), eh.v1()) <<
"second vertex of edge does not match";
190 for (
auto fh : mesh_.faces())
192 EXPECT_EQ(mesh_.halfedge_handle(fh), fh.halfedge()) <<
"halfedge of face does not match";
199TEST_F(OpenMeshSmartHandles, SimpleRanges)
201 for (
auto vh : mesh_.vertices())
204 std::vector<OpenMesh::VertexHandle> handles0;
205 std::vector<OpenMesh::VertexHandle> handles1;
206 for (
auto h : mesh_.vv_range(vh))
207 handles0.push_back(h);
208 for (
auto h : vh.vertices())
209 handles1.push_back(h);
210 EXPECT_EQ(handles0, handles1) <<
"vertex range of vertex does not match";
213 std::vector<OpenMesh::HalfedgeHandle> handles0;
214 std::vector<OpenMesh::HalfedgeHandle> handles1;
215 for (
auto h : mesh_.voh_range(vh))
216 handles0.push_back(h);
217 for (
auto h : vh.outgoing_halfedges())
218 handles1.push_back(h);
219 EXPECT_EQ(handles0, handles1) <<
"outgoing halfedge range of vertex does not match";
222 std::vector<OpenMesh::HalfedgeHandle> handles0;
223 std::vector<OpenMesh::HalfedgeHandle> handles1;
224 for (
auto h : mesh_.vih_range(vh))
225 handles0.push_back(h);
226 for (
auto h : vh.incoming_halfedges())
227 handles1.push_back(h);
228 EXPECT_EQ(handles0, handles1) <<
"incoming halfedge range of vertex does not match";
231 std::vector<OpenMesh::EdgeHandle> handles0;
232 std::vector<OpenMesh::EdgeHandle> handles1;
233 for (
auto h : mesh_.ve_range(vh))
234 handles0.push_back(h);
235 for (
auto h : vh.edges())
236 handles1.push_back(h);
237 EXPECT_EQ(handles0, handles1) <<
"edge range of vertex does not match";
240 std::vector<OpenMesh::FaceHandle> handles0;
241 std::vector<OpenMesh::FaceHandle> handles1;
242 for (
auto h : mesh_.vf_range(vh))
243 handles0.push_back(h);
244 for (
auto h : vh.faces())
245 handles1.push_back(h);
246 EXPECT_EQ(handles0, handles1) <<
"face range of vertex does not match";
250 for (
auto fh : mesh_.faces())
253 std::vector<OpenMesh::VertexHandle> handles0;
254 std::vector<OpenMesh::VertexHandle> handles1;
255 for (
auto h : mesh_.fv_range(fh))
256 handles0.push_back(h);
257 for (
auto h : fh.vertices())
258 handles1.push_back(h);
259 EXPECT_EQ(handles0, handles1) <<
"vertex range of face does not match";
262 std::vector<OpenMesh::HalfedgeHandle> handles0;
263 std::vector<OpenMesh::HalfedgeHandle> handles1;
264 for (
auto h : mesh_.fh_range(fh))
265 handles0.push_back(h);
266 for (
auto h : fh.halfedges())
267 handles1.push_back(h);
268 EXPECT_EQ(handles0, handles1) <<
"halfedge range of face does not match";
271 std::vector<OpenMesh::EdgeHandle> handles0;
272 std::vector<OpenMesh::EdgeHandle> handles1;
273 for (
auto h : mesh_.fe_range(fh))
274 handles0.push_back(h);
275 for (
auto h : fh.edges())
276 handles1.push_back(h);
277 EXPECT_EQ(handles0, handles1) <<
"edge range of face does not match";
280 std::vector<OpenMesh::FaceHandle> handles0;
281 std::vector<OpenMesh::FaceHandle> handles1;
282 for (
auto h : mesh_.ff_range(fh))
283 handles0.push_back(h);
284 for (
auto h : fh.faces())
285 handles1.push_back(h);
286 EXPECT_EQ(handles0, handles1) <<
"face range of face does not match";
293TEST_F(OpenMeshSmartHandles, RangesOfRanges)
295 for (
auto vh : mesh_.vertices())
298 std::vector<OpenMesh::VertexHandle> handles0;
299 std::vector<OpenMesh::VertexHandle> handles1;
300 for (
auto h : mesh_.vv_range(vh))
301 for (auto h2 : mesh_.vv_range(h))
302 handles0.push_back(h2);
303 for (
auto h : vh.vertices())
304 for (auto h2 : h.vertices())
305 handles1.push_back(h2);
306 EXPECT_EQ(handles0, handles1) <<
"vertex range of vertex range does not match";
309 std::vector<OpenMesh::HalfedgeHandle> handles0;
310 std::vector<OpenMesh::HalfedgeHandle> handles1;
311 for (
auto h : mesh_.vv_range(vh))
312 for (auto h2 : mesh_.voh_range(h))
313 handles0.push_back(h2);
314 for (
auto h : vh.vertices())
315 for (auto h2 : h.outgoing_halfedges())
316 handles1.push_back(h2);
317 EXPECT_EQ(handles0, handles1) <<
"outgoing halfedge range of vertex range does not match";
320 std::vector<OpenMesh::HalfedgeHandle> handles0;
321 std::vector<OpenMesh::HalfedgeHandle> handles1;
322 for (
auto h : mesh_.vv_range(vh))
323 for (auto h2 : mesh_.vih_range(h))
324 handles0.push_back(h2);
325 for (
auto h : vh.vertices())
326 for (auto h2 : h.incoming_halfedges())
327 handles1.push_back(h2);
328 EXPECT_EQ(handles0, handles1) <<
"incoming halfedge range of vertex range does not match";
331 std::vector<OpenMesh::EdgeHandle> handles0;
332 std::vector<OpenMesh::EdgeHandle> handles1;
333 for (
auto h : mesh_.vv_range(vh))
334 for (auto h2 : mesh_.ve_range(h))
335 handles0.push_back(h2);
336 for (
auto h : vh.vertices())
337 for (auto h2 : h.edges())
338 handles1.push_back(h2);
339 EXPECT_EQ(handles0, handles1) <<
"edge range of vertex range does not match";
342 std::vector<OpenMesh::FaceHandle> handles0;
343 std::vector<OpenMesh::FaceHandle> handles1;
344 for (
auto h : mesh_.vv_range(vh))
345 for (auto h2 : mesh_.vf_range(h))
346 handles0.push_back(h2);
347 for (
auto h : vh.vertices())
348 for (auto h2 : h.faces())
349 handles1.push_back(h2);
350 EXPECT_EQ(handles0, handles1) <<
"face range of vertex range does not match";
353 std::vector<OpenMesh::VertexHandle> handles0;
354 std::vector<OpenMesh::VertexHandle> handles1;
355 for (
auto h : mesh_.vf_range(vh))
356 for (auto h2 : mesh_.fv_range(h))
357 handles0.push_back(h2);
358 for (
auto h : vh.faces())
359 for (auto h2 : h.vertices())
360 handles1.push_back(h2);
361 EXPECT_EQ(handles0, handles1) <<
"vertex range of face range does not match";
364 std::vector<OpenMesh::HalfedgeHandle> handles0;
365 std::vector<OpenMesh::HalfedgeHandle> handles1;
366 for (
auto h : mesh_.vf_range(vh))
367 for (auto h2 : mesh_.fh_range(h))
368 handles0.push_back(h2);
369 for (
auto h : vh.faces())
370 for (auto h2 : h.halfedges())
371 handles1.push_back(h2);
372 EXPECT_EQ(handles0, handles1) <<
"vertex range of face range does not match";
375 std::vector<OpenMesh::FaceHandle> handles0;
376 std::vector<OpenMesh::FaceHandle> handles1;
377 for (
auto h : mesh_.vf_range(vh))
378 for (auto h2 : mesh_.ff_range(h))
379 handles0.push_back(h2);
380 for (
auto h : vh.faces())
381 for (auto h2 : h.faces())
382 handles1.push_back(h2);
383 EXPECT_EQ(handles0, handles1) <<
"vertex range of face range does not match";
391TEST_F(OpenMeshSmartHandles, ComplicatedNavigtaion)
393 for (
auto vh : mesh_.vertices())
395 EXPECT_EQ(mesh_.next_halfedge_handle(
396 mesh_.opposite_halfedge_handle(
397 mesh_.halfedge_handle(vh))),
398 vh.out().opp().next());
399 EXPECT_EQ(mesh_.prev_halfedge_handle(
400 mesh_.prev_halfedge_handle(
401 mesh_.opposite_halfedge_handle(
402 mesh_.next_halfedge_handle(
403 mesh_.next_halfedge_handle(
404 mesh_.halfedge_handle(vh)))))),
405 vh.out().next().next().opp().prev().prev());
406 EXPECT_EQ(mesh_.face_handle(
407 mesh_.opposite_halfedge_handle(
408 mesh_.halfedge_handle(
410 mesh_.opposite_halfedge_handle(
411 mesh_.next_halfedge_handle(
412 mesh_.halfedge_handle(vh))))))),
413 vh.out().next().opp().face().halfedge().opp().face());
420TEST_F(OpenMeshSmartHandles, Performance)
423 int n_tests = 10000000;
425 int n_tests = 300000;
428 auto t_before_old = std::chrono::high_resolution_clock::now();
430 std::vector<OpenMesh::HalfedgeHandle> halfedges0;
431 for (
int i = 0; i < n_tests; ++i)
433 for (
auto vh : mesh_.vertices())
435 auto heh = mesh_.prev_halfedge_handle(
436 mesh_.prev_halfedge_handle(
437 mesh_.opposite_halfedge_handle(
438 mesh_.next_halfedge_handle(
439 mesh_.next_halfedge_handle(
440 mesh_.halfedge_handle(vh))))));
442 halfedges0.push_back(heh);
446 auto t_after_old = std::chrono::high_resolution_clock::now();
448 std::vector<OpenMesh::HalfedgeHandle> halfedges1;
449 for (
int i = 0; i < n_tests; ++i)
451 for (
auto vh : mesh_.vertices())
453 auto heh = vh.out().next().next().opp().prev().prev();
455 halfedges1.push_back(heh);
459 auto t_after_new = std::chrono::high_resolution_clock::now();
461 std::cout <<
"Conventional navigation took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_after_old-t_before_old).count() <<
"ms" << std::endl;
462 std::cout <<
"SmartHandle navigation took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_after_new-t_after_old ).count() <<
"ms" << std::endl;
464 EXPECT_EQ(halfedges0, halfedges1) <<
"halfedges do not match";
471TEST_F(OpenMeshSmartHandles, MixOldAndNew)
475 heh = mesh_.opposite_halfedge_handle(heh);
486TEST_F(OpenMeshSmartHandles, ComparisionBetweenSmartHandleAndNormalHandles)
490 EXPECT_EQ(vh, svh) <<
"Vertex handle and smart vertex handle are different";
497 std::vector<OpenMesh::SmartVertexHandle> smart_vertices = mesh_.vertices().to_vector();
508TEST(OpenMeshSmartHandlesNoFixture, AddingFacesPolyMesh)
514 std::vector<OpenMesh::SmartVertexHandle> vertices;
515 for (
int i = 0; i < 4; ++i)
518 auto fh = mesh.add_face(vertices);
520 for (
auto heh : fh.halfedges())
526TEST(OpenMeshSmartHandlesNoFixture, AddingFacesTriMesh)
532 std::vector<OpenMesh::SmartVertexHandle> vertices;
533 for (
int i = 0; i < 4; ++i)
536 auto fh = mesh.add_face(vertices);
538 for (
auto heh : fh.halfedges())
544TEST(OpenMeshSmartHandlesNoFixture, SplitTriMesh)
550 std::vector<OpenMesh::SmartVertexHandle> vertices;
551 for (
int i = 0; i < 3; ++i)
554 auto fh = mesh.add_face(vertices);
562 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";
567template <
typename MeshT,
typename RangeT>
568void test_status_fields(
MeshT& _mesh,
const RangeT& _range)
570 for (
auto el : _range)
571 _mesh.status(el).set_selected(el.idx() % 3 == 0);
572 for (
auto el : _range)
573 EXPECT_EQ(_mesh.status(el).selected(), el.selected());
575 for (
auto el : _range)
576 _mesh.status(el).set_feature(el.idx() % 3 == 0);
577 for (
auto el : _range)
578 EXPECT_EQ(_mesh.status(el).feature(), el.feature());
580 for (
auto el : _range)
581 _mesh.status(el).set_tagged(el.idx() % 3 == 0);
582 for (
auto el : _range)
583 EXPECT_EQ(_mesh.status(el).tagged(), el.tagged());
585 for (
auto el : _range)
586 _mesh.status(el).set_tagged2(el.idx() % 3 == 0);
587 for (
auto el : _range)
588 EXPECT_EQ(_mesh.status(el).tagged2(), el.tagged2());
590 for (
auto el : _range)
591 _mesh.status(el).set_hidden(el.idx() % 3 == 0);
592 for (
auto el : _range)
593 EXPECT_EQ(_mesh.status(el).hidden(), el.hidden());
595 for (
auto el : _range)
596 _mesh.status(el).set_locked(el.idx() % 3 == 0);
597 for (
auto el : _range)
598 EXPECT_EQ(_mesh.status(el).locked(), el.locked());
600 for (
auto el : _range)
601 _mesh.status(el).set_deleted(el.idx() % 3 == 0);
602 for (
auto el : _range)
603 EXPECT_EQ(_mesh.status(el).deleted(), el.deleted());
606TEST_F(OpenMeshSmartHandles, StatusAccess)
608 ASSERT_TRUE(mesh_.n_vertices() > 0) <<
"Mesh is empty";
610 mesh_.request_vertex_status();
611 mesh_.request_halfedge_status();
612 mesh_.request_edge_status();
613 mesh_.request_face_status();
615 test_status_fields(mesh_, mesh_.all_vertices());
616 test_status_fields(mesh_, mesh_.all_edges());
617 test_status_fields(mesh_, mesh_.all_halfedges());
618 test_status_fields(mesh_, mesh_.all_faces());
int idx() const
Get the underlying index of this handle.
static SmartEdgeHandle s_edge_handle(SmartHalfedgeHandle _heh)
returns the face handle of the opposite halfedge
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
SmartVertexHandle add_vertex(const Point _p)
Kernel::Point Point
Coordinate type.
SmartVertexHandle split(EdgeHandle _eh, const Point &_p)
Edge split (= 2-to-4 split)
SmartHalfedgeHandle halfedge(unsigned int _i) const
Returns one of the two halfedges of the edge.
SmartEdgeHandle edge() const
Returns incident edge of halfedge.
Smart version of VertexHandle contains a pointer to the corresponding mesh and allows easier access t...
Handle for a vertex entity.