From a705d57bd097baf35fa399edca5e461581303be6 Mon Sep 17 00:00:00 2001 From: Hans-Christian Ebke Date: Mon, 12 Sep 2016 16:57:33 +0200 Subject: [PATCH 1/3] PropertyManager: Add C++11 range-based set_range() version. --- src/OpenMesh/Core/Utils/PropertyManager.hh | 8 ++ src/Unittests/unittests_propertymanager.cc | 96 +++++++++++++++------- 2 files changed, 76 insertions(+), 28 deletions(-) diff --git a/src/OpenMesh/Core/Utils/PropertyManager.hh b/src/OpenMesh/Core/Utils/PropertyManager.hh index 51fc269e..d956a420 100644 --- a/src/OpenMesh/Core/Utils/PropertyManager.hh +++ b/src/OpenMesh/Core/Utils/PropertyManager.hh @@ -353,6 +353,14 @@ class PropertyManager { (*this)[*begin] = value; } +#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) + template + void set_range(HandleTypeIteratorRange &range, + const PROP_VALUE &value) { + set_range(range.begin(), range.end(), value); + } +#endif + /** * Conveniently transfer the values managed by one property manager * onto the values managed by a different property manager. diff --git a/src/Unittests/unittests_propertymanager.cc b/src/Unittests/unittests_propertymanager.cc index acf404f3..7a1f1d21 100644 --- a/src/Unittests/unittests_propertymanager.cc +++ b/src/Unittests/unittests_propertymanager.cc @@ -60,36 +60,76 @@ TEST_F(OpenMeshPropertyManager, set_range_bool) { face_vhandles.push_back(vhandle[3]); mesh_.add_face(face_vhandles); - OpenMesh::PropertyManager< - OpenMesh::VPropHandleT, Mesh> pm_v_bool(mesh_, "pm_v_bool"); - pm_v_bool.set_range(mesh_.vertices_begin(), mesh_.vertices_end(), false); - for (int i = 0; i < 4; ++i) - ASSERT_FALSE(pm_v_bool[vhandle[i]]); - pm_v_bool.set_range(mesh_.vertices_begin(), mesh_.vertices_end(), true); - for (int i = 0; i < 4; ++i) - ASSERT_TRUE(pm_v_bool[vhandle[i]]); + { + OpenMesh::PropertyManager< + OpenMesh::VPropHandleT, Mesh> pm_v_bool(mesh_, "pm_v_bool"); + pm_v_bool.set_range(mesh_.vertices_begin(), mesh_.vertices_end(), false); + for (int i = 0; i < 4; ++i) + ASSERT_FALSE(pm_v_bool[vhandle[i]]); + pm_v_bool.set_range(mesh_.vertices_begin(), mesh_.vertices_end(), true); + for (int i = 0; i < 4; ++i) + ASSERT_TRUE(pm_v_bool[vhandle[i]]); - OpenMesh::PropertyManager< - OpenMesh::EPropHandleT, Mesh> pm_e_bool(mesh_, "pm_e_bool"); - pm_e_bool.set_range(mesh_.edges_begin(), mesh_.edges_end(), false); - for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end(); - e_it != f_end; ++e_it) - ASSERT_FALSE(pm_e_bool[*e_it]); - pm_e_bool.set_range(mesh_.edges_begin(), mesh_.edges_end(), true); - for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end(); - e_it != f_end; ++e_it) - ASSERT_TRUE(pm_e_bool[*e_it]); + OpenMesh::PropertyManager< + OpenMesh::EPropHandleT, Mesh> pm_e_bool(mesh_, "pm_e_bool"); + pm_e_bool.set_range(mesh_.edges_begin(), mesh_.edges_end(), false); + for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end(); + e_it != f_end; ++e_it) + ASSERT_FALSE(pm_e_bool[*e_it]); + pm_e_bool.set_range(mesh_.edges_begin(), mesh_.edges_end(), true); + for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end(); + e_it != f_end; ++e_it) + ASSERT_TRUE(pm_e_bool[*e_it]); - OpenMesh::PropertyManager< - OpenMesh::FPropHandleT, Mesh> pm_f_bool(mesh_, "pm_f_bool"); - pm_f_bool.set_range(mesh_.faces_begin(), mesh_.faces_end(), false); - for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end(); - f_it != f_end; ++f_it) - ASSERT_FALSE(pm_f_bool[*f_it]); - pm_f_bool.set_range(mesh_.faces_begin(), mesh_.faces_end(), true); - for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end(); - f_it != f_end; ++f_it) - ASSERT_TRUE(pm_f_bool[*f_it]); + OpenMesh::PropertyManager< + OpenMesh::FPropHandleT, Mesh> pm_f_bool(mesh_, "pm_f_bool"); + pm_f_bool.set_range(mesh_.faces_begin(), mesh_.faces_end(), false); + for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end(); + f_it != f_end; ++f_it) + ASSERT_FALSE(pm_f_bool[*f_it]); + pm_f_bool.set_range(mesh_.faces_begin(), mesh_.faces_end(), true); + for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end(); + f_it != f_end; ++f_it) + ASSERT_TRUE(pm_f_bool[*f_it]); + } + +#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) + /* + * Same thing again, this time with C++11 ranges. + */ + { + OpenMesh::PropertyManager< + OpenMesh::VPropHandleT, Mesh> pm_v_bool(mesh_, "pm_v_bool2"); + pm_v_bool.set_range(mesh_.vertices(), false); + for (int i = 0; i < 4; ++i) + ASSERT_FALSE(pm_v_bool[vhandle[i]]); + pm_v_bool.set_range(mesh_.vertices(), true); + for (int i = 0; i < 4; ++i) + ASSERT_TRUE(pm_v_bool[vhandle[i]]); + + OpenMesh::PropertyManager< + OpenMesh::EPropHandleT, Mesh> pm_e_bool(mesh_, "pm_e_bool2"); + pm_e_bool.set_range(mesh_.edges(), false); + for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end(); + e_it != f_end; ++e_it) + ASSERT_FALSE(pm_e_bool[*e_it]); + pm_e_bool.set_range(mesh_.edges(), true); + for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end(); + e_it != f_end; ++e_it) + ASSERT_TRUE(pm_e_bool[*e_it]); + + OpenMesh::PropertyManager< + OpenMesh::FPropHandleT, Mesh> pm_f_bool(mesh_, "pm_f_bool2"); + pm_f_bool.set_range(mesh_.faces(), false); + for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end(); + f_it != f_end; ++f_it) + ASSERT_FALSE(pm_f_bool[*f_it]); + pm_f_bool.set_range(mesh_.faces(), true); + for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end(); + f_it != f_end; ++f_it) + ASSERT_TRUE(pm_f_bool[*f_it]); + } +#endif } /* From ab51547d92f861cc5559ece39b512a368f1c32c7 Mon Sep 17 00:00:00 2001 From: Hans-Christian Ebke Date: Mon, 12 Sep 2016 16:58:03 +0200 Subject: [PATCH 2/3] PropertyManager: Add initializing createIfNotExists() versions. --- src/OpenMesh/Core/Utils/PropertyManager.hh | 99 ++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/src/OpenMesh/Core/Utils/PropertyManager.hh b/src/OpenMesh/Core/Utils/PropertyManager.hh index d956a420..69e08a1c 100644 --- a/src/OpenMesh/Core/Utils/PropertyManager.hh +++ b/src/OpenMesh/Core/Utils/PropertyManager.hh @@ -208,6 +208,42 @@ class PropertyManager { return std::move(pm); } + /** + * Like createIfNotExists() with two parameters except, if the property + * doesn't exist, it is initialized with the supplied value over + * the supplied range after creation. If the property already exists, + * this method has the exact same effect as the two parameter version. + * Lifecycle management is disabled in any case. + * + * @see makePropertyManagerFromExistingOrNew + */ + template + static PropertyManager createIfNotExists(MeshT &mesh, const char *propname, + const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end, + const PROP_VALUE &init_value) { + const bool exists = propertyExists(mesh, propname); + PropertyManager pm(mesh, propname, exists); + pm.retain(); + if (!exists) + pm.set_range(begin, end, init_value); + return std::move(pm); + } + + /** + * Like createIfNotExists() with two parameters except, if the property + * doesn't exist, it is initialized with the supplied value over + * the supplied range after creation. If the property already exists, + * this method has the exact same effect as the two parameter version. + * Lifecycle management is disabled in any case. + * + * @see makePropertyManagerFromExistingOrNew + */ + template + static PropertyManager createIfNotExists(MeshT &mesh, const char *propname, + const ITERATOR_RANGE &range, const PROP_VALUE &init_value) { + return createIfNotExists( + mesh, propname, range.begin(), range.end(), init_value); + } PropertyManager duplicate(const char *clone_name) { PropertyManager pm(*mesh_, clone_name, false); @@ -267,6 +303,27 @@ class PropertyManager { return (Proxy)pm; } + /** + * Like createIfNotExists() with two parameters except, if the property + * doesn't exist, it is initialized with the supplied value over + * the supplied range after creation. If the property already exists, + * this method has the exact same effect as the two parameter version. + * Lifecycle management is disabled in any case. + * + * @see makePropertyManagerFromExistingOrNew + */ + template + static Proxy createIfNotExists(MeshT &mesh, const char *propname, + const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end, + const PROP_VALUE &init_value) { + const bool exists = propertyExists(mesh, propname); + PropertyManager pm(mesh, propname, exists); + pm.retain(); + if (!exists) + pm.set_range(begin, end, init_value); + return (Proxy)pm; + } + Proxy duplicate(const char *clone_name) { PropertyManager pm(*mesh_, clone_name, false); pm.mesh_->property(pm.prop_) = mesh_->property(prop_); @@ -474,5 +531,47 @@ PropertyManager makePropertyManagerFromExistingOrNew(MeshT &mes return PropertyManager::createIfNotExists(mesh, propname); } +/** \relates PropertyManager + * Like the two parameter version of makePropertyManagerFromExistingOrNew() + * except it initializes the property with the specified value over the + * specified range if it needs to be created. If the property already exists, + * this function has the exact same effect as the two parameter version. + * + * Creates a non-owning wrapper for a mesh property (no lifecycle management). + * If the given property does not exist, it is created. + * + * Intended for creating or accessing persistent properties. + */ +template +PropertyManager makePropertyManagerFromExistingOrNew( + MeshT &mesh, const char *propname, + const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end, + const PROP_VALUE &init_value) { + return PropertyManager::createIfNotExists( + mesh, propname, begin, end, init_value); +} + +/** \relates PropertyManager + * Like the two parameter version of makePropertyManagerFromExistingOrNew() + * except it initializes the property with the specified value over the + * specified range if it needs to be created. If the property already exists, + * this function has the exact same effect as the two parameter version. + * + * Creates a non-owning wrapper for a mesh property (no lifecycle management). + * If the given property does not exist, it is created. + * + * Intended for creating or accessing persistent properties. + */ +template +PropertyManager makePropertyManagerFromExistingOrNew( + MeshT &mesh, const char *propname, + const ITERATOR_RANGE &range, + const PROP_VALUE &init_value) { + return makePropertyManagerFromExistingOrNew( + mesh, propname, range.begin(), range.end(), init_value); +} + } /* namespace OpenMesh */ #endif /* PROPERTYMANAGER_HH_ */ From f08f96eb71991a2f4d59c7ebdc23fa78e5f800df Mon Sep 17 00:00:00 2001 From: Hans-Christian Ebke Date: Mon, 12 Sep 2016 17:06:56 +0200 Subject: [PATCH 3/3] Fixed constness fail in PropertyManager::set_range(). --- src/OpenMesh/Core/Utils/PropertyManager.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OpenMesh/Core/Utils/PropertyManager.hh b/src/OpenMesh/Core/Utils/PropertyManager.hh index 69e08a1c..2f38ca40 100644 --- a/src/OpenMesh/Core/Utils/PropertyManager.hh +++ b/src/OpenMesh/Core/Utils/PropertyManager.hh @@ -412,7 +412,7 @@ class PropertyManager { #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) template - void set_range(HandleTypeIteratorRange &range, + void set_range(const HandleTypeIteratorRange &range, const PROP_VALUE &value) { set_range(range.begin(), range.end(), value); }