#include #include #include #include namespace { class OpenMeshPropertyManager : public OpenMeshBase { protected: // This function is called before each test is run virtual void SetUp() { } // 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_; }; /* * ==================================================================== * General Tests * ==================================================================== */ /* * Collapsing a tetrahedron */ TEST_F(OpenMeshPropertyManager, set_range_bool) { mesh_.clear(); // Add some vertices Mesh::VertexHandle vhandle[4]; vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0)); vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0)); vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0)); vhandle[3] = mesh_.add_vertex(Mesh::Point(0, 0, 1)); // 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[0]); face_vhandles.push_back(vhandle[2]); face_vhandles.push_back(vhandle[3]); mesh_.add_face(face_vhandles); { OpenMesh::PropertyManager< OpenMesh::VPropHandleT> 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> 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> 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]); } /* * Same thing again, this time with C++11 ranges. */ { OpenMesh::PropertyManager< OpenMesh::VPropHandleT> 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> 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> 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]); } } /* * ==================================================================== * Factory Functions * ==================================================================== */ /* * Temporary property */ TEST_F(OpenMeshPropertyManager, cpp11_temp_property) { using handle_type = OpenMesh::VPropHandleT; const auto prop_name = "pm_v_test_property"; ASSERT_FALSE((OpenMesh::hasProperty(mesh_, prop_name))); { auto vprop = OpenMesh::makeTemporaryProperty(mesh_, prop_name); static_cast(vprop); // Unused variable ASSERT_TRUE((OpenMesh::hasProperty(mesh_, prop_name))); } ASSERT_FALSE((OpenMesh::hasProperty(mesh_, prop_name))); } /* * Two temporary properties on a mesh using the same name and type. The second * (inner) one shadows the first (outer) one instead of aliasing. */ TEST_F(OpenMeshPropertyManager, cpp11_temp_property_shadowing) { auto vh = mesh_.add_vertex({0,0,0}); // Dummy vertex to attach properties to const auto prop_name = "pm_v_test_property"; auto outer_prop = OpenMesh::makeTemporaryProperty(mesh_, prop_name); outer_prop[vh] = 100; ASSERT_EQ(100, outer_prop[vh]); { // inner_prop uses same type and name as outer_prop auto inner_prop = OpenMesh::makeTemporaryProperty(mesh_, prop_name); inner_prop[vh] = 200; ASSERT_EQ(200, inner_prop[vh]); // End of scope: inner_prop is removed from mesh_ } // Ensure outer_prop still exists and its data has not been overwritten by inner_prop ASSERT_TRUE((OpenMesh::hasProperty(mesh_, prop_name))); ASSERT_EQ(100, outer_prop[vh]); } /* * In sequence: * - add a persistent property to a mesh * - retrieve an existing property of a mesh and modify it * - obtain a non-owning property handle * - attempt to obtain a non-owning handle to a non-existing property (throws) */ TEST_F(OpenMeshPropertyManager, cpp11_persistent_and_non_owning_properties) { auto vh = mesh_.add_vertex({0,0,0}); // Dummy vertex to attach properties to const auto prop_name = "pm_v_test_property"; ASSERT_FALSE((OpenMesh::hasProperty(mesh_, prop_name))); { auto prop = OpenMesh::getOrMakeProperty(mesh_, prop_name); prop[vh] = 100; // End of scope, property persists } ASSERT_TRUE((OpenMesh::hasProperty(mesh_, prop_name))); { // Since a property of the same name and type already exists, this refers to the existing property. auto prop = OpenMesh::getOrMakeProperty(mesh_, prop_name); ASSERT_EQ(100, prop[vh]); prop[vh] = 200; // End of scope, property persists } ASSERT_TRUE((OpenMesh::hasProperty(mesh_, prop_name))); { // Acquire non-owning handle to the property, knowing it exists auto prop = OpenMesh::getProperty(mesh_, prop_name); ASSERT_EQ(200, prop[vh]); } ASSERT_TRUE((OpenMesh::hasProperty(mesh_, prop_name))); { // Attempt to acquire non-owning handle for a non-existing property auto code_that_throws = [&](){ OpenMesh::getProperty(mesh_, "wrong_prop_name"); }; ASSERT_THROW(code_that_throws(), std::runtime_error); } ASSERT_TRUE((OpenMesh::hasProperty(mesh_, prop_name))); } }