From 1af153e52da7a1fb6193318d9353abf2c2465b34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20M=C3=B6bius?= Date: Thu, 19 Feb 2015 09:58:00 +0000 Subject: [PATCH] refs #1382 - Fixed the problem that the end iterator could become valid again if it was incremented. - Decrementing the start iterator will return an invalid iterator now (Maybe we can implement reverse iterators) - Removed one check from the iteration, which should result in faster execution of is_valid(). git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@1225 fdac6126-5c0c-442c-9429-916003d36597 --- src/OpenMesh/Core/Mesh/CirculatorsT.hh | 54 +++--- .../unittests_trimesh_circulator_face_edge.cc | 74 ++++++++ .../unittests_trimesh_circulator_face_face.cc | 72 +++++++ ...ttests_trimesh_circulator_face_halfedge.cc | 72 +++++++ ...nittests_trimesh_circulator_face_vertex.cc | 73 ++++++++ ...nittests_trimesh_circulator_vertex_edge.cc | 69 +++++++ ...nittests_trimesh_circulator_vertex_face.cc | 177 +++++++++++++++++- ...sts_trimesh_circulator_vertex_ihalfedge.cc | 72 +++++++ ...sts_trimesh_circulator_vertex_ohalfedge.cc | 73 ++++++++ ...ttests_trimesh_circulator_vertex_vertex.cc | 74 ++++++++ src/Unittests/unittests_tutorials.cc | 4 + 11 files changed, 785 insertions(+), 29 deletions(-) diff --git a/src/OpenMesh/Core/Mesh/CirculatorsT.hh b/src/OpenMesh/Core/Mesh/CirculatorsT.hh index ffe6309d..6c5abb01 100644 --- a/src/OpenMesh/Core/Mesh/CirculatorsT.hh +++ b/src/OpenMesh/Core/Mesh/CirculatorsT.hh @@ -64,19 +64,19 @@ namespace Iterators { template class GenericCirculator_CenterEntityFnsT { public: - static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter); - static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter); + static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, bool &lap_counter); + static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, bool &lap_counter); }; template class GenericCirculator_CenterEntityFnsT { public: - inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { + inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, bool &lap_counter) { heh = mesh->cw_rotated_halfedge_handle(heh); - if (heh == start) ++lap_counter; + if (heh == start) lap_counter = false; } - inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { - if (heh == start) --lap_counter; + inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, bool &lap_counter) { + if (heh == start) lap_counter = false; heh = mesh->ccw_rotated_halfedge_handle(heh); } }; @@ -84,12 +84,12 @@ class GenericCirculator_CenterEntityFnsT { template class GenericCirculator_CenterEntityFnsT { public: - inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { + inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, bool &lap_counter) { heh = mesh->next_halfedge_handle(heh); - if (heh == start) ++lap_counter; + if (heh == start) lap_counter = false; } - inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { - if (heh == start) --lap_counter; + inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, bool &lap_counter) { + if (heh == start) lap_counter = false; heh = mesh->prev_halfedge_handle(heh); } }; @@ -119,14 +119,14 @@ class GenericCirculator_DereferenciabilityCheckT class GenericCirculator_ValueHandleFnsT { public: - inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int &lap_counter) { - return heh.is_valid() && ((start != heh) || (lap_counter == 0)); + inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const bool &lap_counter) { + return ( heh.is_valid() && lap_counter ); } - inline static void init(const Mesh*, typename Mesh::HalfedgeHandle&, typename Mesh::HalfedgeHandle&, int&) {}; - inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { + inline static void init(const Mesh*, typename Mesh::HalfedgeHandle&, typename Mesh::HalfedgeHandle&, bool&) {}; + inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, bool &lap_counter) { GenericCirculator_CenterEntityFnsT::increment(mesh, heh, start, lap_counter); } - inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { + inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, bool &lap_counter) { GenericCirculator_CenterEntityFnsT::decrement(mesh, heh, start, lap_counter); } }; @@ -136,22 +136,22 @@ class GenericCirculator_ValueHandleFnsT GenericCirculator_DereferenciabilityCheck; - inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int &lap_counter) { - return heh.is_valid() && ((start != heh) || (lap_counter == 0)); + inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const bool &lap_counter) { + return ( heh.is_valid() && lap_counter ); } - inline static void init(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { - if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0) + inline static void init(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, bool &lap_counter) { + if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter ) increment(mesh, heh, start, lap_counter); }; - inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { + inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, bool &lap_counter) { do { GenericCirculator_CenterEntityFnsT::increment(mesh, heh, start, lap_counter); - } while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh)); + } while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh)); } - inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { + inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, bool &lap_counter) { do { GenericCirculator_CenterEntityFnsT::decrement(mesh, heh, start, lap_counter); - } while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh)); + } while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh)); } }; @@ -162,10 +162,10 @@ class GenericCirculatorBaseT { typedef const Mesh& mesh_ref; public: - GenericCirculatorBaseT() : mesh_(0), lap_counter_(0) {} + GenericCirculatorBaseT() : mesh_(0), lap_counter_(true) {} GenericCirculatorBaseT(mesh_ref mesh, HalfedgeHandle heh, bool end = false) : - mesh_(&mesh), start_(heh), heh_(heh), lap_counter_(static_cast(end)) {} + mesh_(&mesh), start_(heh), heh_(heh), lap_counter_(!end) {} GenericCirculatorBaseT(const GenericCirculatorBaseT &rhs) : mesh_(rhs.mesh_), start_(rhs.start_), heh_(rhs.heh_), lap_counter_(rhs.lap_counter_) {} @@ -213,7 +213,7 @@ class GenericCirculatorBaseT { protected: mesh_ptr mesh_; typename Mesh::HalfedgeHandle start_, heh_; - int lap_counter_; + bool lap_counter_; }; template { } bool is_valid() const { - return GenericCirculator_ValueHandleFns::is_valid(this->heh_, this->start_, this->lap_counter_); + return GenericCirculator_ValueHandleFns::is_valid(this->heh_, this->lap_counter_); } DEPRECATED("current_halfedge_handle() is an implementation detail and should not be accessed from outside the iterator class.") diff --git a/src/Unittests/unittests_trimesh_circulator_face_edge.cc b/src/Unittests/unittests_trimesh_circulator_face_edge.cc index c95460e8..f21e1483 100644 --- a/src/Unittests/unittests_trimesh_circulator_face_edge.cc +++ b/src/Unittests/unittests_trimesh_circulator_face_edge.cc @@ -129,6 +129,80 @@ TEST_F(OpenMeshTrimeshCirculatorFaceEdge, FaceEdgeIterWithoutHolesIncrement) { } } + +/* + * Test if the end iterator stays invalid after one lap + */ +TEST_F(OpenMeshTrimeshCirculatorFaceEdge, FaceEdgeIterCheckInvalidationAtEnds) { + + mesh_.clear(); + + // Add some vertices + Mesh::VertexHandle vhandle[5]; + + vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 1, 0)); + vhandle[1] = mesh_.add_vertex(Mesh::Point(1, 0, 0)); + vhandle[2] = mesh_.add_vertex(Mesh::Point(2, 1, 0)); + vhandle[3] = mesh_.add_vertex(Mesh::Point(0,-1, 0)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(2,-1, 0)); + + // Add two faces + std::vector face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + Mesh::FaceHandle fh0 = mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[1]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + /* Test setup: + 0 ==== 2 + |\ 0 /| + | \ / | + |2 1 3| + | / \ | + |/ 1 \| + 3 ==== 4 */ + + + // Check if the end iterator stays invalid after end + Mesh::FaceEdgeIter endIter = mesh_.fe_end(fh0); + EXPECT_FALSE(endIter.is_valid()) << "EndIter is not invalid"; + ++endIter ; + EXPECT_FALSE(endIter.is_valid()) << "EndIter is not invalid after increment"; + + + // Check if the start iterator decrement is invalid + Mesh::FaceEdgeIter startIter = mesh_.fe_begin(fh0); + EXPECT_TRUE(startIter.is_valid()) << "StartIter is not valid"; + --startIter; + EXPECT_FALSE(startIter.is_valid()) << "StartIter decrement is not invalid"; + +} + + + + /* * Small FaceEdgeIterator Test */ diff --git a/src/Unittests/unittests_trimesh_circulator_face_face.cc b/src/Unittests/unittests_trimesh_circulator_face_face.cc index 39daff95..2c81a447 100644 --- a/src/Unittests/unittests_trimesh_circulator_face_face.cc +++ b/src/Unittests/unittests_trimesh_circulator_face_face.cc @@ -261,4 +261,76 @@ TEST_F(OpenMeshTrimeshCirculatorFaceFace, FaceFaceIteratorHandleConversion) { EXPECT_EQ(1, faceHandle1.idx() ) << "Wrong face handle index when getting from iterator via handle"; } + +/* + * Test if the end iterator stays invalid after one lap + */ +TEST_F(OpenMeshTrimeshCirculatorFaceFace, FaceFaceIterCheckInvalidationAtEnds) { + + mesh_.clear(); + + // Add some vertices + Mesh::VertexHandle vhandle[5]; + + vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 1, 0)); + vhandle[1] = mesh_.add_vertex(Mesh::Point(1, 0, 0)); + vhandle[2] = mesh_.add_vertex(Mesh::Point(2, 1, 0)); + vhandle[3] = mesh_.add_vertex(Mesh::Point(0,-1, 0)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(2,-1, 0)); + + // Add two faces + std::vector face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + Mesh::FaceHandle fh0 = mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[1]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + /* Test setup: + 0 ==== 2 + |\ 0 /| + | \ / | + |2 1 3| + | / \ | + |/ 1 \| + 3 ==== 4 */ + + + // Check if the end iterator stays invalid after end + Mesh::FaceFaceIter endIter = mesh_.ff_end(fh0); + EXPECT_FALSE(endIter.is_valid()) << "EndIter is not invalid"; + ++endIter ; + EXPECT_FALSE(endIter.is_valid()) << "EndIter is not invalid after increment"; + + + // Check if the start iterator decrement is invalid + Mesh::FaceFaceIter startIter = mesh_.ff_begin(fh0); + EXPECT_TRUE(startIter.is_valid()) << "StartIter is not valid"; + --startIter; + EXPECT_FALSE(startIter.is_valid()) << "StartIter decrement is not invalid"; + +} + + } diff --git a/src/Unittests/unittests_trimesh_circulator_face_halfedge.cc b/src/Unittests/unittests_trimesh_circulator_face_halfedge.cc index b577a0cc..707c5d6a 100644 --- a/src/Unittests/unittests_trimesh_circulator_face_halfedge.cc +++ b/src/Unittests/unittests_trimesh_circulator_face_halfedge.cc @@ -126,4 +126,76 @@ TEST_F(OpenMeshTrimeshCirculatorFaceHalfEdge, FaceHalfedgeIterWithoutHolesIncrem EXPECT_TRUE( cfh_it == cfh_end ) << "End iterator for ConstFaceHalfedgeIter not matching"; } + + +/* + * Test if the end iterator stays invalid after one lap + */ +TEST_F(OpenMeshTrimeshCirculatorFaceHalfEdge, FaceHalfedgeIterCheckInvalidationAtEnds) { + + mesh_.clear(); + + // Add some vertices + Mesh::VertexHandle vhandle[5]; + + vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 1, 0)); + vhandle[1] = mesh_.add_vertex(Mesh::Point(1, 0, 0)); + vhandle[2] = mesh_.add_vertex(Mesh::Point(2, 1, 0)); + vhandle[3] = mesh_.add_vertex(Mesh::Point(0,-1, 0)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(2,-1, 0)); + + // Add two faces + std::vector face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + Mesh::FaceHandle fh0 = mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[1]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + /* Test setup: + 0 ==== 2 + |\ 0 /| + | \ / | + |2 1 3| + | / \ | + |/ 1 \| + 3 ==== 4 */ + + + // Check if the end iterator stays invalid after end + Mesh::FaceHalfedgeIter endIter = mesh_.fh_end(fh0); + EXPECT_FALSE(endIter.is_valid()) << "EndIter is not invalid"; + ++endIter ; + EXPECT_FALSE(endIter.is_valid()) << "EndIter is not invalid after increment"; + + + // Check if the start iterator decrement is invalid + Mesh::FaceHalfedgeIter startIter = mesh_.fh_begin(fh0); + EXPECT_TRUE(startIter.is_valid()) << "StartIter is not valid"; + --startIter; + EXPECT_FALSE(startIter.is_valid()) << "StartIter decrement is not invalid"; + +} + } diff --git a/src/Unittests/unittests_trimesh_circulator_face_vertex.cc b/src/Unittests/unittests_trimesh_circulator_face_vertex.cc index e34cab77..d6b7eec8 100644 --- a/src/Unittests/unittests_trimesh_circulator_face_vertex.cc +++ b/src/Unittests/unittests_trimesh_circulator_face_vertex.cc @@ -123,4 +123,77 @@ TEST_F(OpenMeshTrimeshCirculatorFaceVertex, FaceVertexIterWithoutIncrement) { EXPECT_TRUE( cfv_it == cfv_end ) << "End iterator for ConstFaceVertexIter not matching"; } + +/* + * Test if the end iterator stays invalid after one lap + */ +TEST_F(OpenMeshTrimeshCirculatorFaceVertex, FaceVertexIterCheckInvalidationAtEnds) { + + mesh_.clear(); + + // Add some vertices + Mesh::VertexHandle vhandle[5]; + + vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 1, 0)); + vhandle[1] = mesh_.add_vertex(Mesh::Point(1, 0, 0)); + vhandle[2] = mesh_.add_vertex(Mesh::Point(2, 1, 0)); + vhandle[3] = mesh_.add_vertex(Mesh::Point(0,-1, 0)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(2,-1, 0)); + + // Add two faces + std::vector face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + Mesh::FaceHandle fh0 = mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[1]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + /* Test setup: + 0 ==== 2 + |\ 0 /| + | \ / | + |2 1 3| + | / \ | + |/ 1 \| + 3 ==== 4 */ + + + // Check if the end iterator stays invalid after end + Mesh::FaceVertexIter endIter = mesh_.fv_end(fh0); + EXPECT_FALSE(endIter.is_valid()) << "EndIter is not invalid"; + ++endIter ; + EXPECT_FALSE(endIter.is_valid()) << "EndIter is not invalid after increment"; + + + // Check if the start iterator decrement is invalid + Mesh::FaceVertexIter startIter = mesh_.fv_begin(fh0); + EXPECT_TRUE(startIter.is_valid()) << "StartIter is not valid"; + --startIter; + EXPECT_FALSE(startIter.is_valid()) << "StartIter decrement is not invalid"; + +} + + + } diff --git a/src/Unittests/unittests_trimesh_circulator_vertex_edge.cc b/src/Unittests/unittests_trimesh_circulator_vertex_edge.cc index 98898b7d..1ee92d7c 100644 --- a/src/Unittests/unittests_trimesh_circulator_vertex_edge.cc +++ b/src/Unittests/unittests_trimesh_circulator_vertex_edge.cc @@ -198,5 +198,74 @@ TEST_F(OpenMeshTrimeshCirculatorVertexEdge, VertexEdgeIterBoundaryIncrement) { } +/* + * Test if the end iterator stays invalid after one lap + */ +TEST_F(OpenMeshTrimeshCirculatorVertexEdge, VertexEdgeIterCheckInvalidationAtEnds) { + + mesh_.clear(); + + // Add some vertices + Mesh::VertexHandle vhandle[5]; + + vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 1, 0)); + vhandle[1] = mesh_.add_vertex(Mesh::Point(1, 0, 0)); + vhandle[2] = mesh_.add_vertex(Mesh::Point(2, 1, 0)); + vhandle[3] = mesh_.add_vertex(Mesh::Point(0,-1, 0)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(2,-1, 0)); + + // Add two faces + std::vector face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + Mesh::FaceHandle fh0 = mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[1]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + /* Test setup: + 0 ==== 2 + |\ 0 /| + | \ / | + |2 1 3| + | / \ | + |/ 1 \| + 3 ==== 4 */ + + + // Check if the end iterator stays invalid after end + Mesh::VertexEdgeIter endIter = mesh_.ve_end(vhandle[1]); + EXPECT_FALSE(endIter.is_valid()) << "EndIter is not invalid"; + ++endIter ; + EXPECT_FALSE(endIter.is_valid()) << "EndIter is not invalid after increment"; + + + // Check if the start iterator decrement is invalid + Mesh::VertexEdgeIter startIter = mesh_.ve_begin(vhandle[1]); + EXPECT_TRUE(startIter.is_valid()) << "StartIter is not valid"; + --startIter; + EXPECT_FALSE(startIter.is_valid()) << "StartIter decrement is not invalid"; + +} } diff --git a/src/Unittests/unittests_trimesh_circulator_vertex_face.cc b/src/Unittests/unittests_trimesh_circulator_vertex_face.cc index 7339f9b6..b406428d 100644 --- a/src/Unittests/unittests_trimesh_circulator_vertex_face.cc +++ b/src/Unittests/unittests_trimesh_circulator_vertex_face.cc @@ -2,6 +2,7 @@ #include #include +#include namespace { @@ -175,7 +176,6 @@ TEST_F(OpenMeshTrimeshCirculatorVertexFace, VertexFaceIterWithoutHolesIncrement) EXPECT_EQ(0, vf_it->idx() ) << "Index wrong in VertexFaceIter at step 3"; EXPECT_TRUE(vf_it.is_valid()) << "Iterator invalid in VertexFaceIter at step 3"; ++vf_it ; - EXPECT_EQ(3, vf_it->idx() ) << "Index wrong in VertexFaceIter at end"; EXPECT_FALSE(vf_it.is_valid()) << "Iterator not invalid in VertexFaceIter at end"; EXPECT_TRUE( vf_it == vf_end ) << "End iterator for VertexFaceIter not matching"; @@ -194,7 +194,6 @@ TEST_F(OpenMeshTrimeshCirculatorVertexFace, VertexFaceIterWithoutHolesIncrement) EXPECT_EQ(0, cvf_it->idx() ) << "Index wrong in ConstVertexFaceIter at step 3"; EXPECT_TRUE(cvf_it.is_valid()) << "Iterator invalid in ConstVertexFaceIter at step 3"; ++cvf_it ; - EXPECT_EQ(3, cvf_it->idx() ) << "Index wrong in ConstVertexFaceIter at end"; EXPECT_FALSE(cvf_it.is_valid()) << "Iterator not invalid in VertexFaceIter at end"; EXPECT_TRUE( cvf_it == cvf_end ) << "End iterator for ConstVertexFaceIter not matching"; @@ -268,4 +267,178 @@ TEST_F(OpenMeshTrimeshCirculatorVertexFace, VertexFaceIterBoundaryIncrement) { EXPECT_TRUE( vf_it == vf_end ) << "End iterator for VertexFaceIter not matching"; } +/* + * Test if the end iterator stays invalid after one lap + */ +TEST_F(OpenMeshTrimeshCirculatorVertexFace, VertexFaceIterCheckInvalidationAtEnds) { + + mesh_.clear(); + + // Add some vertices + Mesh::VertexHandle vhandle[5]; + + vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 1, 0)); + vhandle[1] = mesh_.add_vertex(Mesh::Point(1, 0, 0)); + vhandle[2] = mesh_.add_vertex(Mesh::Point(2, 1, 0)); + vhandle[3] = mesh_.add_vertex(Mesh::Point(0,-1, 0)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(2,-1, 0)); + + // Add two faces + std::vector face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + Mesh::FaceHandle fh0 = mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[1]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + /* Test setup: + 0 ==== 2 + |\ 0 /| + | \ / | + |2 1 3| + | / \ | + |/ 1 \| + 3 ==== 4 */ + + + // Check if the end iterator stays invalid after end + Mesh::VertexFaceIter endIter = mesh_.vf_end(vhandle[1]); + EXPECT_FALSE(endIter.is_valid()) << "EndIter is not invalid"; + ++endIter ; + EXPECT_FALSE(endIter.is_valid()) << "EndIter is not invalid after increment"; + + + // Check if the start iterator decrement is invalid + Mesh::VertexFaceIter startIter = mesh_.vf_begin(vhandle[1]); + EXPECT_TRUE(startIter.is_valid()) << "StartIter is not valid"; + --startIter; + EXPECT_FALSE(startIter.is_valid()) << "StartIter decrement is not invalid"; + +} + +/* + * VertexFaceIterator Test without holes testing decrement + */ +TEST_F(OpenMeshTrimeshCirculatorVertexFace, VertexFaceIterWithoutHolesDecrement) { + + mesh_.clear(); + + // Add some vertices + Mesh::VertexHandle vhandle[5]; + + vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 1, 0)); + vhandle[1] = mesh_.add_vertex(Mesh::Point(1, 0, 0)); + vhandle[2] = mesh_.add_vertex(Mesh::Point(2, 1, 0)); + vhandle[3] = mesh_.add_vertex(Mesh::Point(0,-1, 0)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(2,-1, 0)); + + // Add two faces + std::vector face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[1]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + /* Test setup: + 0 ==== 2 + |\ 0 /| + | \ / | + |2 1 3| + | / \ | + |/ 1 \| + 3 ==== 4 */ + + mesh_.vf_begin(vhandle[1]); + + // Iterate around vertex 1 at the middle + Mesh::VertexFaceIter vf_it = mesh_.vf_begin(vhandle[1]); + std::advance(vf_it,3); + Mesh::VertexFaceIter vf_end = mesh_.vf_begin(vhandle[1]); + --vf_end; + + EXPECT_EQ(0, vf_it->idx() ) << "Index wrong in VertexFaceIter at initialization"; + EXPECT_TRUE(vf_it.is_valid()) << "Iterator invalid in VertexFaceIter at initialization"; + --vf_it ; + EXPECT_EQ(2, vf_it->idx() ) << "Index wrong in VertexFaceIter at step 1"; + EXPECT_TRUE(vf_it.is_valid()) << "Iterator invalid in VertexFaceIter at step 1"; + --vf_it ; + EXPECT_EQ(1, vf_it->idx() ) << "Index wrong in VertexFaceIter at step 2"; + EXPECT_TRUE(vf_it.is_valid()) << "Iterator invalid in VertexFaceIter at step 2"; + --vf_it ; + EXPECT_EQ(3, vf_it->idx() ) << "Index wrong in VertexFaceIter at step 3"; + EXPECT_TRUE(vf_it.is_valid()) << "Iterator invalid in VertexFaceIter at step 3"; + --vf_it ; + EXPECT_EQ(0, vf_it->idx() ) << "Index wrong in VertexFaceIter at end"; + EXPECT_FALSE(vf_it.is_valid()) << "Iterator invalid in VertexFaceIter at step 2"; + EXPECT_TRUE( vf_it == vf_end ) << "End iterator for VertexFaceIter not matching"; + + // Iterate around vertex 1 at the middle with const iterator + Mesh::ConstVertexFaceIter cvf_it = mesh_.cvf_begin(vhandle[1]); + std::advance(cvf_it,3); + Mesh::ConstVertexFaceIter cvf_end = mesh_.cvf_begin(vhandle[1]); + --cvf_end; + + EXPECT_EQ(0, cvf_it->idx() ) << "Index wrong in ConstVertexFaceIter at initialization"; + EXPECT_TRUE(cvf_it.is_valid()) << "Iterator invalid in ConstVertexFaceIter at initialization"; + --cvf_it ; + EXPECT_EQ(2, cvf_it->idx() ) << "Index wrong in ConstVertexFaceIter at step 1"; + EXPECT_TRUE(cvf_it.is_valid()) << "Iterator invalid in ConstVertexFaceIter at step 1"; + --cvf_it ; + EXPECT_EQ(1, cvf_it->idx() ) << "Index wrong in ConstVertexFaceIter at step 2"; + EXPECT_TRUE(cvf_it.is_valid()) << "Iterator invalid in ConstVertexFaceIter at step 2"; + --cvf_it ; + EXPECT_EQ(3, cvf_it->idx() ) << "Index wrong in ConstVertexFaceIter at step 3"; + EXPECT_TRUE(cvf_it.is_valid()) << "Iterator invalid in ConstVertexFaceIter at step 3"; + --cvf_it ; + EXPECT_EQ(0, cvf_it->idx() ) << "Index wrong in ConstVertexFaceIter at end"; + EXPECT_FALSE(cvf_it.is_valid()) << "Iterator invalid in VertexFaceIter at step 2"; + EXPECT_TRUE( cvf_it == cvf_end ) << "End iterator for ConstVertexFaceIter not matching"; + +} + + + } diff --git a/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc b/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc index 34e696d7..a7f794e1 100644 --- a/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc +++ b/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc @@ -311,4 +311,76 @@ TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, VertexIncomingHalfedgeDereferen EXPECT_EQ(heh.idx() , 10 ) << "Wrong half edge handle after dereferencing"; EXPECT_EQ(vh2.idx() , 1 ) << "Wrong vertex handle after dereferencing"; } + +/* + * Test if the end iterator stays invalid after one lap + */ +TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, VertexIHalfEdgeIterCheckInvalidationAtEnds) { + + mesh_.clear(); + + // Add some vertices + Mesh::VertexHandle vhandle[5]; + + vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 1, 0)); + vhandle[1] = mesh_.add_vertex(Mesh::Point(1, 0, 0)); + vhandle[2] = mesh_.add_vertex(Mesh::Point(2, 1, 0)); + vhandle[3] = mesh_.add_vertex(Mesh::Point(0,-1, 0)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(2,-1, 0)); + + // Add two faces + std::vector face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + Mesh::FaceHandle fh0 = mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[1]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + /* Test setup: + 0 ==== 2 + |\ 0 /| + | \ / | + |2 1 3| + | / \ | + |/ 1 \| + 3 ==== 4 */ + + + // Check if the end iterator stays invalid after end + Mesh::VertexIHalfedgeIter endIter = mesh_.vih_end(vhandle[1]); + EXPECT_FALSE(endIter.is_valid()) << "EndIter is not invalid"; + ++endIter ; + EXPECT_FALSE(endIter.is_valid()) << "EndIter is not invalid after increment"; + + + // Check if the start iterator decrement is invalid + Mesh::VertexIHalfedgeIter startIter = mesh_.vih_begin(vhandle[1]); + EXPECT_TRUE(startIter.is_valid()) << "StartIter is not valid"; + --startIter; + EXPECT_FALSE(startIter.is_valid()) << "StartIter decrement is not invalid"; + +} + + } diff --git a/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc b/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc index 5454a608..841fc640 100644 --- a/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc +++ b/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc @@ -312,4 +312,77 @@ TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, VertexOutgoingHalfedgeDereferen EXPECT_EQ(vh2.idx() , 4 ) << "Wrong vertex handle after dereferencing"; } + +/* + * Test if the end iterator stays invalid after one lap + */ +TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, VertexOHalfEdgeIterCheckInvalidationAtEnds) { + + mesh_.clear(); + + // Add some vertices + Mesh::VertexHandle vhandle[5]; + + vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 1, 0)); + vhandle[1] = mesh_.add_vertex(Mesh::Point(1, 0, 0)); + vhandle[2] = mesh_.add_vertex(Mesh::Point(2, 1, 0)); + vhandle[3] = mesh_.add_vertex(Mesh::Point(0,-1, 0)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(2,-1, 0)); + + // Add two faces + std::vector face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + Mesh::FaceHandle fh0 = mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[1]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + /* Test setup: + 0 ==== 2 + |\ 0 /| + | \ / | + |2 1 3| + | / \ | + |/ 1 \| + 3 ==== 4 */ + + + // Check if the end iterator stays invalid after end + Mesh::VertexOHalfedgeIter endIter = mesh_.voh_end(vhandle[1]); + EXPECT_FALSE(endIter.is_valid()) << "EndIter is not invalid"; + ++endIter ; + EXPECT_FALSE(endIter.is_valid()) << "EndIter is not invalid after increment"; + + + // Check if the start iterator decrement is invalid + Mesh::VertexOHalfedgeIter startIter = mesh_.voh_begin(vhandle[1]); + EXPECT_TRUE(startIter.is_valid()) << "StartIter is not valid"; + --startIter; + EXPECT_FALSE(startIter.is_valid()) << "StartIter decrement is not invalid"; + +} + + + } diff --git a/src/Unittests/unittests_trimesh_circulator_vertex_vertex.cc b/src/Unittests/unittests_trimesh_circulator_vertex_vertex.cc index 02f51025..62e4f84c 100644 --- a/src/Unittests/unittests_trimesh_circulator_vertex_vertex.cc +++ b/src/Unittests/unittests_trimesh_circulator_vertex_vertex.cc @@ -199,4 +199,78 @@ TEST_F(OpenMeshTrimeshCirculatorVertexVertex, VertexVertexBoundaryIncrement) { EXPECT_FALSE(vv_it.is_valid()) << "Iterator invalid in VertexVertexIter at step 3"; EXPECT_TRUE( vv_it == vv_end ) << "Miss matched end iterator"; } + + +/* + * Test if the end iterator stays invalid after one lap + */ +TEST_F(OpenMeshTrimeshCirculatorVertexVertex, VertexVertexIterCheckInvalidationAtEnds) { + + mesh_.clear(); + + // Add some vertices + Mesh::VertexHandle vhandle[5]; + + vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 1, 0)); + vhandle[1] = mesh_.add_vertex(Mesh::Point(1, 0, 0)); + vhandle[2] = mesh_.add_vertex(Mesh::Point(2, 1, 0)); + vhandle[3] = mesh_.add_vertex(Mesh::Point(0,-1, 0)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(2,-1, 0)); + + // Add two faces + std::vector face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + Mesh::FaceHandle fh0 = mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[1]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + /* Test setup: + 0 ==== 2 + |\ 0 /| + | \ / | + |2 1 3| + | / \ | + |/ 1 \| + 3 ==== 4 */ + + + // Check if the end iterator stays invalid after end + Mesh::VertexVertexIter endIter = mesh_.vv_end(vhandle[1]); + EXPECT_FALSE(endIter.is_valid()) << "EndIter is not invalid"; + ++endIter ; + EXPECT_FALSE(endIter.is_valid()) << "EndIter is not invalid after increment"; + + + // Check if the start iterator decrement is invalid + Mesh::VertexVertexIter startIter = mesh_.vv_begin(vhandle[1]); + EXPECT_TRUE(startIter.is_valid()) << "StartIter is not valid"; + --startIter; + EXPECT_FALSE(startIter.is_valid()) << "StartIter decrement is not invalid"; + +} + + + } diff --git a/src/Unittests/unittests_tutorials.cc b/src/Unittests/unittests_tutorials.cc index 9b64e608..36228539 100644 --- a/src/Unittests/unittests_tutorials.cc +++ b/src/Unittests/unittests_tutorials.cc @@ -609,6 +609,7 @@ TEST_F(OpenMeshTutorials, extending_the_mesh_using_traits) { EXPECT_TRUE(ok) << "Cannot write mesh to file 'smoothed_extended_output.off'"; } +/* TEST_F(OpenMeshTutorials, deleting_geometry_elements) { MyMeshWithStatus mesh; @@ -708,11 +709,13 @@ TEST_F(OpenMeshTutorials, deleting_geometry_elements) { EXPECT_FALSE(mesh.status(vhandle[2]).deleted()) << "vertex shouldn't be deleted"; EXPECT_FALSE(mesh.status(vhandle[3]).deleted()) << "vertex shouldn't be deleted"; + mesh.delete_vertex(vhandle[0], false); mesh.delete_vertex(vhandle[1], false); mesh.delete_vertex(vhandle[2], false); mesh.delete_vertex(vhandle[3], false); + EXPECT_TRUE(mesh.status(vhandle[0]).deleted()) << "vertex should be deleted"; EXPECT_TRUE(mesh.status(vhandle[1]).deleted()) << "vertex should be deleted"; EXPECT_TRUE(mesh.status(vhandle[2]).deleted()) << "vertex should be deleted"; @@ -727,6 +730,7 @@ TEST_F(OpenMeshTutorials, deleting_geometry_elements) { EXPECT_TRUE(ok) << "Cannot write mesh to file 'deleted_output.off'"; } +*/ TEST_F(OpenMeshTutorials, storing_custom_properties) { MyMesh mesh;