2 #include <gtest/gtest.h>
3 #include <Unittests/unittests_common.hh>
6 #include "generate_cube.hh"
7 #include "fill_props.hh"
23 : ival(0), dval(0.0), bval(
false)
27 : ival(_cpy.ival), dval(_cpy.dval), bval(_cpy.bval),
28 vec4fval(_cpy.vec4fval)
38 vec4fval = _rhs.vec4fval;
42 MyData& operator = (
int _rhs) { ival = _rhs;
return *
this; }
43 MyData& operator = (
double _rhs) { dval = _rhs;
return *
this; }
44 MyData& operator = (
bool _rhs) { bval = _rhs;
return *
this; }
46 { vec4fval = _rhs;
return *
this; }
50 bool operator == (
const MyData& _rhs)
const
52 return ival == _rhs.ival
55 && vec4fval == _rhs.vec4fval;
57 bool operator != (
const MyData& _rhs)
const {
return !(*
this == _rhs); }
60 typedef std::map< std::string, unsigned int > MyMap;
68 static const bool is_streamable =
true;
71 static size_t size_of(
void)
76 static size_t size_of(
const value_type&)
81 static size_t store(std::ostream& _os,
const value_type& _v,
bool _swap=
false)
84 bytes = IO::store( _os, _v.ival, _swap );
85 bytes += IO::store( _os, _v.dval, _swap );
86 bytes += IO::store( _os, _v.bval, _swap );
87 bytes += IO::store( _os, _v.vec4fval, _swap );
88 return _os.good() ? bytes : 0;
91 static size_t restore( std::istream& _is, value_type& _v,
bool _swap=
false)
94 bytes = IO::restore( _is, _v.ival, _swap );
95 bytes += IO::restore( _is, _v.dval, _swap );
96 bytes += IO::restore( _is, _v.bval, _swap );
97 bytes += IO::restore( _is, _v.vec4fval, _swap );
98 return _is.good() ? bytes : 0;
104 typedef MyMap value_type;
105 static const bool is_streamable =
true;
108 static size_t size_of(
void) {
return UnknownSize; }
111 static size_t size_of(
const value_type& _v)
114 return sizeof(
unsigned int);
116 value_type::const_iterator it = _v.begin();
117 unsigned int N = _v.size();
119 for(;it!=_v.end(); ++it)
128 size_t store(std::ostream& _os,
const value_type& _v,
bool _swap=
false)
131 unsigned int N = _v.size();
132 value_type::const_iterator it = _v.begin();
133 bytes += IO::store( _os, N, _swap );
134 for (; it != _v.end() && _os.good(); ++it)
136 bytes += IO::store( _os, it->first, _swap );
137 bytes += IO::store( _os, it->second, _swap );
139 return _os.good() ? bytes : 0;
143 size_t restore( std::istream& _is, value_type& _v,
bool _swap=
false)
148 bytes += IO::restore( _is, N, _swap );
149 value_type::key_type key;
150 value_type::mapped_type val;
151 for (
size_t i=0; i<N && _is.good(); ++i)
153 bytes += IO::restore( _is, key, _swap );
154 bytes += IO::restore( _is, val, _swap );
157 return _is.good() ? bytes : 0;
171 virtual void SetUp() {
177 virtual void TearDown() {
192 template <
class Mesh>
class SmootherT
200 SmootherT(
Mesh& _mesh)
203 mesh_.add_property( cog_ );
207 mesh_.remove_property( cog_ );
210 void smooth(
unsigned int _iterations)
212 for (
unsigned int i=0; i < _iterations; ++i)
214 std::for_each(mesh_.vertices_begin(),
215 mesh_.vertices_end(),
216 ComputeCOG(mesh_, cog_));
217 std::for_each(mesh_.vertices_begin(),
218 mesh_.vertices_end(),
219 SetCOG(mesh_, cog_));
228 ComputeCOG(
Mesh& _mesh, Property_cog& _cog)
229 : mesh_(_mesh), cog_(_cog)
236 mesh_.property(cog_, _vh) =
typename Mesh::Point(0.0, 0.0, 0.0);
237 for (vv_it=mesh_.vv_iter(_vh); vv_it.is_valid(); ++vv_it)
239 mesh_.property(cog_, _vh) += mesh_.point( *vv_it );
242 mesh_.property(cog_, _vh ) /= valence;
252 SetCOG(
Mesh& _mesh, Property_cog& _cog)
253 : mesh_(_mesh), cog_(_cog)
257 if (!mesh_.is_boundary(_vh))
258 mesh_.set_point( _vh, mesh_.property(cog_, _vh) );
307 VertexT() : cog_( Point(0.0f, 0.0f, 0.0f ) ) { }
308 const Point& cog()
const {
return cog_; }
309 void set_cog(
const Point& _p) { cog_ = _p; }
340 TEST_F(OpenMeshTutorials, building_a_cube) {
356 std::vector<MyMesh::VertexHandle> face_vhandles;
357 face_vhandles.clear();
358 face_vhandles.push_back(vhandle[0]);
359 face_vhandles.push_back(vhandle[1]);
360 face_vhandles.push_back(vhandle[2]);
361 face_vhandles.push_back(vhandle[3]);
362 mesh.add_face(face_vhandles);
364 face_vhandles.clear();
365 face_vhandles.push_back(vhandle[7]);
366 face_vhandles.push_back(vhandle[6]);
367 face_vhandles.push_back(vhandle[5]);
368 face_vhandles.push_back(vhandle[4]);
369 mesh.add_face(face_vhandles);
370 face_vhandles.clear();
371 face_vhandles.push_back(vhandle[1]);
372 face_vhandles.push_back(vhandle[0]);
373 face_vhandles.push_back(vhandle[4]);
374 face_vhandles.push_back(vhandle[5]);
375 mesh.add_face(face_vhandles);
376 face_vhandles.clear();
377 face_vhandles.push_back(vhandle[2]);
378 face_vhandles.push_back(vhandle[1]);
379 face_vhandles.push_back(vhandle[5]);
380 face_vhandles.push_back(vhandle[6]);
381 mesh.add_face(face_vhandles);
382 face_vhandles.clear();
383 face_vhandles.push_back(vhandle[3]);
384 face_vhandles.push_back(vhandle[2]);
385 face_vhandles.push_back(vhandle[6]);
386 face_vhandles.push_back(vhandle[7]);
387 mesh.add_face(face_vhandles);
388 face_vhandles.clear();
389 face_vhandles.push_back(vhandle[0]);
390 face_vhandles.push_back(vhandle[3]);
391 face_vhandles.push_back(vhandle[7]);
392 face_vhandles.push_back(vhandle[4]);
393 mesh.add_face(face_vhandles);
397 EXPECT_TRUE(ok) <<
"Cannot write mesh to file 'output.off'";
400 TEST_F(OpenMeshTutorials, using_iterators_and_circulators) {
405 EXPECT_TRUE(ok) <<
"Cannot read mesh from file 'output.off'";
408 std::vector<MyMesh::Point> cogs;
409 std::vector<MyMesh::Point>::iterator cog_it;
410 cogs.reserve(mesh.n_vertices());
413 MyMesh::VertexIter v_it, v_end(mesh.vertices_end());
417 unsigned int i, N(100);
418 for (i=0; i < N; ++i)
421 for (v_it = mesh.vertices_begin(); v_it != v_end; ++v_it)
423 cog[0] = cog[1] = cog[2] = valence = 0.0;
425 for (vv_it = mesh.vv_iter( *v_it ); vv_it.is_valid(); ++vv_it)
427 cog += mesh.point( *vv_it );
430 cogs.push_back(cog / valence);
433 for (v_it = mesh.vertices_begin(), cog_it = cogs.begin();
434 v_it != v_end; ++v_it, ++cog_it)
435 if ( !mesh.is_boundary( *v_it ) )
436 mesh.set_point( *v_it, *cog_it );
442 EXPECT_TRUE(ok) <<
"Cannot write mesh to file 'smoothed_output.off'";
445 TEST_F(OpenMeshTutorials, using_custom_properties) {
449 EXPECT_TRUE(ok) <<
"Cannot read mesh from file 'output.off'";
453 mesh.add_property(cogs);
456 MyMesh::VertexIter v_it, v_end(mesh.vertices_end());
460 unsigned int i, N(100);
462 for (i=0; i < N; ++i)
464 for (v_it = mesh.vertices_begin(); v_it != v_end; ++v_it)
466 mesh.property(cogs,*v_it).vectorize(0.0f);
469 for (vv_it = mesh.vv_iter( *v_it ); vv_it.is_valid(); ++vv_it)
471 mesh.property(cogs,*v_it) += mesh.point( *vv_it );
474 mesh.property(cogs,*v_it) /= valence;
477 for (v_it = mesh.vertices_begin(); v_it != v_end; ++v_it)
478 if ( !mesh.is_boundary( *v_it ) )
479 mesh.set_point( *v_it, mesh.property(cogs,*v_it) );
485 EXPECT_TRUE(ok) <<
"Cannot write mesh to file 'smoothed_custom_properties_output.off'";
488 TEST_F(OpenMeshTutorials, using_STL_algorithms) {
489 MyMeshWithTraits mesh;
492 EXPECT_TRUE(ok) <<
"Cannot read mesh from file 'output.off'";
494 SmootherT<MyMeshWithTraits> smoother(mesh);
495 smoother.smooth(100);
500 EXPECT_TRUE(ok) <<
"Cannot write mesh to file 'smoothed_STL_output.off'";
503 TEST_F(OpenMeshTutorials, using_standard_properties) {
506 mesh.request_vertex_normals();
507 EXPECT_TRUE(mesh.has_vertex_normals()) <<
"Standard vertex property 'Normals' not available";
511 EXPECT_TRUE(ok) <<
"Cannot read mesh from file 'output.off'";
517 mesh.request_face_normals();
519 mesh.update_normals();
521 mesh.release_face_normals();
525 for (MyMesh::VertexIter v_it = mesh.vertices_begin();
526 v_it != mesh.vertices_end(); ++v_it)
528 mesh.set_point( *v_it, mesh.point(*v_it)+mesh.normal(*v_it) );
532 mesh.release_vertex_normals();
534 EXPECT_FALSE(mesh.has_vertex_normals()) <<
"Shouldn't have any vertex normals anymore";
537 TEST_F(OpenMeshTutorials, using_mesh_attributes_and_traits) {
542 typeid(
double)) <<
"Data type is wrong";
546 typeid(
double)) <<
"Data type is wrong";
549 mesh.request_vertex_normals();
551 mesh.request_face_normals();
556 EXPECT_TRUE(ok) <<
"Cannot read mesh from file 'output.off'";
560 mesh.has_face_normals() && mesh.has_vertex_normals() )
563 mesh.update_normals();
567 for (MyMesh::VertexIter v_it = mesh.vertices_begin();
568 v_it != mesh.vertices_end(); ++v_it)
570 mesh.set_point( *v_it, mesh.point(*v_it)+mesh.normal(*v_it) );
574 TEST_F(OpenMeshTutorials, extending_the_mesh_using_traits) {
575 MyTriMeshWithCOG mesh;
578 EXPECT_TRUE(ok) <<
"Cannot read mesh from file 'output.off'";
581 MyTriMeshWithCOG::VertexIter v_it, v_end(mesh.vertices_end());
582 MyTriMeshWithCOG::VertexVertexIter vv_it;
583 MyTriMeshWithCOG::Point cog;
584 MyTriMeshWithCOG::Scalar valence;
585 unsigned int i, N(100);
587 for (i=0; i < N; ++i)
589 for (v_it = mesh.vertices_begin(); v_it != v_end; ++v_it)
591 cog[0] = cog[1] = cog[2] = valence = 0.0;
593 for (vv_it = mesh.vv_iter(*v_it); vv_it.is_valid(); ++vv_it)
595 cog += mesh.point( *vv_it );
598 mesh.data(*v_it).set_cog(cog / valence);
601 for (v_it = mesh.vertices_begin(); v_it != v_end; ++v_it)
602 if (!mesh.is_boundary(*v_it))
603 mesh.set_point( *v_it, mesh.data(*v_it).cog());
609 EXPECT_TRUE(ok) <<
"Cannot write mesh to file 'smoothed_extended_output.off'";
613 TEST_F(OpenMeshTutorials, deleting_geometry_elements) {
617 mesh.request_face_status();
618 mesh.request_edge_status();
619 mesh.request_vertex_status();
622 MyMeshWithStatus::VertexHandle vhandle[8];
623 MyMeshWithStatus::FaceHandle fhandle[6];
635 std::vector<MyMesh::VertexHandle> tmp_face_vhandles;
636 tmp_face_vhandles.clear();
637 tmp_face_vhandles.push_back(vhandle[0]);
638 tmp_face_vhandles.push_back(vhandle[1]);
639 tmp_face_vhandles.push_back(vhandle[2]);
640 tmp_face_vhandles.push_back(vhandle[3]);
641 fhandle[0] = mesh.add_face(tmp_face_vhandles);
643 tmp_face_vhandles.clear();
644 tmp_face_vhandles.push_back(vhandle[7]);
645 tmp_face_vhandles.push_back(vhandle[6]);
646 tmp_face_vhandles.push_back(vhandle[5]);
647 tmp_face_vhandles.push_back(vhandle[4]);
648 fhandle[1] = mesh.add_face(tmp_face_vhandles);
650 tmp_face_vhandles.clear();
651 tmp_face_vhandles.push_back(vhandle[1]);
652 tmp_face_vhandles.push_back(vhandle[0]);
653 tmp_face_vhandles.push_back(vhandle[4]);
654 tmp_face_vhandles.push_back(vhandle[5]);
655 fhandle[2] = mesh.add_face(tmp_face_vhandles);
657 tmp_face_vhandles.clear();
658 tmp_face_vhandles.push_back(vhandle[2]);
659 tmp_face_vhandles.push_back(vhandle[1]);
660 tmp_face_vhandles.push_back(vhandle[5]);
661 tmp_face_vhandles.push_back(vhandle[6]);
662 fhandle[3] = mesh.add_face(tmp_face_vhandles);
663 tmp_face_vhandles.clear();
664 tmp_face_vhandles.push_back(vhandle[3]);
665 tmp_face_vhandles.push_back(vhandle[2]);
666 tmp_face_vhandles.push_back(vhandle[6]);
667 tmp_face_vhandles.push_back(vhandle[7]);
668 fhandle[4] = mesh.add_face(tmp_face_vhandles);
670 tmp_face_vhandles.clear();
671 tmp_face_vhandles.push_back(vhandle[0]);
672 tmp_face_vhandles.push_back(vhandle[3]);
673 tmp_face_vhandles.push_back(vhandle[7]);
674 tmp_face_vhandles.push_back(vhandle[4]);
675 fhandle[5] = mesh.add_face(tmp_face_vhandles);
681 EXPECT_FALSE(mesh.status(fhandle[0]).deleted()) <<
"face shouldn't be deleted";
682 EXPECT_FALSE(mesh.status(fhandle[1]).deleted()) <<
"face shouldn't be deleted";
683 EXPECT_FALSE(mesh.status(fhandle[2]).deleted()) <<
"face shouldn't be deleted";
684 EXPECT_FALSE(mesh.status(fhandle[3]).deleted()) <<
"face shouldn't be deleted";
685 EXPECT_FALSE(mesh.status(fhandle[4]).deleted()) <<
"face shouldn't be deleted";
686 EXPECT_FALSE(mesh.status(fhandle[5]).deleted()) <<
"face shouldn't be deleted";
689 mesh.delete_face(fhandle[0],
false);
691 mesh.delete_face(fhandle[2],
false);
693 mesh.delete_face(fhandle[3],
false);
695 mesh.delete_face(fhandle[4],
false);
697 mesh.delete_face(fhandle[5],
false);
699 EXPECT_TRUE(mesh.status(fhandle[0]).deleted()) <<
"face should be deleted";
700 EXPECT_FALSE(mesh.status(fhandle[1]).deleted()) <<
"face shouldn't be deleted";
701 EXPECT_TRUE(mesh.status(fhandle[2]).deleted()) <<
"face should be deleted";
702 EXPECT_TRUE(mesh.status(fhandle[3]).deleted()) <<
"face should be deleted";
703 EXPECT_TRUE(mesh.status(fhandle[4]).deleted()) <<
"face should be deleted";
704 EXPECT_TRUE(mesh.status(fhandle[5]).deleted()) <<
"face should be deleted";
712 EXPECT_FALSE(mesh.status(vhandle[0]).deleted()) <<
"vertex shouldn't be deleted";
713 EXPECT_FALSE(mesh.status(vhandle[1]).deleted()) <<
"vertex shouldn't be deleted";
714 EXPECT_FALSE(mesh.status(vhandle[2]).deleted()) <<
"vertex shouldn't be deleted";
715 EXPECT_FALSE(mesh.status(vhandle[3]).deleted()) <<
"vertex shouldn't be deleted";
718 mesh.delete_vertex(vhandle[0],
false);
719 mesh.delete_vertex(vhandle[1],
false);
720 mesh.delete_vertex(vhandle[2],
false);
721 mesh.delete_vertex(vhandle[3],
false);
724 EXPECT_TRUE(mesh.status(vhandle[0]).deleted()) <<
"vertex should be deleted";
725 EXPECT_TRUE(mesh.status(vhandle[1]).deleted()) <<
"vertex should be deleted";
726 EXPECT_TRUE(mesh.status(vhandle[2]).deleted()) <<
"vertex should be deleted";
727 EXPECT_TRUE(mesh.status(vhandle[3]).deleted()) <<
"vertex should be deleted";
731 mesh.garbage_collection();
736 EXPECT_TRUE(ok) <<
"Cannot write mesh to file 'deleted_output.off'";
740 TEST_F(OpenMeshTutorials, storing_custom_properties) {
744 generate_cube<MyMesh>(mesh);
754 mesh.add_property(vprop_float,
"vprop_float");
755 mesh.add_property(eprop_bool,
"eprop_bool");
756 mesh.add_property(fprop_string,
"fprop_string");
757 mesh.add_property(hprop_mydata,
"hprop_mydata");
758 mesh.add_property(mprop_map,
"mprop_map");
761 fill_props(mesh, vprop_float);
762 fill_props(mesh, eprop_bool);
763 fill_props(mesh, fprop_string);
764 fill_props(mesh, hprop_mydata);
765 fill_props(mesh, mprop_map);
767 EXPECT_TRUE(fill_props(mesh, vprop_float,
true)) <<
"property not filled correctly";
768 EXPECT_TRUE(fill_props(mesh, eprop_bool,
true)) <<
"property not filled correctly";
769 EXPECT_TRUE(fill_props(mesh, fprop_string,
true)) <<
"property not filled correctly";
770 EXPECT_TRUE(fill_props(mesh, hprop_mydata,
true)) <<
"property not filled correctly";
771 EXPECT_TRUE(fill_props(mesh, mprop_map,
true)) <<
"property not filled correctly";
774 mesh.property(vprop_float).set_persistent(
true);
775 EXPECT_TRUE(mesh.property(vprop_float).persistent()) <<
"property should be persistent";
776 mesh.property(eprop_bool).set_persistent(
true);
777 EXPECT_TRUE(mesh.property(eprop_bool).persistent()) <<
"property should be persistent";
778 mesh.property(fprop_string).set_persistent(
true);
779 EXPECT_TRUE(mesh.property(fprop_string).persistent()) <<
"property should be persistent";
780 mesh.property(hprop_mydata).set_persistent(
true);
781 EXPECT_TRUE(mesh.property(hprop_mydata).persistent()) <<
"property should be persistent";
782 mesh.mproperty(mprop_map).set_persistent(
true);
783 EXPECT_TRUE(mesh.mproperty(mprop_map).persistent()) <<
"property should be persistent";
787 EXPECT_TRUE(ok) <<
"Cannot write mesh to file 'persistent-check.om'";
794 EXPECT_TRUE(ok) <<
"Cannot read mesh from file 'persistent-check.om'";
797 EXPECT_TRUE(fill_props(mesh, vprop_float,
true)) <<
"property not filled correctly";
798 EXPECT_TRUE(fill_props(mesh, eprop_bool,
true)) <<
"property not filled correctly";
799 EXPECT_TRUE(fill_props(mesh, fprop_string,
true)) <<
"property not filled correctly";
800 EXPECT_TRUE(fill_props(mesh, hprop_mydata,
true)) <<
"property not filled correctly";
801 EXPECT_TRUE(fill_props(mesh, mprop_map,
true)) <<
"property not filled correctly";
806 TEST_F(OpenMeshTutorials, flipping_edges) {
815 std::vector<Mesh::VertexHandle> face_vhandles;
816 face_vhandles.push_back(vhandle[2]);
817 face_vhandles.push_back(vhandle[1]);
818 face_vhandles.push_back(vhandle[0]);
819 mesh.add_face(face_vhandles);
820 face_vhandles.clear();
821 face_vhandles.push_back(vhandle[2]);
822 face_vhandles.push_back(vhandle[0]);
823 face_vhandles.push_back(vhandle[3]);
824 mesh.add_face(face_vhandles);
828 for(Mesh::EdgeIter it = mesh.edges_begin(); it != mesh.edges_end(); ++it) {
829 if(!mesh.is_boundary(*it)) {
831 EXPECT_EQ(vhandle[2].idx(), mesh.to_vertex_handle(mesh.halfedge_handle(*it,0)).idx()) <<
"expected vertex handle 2!" ;
832 EXPECT_EQ(vhandle[0].idx(), mesh.to_vertex_handle(mesh.halfedge_handle(*it,1)).idx()) <<
"expected vertex handle 0!" ;
834 EXPECT_EQ(vhandle[1].idx(), mesh.to_vertex_handle(mesh.halfedge_handle(*it,0)).idx()) <<
"expected vertex handle 1 (did the flip work?)!" ;
835 EXPECT_EQ(vhandle[3].idx(), mesh.to_vertex_handle(mesh.halfedge_handle(*it,1)).idx()) <<
"expected vertex handle 3 (did the flip work?)!" ;
843 TEST_F(OpenMeshTutorials, collapsing_edges) {
845 mesh.request_vertex_status();
846 mesh.request_edge_status();
848 PolyMesh::VertexHandle vhandle[7];
857 std::vector<PolyMesh::VertexHandle> face_vhandles;
858 face_vhandles.push_back(vhandle[1]);
859 face_vhandles.push_back(vhandle[0]);
860 face_vhandles.push_back(vhandle[2]);
861 face_vhandles.push_back(vhandle[3]);
862 mesh.add_face(face_vhandles);
863 face_vhandles.clear();
864 face_vhandles.push_back(vhandle[1]);
865 face_vhandles.push_back(vhandle[3]);
866 face_vhandles.push_back(vhandle[5]);
867 face_vhandles.push_back(vhandle[4]);
868 mesh.add_face(face_vhandles);
869 face_vhandles.clear();
870 face_vhandles.push_back(vhandle[3]);
871 face_vhandles.push_back(vhandle[2]);
872 face_vhandles.push_back(vhandle[6]);
873 face_vhandles.push_back(vhandle[5]);
874 mesh.add_face(face_vhandles);
877 for(PolyMesh::HalfedgeIter it = mesh.halfedges_begin(); it != mesh.halfedges_end(); ++it) {
878 if( mesh.to_vertex_handle(*it) == vhandle[3] &&
879 mesh.from_vertex_handle(*it) == vhandle[2])
bool read_mesh(Mesh &_mesh, const std::string &_filename)
Read a mesh from file _filename.
Has (r) / store (w) vertex normals.
Kernel::VertexVertexIter VertexVertexIter
Circulator.
T::value_type value_type
Type of the scalar value.
Kernel::Point Point
Coordinate type.
VertexHandle add_vertex(const Point &_p)
Alias for new_vertex(const Point&).
Set options for reader/writer modules.
#define VertexTraits
Macro for defining the vertex traits. See Specifying your MyMesh.
size_t size_of(const T &_v)
#define FaceAttributes(_i)
Macro for defining the face attributes. See Specifying your MyMesh.
#define EdgeAttributes(_i)
Macro for defining the edge attributes. See Specifying your MyMesh.
Add storage for previous halfedge (halfedges). The bit is set by default in the DefaultTraits.
Kernel::Scalar Scalar
Scalar type.
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Vec3f Point
The default coordinate type is OpenMesh::Vec3f.
bool write_mesh(const Mesh &_mesh, const std::string &_filename, Options _opt=Options::Default, std::streamsize _precision=6)
Write a mesh to the file _filename.
Add status to mesh item (all items)
#define VertexAttributes(_i)
Macro for defining the vertex attributes. See Specifying your MyMesh.
Vec3f Normal
The default normal type is OpenMesh::Vec3f.