Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
unittests_propertymanager.cc
1 #include <gtest/gtest.h>
2 #include <Unittests/unittests_common.hh>
3 #include <OpenMesh/Core/Utils/PropertyManager.hh>
4 
5 #include <iostream>
6 
7 namespace {
8 
9 class OpenMeshPropertyManager : public OpenMeshBase {
10 
11  protected:
12 
13  // This function is called before each test is run
14  virtual void SetUp() {
15  }
16 
17  // This function is called after all tests are through
18  virtual void TearDown() {
19 
20  // Do some final stuff with the member data here...
21  }
22 
23  // Member already defined in OpenMeshBase
24  //Mesh mesh_;
25 };
26 
27 /*
28  * ====================================================================
29  * General Tests
30  * ====================================================================
31  */
32 
33 /*
34  * Collapsing a tetrahedron
35  */
36 TEST_F(OpenMeshPropertyManager, set_range_bool) {
37 
38  mesh_.clear();
39 
40  // Add some vertices
41  Mesh::VertexHandle vhandle[4];
42 
43  vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
44  vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
45  vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
46  vhandle[3] = mesh_.add_vertex(Mesh::Point(0, 0, 1));
47 
48  // Add two faces
49  std::vector<Mesh::VertexHandle> face_vhandles;
50 
51  face_vhandles.push_back(vhandle[0]);
52  face_vhandles.push_back(vhandle[1]);
53  face_vhandles.push_back(vhandle[2]);
54  mesh_.add_face(face_vhandles);
55 
56  face_vhandles.clear();
57 
58  face_vhandles.push_back(vhandle[0]);
59  face_vhandles.push_back(vhandle[2]);
60  face_vhandles.push_back(vhandle[3]);
61  mesh_.add_face(face_vhandles);
62 
64  OpenMesh::VPropHandleT<bool>, Mesh> pm_v_bool(mesh_, "pm_v_bool");
65  pm_v_bool.set_range(mesh_.vertices_begin(), mesh_.vertices_end(), false);
66  for (int i = 0; i < 4; ++i)
67  ASSERT_FALSE(pm_v_bool[vhandle[i]]);
68  pm_v_bool.set_range(mesh_.vertices_begin(), mesh_.vertices_end(), true);
69  for (int i = 0; i < 4; ++i)
70  ASSERT_TRUE(pm_v_bool[vhandle[i]]);
71 
73  OpenMesh::EPropHandleT<bool>, Mesh> pm_e_bool(mesh_, "pm_e_bool");
74  pm_e_bool.set_range(mesh_.edges_begin(), mesh_.edges_end(), false);
75  for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end();
76  e_it != f_end; ++e_it)
77  ASSERT_FALSE(pm_e_bool[*e_it]);
78  pm_e_bool.set_range(mesh_.edges_begin(), mesh_.edges_end(), true);
79  for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end();
80  e_it != f_end; ++e_it)
81  ASSERT_TRUE(pm_e_bool[*e_it]);
82 
84  OpenMesh::FPropHandleT<bool>, Mesh> pm_f_bool(mesh_, "pm_f_bool");
85  pm_f_bool.set_range(mesh_.faces_begin(), mesh_.faces_end(), false);
86  for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end();
87  f_it != f_end; ++f_it)
88  ASSERT_FALSE(pm_f_bool[*f_it]);
89  pm_f_bool.set_range(mesh_.faces_begin(), mesh_.faces_end(), true);
90  for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end();
91  f_it != f_end; ++f_it)
92  ASSERT_TRUE(pm_f_bool[*f_it]);
93 }
94 
95 /*
96  * ====================================================================
97  * C++11 Specific Tests
98  * ====================================================================
99  */
100 #if _MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
101 
102 template<typename PropHandle, typename Mesh>
103 bool has_property(const Mesh& _mesh, const std::string& _name) {
104  auto dummy_handle = PropHandle{};
105  return _mesh.get_property_handle(dummy_handle, _name);
106 }
107 
108 /*
109  * Temporary property
110  */
111 TEST_F(OpenMeshPropertyManager, cpp11_temp_property) {
112  using handle_type = OpenMesh::VPropHandleT<int>;
113  const auto prop_name = "pm_v_test_property";
114  ASSERT_FALSE(has_property<handle_type>(mesh_, prop_name));
115 
116  {
117  auto vprop = OpenMesh::makePropertyManagerFromNew<handle_type>(mesh_, prop_name);
118  static_cast<void>(vprop); // Unused variable
119  ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
120  }
121 
122  ASSERT_FALSE(has_property<handle_type>(mesh_, prop_name));
123 }
124 
125 /*
126  * Two temporary properties on a mesh using the same name and type. The second
127  * (inner) one shadows the first (outer) one instead of aliasing.
128  */
129 TEST_F(OpenMeshPropertyManager, cpp11_temp_property_shadowing) {
130  auto vh = mesh_.add_vertex({0,0,0}); // Dummy vertex to attach properties to
131 
132  using handle_type = OpenMesh::VPropHandleT<int>;
133  const auto prop_name = "pm_v_test_property";
134 
135  auto outer_prop = OpenMesh::makePropertyManagerFromNew<handle_type>(mesh_, prop_name);
136  outer_prop[vh] = 100;
137  ASSERT_EQ(100, outer_prop[vh]);
138 
139  {
140  // inner_prop uses same type and name as outer_prop
141  auto inner_prop = OpenMesh::makePropertyManagerFromNew<handle_type>(mesh_, prop_name);
142  inner_prop[vh] = 200;
143  ASSERT_EQ(200, inner_prop[vh]);
144  // End of scope: inner_prop is removed from mesh_
145  }
146 
147  // Ensure outer_prop still exists and its data has not been overwritten by inner_prop
148  ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
149  ASSERT_EQ(100, outer_prop[vh]);
150 }
151 
152 /*
153  * In sequence:
154  * - add a persistent property to a mesh
155  * - retrieve an existing property of a mesh and modify it
156  * - obtain a non-owning property handle
157  * - attempt to obtain a non-owning handle to a non-existing property (throws)
158  */
159 TEST_F(OpenMeshPropertyManager, cpp11_persistent_and_non_owning_properties) {
160  auto vh = mesh_.add_vertex({0,0,0}); // Dummy vertex to attach properties to
161 
162  using handle_type = OpenMesh::VPropHandleT<int>;
163  const auto prop_name = "pm_v_test_property";
164 
165  ASSERT_FALSE(has_property<handle_type>(mesh_, prop_name));
166 
167  {
168  auto prop = OpenMesh::makePropertyManagerFromExistingOrNew<handle_type>(mesh_, prop_name);
169  prop[vh] = 100;
170  // End of scope, property persists
171  }
172 
173  ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
174 
175  {
176  // Since a property of the same name and type already exists, this refers to the existing property.
177  auto prop = OpenMesh::makePropertyManagerFromExistingOrNew<handle_type>(mesh_, prop_name);
178  ASSERT_EQ(100, prop[vh]);
179  prop[vh] = 200;
180  // End of scope, property persists
181  }
182 
183  ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
184 
185  {
186  // Acquire non-owning handle to the property, knowing it exists
187  auto prop = OpenMesh::makePropertyManagerFromExisting<handle_type>(mesh_, prop_name);
188  ASSERT_EQ(200, prop[vh]);
189  }
190 
191  ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
192 
193  {
194  // Attempt to acquire non-owning handle for a non-existing property
195  ASSERT_THROW(OpenMesh::makePropertyManagerFromExisting<handle_type>(mesh_, "wrong_property_name"), std::runtime_error);
196  }
197 
198  ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
199 }
200 
201 #endif
202 
203 }
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:115
VertexHandle add_vertex(const Point &_p)
Alias for new_vertex(const Point&).
Definition: PolyMeshT.hh:236
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:139