Developer Documentation
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 
63  {
65  OpenMesh::VPropHandleT<bool>, Mesh> pm_v_bool(mesh_, "pm_v_bool");
66  pm_v_bool.set_range(mesh_.vertices_begin(), mesh_.vertices_end(), false);
67  for (int i = 0; i < 4; ++i)
68  ASSERT_FALSE(pm_v_bool[vhandle[i]]);
69  pm_v_bool.set_range(mesh_.vertices_begin(), mesh_.vertices_end(), true);
70  for (int i = 0; i < 4; ++i)
71  ASSERT_TRUE(pm_v_bool[vhandle[i]]);
72 
74  OpenMesh::EPropHandleT<bool>, Mesh> pm_e_bool(mesh_, "pm_e_bool");
75  pm_e_bool.set_range(mesh_.edges_begin(), mesh_.edges_end(), false);
76  for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end();
77  e_it != f_end; ++e_it)
78  ASSERT_FALSE(pm_e_bool[*e_it]);
79  pm_e_bool.set_range(mesh_.edges_begin(), mesh_.edges_end(), true);
80  for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end();
81  e_it != f_end; ++e_it)
82  ASSERT_TRUE(pm_e_bool[*e_it]);
83 
85  OpenMesh::FPropHandleT<bool>, Mesh> pm_f_bool(mesh_, "pm_f_bool");
86  pm_f_bool.set_range(mesh_.faces_begin(), mesh_.faces_end(), false);
87  for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end();
88  f_it != f_end; ++f_it)
89  ASSERT_FALSE(pm_f_bool[*f_it]);
90  pm_f_bool.set_range(mesh_.faces_begin(), mesh_.faces_end(), true);
91  for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end();
92  f_it != f_end; ++f_it)
93  ASSERT_TRUE(pm_f_bool[*f_it]);
94  }
95 
96  /*
97  * Same thing again, this time with C++11 ranges.
98  */
99  {
101  OpenMesh::VPropHandleT<bool>, Mesh> pm_v_bool(mesh_, "pm_v_bool2");
102  pm_v_bool.set_range(mesh_.vertices(), false);
103  for (int i = 0; i < 4; ++i)
104  ASSERT_FALSE(pm_v_bool[vhandle[i]]);
105  pm_v_bool.set_range(mesh_.vertices(), true);
106  for (int i = 0; i < 4; ++i)
107  ASSERT_TRUE(pm_v_bool[vhandle[i]]);
108 
110  OpenMesh::EPropHandleT<bool>, Mesh> pm_e_bool(mesh_, "pm_e_bool2");
111  pm_e_bool.set_range(mesh_.edges(), false);
112  for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end();
113  e_it != f_end; ++e_it)
114  ASSERT_FALSE(pm_e_bool[*e_it]);
115  pm_e_bool.set_range(mesh_.edges(), true);
116  for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end();
117  e_it != f_end; ++e_it)
118  ASSERT_TRUE(pm_e_bool[*e_it]);
119 
121  OpenMesh::FPropHandleT<bool>, Mesh> pm_f_bool(mesh_, "pm_f_bool2");
122  pm_f_bool.set_range(mesh_.faces(), false);
123  for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end();
124  f_it != f_end; ++f_it)
125  ASSERT_FALSE(pm_f_bool[*f_it]);
126  pm_f_bool.set_range(mesh_.faces(), true);
127  for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end();
128  f_it != f_end; ++f_it)
129  ASSERT_TRUE(pm_f_bool[*f_it]);
130  }
131 }
132 
133 /*
134  * ====================================================================
135  * Factory Functions
136  * ====================================================================
137  */
138 
139 template<typename PropHandle, typename Mesh>
140 bool has_property(const Mesh& _mesh, const std::string& _name) {
141  auto dummy_handle = PropHandle{};
142  return _mesh.get_property_handle(dummy_handle, _name);
143 }
144 
145 /*
146  * Temporary property
147  */
148 TEST_F(OpenMeshPropertyManager, cpp11_temp_property) {
149  using handle_type = OpenMesh::VPropHandleT<int>;
150  const auto prop_name = "pm_v_test_property";
151  ASSERT_FALSE(has_property<handle_type>(mesh_, prop_name));
152 
153  {
154  auto vprop = OpenMesh::makeTemporaryProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name);
155  static_cast<void>(vprop); // Unused variable
156  ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
157  }
158 
159  ASSERT_FALSE(has_property<handle_type>(mesh_, prop_name));
160 }
161 
162 /*
163  * Two temporary properties on a mesh using the same name and type. The second
164  * (inner) one shadows the first (outer) one instead of aliasing.
165  */
166 TEST_F(OpenMeshPropertyManager, cpp11_temp_property_shadowing) {
167  auto vh = mesh_.add_vertex({0,0,0}); // Dummy vertex to attach properties to
168 
169  using handle_type = OpenMesh::VPropHandleT<int>;
170  const auto prop_name = "pm_v_test_property";
171 
172  auto outer_prop = OpenMesh::makeTemporaryProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name);
173  outer_prop[vh] = 100;
174  ASSERT_EQ(100, outer_prop[vh]);
175 
176  {
177  // inner_prop uses same type and name as outer_prop
178  auto inner_prop = OpenMesh::makeTemporaryProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name);
179  inner_prop[vh] = 200;
180  ASSERT_EQ(200, inner_prop[vh]);
181  // End of scope: inner_prop is removed from mesh_
182  }
183 
184  // Ensure outer_prop still exists and its data has not been overwritten by inner_prop
185  ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
186  ASSERT_EQ(100, outer_prop[vh]);
187 }
188 
189 /*
190  * In sequence:
191  * - add a persistent property to a mesh
192  * - retrieve an existing property of a mesh and modify it
193  * - obtain a non-owning property handle
194  * - attempt to obtain a non-owning handle to a non-existing property (throws)
195  */
196 TEST_F(OpenMeshPropertyManager, cpp11_persistent_and_non_owning_properties) {
197  auto vh = mesh_.add_vertex({0,0,0}); // Dummy vertex to attach properties to
198 
199  using handle_type = OpenMesh::VPropHandleT<int>;
200  const auto prop_name = "pm_v_test_property";
201 
202  ASSERT_FALSE(has_property<handle_type>(mesh_, prop_name));
203 
204  {
205  auto prop = OpenMesh::getOrMakeProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name);
206  prop[vh] = 100;
207  // End of scope, property persists
208  }
209 
210  ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
211 
212  {
213  // Since a property of the same name and type already exists, this refers to the existing property.
214  auto prop = OpenMesh::getOrMakeProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name);
215  ASSERT_EQ(100, prop[vh]);
216  prop[vh] = 200;
217  // End of scope, property persists
218  }
219 
220  ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
221 
222  {
223  // Acquire non-owning handle to the property, knowing it exists
224  auto prop = OpenMesh::getProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name);
225  ASSERT_EQ(200, prop[vh]);
226  }
227 
228  ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
229 
230  {
231  // Attempt to acquire non-owning handle for a non-existing property
232  auto code_that_throws = [&](){
233  OpenMesh::getProperty<OpenMesh::VertexHandle, int>(mesh_, "wrong_prop_name");
234  };
235  ASSERT_THROW(code_that_throws(), std::runtime_error);
236  }
237 
238  ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
239 }
240 
241 }
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:112
VertexHandle add_vertex(const Point &_p)
Alias for new_vertex(const Point&).
Definition: PolyMeshT.hh:235
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:136