1 #include <gtest/gtest.h> 2 #include <Unittests/unittests_common.hh> 3 #include <OpenMesh/Core/Utils/PropertyManager.hh> 8 #ifdef ENABLE_PROPERTY_TIMING_OUTPUT 9 #define N_VERTICES_TIMING 1000000 10 #define TIMING_OUTPUT(X) X 12 #define N_VERTICES_TIMING 10 13 #define TIMING_OUTPUT(X) 23 virtual void SetUp() {
27 virtual void TearDown() {
45 TEST_F(OpenMeshPropertyManager, set_range_bool) {
58 std::vector<Mesh::VertexHandle> face_vhandles;
60 face_vhandles.push_back(vhandle[0]);
61 face_vhandles.push_back(vhandle[1]);
62 face_vhandles.push_back(vhandle[2]);
63 mesh_.add_face(face_vhandles);
65 face_vhandles.clear();
67 face_vhandles.push_back(vhandle[0]);
68 face_vhandles.push_back(vhandle[2]);
69 face_vhandles.push_back(vhandle[3]);
70 mesh_.add_face(face_vhandles);
75 pm_v_bool.set_range(mesh_.vertices_begin(), mesh_.vertices_end(),
false);
76 for (
int i = 0; i < 4; ++i)
77 ASSERT_FALSE(pm_v_bool[vhandle[i]]);
78 pm_v_bool.set_range(mesh_.vertices_begin(), mesh_.vertices_end(),
true);
79 for (
int i = 0; i < 4; ++i)
80 ASSERT_TRUE(pm_v_bool[vhandle[i]]);
84 pm_e_bool.set_range(mesh_.edges_begin(), mesh_.edges_end(),
false);
85 for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end();
86 e_it != f_end; ++e_it)
87 ASSERT_FALSE(pm_e_bool[*e_it]);
88 pm_e_bool.set_range(mesh_.edges_begin(), mesh_.edges_end(),
true);
89 for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end();
90 e_it != f_end; ++e_it)
91 ASSERT_TRUE(pm_e_bool[*e_it]);
95 pm_f_bool.set_range(mesh_.faces_begin(), mesh_.faces_end(),
false);
96 for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end();
97 f_it != f_end; ++f_it)
98 ASSERT_FALSE(pm_f_bool[*f_it]);
99 pm_f_bool.set_range(mesh_.faces_begin(), mesh_.faces_end(),
true);
100 for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end();
101 f_it != f_end; ++f_it)
102 ASSERT_TRUE(pm_f_bool[*f_it]);
111 pm_v_bool.set_range(mesh_.vertices(),
false);
112 for (
int i = 0; i < 4; ++i)
113 ASSERT_FALSE(pm_v_bool[vhandle[i]]);
114 pm_v_bool.set_range(mesh_.vertices(),
true);
115 for (
int i = 0; i < 4; ++i)
116 ASSERT_TRUE(pm_v_bool[vhandle[i]]);
120 pm_e_bool.set_range(mesh_.edges(),
false);
121 for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end();
122 e_it != f_end; ++e_it)
123 ASSERT_FALSE(pm_e_bool[*e_it]);
124 pm_e_bool.set_range(mesh_.edges(),
true);
125 for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end();
126 e_it != f_end; ++e_it)
127 ASSERT_TRUE(pm_e_bool[*e_it]);
131 pm_f_bool.set_range(mesh_.faces(),
false);
132 for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end();
133 f_it != f_end; ++f_it)
134 ASSERT_FALSE(pm_f_bool[*f_it]);
135 pm_f_bool.set_range(mesh_.faces(),
true);
136 for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end();
137 f_it != f_end; ++f_it)
138 ASSERT_TRUE(pm_f_bool[*f_it]);
149 TEST_F(OpenMeshPropertyManager, cpp11_persistent_and_non_owning_properties) {
152 const auto prop_name =
"pm_v_test_property";
154 ASSERT_FALSE((OpenMesh::hasProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name)));
157 auto prop = OpenMesh::getOrMakeProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name);
162 ASSERT_TRUE((OpenMesh::hasProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name)));
166 auto prop = OpenMesh::getOrMakeProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name);
167 ASSERT_EQ(100, prop[vh]);
172 ASSERT_TRUE((OpenMesh::hasProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name)));
176 auto prop = OpenMesh::getProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name);
177 ASSERT_EQ(200, prop[vh]);
180 ASSERT_TRUE((OpenMesh::hasProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name)));
184 auto code_that_throws = [&](){
185 OpenMesh::getProperty<OpenMesh::VertexHandle, int>(mesh_,
"wrong_prop_name");
187 ASSERT_THROW(code_that_throws(), std::runtime_error);
190 ASSERT_TRUE((OpenMesh::hasProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name)));
194 TEST_F(OpenMeshPropertyManager, property_copy_construction) {
195 for (
int i = 0; i < N_VERTICES_TIMING; ++i)
201 for (
auto vh : mesh_.vertices())
202 prop1[vh] = vh.idx()*2-13;
214 for (
auto vh : mesh_.vertices())
215 prop1[vh] = vh.idx()*2-13;
221 prop1.set_range(mesh_.vertices(), 0);
227 TEST_F(OpenMeshPropertyManager, property_move_construction) {
228 for (
int i = 0; i < N_VERTICES_TIMING; ++i)
234 for (
auto vh : mesh_.vertices())
235 prop1[vh] = vh.idx()*2-13;
237 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
238 auto prop2 = std::move(prop1);
239 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
240 TIMING_OUTPUT(std::cout <<
"move constructing property from temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
242 EXPECT_FALSE(prop1.isValid()) <<
"prop1 should have been invalidated";
250 for (
auto vh : mesh_.vertices())
251 prop1[vh] = vh.idx()*2-13;
253 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
254 auto prop2 = std::move(prop1);
255 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
256 TIMING_OUTPUT(std::cout <<
"move constructing from named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
258 EXPECT_TRUE(prop1.isValid()) <<
"named properties cannot be invalidated";
263 prop1.set_range(mesh_.vertices(), 0);
271 TEST_F(OpenMeshPropertyManager, property_copying_same_mesh) {
273 for (
int i = 0; i < N_VERTICES_TIMING; ++i)
283 for (
auto vh : mesh_.vertices())
284 prop1[vh] = vh.idx()*2-13;
288 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
290 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
291 TIMING_OUTPUT(std::cout <<
"copying property temporary to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
295 prop1.set_range(mesh_.vertices(), 0);
307 for (
auto vh : mesh_.vertices())
308 prop1[vh] = vh.idx()*2-13;
312 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
314 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
315 TIMING_OUTPUT(std::cout <<
"copying property temporary to named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
319 prop1.set_range(mesh_.vertices(), 0);
334 for (
auto vh : mesh_.vertices())
335 prop1[vh] = vh.idx()*2-13;
337 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
339 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
340 TIMING_OUTPUT(std::cout <<
"copying property named to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
342 prop1.set_range(mesh_.vertices(), 0);
355 for (
auto vh : mesh_.vertices())
356 prop1[vh] = vh.idx()*2-13;
360 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
362 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
363 TIMING_OUTPUT(std::cout <<
"copying property named to named with different name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
365 prop1.set_range(mesh_.vertices(), 0);
375 for (
auto vh : mesh_.vertices())
376 prop1[vh] = vh.idx()*2-13;
381 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
383 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
384 TIMING_OUTPUT(std::cout <<
"copying property named to named with same name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
389 prop1.set_range(mesh_.vertices(), 42);
405 prop2 = std::move(prop1);
410 TEST_F(OpenMeshPropertyManager, property_moving_same_mesh) {
412 for (
int i = 0; i < N_VERTICES_TIMING; ++i)
421 for (
auto vh : mesh_.vertices())
422 prop1[vh] = vh.idx()*2-13;
426 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
427 prop2 = std::move(prop1);
428 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
429 TIMING_OUTPUT(std::cout <<
"moving property temporary to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
431 EXPECT_FALSE(prop1.isValid()) <<
"prop1 not invalidated after moving";
443 for (
auto vh : mesh_.vertices())
444 prop1[vh] = vh.idx()*2-13;
448 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
449 prop2 = std::move(prop1);
450 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
451 TIMING_OUTPUT(std::cout <<
"moving property temporary to named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
453 EXPECT_FALSE(prop1.isValid()) <<
"prop1 not invalidated after moving";
468 for (
auto vh : mesh_.vertices())
469 prop1[vh] = vh.idx()*2-13;
471 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
472 prop2 = std::move(prop1);
473 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
474 TIMING_OUTPUT(std::cout <<
"moving property named to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
476 EXPECT_TRUE(prop1.isValid()) <<
"named prop1 should not be invalidated by moving";
478 prop1.set_range(mesh_.vertices(), 0);
491 for (
auto vh : mesh_.vertices())
492 prop1[vh] = vh.idx()*2-13;
496 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
497 prop2 = std::move(prop1);
498 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
499 TIMING_OUTPUT(std::cout <<
"moving property named to named with different name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
501 EXPECT_TRUE(prop1.isValid()) <<
"named prop1 should not be invalidated by moving";
503 prop1.set_range(mesh_.vertices(), 0);
513 for (
auto vh : mesh_.vertices())
514 prop1[vh] = vh.idx()*2-13;
519 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
520 prop2 = std::move(prop1);
521 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
522 TIMING_OUTPUT(std::cout <<
"moving property named to named with same name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
524 EXPECT_TRUE(prop1.isValid()) <<
"named prop1 should not be invalidated by moving";
529 prop1.set_range(mesh_.vertices(), 0);
541 TEST_F(OpenMeshPropertyManager, property_copying_different_mesh) {
543 for (
int i = 0; i < N_VERTICES_TIMING; ++i)
547 for (
int i = 0; i < 10; ++i)
557 for (
auto vh : mesh_.vertices())
558 prop1[vh] = vh.idx()*2-13;
562 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
564 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
565 TIMING_OUTPUT(std::cout <<
"copying property temporary to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
569 prop1.set_range(mesh_.vertices(), 0);
573 EXPECT_NO_FATAL_FAILURE(prop2[
OpenMesh::VertexHandle(static_cast<int>(copy.n_vertices())-1)]) <<
"Property not correctly resized";
582 for (
auto vh : mesh_.vertices())
583 prop1[vh] = vh.idx()*2-13;
587 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
589 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
590 TIMING_OUTPUT(std::cout <<
"copying property temporary to named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
594 prop1.set_range(mesh_.vertices(), 0);
609 for (
auto vh : mesh_.vertices())
610 prop1[vh] = vh.idx()*2-13;
612 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
614 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
615 TIMING_OUTPUT(std::cout <<
"copying property named to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
617 prop1.set_range(mesh_.vertices(), 0);
630 for (
auto vh : mesh_.vertices())
631 prop1[vh] = vh.idx()*2-13;
635 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
637 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
638 TIMING_OUTPUT(std::cout <<
"copying property named to named with different name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
640 prop1.set_range(mesh_.vertices(), 0);
650 for (
auto vh : mesh_.vertices())
651 prop1[vh] = vh.idx()*2-13;
655 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
657 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
658 TIMING_OUTPUT(std::cout <<
"copying property named to named with same name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
663 prop1.set_range(mesh_.vertices(), 42);
676 TEST_F(OpenMeshPropertyManager, property_moving_different_mesh) {
678 for (
int i = 0; i < N_VERTICES_TIMING; ++i)
682 for (
int i = 0; i < 10; ++i)
691 for (
auto vh : mesh_.vertices())
692 prop1[vh] = vh.idx()*2-13;
696 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
697 prop2 = std::move(prop1);
698 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
699 TIMING_OUTPUT(std::cout <<
"moving property temporary to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
701 EXPECT_FALSE(prop1.isValid()) <<
"prop1 not invalidated after moving";
704 EXPECT_NO_FATAL_FAILURE(prop2[
OpenMesh::VertexHandle(static_cast<int>(copy.n_vertices())-1)]) <<
"Property not correctly resized";
714 for (
auto vh : mesh_.vertices())
715 prop1[vh] = vh.idx()*2-13;
719 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
720 prop2 = std::move(prop1);
721 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
722 TIMING_OUTPUT(std::cout <<
"moving property temporary to named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
724 EXPECT_FALSE(prop1.isValid()) <<
"prop1 not invalidated after moving";
739 for (
auto vh : mesh_.vertices())
740 prop1[vh] = vh.idx()*2-13;
742 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
743 prop2 = std::move(prop1);
744 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
745 TIMING_OUTPUT(std::cout <<
"moving property named to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
747 EXPECT_TRUE(prop1.isValid()) <<
"named prop1 should not be invalidated by moving";
749 prop1.set_range(mesh_.vertices(), 0);
762 for (
auto vh : mesh_.vertices())
763 prop1[vh] = vh.idx()*2-13;
767 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
768 prop2 = std::move(prop1);
769 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
770 TIMING_OUTPUT(std::cout <<
"moving property named to named with different name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
772 EXPECT_TRUE(prop1.isValid()) <<
"named prop1 should not be invalidated by moving";
774 prop1.set_range(mesh_.vertices(), 0);
787 for (
auto vh : mesh_.vertices())
788 prop1[vh] = vh.idx()*2-13;
792 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
793 prop2 = std::move(prop1);
794 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
795 TIMING_OUTPUT(std::cout <<
"moving property named to named with same name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
797 EXPECT_TRUE(prop1.isValid()) <<
"named prop1 should not be invalidated by moving";
802 prop1.set_range(mesh_.vertices(), 42);
815 TEST_F(OpenMeshPropertyManager, temporary_property_on_const_mesh) {
817 const auto& const_ref = mesh_;
820 auto points = OpenMesh::getPointsProperty(const_ref);
822 for (
auto fh : const_ref.faces())
823 cog(fh) = fh.vertices().avg(points);
827 for (
auto fh : const_ref.faces())
829 EXPECT_NE(&cog(fh), &cog_copy(fh)) <<
"Both properties point to the same memory";
830 EXPECT_EQ(cog(fh), cog_copy(fh)) <<
"Property not copied correctly";
834 description() =
"Cool Const Mesh";
843 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
847 id_prop(vh) = vh.idx();
849 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
850 TIMING_OUTPUT(std::cout <<
"Time spend in function: " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
855 TEST_F(OpenMeshPropertyManager, return_property_from_function) {
857 for (
int i = 0; i < N_VERTICES_TIMING; ++i)
860 TIMING_OUTPUT(
auto t_start = std::chrono::high_resolution_clock::now();)
861 auto id_p = get_id_prop(mesh_);
862 TIMING_OUTPUT(
auto t_end = std::chrono::high_resolution_clock::now();)
863 TIMING_OUTPUT(std::cout <<
"Time spend around function " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() <<
"ms" << std::endl;)
865 for (
auto vh : mesh_.vertices())
867 EXPECT_EQ(id_p(vh), vh.idx()) <<
"Property not returned correctly" << std::endl;
Handle type for meshes to simplify some template programming.
void set_range(HandleTypeIterator begin, HandleTypeIterator end, const PROP_VALUE &value)
Kernel::Point Point
Coordinate type.
ConstVertexRangeSkipping vertices() const
Handle for a vertex entity.
SmartVertexHandle add_vertex(const Point &_p)
Alias for new_vertex(const Point&).
Connectivity Class for polygonal meshes.
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.