From fd5e4ef9e33ba43aa6f63af04ec4ce977148f7b0 Mon Sep 17 00:00:00 2001 From: Jan Date: Wed, 17 Feb 2021 17:54:15 +0100 Subject: [PATCH 1/9] Only trigger python build for master --- .gitlab-ci.yml | 2 ++ CI/gitlab-ci/ci-master.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8147cf6c..40a690ff 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -854,6 +854,8 @@ Sources: trigger_openmesh-python-rebuild: stage: deploy + only: + - master script: - "curl -X POST -F token=b63ed804ada51d7d1ffe5d6ea0dfa2 -F ref=track-OM-master https://www.graphics.rwth-aachen.de:9000/api/v4/projects/1024/trigger/pipeline" diff --git a/CI/gitlab-ci/ci-master.yml b/CI/gitlab-ci/ci-master.yml index 7db5134e..ba9fd179 100644 --- a/CI/gitlab-ci/ci-master.yml +++ b/CI/gitlab-ci/ci-master.yml @@ -37,6 +37,8 @@ Sources: trigger_openmesh-python-rebuild: stage: deploy + only: + - master script: - "curl -X POST -F token=b63ed804ada51d7d1ffe5d6ea0dfa2 -F ref=track-OM-master https://www.graphics.rwth-aachen.de:9000/api/v4/projects/1024/trigger/pipeline" From b3821e6289903266fd9c4aea3b2546b5a10d6ad9 Mon Sep 17 00:00:00 2001 From: Max Lyon Date: Tue, 9 Mar 2021 09:03:55 +0100 Subject: [PATCH 2/9] allow custom start for vih_range and voh_range --- src/OpenMesh/Core/Mesh/CirculatorsT.hh | 17 +++++++++--- src/OpenMesh/Core/Mesh/PolyConnectivity.hh | 20 ++++++++++++-- .../Core/Mesh/PolyConnectivity_inline_impl.hh | 27 ++++++++++++++++--- 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/OpenMesh/Core/Mesh/CirculatorsT.hh b/src/OpenMesh/Core/Mesh/CirculatorsT.hh index c9c537d3..e3aaa6e1 100644 --- a/src/OpenMesh/Core/Mesh/CirculatorsT.hh +++ b/src/OpenMesh/Core/Mesh/CirculatorsT.hh @@ -60,6 +60,9 @@ //== NAMESPACES =============================================================== namespace OpenMesh { + +template class CirculatorRange; + namespace Iterators { template @@ -192,6 +195,8 @@ class GenericCirculatorBaseT { typedef const Mesh* mesh_ptr; typedef const Mesh& mesh_ref; + template friend class OpenMesh::CirculatorRange; + public: GenericCirculatorBaseT() : mesh_(0), lap_counter_(0) {} @@ -267,16 +272,18 @@ class GenericCirculatorT : protected GenericCirculatorBaseT::mesh_ref mesh_ref; typedef GenericCirculator_ValueHandleFnsT GenericCirculator_ValueHandleFns; + template friend class OpenMesh::CirculatorRange; + public: GenericCirculatorT() {} GenericCirculatorT(mesh_ref mesh, CenterEntityHandle start, bool end = false) : - GenericCirculatorBaseT(mesh, mesh.halfedge_handle(start), end) { - + GenericCirculatorBaseT(mesh, mesh.halfedge_handle(start), end) + { GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_); } GenericCirculatorT(mesh_ref mesh, typename Mesh::HalfedgeHandle heh, bool end = false) : - GenericCirculatorBaseT(mesh, heh, end) { - + GenericCirculatorBaseT(mesh, heh, end) + { GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_); } GenericCirculatorT(const GenericCirculatorT &rhs) : GenericCirculatorBaseT(rhs) {} @@ -440,6 +447,8 @@ class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT::mesh_ref mesh_ref; typedef GenericCirculator_ValueHandleFnsT_DEPRECATED GenericCirculator_ValueHandleFns; + template friend class OpenMesh::CirculatorRange; + public: GenericCirculatorT_DEPRECATED() {} GenericCirculatorT_DEPRECATED(mesh_ref mesh, CenterEntityHandle start, bool end = false) : diff --git a/src/OpenMesh/Core/Mesh/PolyConnectivity.hh b/src/OpenMesh/Core/Mesh/PolyConnectivity.hh index dcacd197..62887446 100644 --- a/src/OpenMesh/Core/Mesh/PolyConnectivity.hh +++ b/src/OpenMesh/Core/Mesh/PolyConnectivity.hh @@ -98,8 +98,10 @@ struct CirculatorRangeTraitT using ITER_TYPE = ITER_T; using CENTER_ENTITY_TYPE = CENTER_ENTITY_T; using TO_ENTITYE_TYPE = TO_ENTITY_T; - static ITER_TYPE begin(const CONTAINER_TYPE& _container, CENTER_ENTITY_TYPE _ce) { return (_container.*begin_fn)(_ce); } - static ITER_TYPE end(const CONTAINER_TYPE& _container, CENTER_ENTITY_TYPE _ce) { return (_container.*end_fn)(_ce); } + static ITER_TYPE begin(const CONTAINER_TYPE& _container, CENTER_ENTITY_TYPE _ce) { return (_container.*begin_fn)(_ce); } + static ITER_TYPE begin(const CONTAINER_TYPE& _container, HalfedgeHandle _heh, int) { return ITER_TYPE(_container, _heh); } + static ITER_TYPE end(const CONTAINER_TYPE& _container, CENTER_ENTITY_TYPE _ce) { return (_container.*end_fn)(_ce); } + static ITER_TYPE end(const CONTAINER_TYPE& _container, HalfedgeHandle _heh, int) { return ITER_TYPE(_container, _heh, true); } }; struct SmartVertexHandle; @@ -1250,12 +1252,26 @@ public: */ ConstVertexIHalfedgeRange vih_range(VertexHandle _vh) const; + /** + * @return The incoming halfedges incident to the specified vertex + * as a range object suitable for C++11 range based for loops. + * Like vih_range(VertexHandle _heh.to()) but starts iteration at _heh + */ + ConstVertexIHalfedgeRange vih_range(HalfedgeHandle _heh) const; + /** * @return The outgoing halfedges incident to the specified vertex * as a range object suitable for C++11 range based for loops. */ ConstVertexOHalfedgeRange voh_range(VertexHandle _vh) const; + /** + * @return The outgoing halfedges incident to the specified vertex + * as a range object suitable for C++11 range based for loops. + * Like voh_range(VertexHandle _heh.from()) but starts iteration at _heh + */ + ConstVertexOHalfedgeRange voh_range(HalfedgeHandle _heh) const; + /** * @return The edges incident to the specified vertex * as a range object suitable for C++11 range based for loops. diff --git a/src/OpenMesh/Core/Mesh/PolyConnectivity_inline_impl.hh b/src/OpenMesh/Core/Mesh/PolyConnectivity_inline_impl.hh index c813faa2..f9292941 100644 --- a/src/OpenMesh/Core/Mesh/PolyConnectivity_inline_impl.hh +++ b/src/OpenMesh/Core/Mesh/PolyConnectivity_inline_impl.hh @@ -43,6 +43,7 @@ #error Do not include this directly, include instead PolyConnectivity.hh #endif // OPENMESH_POLYCONNECTIVITY_INTERFACE_INCLUDE +#include // To help some IDEs #include #include @@ -99,13 +100,23 @@ class CirculatorRange : public SmartRangeT Date: Tue, 9 Mar 2021 09:04:25 +0100 Subject: [PATCH 3/9] add cw and ccw version for ranges --- src/OpenMesh/Core/Mesh/PolyConnectivity.hh | 252 +++++++++++++----- .../Core/Mesh/PolyConnectivity_inline_impl.hh | 98 +++++++ 2 files changed, 280 insertions(+), 70 deletions(-) diff --git a/src/OpenMesh/Core/Mesh/PolyConnectivity.hh b/src/OpenMesh/Core/Mesh/PolyConnectivity.hh index 62887446..c71033fe 100644 --- a/src/OpenMesh/Core/Mesh/PolyConnectivity.hh +++ b/src/OpenMesh/Core/Mesh/PolyConnectivity.hh @@ -1169,76 +1169,38 @@ public: typename ElementRange::Range all_elements() const; - typedef CirculatorRange> ConstVertexVertexRange; - typedef CirculatorRange> ConstVertexIHalfedgeRange; - typedef CirculatorRange> ConstVertexOHalfedgeRange; - typedef CirculatorRange> ConstVertexEdgeRange; - typedef CirculatorRange> ConstVertexFaceRange; - typedef CirculatorRange> ConstFaceVertexRange; - typedef CirculatorRange> ConstFaceHalfedgeRange; - typedef CirculatorRange> ConstFaceEdgeRange; - typedef CirculatorRange> ConstFaceFaceRange; - typedef CirculatorRange> ConstHalfedgeLoopRange; + typedef CirculatorRange> ConstVertexVertexRange; + typedef CirculatorRange> ConstVertexIHalfedgeRange; + typedef CirculatorRange> ConstVertexOHalfedgeRange; + typedef CirculatorRange> ConstVertexEdgeRange; + typedef CirculatorRange> ConstVertexFaceRange; + typedef CirculatorRange> ConstFaceVertexRange; + typedef CirculatorRange> ConstFaceHalfedgeRange; + typedef CirculatorRange> ConstFaceEdgeRange; + typedef CirculatorRange> ConstFaceFaceRange; + typedef CirculatorRange> ConstHalfedgeLoopRange; + + typedef CirculatorRange> ConstVertexVertexCWRange; + typedef CirculatorRange> ConstVertexIHalfedgeCWRange; + typedef CirculatorRange> ConstVertexOHalfedgeCWRange; + typedef CirculatorRange> ConstVertexEdgeCWRange; + typedef CirculatorRange> ConstVertexFaceCWRange; + typedef CirculatorRange> ConstFaceVertexCWRange; + typedef CirculatorRange> ConstFaceHalfedgeCWRange; + typedef CirculatorRange> ConstFaceEdgeCWRange; + typedef CirculatorRange> ConstFaceFaceCWRange; + typedef CirculatorRange> ConstHalfedgeLoopCWRange; + + typedef CirculatorRange> ConstVertexVertexCCWRange; + typedef CirculatorRange> ConstVertexIHalfedgeCCWRange; + typedef CirculatorRange> ConstVertexOHalfedgeCCWRange; + typedef CirculatorRange> ConstVertexEdgeCCWRange; + typedef CirculatorRange> ConstVertexFaceCCWRange; + typedef CirculatorRange> ConstFaceVertexCCWRange; + typedef CirculatorRange> ConstFaceHalfedgeCCWRange; + typedef CirculatorRange> ConstFaceEdgeCCWRange; + typedef CirculatorRange> ConstFaceFaceCCWRange; + typedef CirculatorRange> ConstHalfedgeLoopCCWRange; /** * @return The vertices adjacent to the specified vertex @@ -1314,6 +1276,156 @@ public: */ ConstHalfedgeLoopRange hl_range(HalfedgeHandle _heh) const; + + /** + * @return The vertices adjacent to the specified vertex + * as a range object suitable for C++11 range based for loops. + */ + ConstVertexVertexCWRange vv_cw_range(VertexHandle _vh) const; + + /** + * @return The incoming halfedges incident to the specified vertex + * as a range object suitable for C++11 range based for loops. + */ + ConstVertexIHalfedgeCWRange vih_cw_range(VertexHandle _vh) const; + + /** + * @return The incoming halfedges incident to the specified vertex + * as a range object suitable for C++11 range based for loops. + * Like vih_cw_range(VertexHandle _heh.to()) but starts iteration at _heh + */ + ConstVertexIHalfedgeCWRange vih_cw_range(HalfedgeHandle _heh) const; + + /** + * @return The outgoing halfedges incident to the specified vertex + * as a range object suitable for C++11 range based for loops. + */ + ConstVertexOHalfedgeCWRange voh_cw_range(VertexHandle _vh) const; + + /** + * @return The outgoing halfedges incident to the specified vertex + * as a range object suitable for C++11 range based for loops. + * Like voh_cw_range(VertexHandle _heh.from()) but starts iteration at _heh + */ + ConstVertexOHalfedgeCWRange voh_cw_range(HalfedgeHandle _heh) const; + + /** + * @return The edges incident to the specified vertex + * as a range object suitable for C++11 range based for loops. + */ + ConstVertexEdgeCWRange ve_cw_range(VertexHandle _vh) const ; + + /** + * @return The faces incident to the specified vertex + * as a range object suitable for C++11 range based for loops. + */ + ConstVertexFaceCWRange vf_cw_range(VertexHandle _vh) const; + + /** + * @return The vertices incident to the specified face + * as a range object suitable for C++11 range based for loops. + */ + ConstFaceVertexCWRange fv_cw_range(FaceHandle _fh) const; + + /** + * @return The halfedges incident to the specified face + * as a range object suitable for C++11 range based for loops. + */ + ConstFaceHalfedgeCWRange fh_cw_range(FaceHandle _fh) const; + + /** + * @return The edges incident to the specified face + * as a range object suitable for C++11 range based for loops. + */ + ConstFaceEdgeCWRange fe_cw_range(FaceHandle _fh) const; + + /** + * @return The faces adjacent to the specified face + * as a range object suitable for C++11 range based for loops. + */ + ConstFaceFaceCWRange ff_cw_range(FaceHandle _fh) const; + + /** + * @return The halfedges in the face + * as a range object suitable for C++11 range based for loops. + */ + ConstHalfedgeLoopCWRange hl_cw_range(HalfedgeHandle _heh) const; + + + /** + * @return The vertices adjacent to the specified vertex + * as a range object suitable for C++11 range based for loops. + */ + ConstVertexVertexCCWRange vv_ccw_range(VertexHandle _vh) const; + + /** + * @return The incoming halfedges incident to the specified vertex + * as a range object suitable for C++11 range based for loops. + */ + ConstVertexIHalfedgeCCWRange vih_ccw_range(VertexHandle _vh) const; + + /** + * @return The incoming halfedges incident to the specified vertex + * as a range object suitable for C++11 range based for loops. + * Like vih_ccw_range(VertexHandle _heh.to()) but starts iteration at _heh + */ + ConstVertexIHalfedgeCCWRange vih_ccw_range(HalfedgeHandle _heh) const; + + /** + * @return The outgoing halfedges incident to the specified vertex + * as a range object suitable for C++11 range based for loops. + */ + ConstVertexOHalfedgeCCWRange voh_ccw_range(VertexHandle _vh) const; + + /** + * @return The outgoing halfedges incident to the specified vertex + * as a range object suitable for C++11 range based for loops. + * Like voh_ccw_range(VertexHandle _heh.from()) but starts iteration at _heh + */ + ConstVertexOHalfedgeCCWRange voh_ccw_range(HalfedgeHandle _heh) const; + + /** + * @return The edges incident to the specified vertex + * as a range object suitable for C++11 range based for loops. + */ + ConstVertexEdgeCCWRange ve_ccw_range(VertexHandle _vh) const ; + + /** + * @return The faces incident to the specified vertex + * as a range object suitable for C++11 range based for loops. + */ + ConstVertexFaceCCWRange vf_ccw_range(VertexHandle _vh) const; + + /** + * @return The vertices incident to the specified face + * as a range object suitable for C++11 range based for loops. + */ + ConstFaceVertexCCWRange fv_ccw_range(FaceHandle _fh) const; + + /** + * @return The halfedges incident to the specified face + * as a range object suitable for C++11 range based for loops. + */ + ConstFaceHalfedgeCCWRange fh_ccw_range(FaceHandle _fh) const; + + /** + * @return The edges incident to the specified face + * as a range object suitable for C++11 range based for loops. + */ + ConstFaceEdgeCCWRange fe_ccw_range(FaceHandle _fh) const; + + /** + * @return The faces adjacent to the specified face + * as a range object suitable for C++11 range based for loops. + */ + ConstFaceFaceCCWRange ff_ccw_range(FaceHandle _fh) const; + + /** + * @return The halfedges in the face + * as a range object suitable for C++11 range based for loops. + */ + ConstHalfedgeLoopCCWRange hl_ccw_range(HalfedgeHandle _heh) const; + //@} //=========================================================================== diff --git a/src/OpenMesh/Core/Mesh/PolyConnectivity_inline_impl.hh b/src/OpenMesh/Core/Mesh/PolyConnectivity_inline_impl.hh index f9292941..84fe2e71 100644 --- a/src/OpenMesh/Core/Mesh/PolyConnectivity_inline_impl.hh +++ b/src/OpenMesh/Core/Mesh/PolyConnectivity_inline_impl.hh @@ -188,6 +188,104 @@ inline PolyConnectivity::ConstHalfedgeLoopRange PolyConnectivity::hl_range(Halfe } +inline PolyConnectivity::ConstVertexVertexCWRange PolyConnectivity::vv_cw_range(VertexHandle _vh) const { + return ConstVertexVertexCWRange(*this, _vh); +} + +inline PolyConnectivity::ConstVertexIHalfedgeCWRange PolyConnectivity::vih_cw_range(VertexHandle _vh) const { + return ConstVertexIHalfedgeCWRange(*this, _vh); +} + +inline PolyConnectivity::ConstVertexIHalfedgeCWRange PolyConnectivity::vih_cw_range(HalfedgeHandle _heh) const { + return ConstVertexIHalfedgeCWRange(*this, opposite_halfedge_handle(_heh), 1); +} + +inline PolyConnectivity::ConstVertexOHalfedgeCWRange PolyConnectivity::voh_cw_range(VertexHandle _vh) const { + return ConstVertexOHalfedgeCWRange(*this, _vh); +} + +inline PolyConnectivity::ConstVertexOHalfedgeCWRange PolyConnectivity::voh_cw_range(HalfedgeHandle _heh) const { + return ConstVertexOHalfedgeCWRange(*this, _heh, 1); +} + +inline PolyConnectivity::ConstVertexEdgeCWRange PolyConnectivity::ve_cw_range(VertexHandle _vh) const { + return ConstVertexEdgeCWRange(*this, _vh); +} + +inline PolyConnectivity::ConstVertexFaceCWRange PolyConnectivity::vf_cw_range(VertexHandle _vh) const { + return ConstVertexFaceCWRange(*this, _vh); +} + +inline PolyConnectivity::ConstFaceVertexCWRange PolyConnectivity::fv_cw_range(FaceHandle _fh) const { + return ConstFaceVertexCWRange(*this, _fh); +} + +inline PolyConnectivity::ConstFaceHalfedgeCWRange PolyConnectivity::fh_cw_range(FaceHandle _fh) const { + return ConstFaceHalfedgeCWRange(*this, _fh); +} + +inline PolyConnectivity::ConstFaceEdgeCWRange PolyConnectivity::fe_cw_range(FaceHandle _fh) const { + return ConstFaceEdgeCWRange(*this, _fh); +} + +inline PolyConnectivity::ConstFaceFaceCWRange PolyConnectivity::ff_cw_range(FaceHandle _fh) const { + return ConstFaceFaceCWRange(*this, _fh); +} + +inline PolyConnectivity::ConstHalfedgeLoopCWRange PolyConnectivity::hl_cw_range(HalfedgeHandle _heh) const { + return ConstHalfedgeLoopCWRange(*this, _heh); +} + + + +inline PolyConnectivity::ConstVertexVertexCCWRange PolyConnectivity::vv_ccw_range(VertexHandle _vh) const { + return ConstVertexVertexCCWRange(*this, _vh); +} + +inline PolyConnectivity::ConstVertexIHalfedgeCCWRange PolyConnectivity::vih_ccw_range(VertexHandle _vh) const { + return ConstVertexIHalfedgeCCWRange(*this, _vh); +} + +inline PolyConnectivity::ConstVertexIHalfedgeCCWRange PolyConnectivity::vih_ccw_range(HalfedgeHandle _heh) const { + return ConstVertexIHalfedgeCCWRange(*this, opposite_halfedge_handle(_heh), 1); +} + +inline PolyConnectivity::ConstVertexOHalfedgeCCWRange PolyConnectivity::voh_ccw_range(VertexHandle _vh) const { + return ConstVertexOHalfedgeCCWRange(*this, _vh); +} + +inline PolyConnectivity::ConstVertexOHalfedgeCCWRange PolyConnectivity::voh_ccw_range(HalfedgeHandle _heh) const { + return ConstVertexOHalfedgeCCWRange(*this, _heh, 1); +} + +inline PolyConnectivity::ConstVertexEdgeCCWRange PolyConnectivity::ve_ccw_range(VertexHandle _vh) const { + return ConstVertexEdgeCCWRange(*this, _vh); +} + +inline PolyConnectivity::ConstVertexFaceCCWRange PolyConnectivity::vf_ccw_range(VertexHandle _vh) const { + return ConstVertexFaceCCWRange(*this, _vh); +} + +inline PolyConnectivity::ConstFaceVertexCCWRange PolyConnectivity::fv_ccw_range(FaceHandle _fh) const { + return ConstFaceVertexCCWRange(*this, _fh); +} + +inline PolyConnectivity::ConstFaceHalfedgeCCWRange PolyConnectivity::fh_ccw_range(FaceHandle _fh) const { + return ConstFaceHalfedgeCCWRange(*this, _fh); +} + +inline PolyConnectivity::ConstFaceEdgeCCWRange PolyConnectivity::fe_ccw_range(FaceHandle _fh) const { + return ConstFaceEdgeCCWRange(*this, _fh); +} + +inline PolyConnectivity::ConstFaceFaceCCWRange PolyConnectivity::ff_ccw_range(FaceHandle _fh) const { + return ConstFaceFaceCCWRange(*this, _fh); +} + +inline PolyConnectivity::ConstHalfedgeLoopCCWRange PolyConnectivity::hl_ccw_range(HalfedgeHandle _heh) const { + return ConstHalfedgeLoopCCWRange(*this, _heh); +} + inline PolyConnectivity::VertexIter PolyConnectivity::vertices_begin() From 69caa276da82806bf5e836c4fbe6fa06bb384efb Mon Sep 17 00:00:00 2001 From: Max Lyon Date: Tue, 9 Mar 2021 09:04:55 +0100 Subject: [PATCH 4/9] test custom starts and cw and ccw ranges for vih_ranges and voh_ranges --- ...sts_trimesh_circulator_vertex_ihalfedge.cc | 111 ++++++++++++++++++ ...sts_trimesh_circulator_vertex_ohalfedge.cc | 110 +++++++++++++++++ 2 files changed, 221 insertions(+) diff --git a/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc b/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc index 370554f4..7b0e4a04 100644 --- a/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc +++ b/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc @@ -532,4 +532,115 @@ TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, CWAndCCWCheck) { } +/* + * Test CW and CCW iterators with custom starts + */ +TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, CustomStart) { + + 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 */ + + + for (auto vh : mesh_.vertices()) + { + auto hes_default_start = mesh_.vih_range(vh).to_vector(); + + int offset = 2; + auto hes_custom_start = mesh_.vih_range(hes_default_start[offset]).to_vector(); + + ASSERT_EQ(hes_default_start.size(), hes_custom_start.size()); + size_t n = hes_default_start.size(); + for (size_t i = 0; i < n; ++i) + EXPECT_EQ(hes_default_start[(i+offset)%n], hes_custom_start[i]); + } + + + for (auto vh : mesh_.vertices()) + { + auto hes_default_start = mesh_.vih_ccw_range(vh).to_vector(); + + int offset = 2; + auto hes_custom_start = mesh_.vih_ccw_range(hes_default_start[offset]).to_vector(); + + ASSERT_EQ(hes_default_start.size(), hes_custom_start.size()); + size_t n = hes_default_start.size(); + for (size_t i = 0; i < n; ++i) + EXPECT_EQ(hes_default_start[(i+offset)%n], hes_custom_start[i]); + } + + + for (auto vh : mesh_.vertices()) + { + auto hes_default_start = mesh_.vih_cw_range(vh).to_vector(); + + int offset = 2; + auto hes_custom_start = mesh_.vih_cw_range(hes_default_start[offset]).to_vector(); + + ASSERT_EQ(hes_default_start.size(), hes_custom_start.size()); + size_t n = hes_default_start.size(); + for (size_t i = 0; i < n; ++i) + EXPECT_EQ(hes_default_start[(i+offset)%n], hes_custom_start[i]); + } + + + for (auto vh : mesh_.vertices()) + { + auto hes_default_start_cw = mesh_.vih_cw_range(vh).to_vector(); + auto hes_default_start_ccw = mesh_.vih_ccw_range(vh).to_vector(); + + ASSERT_EQ(hes_default_start_cw.size(), hes_default_start_ccw.size()); + size_t n = hes_default_start_cw.size(); + for (size_t i = 0; i < n; ++i) + EXPECT_EQ(hes_default_start_cw[(n-i)%n], hes_default_start_ccw[i]); + } + +} + + } diff --git a/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc b/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc index 7d66b6df..c9e408cf 100644 --- a/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc +++ b/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc @@ -532,6 +532,116 @@ TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, CWAndCCWCheck) { } +/* + * Test CW and CCW iterators with custom starts + */ +TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, CustomStart) { + + 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 */ + + for (auto vh : mesh_.vertices()) + { + auto hes_default_start = mesh_.voh_range(vh).to_vector(); + + int offset = 2; + auto hes_custom_start = mesh_.voh_range(hes_default_start[offset]).to_vector(); + + ASSERT_EQ(hes_default_start.size(), hes_custom_start.size()); + size_t n = hes_default_start.size(); + for (size_t i = 0; i < n; ++i) + EXPECT_EQ(hes_default_start[(i+offset)%n], hes_custom_start[i]); + } + + + for (auto vh : mesh_.vertices()) + { + auto hes_default_start = mesh_.voh_ccw_range(vh).to_vector(); + + int offset = 2; + auto hes_custom_start = mesh_.voh_ccw_range(hes_default_start[offset]).to_vector(); + + ASSERT_EQ(hes_default_start.size(), hes_custom_start.size()); + size_t n = hes_default_start.size(); + for (size_t i = 0; i < n; ++i) + EXPECT_EQ(hes_default_start[(i+offset)%n], hes_custom_start[i]); + } + + + for (auto vh : mesh_.vertices()) + { + auto hes_default_start = mesh_.voh_cw_range(vh).to_vector(); + + int offset = 2; + auto hes_custom_start = mesh_.voh_cw_range(hes_default_start[offset]).to_vector(); + + ASSERT_EQ(hes_default_start.size(), hes_custom_start.size()); + size_t n = hes_default_start.size(); + for (size_t i = 0; i < n; ++i) + EXPECT_EQ(hes_default_start[(i+offset)%n], hes_custom_start[i]); + } + + + for (auto vh : mesh_.vertices()) + { + auto hes_default_start_cw = mesh_.voh_cw_range(vh).to_vector(); + auto hes_default_start_ccw = mesh_.voh_ccw_range(vh).to_vector(); + + ASSERT_EQ(hes_default_start_cw.size(), hes_default_start_ccw.size()); + size_t n = hes_default_start_cw.size(); + for (size_t i = 0; i < n; ++i) + EXPECT_EQ(hes_default_start_cw[(n-i)%n], hes_default_start_ccw[i]); + } + +} + + } From b2bcded8ec5bd14f9d5dbd6c207b7aaa02b8be3e Mon Sep 17 00:00:00 2001 From: Max Lyon Date: Tue, 9 Mar 2021 10:57:17 +0100 Subject: [PATCH 5/9] add access to cw and ccw ranges in SmartHandles --- .../Core/Mesh/PolyConnectivity_inline_impl.hh | 94 ++++++++----------- src/OpenMesh/Core/Mesh/SmartHandles.hh | 74 ++++++++++++--- 2 files changed, 102 insertions(+), 66 deletions(-) diff --git a/src/OpenMesh/Core/Mesh/PolyConnectivity_inline_impl.hh b/src/OpenMesh/Core/Mesh/PolyConnectivity_inline_impl.hh index 84fe2e71..2be178e2 100644 --- a/src/OpenMesh/Core/Mesh/PolyConnectivity_inline_impl.hh +++ b/src/OpenMesh/Core/Mesh/PolyConnectivity_inline_impl.hh @@ -893,70 +893,54 @@ inline PolyConnectivity::ConstHalfedgeLoopCCWIter PolyConnectivity::chl_ccwend(H { return ConstHalfedgeLoopCCWIter(*this, _heh, true); } -inline PolyConnectivity::ConstVertexFaceRange SmartVertexHandle::faces() const -{ - assert(mesh() != nullptr); - return mesh()->vf_range(*this); -} +inline PolyConnectivity::ConstVertexFaceRange SmartVertexHandle::faces() const { assert(mesh() != nullptr); return mesh()->vf_range (*this); } +inline PolyConnectivity::ConstVertexFaceCWRange SmartVertexHandle::faces_cw() const { assert(mesh() != nullptr); return mesh()->vf_cw_range (*this); } +inline PolyConnectivity::ConstVertexFaceCCWRange SmartVertexHandle::faces_ccw() const { assert(mesh() != nullptr); return mesh()->vf_ccw_range(*this); } -inline PolyConnectivity::ConstVertexEdgeRange SmartVertexHandle::edges() const -{ - assert(mesh() != nullptr); - return mesh()->ve_range(*this); -} +inline PolyConnectivity::ConstVertexEdgeRange SmartVertexHandle::edges() const { assert(mesh() != nullptr); return mesh()->ve_range (*this); } +inline PolyConnectivity::ConstVertexEdgeCWRange SmartVertexHandle::edges_cw() const { assert(mesh() != nullptr); return mesh()->ve_cw_range (*this); } +inline PolyConnectivity::ConstVertexEdgeCCWRange SmartVertexHandle::edges_ccw() const { assert(mesh() != nullptr); return mesh()->ve_ccw_range(*this); } -inline PolyConnectivity::ConstVertexVertexRange -SmartVertexHandle::vertices() const -{ - assert(mesh() != nullptr); - return mesh()->vv_range(*this); -} +inline PolyConnectivity::ConstVertexVertexRange SmartVertexHandle::vertices() const { assert(mesh() != nullptr); return mesh()->vv_range (*this); } +inline PolyConnectivity::ConstVertexVertexCWRange SmartVertexHandle::vertices_cw() const { assert(mesh() != nullptr); return mesh()->vv_cw_range (*this); } +inline PolyConnectivity::ConstVertexVertexCCWRange SmartVertexHandle::vertices_ccw() const { assert(mesh() != nullptr); return mesh()->vv_ccw_range (*this); } -inline PolyConnectivity::ConstVertexIHalfedgeRange -SmartVertexHandle::incoming_halfedges() const -{ - assert(mesh() != nullptr); - return mesh()->vih_range(*this); -} +inline PolyConnectivity::ConstVertexIHalfedgeRange SmartVertexHandle::incoming_halfedges() const { assert(mesh() != nullptr); return mesh()->vih_range (*this); } +inline PolyConnectivity::ConstVertexIHalfedgeCWRange SmartVertexHandle::incoming_halfedges_cw() const { assert(mesh() != nullptr); return mesh()->vih_cw_range (*this); } +inline PolyConnectivity::ConstVertexIHalfedgeCCWRange SmartVertexHandle::incoming_halfedges_ccw() const { assert(mesh() != nullptr); return mesh()->vih_ccw_range(*this); } -inline PolyConnectivity::ConstVertexOHalfedgeRange -SmartVertexHandle::outgoing_halfedges() const -{ - assert(mesh() != nullptr); - return mesh()->voh_range(*this); -} +inline PolyConnectivity::ConstVertexIHalfedgeRange SmartVertexHandle::incoming_halfedges (HalfedgeHandle _heh) const { assert(mesh() != nullptr); return mesh()->vih_range (_heh); } +inline PolyConnectivity::ConstVertexIHalfedgeCWRange SmartVertexHandle::incoming_halfedges_cw (HalfedgeHandle _heh) const { assert(mesh() != nullptr); return mesh()->vih_cw_range (_heh); } +inline PolyConnectivity::ConstVertexIHalfedgeCCWRange SmartVertexHandle::incoming_halfedges_ccw(HalfedgeHandle _heh) const { assert(mesh() != nullptr); return mesh()->vih_ccw_range(_heh); } -inline PolyConnectivity::ConstHalfedgeLoopRange -SmartHalfedgeHandle::loop() const -{ - assert(mesh() != nullptr); - return mesh()->hl_range(*this); -} +inline PolyConnectivity::ConstVertexOHalfedgeRange SmartVertexHandle::outgoing_halfedges() const { assert(mesh() != nullptr); return mesh()->voh_range (*this); } +inline PolyConnectivity::ConstVertexOHalfedgeCWRange SmartVertexHandle::outgoing_halfedges_cw() const { assert(mesh() != nullptr); return mesh()->voh_cw_range (*this); } +inline PolyConnectivity::ConstVertexOHalfedgeCCWRange SmartVertexHandle::outgoing_halfedges_ccw() const { assert(mesh() != nullptr); return mesh()->voh_ccw_range(*this); } + +inline PolyConnectivity::ConstVertexOHalfedgeRange SmartVertexHandle::outgoing_halfedges (HalfedgeHandle _heh) const { assert(mesh() != nullptr); return mesh()->voh_range (_heh); } +inline PolyConnectivity::ConstVertexOHalfedgeCWRange SmartVertexHandle::outgoing_halfedges_cw (HalfedgeHandle _heh) const { assert(mesh() != nullptr); return mesh()->voh_cw_range (_heh); } +inline PolyConnectivity::ConstVertexOHalfedgeCCWRange SmartVertexHandle::outgoing_halfedges_ccw(HalfedgeHandle _heh) const { assert(mesh() != nullptr); return mesh()->voh_ccw_range(_heh); } -inline PolyConnectivity::ConstFaceVertexRange SmartFaceHandle::vertices() const -{ - assert(mesh() != nullptr); - return mesh()->fv_range(*this); -} +inline PolyConnectivity::ConstHalfedgeLoopRange SmartHalfedgeHandle::loop() const { assert(mesh() != nullptr); return mesh()->hl_range (*this); } +inline PolyConnectivity::ConstHalfedgeLoopCWRange SmartHalfedgeHandle::loop_cw() const { assert(mesh() != nullptr); return mesh()->hl_cw_range (*this); } +inline PolyConnectivity::ConstHalfedgeLoopCCWRange SmartHalfedgeHandle::loop_ccw() const { assert(mesh() != nullptr); return mesh()->hl_ccw_range (*this); } -inline PolyConnectivity::ConstFaceHalfedgeRange -SmartFaceHandle::halfedges() const -{ - assert(mesh() != nullptr); - return mesh()->fh_range(*this); -} -inline PolyConnectivity::ConstFaceEdgeRange SmartFaceHandle::edges() const -{ - assert(mesh() != nullptr); - return mesh()->fe_range(*this); -} +inline PolyConnectivity::ConstFaceVertexRange SmartFaceHandle::vertices() const { assert(mesh() != nullptr); return mesh()->fv_range (*this); } +inline PolyConnectivity::ConstFaceVertexCWRange SmartFaceHandle::vertices_cw() const { assert(mesh() != nullptr); return mesh()->fv_cw_range (*this); } +inline PolyConnectivity::ConstFaceVertexCCWRange SmartFaceHandle::vertices_ccw() const { assert(mesh() != nullptr); return mesh()->fv_ccw_range(*this); } -inline PolyConnectivity::ConstFaceFaceRange SmartFaceHandle::faces() const -{ - assert(mesh() != nullptr); - return mesh()->ff_range(*this); -} +inline PolyConnectivity::ConstFaceHalfedgeRange SmartFaceHandle::halfedges() const { assert(mesh() != nullptr); return mesh()->fh_range (*this); } +inline PolyConnectivity::ConstFaceHalfedgeCWRange SmartFaceHandle::halfedges_cw() const { assert(mesh() != nullptr); return mesh()->fh_cw_range (*this); } +inline PolyConnectivity::ConstFaceHalfedgeCCWRange SmartFaceHandle::halfedges_ccw() const { assert(mesh() != nullptr); return mesh()->fh_ccw_range(*this); } + +inline PolyConnectivity::ConstFaceEdgeRange SmartFaceHandle::edges() const { assert(mesh() != nullptr); return mesh()->fe_range (*this); } +inline PolyConnectivity::ConstFaceEdgeCWRange SmartFaceHandle::edges_cw() const { assert(mesh() != nullptr); return mesh()->fe_cw_range (*this); } +inline PolyConnectivity::ConstFaceEdgeCCWRange SmartFaceHandle::edges_ccw() const { assert(mesh() != nullptr); return mesh()->fe_ccw_range(*this); } + +inline PolyConnectivity::ConstFaceFaceRange SmartFaceHandle::faces() const { assert(mesh() != nullptr); return mesh()->ff_range (*this); } +inline PolyConnectivity::ConstFaceFaceCWRange SmartFaceHandle::faces_cw() const { assert(mesh() != nullptr); return mesh()->ff_cw_range (*this); } +inline PolyConnectivity::ConstFaceFaceCCWRange SmartFaceHandle::faces_ccw() const { assert(mesh() != nullptr); return mesh()->ff_ccw_range(*this); } }//namespace OpenMesh diff --git a/src/OpenMesh/Core/Mesh/SmartHandles.hh b/src/OpenMesh/Core/Mesh/SmartHandles.hh index fbe4a94e..66c5bb18 100644 --- a/src/OpenMesh/Core/Mesh/SmartHandles.hh +++ b/src/OpenMesh/Core/Mesh/SmartHandles.hh @@ -118,15 +118,47 @@ struct OPENMESHDLLEXPORT SmartVertexHandle : public SmartBaseHandle, VertexHandl SmartHalfedgeHandle in() const; /// Returns a range of faces incident to the vertex (PolyConnectivity::vf_range()) - PolyConnectivity::ConstVertexFaceRange faces() const; + PolyConnectivity::ConstVertexFaceRange faces() const; + /// Returns a range of faces incident to the vertex (PolyConnectivity::vf_cw_range()) + PolyConnectivity::ConstVertexFaceCWRange faces_cw() const; + /// Returns a range of faces incident to the vertex (PolyConnectivity::vf_ccw_range()) + PolyConnectivity::ConstVertexFaceCCWRange faces_ccw() const; /// Returns a range of edges incident to the vertex (PolyConnectivity::ve_range()) - PolyConnectivity::ConstVertexEdgeRange edges() const; + PolyConnectivity::ConstVertexEdgeRange edges() const; + /// Returns a range of edges incident to the vertex (PolyConnectivity::ve_cw_range()) + PolyConnectivity::ConstVertexEdgeCWRange edges_cw() const; + /// Returns a range of edges incident to the vertex (PolyConnectivity::ve_ccw_range()) + PolyConnectivity::ConstVertexEdgeCCWRange edges_ccw() const; /// Returns a range of vertices adjacent to the vertex (PolyConnectivity::vv_range()) - PolyConnectivity::ConstVertexVertexRange vertices() const; + PolyConnectivity::ConstVertexVertexRange vertices() const; + /// Returns a range of vertices adjacent to the vertex (PolyConnectivity::vv_cw_range()) + PolyConnectivity::ConstVertexVertexCWRange vertices_cw() const; + /// Returns a range of vertices adjacent to the vertex (PolyConnectivity::vv_ccw_range()) + PolyConnectivity::ConstVertexVertexCCWRange vertices_ccw() const; /// Returns a range of outgoing halfedges incident to the vertex (PolyConnectivity::voh_range()) - PolyConnectivity::ConstVertexIHalfedgeRange incoming_halfedges() const; - /// Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::vih_range()) - PolyConnectivity::ConstVertexOHalfedgeRange outgoing_halfedges() const; + PolyConnectivity::ConstVertexIHalfedgeRange incoming_halfedges() const; + /// Returns a range of outgoing halfedges incident to the vertex (PolyConnectivity::voh_cw_range()) + PolyConnectivity::ConstVertexIHalfedgeCWRange incoming_halfedges_cw() const; + /// Returns a range of outgoing halfedges incident to the vertex (PolyConnectivity::voh_ccw_range()) + PolyConnectivity::ConstVertexIHalfedgeCCWRange incoming_halfedges_ccw() const; + /// Returns a range of outgoing halfedges incident to the vertex (PolyConnectivity::vih_range()) + PolyConnectivity::ConstVertexIHalfedgeRange incoming_halfedges(HalfedgeHandle _heh) const; + /// Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::vih_cw_range()) + PolyConnectivity::ConstVertexIHalfedgeCWRange incoming_halfedges_cw(HalfedgeHandle _heh) const; + /// Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::vih_ccw_range()) + PolyConnectivity::ConstVertexIHalfedgeCCWRange incoming_halfedges_ccw(HalfedgeHandle _heh) const; + /// Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::voh_range()) + PolyConnectivity::ConstVertexOHalfedgeRange outgoing_halfedges() const; + /// Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::voh_cw_range()) + PolyConnectivity::ConstVertexOHalfedgeCWRange outgoing_halfedges_cw() const; + /// Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::voh_ccw_range()) + PolyConnectivity::ConstVertexOHalfedgeCCWRange outgoing_halfedges_ccw() const; + /// Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::voh_range()) + PolyConnectivity::ConstVertexOHalfedgeRange outgoing_halfedges(HalfedgeHandle _heh) const; + /// Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::voh_cw_range()) + PolyConnectivity::ConstVertexOHalfedgeCWRange outgoing_halfedges_cw(HalfedgeHandle _heh) const; + /// Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::voh_ccw_range()) + PolyConnectivity::ConstVertexOHalfedgeCCWRange outgoing_halfedges_ccw(HalfedgeHandle _heh) const; /// Returns valence of the vertex uint valence() const; @@ -154,7 +186,11 @@ struct OPENMESHDLLEXPORT SmartHalfedgeHandle : public SmartBaseHandle, HalfedgeH SmartFaceHandle face() const; /// Returns a range of halfedges in the face of the halfedge (or along the boundary) (PolyConnectivity::hl_range()) - PolyConnectivity::ConstHalfedgeLoopRange loop() const; + PolyConnectivity::ConstHalfedgeLoopRange loop() const; + /// Returns a range of halfedges in the face of the halfedge (or along the boundary) (PolyConnectivity::hl_cw_range()) + PolyConnectivity::ConstHalfedgeLoopCWRange loop_cw() const; + /// Returns a range of halfedges in the face of the halfedge (or along the boundary) (PolyConnectivity::hl_ccw_range()) + PolyConnectivity::ConstHalfedgeLoopCCWRange loop_ccw() const; }; struct OPENMESHDLLEXPORT SmartEdgeHandle : public SmartBaseHandle, EdgeHandle, SmartHandleStatusPredicates, SmartHandleBoundaryPredicate @@ -187,13 +223,29 @@ struct OPENMESHDLLEXPORT SmartFaceHandle : public SmartBaseHandle, FaceHandle, S SmartHalfedgeHandle halfedge() const; /// Returns a range of vertices incident to the face (PolyConnectivity::fv_range()) - PolyConnectivity::ConstFaceVertexRange vertices() const; + PolyConnectivity::ConstFaceVertexRange vertices() const; + /// Returns a range of vertices incident to the face (PolyConnectivity::fv_cw_range()) + PolyConnectivity::ConstFaceVertexCWRange vertices_cw() const; + /// Returns a range of vertices incident to the face (PolyConnectivity::fv_ccw_range()) + PolyConnectivity::ConstFaceVertexCCWRange vertices_ccw() const; /// Returns a range of halfedges of the face (PolyConnectivity::fh_range()) - PolyConnectivity::ConstFaceHalfedgeRange halfedges() const; + PolyConnectivity::ConstFaceHalfedgeRange halfedges() const; + /// Returns a range of halfedges of the face (PolyConnectivity::fh_cw_range()) + PolyConnectivity::ConstFaceHalfedgeCWRange halfedges_cw() const; + /// Returns a range of halfedges of the face (PolyConnectivity::fh_ccw_range()) + PolyConnectivity::ConstFaceHalfedgeCCWRange halfedges_ccw() const; /// Returns a range of edges of the face (PolyConnectivity::fv_range()) - PolyConnectivity::ConstFaceEdgeRange edges() const; + PolyConnectivity::ConstFaceEdgeRange edges() const; + /// Returns a range of edges of the face (PolyConnectivity::fv_cw_range()) + PolyConnectivity::ConstFaceEdgeCWRange edges_cw() const; + /// Returns a range of edges of the face (PolyConnectivity::fv_ccw_range()) + PolyConnectivity::ConstFaceEdgeCCWRange edges_ccw() const; /// Returns a range adjacent faces of the face (PolyConnectivity::ff_range()) - PolyConnectivity::ConstFaceFaceRange faces() const; + PolyConnectivity::ConstFaceFaceRange faces() const; + /// Returns a range adjacent faces of the face (PolyConnectivity::ff_cw_range()) + PolyConnectivity::ConstFaceFaceCWRange faces_cw() const; + /// Returns a range adjacent faces of the face (PolyConnectivity::ff_ccw_range()) + PolyConnectivity::ConstFaceFaceCCWRange faces_ccw() const; /// Returns the valence of the face uint valence() const; From f63c4a54bb199fefb22b41ad2d42530022cac273 Mon Sep 17 00:00:00 2001 From: Max Lyon Date: Tue, 9 Mar 2021 10:57:44 +0100 Subject: [PATCH 6/9] add test file for range tests --- ...sts_trimesh_circulator_vertex_ihalfedge.cc | 112 ----- ...sts_trimesh_circulator_vertex_ohalfedge.cc | 113 ------ src/Unittests/unittests_trimesh_ranges.cc | 382 ++++++++++++++++++ 3 files changed, 382 insertions(+), 225 deletions(-) create mode 100644 src/Unittests/unittests_trimesh_ranges.cc diff --git a/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc b/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc index 7b0e4a04..85559b0b 100644 --- a/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc +++ b/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc @@ -531,116 +531,4 @@ TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, CWAndCCWCheck) { } - -/* - * Test CW and CCW iterators with custom starts - */ -TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, CustomStart) { - - 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 */ - - - for (auto vh : mesh_.vertices()) - { - auto hes_default_start = mesh_.vih_range(vh).to_vector(); - - int offset = 2; - auto hes_custom_start = mesh_.vih_range(hes_default_start[offset]).to_vector(); - - ASSERT_EQ(hes_default_start.size(), hes_custom_start.size()); - size_t n = hes_default_start.size(); - for (size_t i = 0; i < n; ++i) - EXPECT_EQ(hes_default_start[(i+offset)%n], hes_custom_start[i]); - } - - - for (auto vh : mesh_.vertices()) - { - auto hes_default_start = mesh_.vih_ccw_range(vh).to_vector(); - - int offset = 2; - auto hes_custom_start = mesh_.vih_ccw_range(hes_default_start[offset]).to_vector(); - - ASSERT_EQ(hes_default_start.size(), hes_custom_start.size()); - size_t n = hes_default_start.size(); - for (size_t i = 0; i < n; ++i) - EXPECT_EQ(hes_default_start[(i+offset)%n], hes_custom_start[i]); - } - - - for (auto vh : mesh_.vertices()) - { - auto hes_default_start = mesh_.vih_cw_range(vh).to_vector(); - - int offset = 2; - auto hes_custom_start = mesh_.vih_cw_range(hes_default_start[offset]).to_vector(); - - ASSERT_EQ(hes_default_start.size(), hes_custom_start.size()); - size_t n = hes_default_start.size(); - for (size_t i = 0; i < n; ++i) - EXPECT_EQ(hes_default_start[(i+offset)%n], hes_custom_start[i]); - } - - - for (auto vh : mesh_.vertices()) - { - auto hes_default_start_cw = mesh_.vih_cw_range(vh).to_vector(); - auto hes_default_start_ccw = mesh_.vih_ccw_range(vh).to_vector(); - - ASSERT_EQ(hes_default_start_cw.size(), hes_default_start_ccw.size()); - size_t n = hes_default_start_cw.size(); - for (size_t i = 0; i < n; ++i) - EXPECT_EQ(hes_default_start_cw[(n-i)%n], hes_default_start_ccw[i]); - } - -} - - } diff --git a/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc b/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc index c9e408cf..49de4076 100644 --- a/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc +++ b/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc @@ -531,117 +531,4 @@ TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, CWAndCCWCheck) { } - -/* - * Test CW and CCW iterators with custom starts - */ -TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, CustomStart) { - - 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 */ - - for (auto vh : mesh_.vertices()) - { - auto hes_default_start = mesh_.voh_range(vh).to_vector(); - - int offset = 2; - auto hes_custom_start = mesh_.voh_range(hes_default_start[offset]).to_vector(); - - ASSERT_EQ(hes_default_start.size(), hes_custom_start.size()); - size_t n = hes_default_start.size(); - for (size_t i = 0; i < n; ++i) - EXPECT_EQ(hes_default_start[(i+offset)%n], hes_custom_start[i]); - } - - - for (auto vh : mesh_.vertices()) - { - auto hes_default_start = mesh_.voh_ccw_range(vh).to_vector(); - - int offset = 2; - auto hes_custom_start = mesh_.voh_ccw_range(hes_default_start[offset]).to_vector(); - - ASSERT_EQ(hes_default_start.size(), hes_custom_start.size()); - size_t n = hes_default_start.size(); - for (size_t i = 0; i < n; ++i) - EXPECT_EQ(hes_default_start[(i+offset)%n], hes_custom_start[i]); - } - - - for (auto vh : mesh_.vertices()) - { - auto hes_default_start = mesh_.voh_cw_range(vh).to_vector(); - - int offset = 2; - auto hes_custom_start = mesh_.voh_cw_range(hes_default_start[offset]).to_vector(); - - ASSERT_EQ(hes_default_start.size(), hes_custom_start.size()); - size_t n = hes_default_start.size(); - for (size_t i = 0; i < n; ++i) - EXPECT_EQ(hes_default_start[(i+offset)%n], hes_custom_start[i]); - } - - - for (auto vh : mesh_.vertices()) - { - auto hes_default_start_cw = mesh_.voh_cw_range(vh).to_vector(); - auto hes_default_start_ccw = mesh_.voh_ccw_range(vh).to_vector(); - - ASSERT_EQ(hes_default_start_cw.size(), hes_default_start_ccw.size()); - size_t n = hes_default_start_cw.size(); - for (size_t i = 0; i < n; ++i) - EXPECT_EQ(hes_default_start_cw[(n-i)%n], hes_default_start_ccw[i]); - } - -} - - - - } diff --git a/src/Unittests/unittests_trimesh_ranges.cc b/src/Unittests/unittests_trimesh_ranges.cc new file mode 100644 index 00000000..d6c1582a --- /dev/null +++ b/src/Unittests/unittests_trimesh_ranges.cc @@ -0,0 +1,382 @@ +#include +#include + +#include + +#include + +namespace { + +class OpenMeshTrimeshRange : public OpenMeshBase { + +protected: + + // This function is called before each test is run + virtual void SetUp() + { + 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 */ + } + + // This function is called after all tests are through + virtual void TearDown() { + + // Do some final stuff with the member data here... + } + + + // Member already defined in OpenMeshBase + //Mesh mesh_; +}; + +/* + * ==================================================================== + * Define tests below + * ==================================================================== + */ + + +template +void compare_ranges(RangeT1&& range1, RangeT2&& range2, int offset, bool reverse) +{ + auto vec1 = range1.to_vector(); + auto vec2 = range2.to_vector(); + + ASSERT_EQ(vec1.size(), vec2.size()) << "Ranges have different number of elements"; + ASSERT_GT(vec1.size(), 0) << "Ranges are empty"; + + size_t n = vec1.size(); + + std::cout << "Vec1 elements: "; + for (auto el : vec1) + std::cout << el.idx() << " "; + std::cout << std::endl; + + std::cout << "Vec2 elements: "; + for (auto el : vec2) + std::cout << el.idx() << " "; + std::cout << std::endl; + + for (size_t i = 0; i < n; ++i) + { + size_t id1 = (i+offset)%n; + size_t id2 = reverse ? (n-i)%n : i; + EXPECT_EQ(vec1[id1].idx(), vec2[id2].idx()) << "Elements are not the same with offset = " << offset << " and reverse = " << std::to_string(reverse); + } +} + + +TEST_F(OpenMeshTrimeshRange, VertexVertexRangeMeshVsSmartHandle) +{ + for (auto vh : mesh_.vertices()) + { + compare_ranges(mesh_.vv_range(vh) , vh.vertices() , 0, false); + compare_ranges(mesh_.vv_cw_range(vh) , vh.vertices_cw() , 0, false); + compare_ranges(mesh_.vv_ccw_range(vh), vh.vertices_ccw(), 0, false); + } +} + +TEST_F(OpenMeshTrimeshRange, VertexVertexRangeCWVsCCW) +{ + for (auto vh : mesh_.vertices()) + compare_ranges(vh.vertices_cw(), vh.vertices_ccw(), 0, true); +} + + +TEST_F(OpenMeshTrimeshRange, VertexEdgeRangeMeshVsSmartHandle) +{ + for (auto vh : mesh_.vertices()) + { + compare_ranges(mesh_.ve_range(vh) , vh.edges() , 0, false); + compare_ranges(mesh_.ve_cw_range(vh) , vh.edges_cw() , 0, false); + compare_ranges(mesh_.ve_ccw_range(vh), vh.edges_ccw(), 0, false); + } +} + +TEST_F(OpenMeshTrimeshRange, VertexEdgeRangeCWVsCCW) +{ + for (auto vh : mesh_.vertices()) + compare_ranges(vh.edges_cw(), vh.edges_ccw(), 0, true); +} + +TEST_F(OpenMeshTrimeshRange, VertexFaceRangeMeshVsSmartHandle) +{ + for (auto vh : mesh_.vertices()) + { + compare_ranges(mesh_.vf_range(vh) , vh.faces() , 0, false); + compare_ranges(mesh_.vf_cw_range(vh) , vh.faces_cw() , 0, false); + compare_ranges(mesh_.vf_ccw_range(vh), vh.faces_ccw(), 0, false); + } +} + +TEST_F(OpenMeshTrimeshRange, VertexFaceRangeCWVsCCW) +{ + for (auto vh : mesh_.vertices()) + compare_ranges(vh.faces_cw(), vh.faces_ccw(), 0, true); +} + +TEST_F(OpenMeshTrimeshRange, VertexIncomingHalfedgesRangeMeshVsSmartHandle) +{ + for (auto vh : mesh_.vertices()) + { + compare_ranges(mesh_.vih_range(vh) , vh.incoming_halfedges() , 0, false); + compare_ranges(mesh_.vih_cw_range(vh) , vh.incoming_halfedges_cw() , 0, false); + compare_ranges(mesh_.vih_ccw_range(vh), vh.incoming_halfedges_ccw(), 0, false); + } +} + +TEST_F(OpenMeshTrimeshRange, VertexIncomingHalfedgesRangeCWVsCCW) +{ + for (auto vh : mesh_.vertices()) + compare_ranges(vh.incoming_halfedges_cw(), vh.incoming_halfedges_ccw(), 0, true); +} + +TEST_F(OpenMeshTrimeshRange, VertexIncomingHalfedgesRangeCustomStart) +{ + const int offset = 2; + for (auto vh : mesh_.vertices()) + { + // mesh vs smart handle access + auto it_cw = mesh_.vih_begin(vh); + auto it_ccw = mesh_.vih_ccwbegin(vh); + for (int i = 0; i < offset; ++i) + { + ++it_cw; + ++it_ccw; + } + OpenMesh::HalfedgeHandle start_heh_cw = *it_cw; + OpenMesh::HalfedgeHandle start_heh_ccw = *it_ccw; + compare_ranges(mesh_.vih_range(vh) , mesh_.vih_range(start_heh_cw) , offset, false); + compare_ranges(mesh_.vih_cw_range(vh) , mesh_.vih_cw_range(start_heh_cw) , offset, false); + compare_ranges(mesh_.vih_ccw_range(vh) , mesh_.vih_ccw_range(start_heh_ccw) , offset, false); + compare_ranges(vh.incoming_halfedges() , vh.incoming_halfedges(start_heh_cw) , offset, false); + compare_ranges(vh.incoming_halfedges_cw() , vh.incoming_halfedges_cw(start_heh_cw) , offset, false); + compare_ranges(vh.incoming_halfedges_ccw(), vh.incoming_halfedges_ccw(start_heh_ccw), offset, false); + + // check that ranges with custom start actually start at that start + auto hes = vh.incoming_halfedges(); + for (auto heh : hes) + { + EXPECT_EQ(heh, *vh.incoming_halfedges (heh).begin()) << "Range does not start at desired start"; + EXPECT_EQ(heh, *vh.incoming_halfedges_cw (heh).begin()) << "Range does not start at desired start"; + EXPECT_EQ(heh, *vh.incoming_halfedges_ccw(heh).begin()) << "Range does not start at desired start"; + } + } +} + + +TEST_F(OpenMeshTrimeshRange, VertexIncomingHalfedgesRangeBoundaryConsistency) +{ + // for boundary vertices cw iterations should start at boundary halfedge + for (auto vh : mesh_.vertices().filtered(OpenMesh::Predicates::Boundary())) + { + EXPECT_TRUE(mesh_.vih_begin(vh)->opp().is_boundary()); + EXPECT_TRUE(mesh_.vih_range(vh).begin()->opp().is_boundary()); + + EXPECT_TRUE(mesh_.vih_cwbegin(vh)->opp().is_boundary()); + EXPECT_TRUE(mesh_.vih_cw_range(vh).begin()->opp().is_boundary()); + + // TODO: this should be false, instead opp should be boundary + EXPECT_TRUE(mesh_.vih_ccwbegin(vh)->opp().is_boundary()); + EXPECT_TRUE(mesh_.vih_ccw_range(vh).begin()->opp().is_boundary()); + } +} + +TEST_F(OpenMeshTrimeshRange, VertexOutgoingHalfedgesRangeMeshVsSmartHandle) +{ + for (auto vh : mesh_.vertices()) + { + compare_ranges(mesh_.voh_range(vh) , vh.outgoing_halfedges() , 0, false); + compare_ranges(mesh_.voh_cw_range(vh) , vh.outgoing_halfedges_cw() , 0, false); + compare_ranges(mesh_.voh_ccw_range(vh), vh.outgoing_halfedges_ccw(), 0, false); + } +} + +TEST_F(OpenMeshTrimeshRange, VertexOutgoingHalfedgesRangeCWVsCCW) +{ + for (auto vh : mesh_.vertices()) + compare_ranges(vh.outgoing_halfedges_cw(), vh.outgoing_halfedges_ccw(), 0, true); +} + +TEST_F(OpenMeshTrimeshRange, VertexOutgoingHalfedgesRangeCustomStart) +{ + const int offset = 2; + for (auto vh : mesh_.vertices()) + { + // mesh vs smart handle access + auto it_cw = mesh_.voh_begin(vh); + auto it_ccw = mesh_.voh_ccwbegin(vh); + for (int i = 0; i < offset; ++i) + { + ++it_cw; + ++it_ccw; + } + OpenMesh::HalfedgeHandle start_heh_cw = *it_cw; + OpenMesh::HalfedgeHandle start_heh_ccw = *it_ccw; + compare_ranges(mesh_.voh_range(vh) , mesh_.voh_range(start_heh_cw) , offset, false); + compare_ranges(mesh_.voh_cw_range(vh) , mesh_.voh_cw_range(start_heh_cw) , offset, false); + compare_ranges(mesh_.voh_ccw_range(vh) , mesh_.voh_ccw_range(start_heh_ccw) , offset, false); + compare_ranges(vh.outgoing_halfedges() , vh.outgoing_halfedges(start_heh_cw) , offset, false); + compare_ranges(vh.outgoing_halfedges_cw() , vh.outgoing_halfedges_cw(start_heh_cw) , offset, false); + compare_ranges(vh.outgoing_halfedges_ccw(), vh.outgoing_halfedges_ccw(start_heh_ccw), offset, false); + + + // check that ranges with custom start actually start at that start + auto hes = vh.outgoing_halfedges(); + for (auto heh : hes) + { + EXPECT_EQ(heh, *vh.outgoing_halfedges (heh).begin()) << "Range does not start at desired start"; + EXPECT_EQ(heh, *vh.outgoing_halfedges_cw (heh).begin()) << "Range does not start at desired start"; + EXPECT_EQ(heh, *vh.outgoing_halfedges_ccw(heh).begin()) << "Range does not start at desired start"; + } + } +} + + +TEST_F(OpenMeshTrimeshRange, VertexOutgoingHalfedgesRangeBoundaryConsistency) +{ + // for boundary vertices cw iterations should start at boundary halfedge + for (auto vh : mesh_.vertices().filtered(OpenMesh::Predicates::Boundary())) + { + EXPECT_TRUE(mesh_.voh_begin(vh)->is_boundary()); + EXPECT_TRUE(mesh_.voh_range(vh).begin()->is_boundary()); + + EXPECT_TRUE(mesh_.voh_cwbegin(vh)->is_boundary()); + EXPECT_TRUE(mesh_.voh_cw_range(vh).begin()->is_boundary()); + + // TODO: this should be false, instead opp should be boundary + EXPECT_TRUE(mesh_.voh_ccwbegin(vh)->is_boundary()); + EXPECT_TRUE(mesh_.voh_ccw_range(vh).begin()->is_boundary()); + } +} + + +TEST_F(OpenMeshTrimeshRange, HalfedgeLoopRangeMeshVsSmartHandle) +{ + for (auto heh : mesh_.halfedges()) + { + compare_ranges(mesh_.hl_range(heh) , heh.loop() , 0, false); + compare_ranges(mesh_.hl_cw_range(heh) , heh.loop_cw() , 0, false); + compare_ranges(mesh_.hl_ccw_range(heh), heh.loop_ccw(), 0, false); + } +} + +TEST_F(OpenMeshTrimeshRange, HalfedgeLoopRangeCWVsCCW) +{ + for (auto heh : mesh_.halfedges()) + compare_ranges(heh.loop_cw(), heh.loop_ccw(), 0, true); +} + + +TEST_F(OpenMeshTrimeshRange, FaceVertexRangeMeshVsSmartHandle) +{ + for (auto fh : mesh_.faces()) + { + compare_ranges(mesh_.fv_range(fh) , fh.vertices() , 0, false); + compare_ranges(mesh_.fv_cw_range(fh) , fh.vertices_cw() , 0, false); + compare_ranges(mesh_.fv_ccw_range(fh), fh.vertices_ccw(), 0, false); + } +} + +TEST_F(OpenMeshTrimeshRange, FaceVertexRangeCWVsCCW) +{ + for (auto fh : mesh_.faces()) + compare_ranges(fh.vertices_cw(), fh.vertices_ccw(), 0, true); +} + +TEST_F(OpenMeshTrimeshRange, FaceEdgeRangeMeshVsSmartHandle) +{ + for (auto fh : mesh_.faces()) + { + compare_ranges(mesh_.fe_range(fh) , fh.edges() , 0, false); + compare_ranges(mesh_.fe_cw_range(fh) , fh.edges_cw() , 0, false); + compare_ranges(mesh_.fe_ccw_range(fh), fh.edges_ccw(), 0, false); + } +} + +TEST_F(OpenMeshTrimeshRange, FaceEdgeRangeCWVsCCW) +{ + for (auto fh : mesh_.faces()) + compare_ranges(fh.edges_cw(), fh.edges_ccw(), 0, true); +} + +TEST_F(OpenMeshTrimeshRange, FaceHalfedgeRangeMeshVsSmartHandle) +{ + for (auto fh : mesh_.faces()) + { + compare_ranges(mesh_.fh_range(fh) , fh.halfedges() , 0, false); + compare_ranges(mesh_.fh_cw_range(fh) , fh.halfedges_cw() , 0, false); + compare_ranges(mesh_.fh_ccw_range(fh), fh.halfedges_ccw(), 0, false); + } +} + +TEST_F(OpenMeshTrimeshRange, FaceHalfedgeRangeCWVsCCW) +{ + for (auto fh : mesh_.faces()) + compare_ranges(fh.halfedges_cw(), fh.halfedges_ccw(), 0, true); +} + +TEST_F(OpenMeshTrimeshRange, FaceFaceRangeMeshVsSmartHandle) +{ + for (auto fh : mesh_.faces()) + { + compare_ranges(mesh_.ff_range(fh) , fh.faces() , 0, false); + compare_ranges(mesh_.ff_cw_range(fh) , fh.faces_cw() , 0, false); + compare_ranges(mesh_.ff_ccw_range(fh), fh.faces_ccw(), 0, false); + } +} + +TEST_F(OpenMeshTrimeshRange, FaceFaceRangeCWVsCCW) +{ + for (auto fh : mesh_.faces()) + compare_ranges(fh.faces_cw(), fh.faces_ccw(), 0, true); +} + + +} From 9b85f7713eb4bfd54128e8509a32f47b1a303137 Mon Sep 17 00:00:00 2001 From: Max Lyon Date: Tue, 9 Mar 2021 15:32:44 +0100 Subject: [PATCH 7/9] make it so that CCW iter ranges are the reverse of CW iter ranges, i.e. they do not start with the same element anymore --- src/OpenMesh/Core/Mesh/CirculatorsT.hh | 36 +++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/OpenMesh/Core/Mesh/CirculatorsT.hh b/src/OpenMesh/Core/Mesh/CirculatorsT.hh index e3aaa6e1..622134e8 100644 --- a/src/OpenMesh/Core/Mesh/CirculatorsT.hh +++ b/src/OpenMesh/Core/Mesh/CirculatorsT.hh @@ -156,7 +156,21 @@ class GenericCirculator_ValueHandleFnsT { inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) { return ( heh.is_valid() && (lap_counter == 0 ) ); } - inline static void init(const Mesh*, typename Mesh::HalfedgeHandle&, typename Mesh::HalfedgeHandle&, int&) {}; + inline static void init(const Mesh* mesh, typename Mesh::HalfedgeHandle& heh, typename Mesh::HalfedgeHandle& start, int& lap_counter, bool adjust_for_ccw) + { + if (!CW) // TODO: constexpr if + { + if (adjust_for_ccw) + { + // increment current heh and start so that cw and ccw version dont start with the same element but ranges are actually reversed + int lc = lap_counter; + increment(mesh, heh, start, lap_counter); + start = heh; + lap_counter = lc; + } + } + } + inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { GenericCirculator_CenterEntityFnsT::increment(mesh, heh, start, lap_counter); } @@ -173,7 +187,19 @@ class GenericCirculator_ValueHandleFnsT(mesh, mesh.halfedge_handle(start), end) { - GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_); + bool adjust_for_ccw = true; + GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_, adjust_for_ccw); } GenericCirculatorT(mesh_ref mesh, typename Mesh::HalfedgeHandle heh, bool end = false) : GenericCirculatorBaseT(mesh, heh, end) { - GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_); + bool adjust_for_ccw = false; // if iterator is initialized with specific heh, we want to start there + GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_, adjust_for_ccw); } GenericCirculatorT(const GenericCirculatorT &rhs) : GenericCirculatorBaseT(rhs) {} From eb9d631346f5f89e76932bc9247416a3154c4282 Mon Sep 17 00:00:00 2001 From: Max Lyon Date: Tue, 9 Mar 2021 15:33:05 +0100 Subject: [PATCH 8/9] adjust unittests for new CW CCW behavior --- .../unittests_trimesh_circulator_face_edge.cc | 29 ++++++++-------- .../unittests_trimesh_circulator_face_face.cc | 27 ++++++++------- ...ttests_trimesh_circulator_face_halfedge.cc | 25 +++++++------- ...nittests_trimesh_circulator_face_vertex.cc | 25 +++++++------- ...nittests_trimesh_circulator_vertex_edge.cc | 33 +++++++++---------- ...nittests_trimesh_circulator_vertex_face.cc | 33 +++++++++---------- ...sts_trimesh_circulator_vertex_ihalfedge.cc | 33 +++++++++---------- ...sts_trimesh_circulator_vertex_ohalfedge.cc | 33 +++++++++---------- ...ttests_trimesh_circulator_vertex_vertex.cc | 33 +++++++++---------- src/Unittests/unittests_trimesh_ranges.cc | 18 +++++----- 10 files changed, 141 insertions(+), 148 deletions(-) diff --git a/src/Unittests/unittests_trimesh_circulator_face_edge.cc b/src/Unittests/unittests_trimesh_circulator_face_edge.cc index 8026da8b..f7b88f2c 100644 --- a/src/Unittests/unittests_trimesh_circulator_face_edge.cc +++ b/src/Unittests/unittests_trimesh_circulator_face_edge.cc @@ -191,9 +191,9 @@ TEST_F(OpenMeshTrimeshCirculatorFaceEdge, CWAndCCWTest) { */ - int indices[4] = {4, 1, 3, 4}; - int rev_indices[4]; - std::reverse_copy(indices,indices+4,rev_indices); + int indices[3] = {4, 1, 3}; + int rev_indices[3]; + std::reverse_copy(indices,indices+3,rev_indices); //CCW Mesh::FaceEdgeCCWIter fe_ccwit = mesh_.fe_ccwbegin(mesh_.face_handle(1)); @@ -243,29 +243,28 @@ TEST_F(OpenMeshTrimeshCirculatorFaceEdge, CWAndCCWTest) { /* * conversion properties: - * a) cw_begin == CWIter(ccw_begin()) + * a) *cw_begin == *++CWIter(ccw_end()) * b) cw_iter->idx() == CCWIter(cw_iter)->idx() for valid iterators * c) --cw_iter == CWIter(++ccwIter) for valid iterators - * d) cw_end == CWIter(ccw_end()) => --cw_end != CWIter(++ccw_end()) * + * d) *cw_begin == *++CWIter(ccw_end()) */ Mesh::FaceEdgeCWIter fe_cwIter = mesh_.fe_cwbegin(mesh_.face_handle(1)); // a) - EXPECT_TRUE( fe_cwIter == Mesh::FaceEdgeCWIter(mesh_.fe_ccwbegin(mesh_.face_handle(1))) ) << "ccw to cw conversion failed"; - EXPECT_TRUE( Mesh::FaceEdgeCCWIter(fe_cwIter) == mesh_.fe_ccwbegin(mesh_.face_handle(1)) ) << "cw to ccw conversion failed"; + EXPECT_TRUE( *fe_cwIter == *++Mesh::FaceEdgeCWIter(mesh_.fe_ccwend(mesh_.face_handle(1)))) << "ccw to cw conversion failed"; + EXPECT_TRUE( *++Mesh::FaceEdgeCCWIter(fe_cwIter) == *mesh_.fe_ccwend(mesh_.face_handle(1)) ) << "cw to ccw conversion failed"; // b) EXPECT_EQ( fe_cwIter->idx(), Mesh::FaceEdgeCCWIter(fe_cwIter)->idx()) << "iterators doesnt point on the same element"; // c) + auto fe_ccwIter = Mesh::FaceEdgeCCWIter(fe_cwIter); + EXPECT_EQ(fe_cwIter->idx(),fe_ccwIter->idx())<< "iterators dont point on the same element"; ++fe_cwIter; - fe_ccwend = mesh_.fe_ccwend(mesh_.face_handle(1)); - --fe_ccwend; - EXPECT_EQ(fe_cwIter->idx(),fe_ccwend->idx()) << "iteratoes are not equal after inc/dec"; - // additional conversion check - fe_ccwend = Mesh::FaceEdgeCCWIter(fe_cwIter); - EXPECT_EQ(fe_cwIter->idx(),fe_ccwend->idx())<< "iterators doesnt point on the same element"; + --fe_ccwIter; + EXPECT_EQ(fe_cwIter->idx(),fe_ccwIter->idx()) << "iteratoes are not equal after inc/dec"; // d) - fe_cwIter = Mesh::FaceEdgeCWIter(mesh_.fe_ccwend(mesh_.face_handle(1))); + auto fe_cwEnd = mesh_.fe_ccwend(mesh_.face_handle(1)); + fe_cwIter = Mesh::FaceEdgeCWIter(fe_cwEnd); EXPECT_FALSE(fe_cwIter.is_valid()) << "end iterator is not invalid"; - EXPECT_TRUE(Mesh::FaceEdgeCCWIter(mesh_.fe_cwend(mesh_.face_handle(1))) == mesh_.fe_ccwend(mesh_.face_handle(1))) << "end iterators are not equal"; + EXPECT_TRUE(*mesh_.fe_cwbegin(mesh_.face_handle(1)) == *++fe_cwIter) << "end iterators are not equal"; } diff --git a/src/Unittests/unittests_trimesh_circulator_face_face.cc b/src/Unittests/unittests_trimesh_circulator_face_face.cc index 0a64570c..2a2bb40d 100644 --- a/src/Unittests/unittests_trimesh_circulator_face_face.cc +++ b/src/Unittests/unittests_trimesh_circulator_face_face.cc @@ -267,9 +267,9 @@ TEST_F(OpenMeshTrimeshCirculatorFaceFace, CWAndCCWCheck) { */ - int indices[4] = {2, 0, 3, 2}; - int rev_indices[4]; - std::reverse_copy(indices,indices+4,rev_indices); + int indices[3] = {2, 0, 3}; + int rev_indices[3]; + std::reverse_copy(indices,indices+3,rev_indices); //CCW Mesh::FaceFaceCCWIter ff_ccwit = mesh_.ff_ccwbegin(mesh_.face_handle(1)); @@ -322,26 +322,25 @@ TEST_F(OpenMeshTrimeshCirculatorFaceFace, CWAndCCWCheck) { * a) cw_begin == CWIter(ccw_begin()) * b) cw_iter->idx() == CCWIter(cw_iter)->idx() for valid iterators * c) --cw_iter == CWIter(++ccwIter) for valid iterators - * d) cw_end == CWIter(ccw_end()) => --cw_end != CWIter(++ccw_end()) * + * d) cw_end == CWIter(ccw_end()) */ Mesh::FaceFaceCWIter ff_cwIter = mesh_.ff_cwbegin(mesh_.face_handle(1)); // a) - EXPECT_TRUE( ff_cwIter == Mesh::FaceFaceCWIter(mesh_.ff_ccwbegin(mesh_.face_handle(1))) ) << "ccw to cw conversion failed"; - EXPECT_TRUE( Mesh::FaceFaceCCWIter(ff_cwIter) == mesh_.ff_ccwbegin(mesh_.face_handle(1)) ) << "cw to ccw conversion failed"; + EXPECT_TRUE( *ff_cwIter == *++Mesh::FaceFaceCWIter(mesh_.ff_ccwend(mesh_.face_handle(1)))) << "ccw to cw conversion failed"; + EXPECT_TRUE( *++Mesh::FaceFaceCCWIter(ff_cwIter) == *mesh_.ff_ccwend(mesh_.face_handle(1)) ) << "cw to ccw conversion failed"; // b) EXPECT_EQ( ff_cwIter->idx(), Mesh::FaceFaceCCWIter(ff_cwIter)->idx()) << "iterators doesnt point on the same element"; // c) + auto ff_ccwIter = Mesh::FaceFaceCCWIter(ff_cwIter); + EXPECT_EQ(ff_cwIter->idx(),ff_ccwIter->idx())<< "iterators dont point on the same element"; ++ff_cwIter; - ff_ccwend = mesh_.ff_ccwend(mesh_.face_handle(1)); - --ff_ccwend; - EXPECT_EQ(ff_cwIter->idx(),ff_ccwend->idx()) << "iteratoes are not equal after inc/dec"; - // additional conversion check - ff_ccwend = Mesh::FaceFaceCCWIter(ff_cwIter); - EXPECT_EQ(ff_cwIter->idx(),ff_ccwend->idx())<< "iterators doesnt point on the same element"; + --ff_ccwIter; + EXPECT_EQ(ff_cwIter->idx(),ff_ccwIter->idx()) << "iteratoes are not equal after inc/dec"; // d) - ff_cwIter = Mesh::FaceFaceCWIter(mesh_.ff_ccwend(mesh_.face_handle(1))); + auto ff_cwEnd = mesh_.ff_ccwend(mesh_.face_handle(1)); + ff_cwIter = Mesh::FaceFaceCWIter(ff_cwEnd); EXPECT_FALSE(ff_cwIter.is_valid()) << "end iterator is not invalid"; - EXPECT_TRUE(Mesh::FaceFaceCCWIter(mesh_.ff_cwend(mesh_.face_handle(1))) == mesh_.ff_ccwend(mesh_.face_handle(1))) << "end iterators are not equal"; + EXPECT_TRUE(*mesh_.ff_cwbegin(mesh_.face_handle(1)) == *++ff_cwIter) << "end iterators are not equal"; } diff --git a/src/Unittests/unittests_trimesh_circulator_face_halfedge.cc b/src/Unittests/unittests_trimesh_circulator_face_halfedge.cc index 8b601485..57485d98 100644 --- a/src/Unittests/unittests_trimesh_circulator_face_halfedge.cc +++ b/src/Unittests/unittests_trimesh_circulator_face_halfedge.cc @@ -189,9 +189,9 @@ TEST_F(OpenMeshTrimeshCirculatorFaceHalfEdge, CWAndCCWTest) { */ - int indices[4] = {8, 3, 6, 8}; - int rev_indices[4]; - std::reverse_copy(indices,indices+4,rev_indices); + int indices[3] = {8, 3, 6}; + int rev_indices[3]; + std::reverse_copy(indices,indices+3,rev_indices); //CCW Mesh::FaceHalfedgeCCWIter fh_ccwit = mesh_.fh_ccwbegin(mesh_.face_handle(1)); @@ -248,22 +248,21 @@ TEST_F(OpenMeshTrimeshCirculatorFaceHalfEdge, CWAndCCWTest) { */ Mesh::FaceHalfedgeCWIter fh_cwIter = mesh_.fh_cwbegin(mesh_.face_handle(1)); // a) - EXPECT_TRUE( fh_cwIter == Mesh::FaceHalfedgeCWIter(mesh_.fh_ccwbegin(mesh_.face_handle(1))) ) << "ccw to cw conversion failed"; - EXPECT_TRUE( Mesh::FaceHalfedgeCCWIter(fh_cwIter) == mesh_.fh_ccwbegin(mesh_.face_handle(1)) ) << "cw to ccw conversion failed"; + EXPECT_TRUE( *fh_cwIter == *++Mesh::FaceHalfedgeCWIter(mesh_.fh_ccwend(mesh_.face_handle(1)))) << "ccw to cw conversion failed"; + EXPECT_TRUE( *++Mesh::FaceHalfedgeCCWIter(fh_cwIter) == *mesh_.fh_ccwend(mesh_.face_handle(1)) ) << "cw to ccw conversion failed"; // b) EXPECT_EQ( fh_cwIter->idx(), Mesh::FaceHalfedgeCCWIter(fh_cwIter)->idx()) << "iterators doesnt point on the same element"; // c) + auto fh_ccwIter = Mesh::FaceHalfedgeCCWIter(fh_cwIter); + EXPECT_EQ(fh_cwIter->idx(),fh_ccwIter->idx())<< "iterators dont point on the same element"; ++fh_cwIter; - fh_ccwend = mesh_.fh_ccwend(mesh_.face_handle(1)); - --fh_ccwend; - EXPECT_EQ(fh_cwIter->idx(),fh_ccwend->idx()) << "iteratoes are not equal after inc/dec"; - // additional conversion check - fh_ccwend = Mesh::FaceHalfedgeCCWIter(fh_cwIter); - EXPECT_EQ(fh_cwIter->idx(),fh_ccwend->idx())<< "iterators doesnt point on the same element"; + --fh_ccwIter; + EXPECT_EQ(fh_cwIter->idx(),fh_ccwIter->idx()) << "iteratoes are not equal after inc/dec"; // d) - fh_cwIter = Mesh::FaceHalfedgeCWIter(mesh_.fh_ccwend(mesh_.face_handle(1))); + auto fh_cwEnd = mesh_.fh_ccwend(mesh_.face_handle(1)); + fh_cwIter = Mesh::FaceHalfedgeCWIter(fh_cwEnd); EXPECT_FALSE(fh_cwIter.is_valid()) << "end iterator is not invalid"; - EXPECT_TRUE(Mesh::FaceHalfedgeCCWIter(mesh_.fh_cwend(mesh_.face_handle(1))) == mesh_.fh_ccwend(mesh_.face_handle(1))) << "end iterators are not equal"; + EXPECT_TRUE(*mesh_.fh_cwbegin(mesh_.face_handle(1)) == *++fh_cwIter) << "end iterators are not equal"; } diff --git a/src/Unittests/unittests_trimesh_circulator_face_vertex.cc b/src/Unittests/unittests_trimesh_circulator_face_vertex.cc index 7daa13bf..89d55f04 100644 --- a/src/Unittests/unittests_trimesh_circulator_face_vertex.cc +++ b/src/Unittests/unittests_trimesh_circulator_face_vertex.cc @@ -261,9 +261,9 @@ TEST_F(OpenMeshTrimeshCirculatorFaceVertex, CWAndCCWCheck) { 3 ==== 4 */ - int indices[4] = {0, 1, 2, 0}; - int rev_indices[4]; - std::reverse_copy(indices,indices+4,rev_indices); + int indices[3] = {0, 1, 2}; + int rev_indices[3]; + std::reverse_copy(indices,indices+3,rev_indices); //CCW Mesh::FaceVertexCCWIter fv_ccwit = mesh_.fv_ccwbegin(fh0); @@ -320,22 +320,21 @@ TEST_F(OpenMeshTrimeshCirculatorFaceVertex, CWAndCCWCheck) { */ Mesh::FaceVertexCWIter fv_cwIter = mesh_.fv_cwbegin(mesh_.face_handle(1)); // a) - EXPECT_TRUE( fv_cwIter == Mesh::FaceVertexCWIter(mesh_.fv_ccwbegin(mesh_.face_handle(1))) ) << "ccw to cw conversion failed"; - EXPECT_TRUE( Mesh::FaceVertexCCWIter(fv_cwIter) == mesh_.fv_ccwbegin(mesh_.face_handle(1)) ) << "cw to ccw conversion failed"; + EXPECT_TRUE( *fv_cwIter == *++Mesh::FaceVertexCWIter(mesh_.fv_ccwend(mesh_.face_handle(1)))) << "ccw to cw conversion failed"; + EXPECT_TRUE( *++Mesh::FaceVertexCCWIter(fv_cwIter) == *mesh_.fv_ccwend(mesh_.face_handle(1)) ) << "cw to ccw conversion failed"; // b) EXPECT_EQ( fv_cwIter->idx(), Mesh::FaceVertexCCWIter(fv_cwIter)->idx()) << "iterators doesnt point on the same element"; // c) + auto fv_ccwIter = Mesh::FaceVertexCCWIter(fv_cwIter); + EXPECT_EQ(fv_cwIter->idx(),fv_ccwIter->idx())<< "iterators dont point on the same element"; ++fv_cwIter; - fv_ccwend = mesh_.fv_ccwend(mesh_.face_handle(1)); - --fv_ccwend; - EXPECT_EQ(fv_cwIter->idx(),fv_ccwend->idx()) << "iteratoes are not equal after inc/dec"; - // additional conversion check - fv_ccwend = Mesh::FaceVertexCCWIter(fv_cwIter); - EXPECT_EQ(fv_cwIter->idx(),fv_ccwend->idx())<< "iterators doesnt point on the same element"; + --fv_ccwIter; + EXPECT_EQ(fv_cwIter->idx(),fv_ccwIter->idx()) << "iteratoes are not equal after inc/dec"; // d) - fv_cwIter = Mesh::FaceVertexCWIter(mesh_.fv_ccwend(mesh_.face_handle(1))); + auto fv_cwEnd = mesh_.fv_ccwend(mesh_.face_handle(1)); + fv_cwIter = Mesh::FaceVertexCWIter(fv_cwEnd); EXPECT_FALSE(fv_cwIter.is_valid()) << "end iterator is not invalid"; - EXPECT_TRUE(Mesh::FaceVertexCCWIter(mesh_.fv_cwend(mesh_.face_handle(1))) == mesh_.fv_ccwend(mesh_.face_handle(1))) << "end iterators are not equal"; + EXPECT_TRUE(*mesh_.fv_cwbegin(mesh_.face_handle(1)) == *++fv_cwIter) << "end iterators are not equal"; } diff --git a/src/Unittests/unittests_trimesh_circulator_vertex_edge.cc b/src/Unittests/unittests_trimesh_circulator_vertex_edge.cc index 9689cf89..6a224444 100644 --- a/src/Unittests/unittests_trimesh_circulator_vertex_edge.cc +++ b/src/Unittests/unittests_trimesh_circulator_vertex_edge.cc @@ -336,9 +336,9 @@ TEST_F(OpenMeshTrimeshCirculatorVertexEdge, CWAndCCWCheck) { 3 ==== 4 */ - int indices[5] = {5, 1, 0, 3, 5}; - int rev_indices[5]; - std::reverse_copy(indices,indices+5,rev_indices); + int ccw_indices[4] = {1, 0, 3, 5}; + int cw_indices[4]; + std::reverse_copy(ccw_indices,ccw_indices+4,cw_indices); Mesh::VertexHandle vh = vhandle[1]; @@ -348,7 +348,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexEdge, CWAndCCWCheck) { size_t i = 0; for (;ve_ccwit != ve_ccwend; ++ve_ccwit, ++i) { - EXPECT_EQ(indices[i], ve_ccwit->idx()) << "Index wrong in VertexEdgeCCWIter"; + EXPECT_EQ(ccw_indices[i], ve_ccwit->idx()) << "Index wrong in VertexEdgeCCWIter"; } EXPECT_FALSE(ve_ccwit.is_valid()) << "Iterator invalid in VertexEdgeCCWIter at end"; @@ -360,7 +360,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexEdge, CWAndCCWCheck) { i = 0; for (;cve_ccwit != cve_ccwend; ++cve_ccwit, ++i) { - EXPECT_EQ(indices[i], cve_ccwit->idx()) << "Index wrong in ConstVertexEdgeCCWIter"; + EXPECT_EQ(ccw_indices[i], cve_ccwit->idx()) << "Index wrong in ConstVertexEdgeCCWIter"; } EXPECT_FALSE(cve_ccwit.is_valid()) << "Iterator invalid in ConstVertexEdgeCCWIter at end"; @@ -372,7 +372,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexEdge, CWAndCCWCheck) { i = 0; for (;ve_cwit != ve_cwend; ++ve_cwit, ++i) { - EXPECT_EQ(rev_indices[i], ve_cwit->idx()) << "Index wrong in VertexEdgeCWIter"; + EXPECT_EQ(cw_indices[i], ve_cwit->idx()) << "Index wrong in VertexEdgeCWIter"; } EXPECT_FALSE(ve_cwit.is_valid()) << "Iterator invalid in VertexEdgeCWIter at end"; EXPECT_TRUE( ve_cwit == ve_cwend ) << "End iterator for VertexEdgeCWIter not matching"; @@ -383,7 +383,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexEdge, CWAndCCWCheck) { i = 0; for (;cve_cwit != cve_cwend; ++cve_cwit, ++i) { - EXPECT_EQ(rev_indices[i], cve_cwit->idx()) << "Index wrong in ConstVertexEdgeCWIter"; + EXPECT_EQ(cw_indices[i], cve_cwit->idx()) << "Index wrong in ConstVertexEdgeCWIter"; } EXPECT_FALSE(cve_cwit.is_valid()) << "Iterator invalid in ConstVertexEdgeCWIter at end"; EXPECT_TRUE( cve_cwit == cve_cwend ) << "End iterator for ConstVertexEdgeCWIter not matching"; @@ -397,22 +397,21 @@ TEST_F(OpenMeshTrimeshCirculatorVertexEdge, CWAndCCWCheck) { */ Mesh::VertexEdgeCWIter ve_cwIter = mesh_.ve_cwbegin(vh); // a) - EXPECT_TRUE( ve_cwIter == Mesh::VertexEdgeCWIter(mesh_.ve_ccwbegin(vh)) ) << "ccw to cw conversion failed"; - EXPECT_TRUE( Mesh::VertexEdgeCCWIter(ve_cwIter) == mesh_.ve_ccwbegin(vh) ) << "cw to ccw conversion failed"; + EXPECT_TRUE( *ve_cwIter == *++Mesh::VertexEdgeCWIter(mesh_.ve_ccwend(vh))) << "ccw to cw conversion failed"; + EXPECT_TRUE( *++Mesh::VertexEdgeCCWIter(ve_cwIter) == *mesh_.ve_ccwend(vh) ) << "cw to ccw conversion failed"; // b) EXPECT_EQ( ve_cwIter->idx(), Mesh::VertexEdgeCCWIter(ve_cwIter)->idx()) << "iterators doesnt point on the same element"; // c) + auto ve_ccwIter = Mesh::VertexEdgeCCWIter(ve_cwIter); + EXPECT_EQ(ve_cwIter->idx(),ve_ccwIter->idx())<< "iterators dont point on the same element"; ++ve_cwIter; - ve_ccwend = mesh_.ve_ccwend(vh); - --ve_ccwend; - EXPECT_EQ(ve_cwIter->idx(),ve_ccwend->idx()) << "iteratoes are not equal after inc/dec"; - // additional conversion check - ve_ccwend = Mesh::VertexEdgeCCWIter(ve_cwIter); - EXPECT_EQ(ve_cwIter->idx(),ve_ccwend->idx())<< "iterators doesnt point on the same element"; + --ve_ccwIter; + EXPECT_EQ(ve_cwIter->idx(),ve_ccwIter->idx()) << "iteratoes are not equal after inc/dec"; // d) - ve_cwIter = Mesh::VertexEdgeCWIter(mesh_.ve_ccwend(vh)); + auto ve_cwEnd = mesh_.ve_ccwend(vh); + ve_cwIter = Mesh::VertexEdgeCWIter(ve_cwEnd); EXPECT_FALSE(ve_cwIter.is_valid()) << "end iterator is not invalid"; - EXPECT_TRUE(Mesh::VertexEdgeCCWIter(mesh_.ve_cwend(vh)) == mesh_.ve_ccwend(vh)) << "end iterators are not equal"; + EXPECT_TRUE(*mesh_.ve_cwbegin(vh) == *++ve_cwIter) << "end iterators are not equal"; } diff --git a/src/Unittests/unittests_trimesh_circulator_vertex_face.cc b/src/Unittests/unittests_trimesh_circulator_vertex_face.cc index de3db015..a97c4e77 100644 --- a/src/Unittests/unittests_trimesh_circulator_vertex_face.cc +++ b/src/Unittests/unittests_trimesh_circulator_vertex_face.cc @@ -509,9 +509,9 @@ TEST_F(OpenMeshTrimeshCirculatorVertexFace, CWAndCCWCheck) { 3 ==== 4 */ - int indices[5] = {3, 0, 2, 1, 3}; - int rev_indices[5]; - std::reverse_copy(indices,indices+5,rev_indices); + int ccw_indices[4] = {0, 2, 1, 3}; + int cw_indices[4]; + std::reverse_copy(ccw_indices,ccw_indices+4,cw_indices); Mesh::VertexHandle vh = vhandle[1]; @@ -521,7 +521,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexFace, CWAndCCWCheck) { size_t i = 0; for (;vf_ccwit != vf_ccwend; ++vf_ccwit, ++i) { - EXPECT_EQ(indices[i], vf_ccwit->idx()) << "Index wrong in VertexFaceCCWIter"; + EXPECT_EQ(ccw_indices[i], vf_ccwit->idx()) << "Index wrong in VertexFaceCCWIter"; } EXPECT_FALSE(vf_ccwit.is_valid()) << "Iterator invalid in VertexFaceCCWIter at end"; @@ -533,7 +533,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexFace, CWAndCCWCheck) { i = 0; for (;cvf_ccwit != cvf_ccwend; ++cvf_ccwit, ++i) { - EXPECT_EQ(indices[i], cvf_ccwit->idx()) << "Index wrong in ConstVertexFaceCCWIter"; + EXPECT_EQ(ccw_indices[i], cvf_ccwit->idx()) << "Index wrong in ConstVertexFaceCCWIter"; } EXPECT_FALSE(cvf_ccwit.is_valid()) << "Iterator invalid in ConstVertexFaceCCWIter at end"; @@ -545,7 +545,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexFace, CWAndCCWCheck) { i = 0; for (;vf_cwit != vf_cwend; ++vf_cwit, ++i) { - EXPECT_EQ(rev_indices[i], vf_cwit->idx()) << "Index wrong in VertexFaceCWIter"; + EXPECT_EQ(cw_indices[i], vf_cwit->idx()) << "Index wrong in VertexFaceCWIter"; } EXPECT_FALSE(vf_cwit.is_valid()) << "Iterator invalid in VertexFaceCWIter at end"; EXPECT_TRUE( vf_cwit == vf_cwend ) << "End iterator for VertexFaceCWIter not matching"; @@ -556,7 +556,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexFace, CWAndCCWCheck) { i = 0; for (;cvf_cwit != cvf_cwend; ++cvf_cwit, ++i) { - EXPECT_EQ(rev_indices[i], cvf_cwit->idx()) << "Index wrong in ConstVertexFaceCWIter"; + EXPECT_EQ(cw_indices[i], cvf_cwit->idx()) << "Index wrong in ConstVertexFaceCWIter"; } EXPECT_FALSE(cvf_cwit.is_valid()) << "Iterator invalid in ConstVertexFaceCWIter at end"; EXPECT_TRUE( cvf_cwit == cvf_cwend ) << "End iterator for ConstVertexFaceCWIter not matching"; @@ -570,22 +570,21 @@ TEST_F(OpenMeshTrimeshCirculatorVertexFace, CWAndCCWCheck) { */ Mesh::VertexFaceCWIter vf_cwIter = mesh_.vf_cwbegin(vh); // a) - EXPECT_TRUE( vf_cwIter == Mesh::VertexFaceCWIter(mesh_.vf_ccwbegin(vh)) ) << "ccw to cw conversion failed"; - EXPECT_TRUE( Mesh::VertexFaceCCWIter(vf_cwIter) == mesh_.vf_ccwbegin(vh) ) << "cw to ccw conversion failed"; + EXPECT_TRUE( *vf_cwIter == *++Mesh::VertexFaceCWIter(mesh_.vf_ccwend(vh))) << "ccw to cw conversion failed"; + EXPECT_TRUE( *++Mesh::VertexFaceCCWIter(vf_cwIter) == *mesh_.vf_ccwend(vh) ) << "cw to ccw conversion failed"; // b) EXPECT_EQ( vf_cwIter->idx(), Mesh::VertexFaceCCWIter(vf_cwIter)->idx()) << "iterators doesnt point on the same element"; // c) + auto vf_ccwIter = Mesh::VertexFaceCCWIter(vf_cwIter); + EXPECT_EQ(vf_cwIter->idx(),vf_ccwIter->idx())<< "iterators dont point on the same element"; ++vf_cwIter; - vf_ccwend = mesh_.vf_ccwend(vh); - --vf_ccwend; - EXPECT_EQ(vf_cwIter->idx(),vf_ccwend->idx()) << "iteratoes are not equal after inc/dec"; - // additional conversion check - vf_ccwend = Mesh::VertexFaceCCWIter(vf_cwIter); - EXPECT_EQ(vf_cwIter->idx(),vf_ccwend->idx())<< "iterators doesnt point on the same element"; + --vf_ccwIter; + EXPECT_EQ(vf_cwIter->idx(),vf_ccwIter->idx()) << "iteratoes are not equal after inc/dec"; // d) - vf_cwIter = Mesh::VertexFaceCWIter(mesh_.vf_ccwend(vh)); + auto vf_cwEnd = mesh_.vf_ccwend(vh); + vf_cwIter = Mesh::VertexFaceCWIter(vf_cwEnd); EXPECT_FALSE(vf_cwIter.is_valid()) << "end iterator is not invalid"; - EXPECT_TRUE(Mesh::VertexFaceCCWIter(mesh_.vf_cwend(vh)) == mesh_.vf_ccwend(vh)) << "end iterators are not equal"; + EXPECT_TRUE(*mesh_.vf_cwbegin(vh) == *++vf_cwIter) << "end iterators are not equal"; } diff --git a/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc b/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc index 85559b0b..9b2e5f5e 100644 --- a/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc +++ b/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc @@ -450,9 +450,9 @@ TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, CWAndCCWCheck) { 3 ==== 4 */ - int indices[4] = {14, 5, 2, 14}; - int rev_indices[4]; - std::reverse_copy(indices,indices+4,rev_indices); + int cw_indices[3] = {14, 2, 5}; + int ccw_indices[3]; + std::reverse_copy(cw_indices,cw_indices+3,ccw_indices); Mesh::VertexHandle vh = vhandle[2]; @@ -462,7 +462,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, CWAndCCWCheck) { size_t i = 0; for (;vih_ccwit != vih_ccwend; ++vih_ccwit, ++i) { - EXPECT_EQ(indices[i], vih_ccwit->idx()) << "Index wrong in VertexIHalfedgeCCWIter"; + EXPECT_EQ(ccw_indices[i], vih_ccwit->idx()) << "Index wrong in VertexIHalfedgeCCWIter"; } EXPECT_FALSE(vih_ccwit.is_valid()) << "Iterator invalid in VertexIHalfedgeCCWIter at end"; @@ -474,7 +474,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, CWAndCCWCheck) { i = 0; for (;cvih_ccwit != cvih_ccwend; ++cvih_ccwit, ++i) { - EXPECT_EQ(indices[i], cvih_ccwit->idx()) << "Index wrong in ConstVertexIHalfedgeCCWIter"; + EXPECT_EQ(ccw_indices[i], cvih_ccwit->idx()) << "Index wrong in ConstVertexIHalfedgeCCWIter"; } EXPECT_FALSE(cvih_ccwit.is_valid()) << "Iterator invalid in ConstVertexIHalfedgeCCWIter at end"; @@ -486,7 +486,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, CWAndCCWCheck) { i = 0; for (;vih_cwit != vih_cwend; ++vih_cwit, ++i) { - EXPECT_EQ(rev_indices[i], vih_cwit->idx()) << "Index wrong in VertexIHalfedgeCWIter"; + EXPECT_EQ(cw_indices[i], vih_cwit->idx()) << "Index wrong in VertexIHalfedgeCWIter"; } EXPECT_FALSE(vih_cwit.is_valid()) << "Iterator invalid in VertexIHalfedgeCWIter at end"; EXPECT_TRUE( vih_cwit == vih_cwend ) << "End iterator for VertexIHalfedgeCWIter not matching"; @@ -497,7 +497,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, CWAndCCWCheck) { i = 0; for (;cvih_cwit != cvih_cwend; ++cvih_cwit, ++i) { - EXPECT_EQ(rev_indices[i], cvih_cwit->idx()) << "Index wrong in ConstVertexIHalfedgeCWIter"; + EXPECT_EQ(cw_indices[i], cvih_cwit->idx()) << "Index wrong in ConstVertexIHalfedgeCWIter"; } EXPECT_FALSE(cvih_cwit.is_valid()) << "Iterator invalid in ConstVertexIHalfedgeCWIter at end"; EXPECT_TRUE( cvih_cwit == cvih_cwend ) << "End iterator for ConstVertexIHalfedgeCWIter not matching"; @@ -511,22 +511,21 @@ TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, CWAndCCWCheck) { */ Mesh::VertexIHalfedgeCWIter vih_cwIter = mesh_.vih_cwbegin(vh); // a) - EXPECT_TRUE( vih_cwIter == Mesh::VertexIHalfedgeCWIter(mesh_.vih_ccwbegin(vh)) ) << "ccw to cw conversion failed"; - EXPECT_TRUE( Mesh::VertexIHalfedgeCCWIter(vih_cwIter) == mesh_.vih_ccwbegin(vh) ) << "cw to ccw conversion failed"; + EXPECT_TRUE( *vih_cwIter == *++Mesh::VertexIHalfedgeCWIter(mesh_.vih_ccwend(vh))) << "ccw to cw conversion failed"; + EXPECT_TRUE( *++Mesh::VertexIHalfedgeCCWIter(vih_cwIter) == *mesh_.vih_ccwend(vh) ) << "cw to ccw conversion failed"; // b) EXPECT_EQ( vih_cwIter->idx(), Mesh::VertexIHalfedgeCCWIter(vih_cwIter)->idx()) << "iterators doesnt point on the same element"; // c) + auto vih_ccwIter = Mesh::VertexIHalfedgeCCWIter(vih_cwIter); + EXPECT_EQ(vih_cwIter->idx(),vih_ccwIter->idx())<< "iterators dont point on the same element"; ++vih_cwIter; - vih_ccwend = mesh_.vih_ccwend(vh); - --vih_ccwend; - EXPECT_EQ(vih_cwIter->idx(),vih_ccwend->idx()) << "iteratoes are not equal after inc/dec"; - // additional conversion check - vih_ccwend = Mesh::VertexIHalfedgeCCWIter(vih_cwIter); - EXPECT_EQ(vih_cwIter->idx(),vih_ccwend->idx())<< "iterators doesnt point on the same element"; + --vih_ccwIter; + EXPECT_EQ(vih_cwIter->idx(),vih_ccwIter->idx()) << "iteratoes are not equal after inc/dec"; // d) - vih_cwIter = Mesh::VertexIHalfedgeCWIter(mesh_.vih_ccwend(vh)); + auto vih_cwEnd = mesh_.vih_ccwend(vh); + vih_cwIter = Mesh::VertexIHalfedgeCWIter(vih_cwEnd); EXPECT_FALSE(vih_cwIter.is_valid()) << "end iterator is not invalid"; - EXPECT_TRUE(Mesh::VertexIHalfedgeCCWIter(mesh_.vih_cwend(vh)) == mesh_.vih_ccwend(vh)) << "end iterators are not equal"; + EXPECT_TRUE(*mesh_.vih_cwbegin(vh) == *++vih_cwIter) << "end iterators are not equal"; } diff --git a/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc b/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc index 49de4076..4ebfa5b9 100644 --- a/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc +++ b/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc @@ -450,9 +450,9 @@ TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, CWAndCCWCheck) { 3 ==== 4 */ - int indices[5] = {11, 2, 1, 6, 11}; - int rev_indices[5]; - std::reverse_copy(indices,indices+5,rev_indices); + int cw_indices[4] = {11, 6, 1, 2}; + int ccw_indices[4]; + std::reverse_copy(cw_indices,cw_indices+4,ccw_indices); Mesh::VertexHandle vh = vhandle[1]; @@ -462,7 +462,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, CWAndCCWCheck) { size_t i = 0; for (;voh_ccwit != voh_ccwend; ++voh_ccwit, ++i) { - EXPECT_EQ(indices[i], voh_ccwit->idx()) << "Index wrong in VertexOHalfedgeCCWIter"; + EXPECT_EQ(ccw_indices[i], voh_ccwit->idx()) << "Index wrong in VertexOHalfedgeCCWIter"; } EXPECT_FALSE(voh_ccwit.is_valid()) << "Iterator invalid in VertexOHalfedgeCCWIter at end"; @@ -474,7 +474,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, CWAndCCWCheck) { i = 0; for (;cvoh_ccwit != cvoh_ccwend; ++cvoh_ccwit, ++i) { - EXPECT_EQ(indices[i], cvoh_ccwit->idx()) << "Index wrong in ConstVertexOHalfedgeCCWIter"; + EXPECT_EQ(ccw_indices[i], cvoh_ccwit->idx()) << "Index wrong in ConstVertexOHalfedgeCCWIter"; } EXPECT_FALSE(cvoh_ccwit.is_valid()) << "Iterator invalid in ConstVertexOHalfedgeCCWIter at end"; @@ -486,7 +486,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, CWAndCCWCheck) { i = 0; for (;voh_cwit != voh_cwend; ++voh_cwit, ++i) { - EXPECT_EQ(rev_indices[i], voh_cwit->idx()) << "Index wrong in VertexOHalfedgeCWIter"; + EXPECT_EQ(cw_indices[i], voh_cwit->idx()) << "Index wrong in VertexOHalfedgeCWIter"; } EXPECT_FALSE(voh_cwit.is_valid()) << "Iterator invalid in VertexOHalfedgeCWIter at end"; EXPECT_TRUE( voh_cwit == voh_cwend ) << "End iterator for VertexOHalfedgeCWIter not matching"; @@ -497,7 +497,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, CWAndCCWCheck) { i = 0; for (;cvoh_cwit != cvoh_cwend; ++cvoh_cwit, ++i) { - EXPECT_EQ(rev_indices[i], cvoh_cwit->idx()) << "Index wrong in ConstVertexOHalfedgeCWIter"; + EXPECT_EQ(cw_indices[i], cvoh_cwit->idx()) << "Index wrong in ConstVertexOHalfedgeCWIter"; } EXPECT_FALSE(cvoh_cwit.is_valid()) << "Iterator invalid in ConstVertexOHalfedgeCWIter at end"; EXPECT_TRUE( cvoh_cwit == cvoh_cwend ) << "End iterator for ConstVertexOHalfedgeCWIter not matching"; @@ -511,22 +511,21 @@ TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, CWAndCCWCheck) { */ Mesh::VertexOHalfedgeCWIter voh_cwIter = mesh_.voh_cwbegin(vh); // a) - EXPECT_TRUE( voh_cwIter == Mesh::VertexOHalfedgeCWIter(mesh_.voh_ccwbegin(vh)) ) << "ccw to cw conversion failed"; - EXPECT_TRUE( Mesh::VertexOHalfedgeCCWIter(voh_cwIter) == mesh_.voh_ccwbegin(vh) ) << "cw to ccw conversion failed"; + EXPECT_TRUE( *voh_cwIter == *++Mesh::VertexOHalfedgeCWIter(mesh_.voh_ccwend(vh))) << "ccw to cw conversion failed"; + EXPECT_TRUE( *++Mesh::VertexOHalfedgeCCWIter(voh_cwIter) == *mesh_.voh_ccwend(vh) ) << "cw to ccw conversion failed"; // b) EXPECT_EQ( voh_cwIter->idx(), Mesh::VertexOHalfedgeCCWIter(voh_cwIter)->idx()) << "iterators doesnt point on the same element"; // c) + auto voh_ccwIter = Mesh::VertexOHalfedgeCCWIter(voh_cwIter); + EXPECT_EQ(voh_cwIter->idx(),voh_ccwIter->idx())<< "iterators dont point on the same element"; ++voh_cwIter; - voh_ccwend = mesh_.voh_ccwend(vh); - --voh_ccwend; - EXPECT_EQ(voh_cwIter->idx(),voh_ccwend->idx()) << "iteratoes are not equal after inc/dec"; - // additional conversion check - voh_ccwend = Mesh::VertexOHalfedgeCCWIter(voh_cwIter); - EXPECT_EQ(voh_cwIter->idx(),voh_ccwend->idx())<< "iterators doesnt point on the same element"; + --voh_ccwIter; + EXPECT_EQ(voh_cwIter->idx(),voh_ccwIter->idx()) << "iteratoes are not equal after inc/dec"; // d) - voh_cwIter = Mesh::VertexOHalfedgeCWIter(mesh_.voh_ccwend(vh)); + auto voh_cwEnd = mesh_.voh_ccwend(vh); + voh_cwIter = Mesh::VertexOHalfedgeCWIter(voh_cwEnd); EXPECT_FALSE(voh_cwIter.is_valid()) << "end iterator is not invalid"; - EXPECT_TRUE(Mesh::VertexOHalfedgeCCWIter(mesh_.voh_cwend(vh)) == mesh_.voh_ccwend(vh)) << "end iterators are not equal"; + EXPECT_TRUE(*mesh_.voh_cwbegin(vh) == *++voh_cwIter) << "end iterators are not equal"; } diff --git a/src/Unittests/unittests_trimesh_circulator_vertex_vertex.cc b/src/Unittests/unittests_trimesh_circulator_vertex_vertex.cc index 18e839ff..c1edd31f 100644 --- a/src/Unittests/unittests_trimesh_circulator_vertex_vertex.cc +++ b/src/Unittests/unittests_trimesh_circulator_vertex_vertex.cc @@ -339,9 +339,9 @@ TEST_F(OpenMeshTrimeshCirculatorVertexVertex, CWAndCCWCheck) { 3 ==== 4 */ - int indices[5] = {4, 2, 0, 3, 4}; - int rev_indices[5]; - std::reverse_copy(indices,indices+5,rev_indices); + int cw_indices[4] = {4, 3, 0, 2}; + int ccw_indices[4]; + std::reverse_copy(cw_indices,cw_indices+4,ccw_indices); Mesh::VertexHandle vh = vhandle[1]; @@ -351,7 +351,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexVertex, CWAndCCWCheck) { size_t i = 0; for (;vv_ccwit != vv_ccwend; ++vv_ccwit, ++i) { - EXPECT_EQ(indices[i], vv_ccwit->idx()) << "Index wrong in VertexVertexCCWIter"; + EXPECT_EQ(ccw_indices[i], vv_ccwit->idx()) << "Index wrong in VertexVertexCCWIter"; } EXPECT_FALSE(vv_ccwit.is_valid()) << "Iterator invalid in VertexVertexCCWIter at end"; @@ -363,7 +363,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexVertex, CWAndCCWCheck) { i = 0; for (;cvv_ccwit != cvv_ccwend; ++cvv_ccwit, ++i) { - EXPECT_EQ(indices[i], cvv_ccwit->idx()) << "Index wrong in ConstVertexVertexCCWIter"; + EXPECT_EQ(ccw_indices[i], cvv_ccwit->idx()) << "Index wrong in ConstVertexVertexCCWIter"; } EXPECT_FALSE(cvv_ccwit.is_valid()) << "Iterator invalid in ConstVertexVertexCCWIter at end"; @@ -375,7 +375,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexVertex, CWAndCCWCheck) { i = 0; for (;vv_cwit != vv_cwend; ++vv_cwit, ++i) { - EXPECT_EQ(rev_indices[i], vv_cwit->idx()) << "Index wrong in VertexVertexCWIter"; + EXPECT_EQ(cw_indices[i], vv_cwit->idx()) << "Index wrong in VertexVertexCWIter"; } EXPECT_FALSE(vv_cwit.is_valid()) << "Iterator invalid in VertexVertexCWIter at end"; EXPECT_TRUE( vv_cwit == vv_cwend ) << "End iterator for VertexVertexCWIter not matching"; @@ -386,7 +386,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexVertex, CWAndCCWCheck) { i = 0; for (;cvv_cwit != cvv_cwend; ++cvv_cwit, ++i) { - EXPECT_EQ(rev_indices[i], cvv_cwit->idx()) << "Index wrong in ConstVertexVertexCWIter"; + EXPECT_EQ(cw_indices[i], cvv_cwit->idx()) << "Index wrong in ConstVertexVertexCWIter"; } EXPECT_FALSE(cvv_cwit.is_valid()) << "Iterator invalid in ConstVertexVertexCWIter at end"; EXPECT_TRUE( cvv_cwit == cvv_cwend ) << "End iterator for ConstVertexVertexCWIter not matching"; @@ -400,22 +400,21 @@ TEST_F(OpenMeshTrimeshCirculatorVertexVertex, CWAndCCWCheck) { */ Mesh::VertexVertexCWIter vv_cwIter = mesh_.vv_cwbegin(vh); // a) - EXPECT_TRUE( vv_cwIter == Mesh::VertexVertexCWIter(mesh_.vv_ccwbegin(vh)) ) << "ccw to cw convvrsion failed"; - EXPECT_TRUE( Mesh::VertexVertexCCWIter(vv_cwIter) == mesh_.vv_ccwbegin(vh) ) << "cw to ccw convvrsion failed"; + EXPECT_TRUE( *vv_cwIter == *++Mesh::VertexVertexCWIter(mesh_.vv_ccwend(vh))) << "ccw to cw conversion failed"; + EXPECT_TRUE( *++Mesh::VertexVertexCCWIter(vv_cwIter) == *mesh_.vv_ccwend(vh) ) << "cw to ccw conversion failed"; // b) EXPECT_EQ( vv_cwIter->idx(), Mesh::VertexVertexCCWIter(vv_cwIter)->idx()) << "iterators doesnt point on the same element"; // c) + auto vv_ccwIter = Mesh::VertexVertexCCWIter(vv_cwIter); + EXPECT_EQ(vv_cwIter->idx(),vv_ccwIter->idx())<< "iterators dont point on the same element"; ++vv_cwIter; - vv_ccwend = mesh_.vv_ccwend(vh); - --vv_ccwend; - EXPECT_EQ(vv_cwIter->idx(),vv_ccwend->idx()) << "iteratoes are not equal after inc/dec"; - // additional conversion check - vv_ccwend = Mesh::VertexVertexCCWIter(vv_cwIter); - EXPECT_EQ(vv_cwIter->idx(),vv_ccwend->idx())<< "iterators doesnt point on the same element"; + --vv_ccwIter; + EXPECT_EQ(vv_cwIter->idx(),vv_ccwIter->idx()) << "iteratoes are not equal after inc/dec"; // d) - vv_cwIter = Mesh::VertexVertexCWIter(mesh_.vv_ccwend(vh)); + auto vv_cwEnd = mesh_.vv_ccwend(vh); + vv_cwIter = Mesh::VertexVertexCWIter(vv_cwEnd); EXPECT_FALSE(vv_cwIter.is_valid()) << "end iterator is not invalid"; - EXPECT_TRUE(Mesh::VertexVertexCCWIter(mesh_.vv_cwend(vh)) == mesh_.vv_ccwend(vh)) << "end iterators are not equal"; + EXPECT_TRUE(*mesh_.vv_cwbegin(vh) == *++vv_cwIter) << "end iterators are not equal"; } diff --git a/src/Unittests/unittests_trimesh_ranges.cc b/src/Unittests/unittests_trimesh_ranges.cc index d6c1582a..c57bcf75 100644 --- a/src/Unittests/unittests_trimesh_ranges.cc +++ b/src/Unittests/unittests_trimesh_ranges.cc @@ -106,7 +106,7 @@ void compare_ranges(RangeT1&& range1, RangeT2&& range2, int offset, bool reverse for (size_t i = 0; i < n; ++i) { size_t id1 = (i+offset)%n; - size_t id2 = reverse ? (n-i)%n : i; + size_t id2 = reverse ? (n-i-1)%n : i; EXPECT_EQ(vec1[id1].idx(), vec2[id2].idx()) << "Elements are not the same with offset = " << offset << " and reverse = " << std::to_string(reverse); } } @@ -222,9 +222,8 @@ TEST_F(OpenMeshTrimeshRange, VertexIncomingHalfedgesRangeBoundaryConsistency) EXPECT_TRUE(mesh_.vih_cwbegin(vh)->opp().is_boundary()); EXPECT_TRUE(mesh_.vih_cw_range(vh).begin()->opp().is_boundary()); - // TODO: this should be false, instead opp should be boundary - EXPECT_TRUE(mesh_.vih_ccwbegin(vh)->opp().is_boundary()); - EXPECT_TRUE(mesh_.vih_ccw_range(vh).begin()->opp().is_boundary()); + EXPECT_TRUE(mesh_.vih_ccwbegin(vh)->is_boundary()); + EXPECT_TRUE(mesh_.vih_ccw_range(vh).begin()->is_boundary()); } } @@ -290,9 +289,8 @@ TEST_F(OpenMeshTrimeshRange, VertexOutgoingHalfedgesRangeBoundaryConsistency) EXPECT_TRUE(mesh_.voh_cwbegin(vh)->is_boundary()); EXPECT_TRUE(mesh_.voh_cw_range(vh).begin()->is_boundary()); - // TODO: this should be false, instead opp should be boundary - EXPECT_TRUE(mesh_.voh_ccwbegin(vh)->is_boundary()); - EXPECT_TRUE(mesh_.voh_ccw_range(vh).begin()->is_boundary()); + EXPECT_TRUE(mesh_.voh_ccwbegin(vh)->opp().is_boundary()); + EXPECT_TRUE(mesh_.voh_ccw_range(vh).begin()->opp().is_boundary()); } } @@ -309,8 +307,12 @@ TEST_F(OpenMeshTrimeshRange, HalfedgeLoopRangeMeshVsSmartHandle) TEST_F(OpenMeshTrimeshRange, HalfedgeLoopRangeCWVsCCW) { + // Halfedge Loops are initialized from a halfedge and always start on that halfedge + // Thus, cw and ccw ranges start on the same element. We account for that by + // setting the offset to 1 for the comparison check. + // TODO: do we want to change that behavior? for (auto heh : mesh_.halfedges()) - compare_ranges(heh.loop_cw(), heh.loop_ccw(), 0, true); + compare_ranges(heh.loop_cw(), heh.loop_ccw(), 1, true); } From 06786e703b05cbd074d8b7801514d6471fd046be Mon Sep 17 00:00:00 2001 From: Max Lyon Date: Tue, 9 Mar 2021 15:38:06 +0100 Subject: [PATCH 9/9] update docu --- Doc/changelog.docu | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Doc/changelog.docu b/Doc/changelog.docu index 14b6228a..784082ac 100644 --- a/Doc/changelog.docu +++ b/Doc/changelog.docu @@ -12,6 +12,7 @@ Breaking Changes
  • Dropped 32-bit Windows continuous integration and artifact builds (This does not mean that OpenMesh will not build and work on 32-bit, but we don't explicitly test and guarantee it anymore).
  • +
  • Changed CCW begin/end/range to start on last element of CW counterpart. May break your code if you depend on CCW begin to start at a specific element.
Core @@ -21,6 +22,8 @@
  • Smart handles now give read access to status fields (feature(), selected(), deleted(), tagged(), tagged2(), hidden(), locked()
  • Add predicates that can be used as smart range filters. There are default predicates to test the status fields and whether an elements is boundary. Predicates can be composed via operators ||, && and !
  • Add make_predicate to create a predicate from anything containing a bool operator(T), e.g. a PropertyManager, a lambda, or a function pointer.
  • +
  • Added CW and CCW ranges.
  • +
  • Vertex incoming/outgoing halfedge circulators can be started for a given halfedge.
  • IO