diff --git a/Doc/changelog.docu b/Doc/changelog.docu
index 720a0d5a..e61521f9 100644
--- a/Doc/changelog.docu
+++ b/Doc/changelog.docu
@@ -10,6 +10,7 @@
Core
+- Implemented a cast from polyMesh to Mesh and vice versa using static_cast(polymeshInstance) or static_cast(trimeshInstance)
- make all negative handles invalid, not just -1
- Several warnings fixed (Including the checked iterators)
diff --git a/src/OpenMesh/Core/Mesh/BaseKernel.hh b/src/OpenMesh/Core/Mesh/BaseKernel.hh
index dde5f7f4..6bca014d 100644
--- a/src/OpenMesh/Core/Mesh/BaseKernel.hh
+++ b/src/OpenMesh/Core/Mesh/BaseKernel.hh
@@ -583,6 +583,18 @@ public:
}
+ /**
+ * @brief copy_all_kernel_properties uses the = operator to copy all properties from a given other BaseKernel.
+ * @param _other Another BaseKernel, to copy the properties from.
+ */
+ void copy_all_kernel_properties(const BaseKernel & _other)
+ {
+ this->vprops_ = _other.vprops_;
+ this->eprops_ = _other.eprops_;
+ this->hprops_ = _other.hprops_;
+ this->fprops_ = _other.fprops_;
+ }
+
protected: //------------------------------------------------- low-level access
public: // used by non-native kernel and MeshIO, should be protected
diff --git a/src/OpenMesh/Core/Mesh/PolyMeshT.hh b/src/OpenMesh/Core/Mesh/PolyMeshT.hh
index d0e4d4f8..d514fedc 100644
--- a/src/OpenMesh/Core/Mesh/PolyMeshT.hh
+++ b/src/OpenMesh/Core/Mesh/PolyMeshT.hh
@@ -186,6 +186,8 @@ public:
// --- constructor/destructor
PolyMeshT() {}
+ template
+ explicit PolyMeshT(const T& t) : Kernel(t) {}
virtual ~PolyMeshT() {}
/** Uses default copy and assignment operator.
diff --git a/src/OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh b/src/OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh
index 3012c266..16f8f5c8 100644
--- a/src/OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh
+++ b/src/OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh
@@ -74,7 +74,8 @@
namespace OpenMesh {
-
+template
+class TriMesh_ArrayKernelT;
//== CLASS DEFINITION =========================================================
/// Helper class to build a PolyMesh-type
@@ -97,7 +98,18 @@ struct PolyMesh_ArrayKernel_GeneratorT
template
class PolyMesh_ArrayKernelT
: public PolyMesh_ArrayKernel_GeneratorT::Mesh
-{};
+{
+public:
+ PolyMesh_ArrayKernelT() {}
+ template
+ PolyMesh_ArrayKernelT( const TriMesh_ArrayKernelT & t)
+ {
+ //assign the connectivity (add vertices)
+ this->assign(t);
+ //copy properties from triMesh
+ this->copy_all_kernel_properties(t);
+ }
+};
//=============================================================================
diff --git a/src/OpenMesh/Core/Mesh/TriMeshT.hh b/src/OpenMesh/Core/Mesh/TriMeshT.hh
index 7c3359eb..bf51e29a 100644
--- a/src/OpenMesh/Core/Mesh/TriMeshT.hh
+++ b/src/OpenMesh/Core/Mesh/TriMeshT.hh
@@ -169,6 +169,10 @@ public:
/// Default constructor
TriMeshT() : PolyMesh() {}
+ explicit TriMeshT(PolyMesh rhs) : PolyMesh((rhs.triangulate(), rhs))
+ {
+ }
+
/// Destructor
virtual ~TriMeshT() {}
diff --git a/src/OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh b/src/OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh
index c179051a..f29cbe0c 100644
--- a/src/OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh
+++ b/src/OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh
@@ -74,7 +74,8 @@
namespace OpenMesh {
-
+template
+class PolyMesh_ArrayKernelT;
//== CLASS DEFINITION =========================================================
@@ -97,7 +98,18 @@ struct TriMesh_ArrayKernel_GeneratorT
template
class TriMesh_ArrayKernelT
: public TriMesh_ArrayKernel_GeneratorT::Mesh
-{};
+{
+public:
+ TriMesh_ArrayKernelT() {}
+ template
+ TriMesh_ArrayKernelT( const PolyMesh_ArrayKernelT & t)
+ {
+ //assign the connectivity (add vertices)
+ this->assign(t);
+ //copy properties from polyMesh
+ this->copy_all_kernel_properties(t);
+ }
+};
//=============================================================================
diff --git a/src/Unittests/unittests_convert_meshes.cc b/src/Unittests/unittests_convert_meshes.cc
new file mode 100644
index 00000000..6cfd01bc
--- /dev/null
+++ b/src/Unittests/unittests_convert_meshes.cc
@@ -0,0 +1,314 @@
+
+#include
+#include
+#include
+
+namespace {
+
+class OpenMeshConvertTriangleMeshToPoly : public OpenMeshBase {
+
+ protected:
+
+ // This function is called before each test is run
+ virtual void SetUp() {
+ 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(1, 0, 0));
+
+ // Add two faces
+ std::vector face_vhandles;
+
+ face_vhandles.push_back(vhandle[2]);
+ face_vhandles.push_back(vhandle[1]);
+ face_vhandles.push_back(vhandle[0]);
+ mesh_.add_face(face_vhandles);
+
+ face_vhandles.clear();
+
+ face_vhandles.push_back(vhandle[2]);
+ face_vhandles.push_back(vhandle[0]);
+ face_vhandles.push_back(vhandle[3]);
+ mesh_.add_face(face_vhandles);
+
+ // Test setup:
+ // 1 === 2
+ // | / |
+ // | / |
+ // | / |
+ // 0 === 3
+ }
+
+ // 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_;
+};
+
+class OpenMeshConvertPolyMeshToTriangle : public OpenMeshBasePoly {
+
+ protected:
+
+ // This function is called before each test is run
+ virtual void SetUp() {
+ 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(1, 0, 0));
+
+ // Add two faces
+ std::vector face_vhandles;
+
+ face_vhandles.push_back(vhandle[2]);
+ face_vhandles.push_back(vhandle[1]);
+ face_vhandles.push_back(vhandle[0]);
+ face_vhandles.push_back(vhandle[3]);
+ mesh_.add_face(face_vhandles);
+
+ // Test setup:
+ // 1 --- 2
+ // | |
+ // | |
+ // | |
+ // 0 --- 3
+ }
+
+ // 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_;
+};
+
+/*
+ * ====================================================================
+ * Define tests below
+ * ====================================================================
+ */
+
+/* Checks the converted mesh #faces and #vertices behaviour of adding
+ * vertices and faces to a trimesh after the conversion.
+ */
+TEST_F(OpenMeshConvertTriangleMeshToPoly, VertexFaceCheck) {
+
+ EXPECT_EQ(4u, mesh_.n_vertices() ) << "Wrong number of vertices in TriMesh";
+ EXPECT_EQ(2u, mesh_.n_faces() ) << "Wrong number of faces in TriMesh";
+
+ //convert triMesh to PolyMesh
+ PolyMesh p = static_cast(mesh_);
+
+ // Check setup
+ EXPECT_EQ(4u, p.n_vertices() ) << "Wrong number of vertices in PolyMesh";
+ EXPECT_EQ(2u, p.n_faces() ) << "Wrong number of faces in PolyMesh";
+
+ //add vertex to original mesh
+ Mesh::VertexHandle vhand = mesh_.add_vertex(Mesh::Point(1, 1, 1));
+
+ EXPECT_EQ(5u, mesh_.n_vertices() ) << "Wrong number of vertices in TriMesh";
+ EXPECT_EQ(4u, p.n_vertices() ) << "Wrong number of vertices in PolyMesh";
+
+ Mesh::VertexIter it = mesh_.vertices_begin();
+ //add face to original mesh
+ mesh_.add_face(vhand,(*it),(*++it));
+
+ EXPECT_EQ(3u, mesh_.n_faces() ) << "Wrong number of faces in TriMesh";
+ EXPECT_EQ(2u, p.n_faces() ) << "Wrong number of faces in PolyMesh";
+}
+
+/* Creates a double property and checks if it works after conversion
+ */
+TEST_F(OpenMeshConvertTriangleMeshToPoly, VertexPropertyCheckDouble) {
+
+ // Add a double vertex property
+ OpenMesh::VPropHandleT doubleHandle;
+
+ EXPECT_FALSE( mesh_.get_property_handle(doubleHandle,"doubleProp") );
+
+ mesh_.add_property(doubleHandle,"doubleProp");
+
+ // Fill property
+ double index = 0.0;
+
+ for ( Mesh::VertexIter v_it = mesh_.vertices_begin() ; v_it != mesh_.vertices_end(); ++v_it ) {
+ mesh_.property(doubleHandle,*v_it) = index;
+ index += 1.0;
+ }
+
+ EXPECT_TRUE(mesh_.get_property_handle(doubleHandle,"doubleProp"));
+
+ //convert triMesh to PolyMesh
+ PolyMesh p = static_cast(mesh_);
+
+ EXPECT_TRUE(p.get_property_handle(doubleHandle,"doubleProp"));
+
+ // Check if it is ok.
+ Mesh::VertexIter v_it = p.vertices_begin();
+ EXPECT_EQ( p.property(doubleHandle,*v_it) , 0.0 ) << "Invalid double value for vertex 0";
+ ++v_it;
+
+ EXPECT_EQ( p.property(doubleHandle,*v_it) , 1.0 ) << "Invalid double value for vertex 1";
+ ++v_it;
+
+ EXPECT_EQ( p.property(doubleHandle,*v_it) , 2.0 ) << "Invalid double value for vertex 2";
+ ++v_it;
+
+ EXPECT_EQ( p.property(doubleHandle,*v_it) , 3.0 ) << "Invalid double value for vertex 3";
+
+ //check if deletion in the original mesh affects the converted one.
+ mesh_.get_property_handle(doubleHandle,"doubleProp");
+ mesh_.remove_property(doubleHandle);
+ EXPECT_FALSE(mesh_.get_property_handle(doubleHandle,"doubleProp"));
+ EXPECT_TRUE(p.get_property_handle(doubleHandle,"doubleProp"));
+
+}
+
+/* Checks the converted mesh #faces and #vertices behaviour of adding
+ * vertices and faces to a trimesh after the conversion.
+ */
+TEST_F(OpenMeshConvertPolyMeshToTriangle, VertexFaceCheck) {
+
+ EXPECT_EQ(4u, mesh_.n_vertices() ) << "Wrong number of vertices in PolyMesh";
+ EXPECT_EQ(1u, mesh_.n_faces() ) << "Wrong number of faces in PolyMesh";
+
+ //convert PolyMesh to TriMesh
+ Mesh p = static_cast(mesh_);
+
+ // Check setup
+ EXPECT_EQ(4u, p.n_vertices() ) << "Wrong number of vertices in TriMesh";
+ EXPECT_EQ(2u, p.n_faces() ) << "Wrong number of faces in TriMesh";
+
+ //add vertex to original mesh
+ Mesh::VertexHandle vhand = mesh_.add_vertex(Mesh::Point(1, 1, 1));
+
+ EXPECT_EQ(5u, mesh_.n_vertices() ) << "Wrong number of vertices in PolyMesh";
+ EXPECT_EQ(4u, p.n_vertices() ) << "Wrong number of vertices in TriMesh";
+
+ Mesh::VertexIter it = mesh_.vertices_begin();
+ //add face to original mesh
+ mesh_.add_face(vhand,(*it),(*++it));
+
+ EXPECT_EQ(2u, mesh_.n_faces() ) << "Wrong number of faces in PolyMesh";
+ EXPECT_EQ(2u, p.n_faces() ) << "Wrong number of faces in TriMesh";
+}
+
+/* Creates a double property and checks if it works after conversion
+ */
+TEST_F(OpenMeshConvertPolyMeshToTriangle, VertexPropertyCheckDouble) {
+
+ // Add a double vertex property
+ OpenMesh::VPropHandleT doubleHandle;
+
+ EXPECT_FALSE( mesh_.get_property_handle(doubleHandle,"doubleProp") );
+
+ mesh_.add_property(doubleHandle,"doubleProp");
+
+ // Fill property
+ double index = 0.0;
+
+ for ( Mesh::VertexIter v_it = mesh_.vertices_begin() ; v_it != mesh_.vertices_end(); ++v_it ) {
+ mesh_.property(doubleHandle,*v_it) = index;
+ index += 1.0;
+ }
+
+ EXPECT_TRUE(mesh_.get_property_handle(doubleHandle,"doubleProp"));
+
+ //convert triMesh to PolyMesh
+ Mesh p = static_cast(mesh_);
+
+ EXPECT_TRUE(p.get_property_handle(doubleHandle,"doubleProp"));
+
+ // Check if it is ok.
+ Mesh::VertexIter v_it = p.vertices_begin();
+ EXPECT_EQ( p.property(doubleHandle,*v_it) , 0.0 ) << "Invalid double value for vertex 0";
+ ++v_it;
+
+ EXPECT_EQ( p.property(doubleHandle,*v_it) , 1.0 ) << "Invalid double value for vertex 1";
+ ++v_it;
+
+ EXPECT_EQ( p.property(doubleHandle,*v_it) , 2.0 ) << "Invalid double value for vertex 2";
+ ++v_it;
+
+ EXPECT_EQ( p.property(doubleHandle,*v_it) , 3.0 ) << "Invalid double value for vertex 3";
+
+ //check if deletion in the original mesh affects the converted one.
+ mesh_.get_property_handle(doubleHandle,"doubleProp");
+ mesh_.remove_property(doubleHandle);
+ EXPECT_FALSE(mesh_.get_property_handle(doubleHandle,"doubleProp"));
+ EXPECT_TRUE(p.get_property_handle(doubleHandle,"doubleProp"));
+
+}
+
+/* Creates a double property and checks if it works after conversion
+ * especially if edge properties are preserved after triangulation
+ */
+TEST_F(OpenMeshConvertPolyMeshToTriangle, EdgePropertyCheckDouble) {
+
+ // Add a double vertex property
+ OpenMesh::EPropHandleT doubleHandle;
+
+ EXPECT_FALSE( mesh_.get_property_handle(doubleHandle,"doubleProp") );
+
+ mesh_.add_property(doubleHandle,"doubleProp");
+
+ // Fill property
+ double index = 0.0;
+
+ for ( Mesh::EdgeIter v_it = mesh_.edges_begin() ; v_it != mesh_.edges_end(); ++v_it ) {
+ mesh_.property(doubleHandle,*v_it) = index;
+ index += 1.0;
+ }
+
+ EXPECT_TRUE(mesh_.get_property_handle(doubleHandle,"doubleProp"));
+
+ //convert triMesh to PolyMesh
+ Mesh p = static_cast(mesh_);
+
+ EXPECT_TRUE(p.get_property_handle(doubleHandle,"doubleProp"));
+
+ // Check if it is ok.
+ Mesh::EdgeIter v_it = p.edges_begin();
+
+ if(p.is_boundary( (*v_it) ))
+ EXPECT_EQ( p.property(doubleHandle,*v_it) , 0.0 ) << "Invalid double value for vertex 0";
+ ++v_it;
+
+ if(p.is_boundary( (*v_it) ))
+ EXPECT_EQ( p.property(doubleHandle,*v_it) , 1.0 ) << "Invalid double value for vertex 1";
+ ++v_it;
+
+ if(p.is_boundary( (*v_it) ))
+ EXPECT_EQ( p.property(doubleHandle,*v_it) , 2.0 ) << "Invalid double value for vertex 2";
+ ++v_it;
+
+ if(p.is_boundary( (*v_it) ))
+ EXPECT_EQ( p.property(doubleHandle,*v_it) , 3.0 ) << "Invalid double value for vertex 3";
+ ++v_it;
+
+ EXPECT_FALSE( p.is_boundary(*v_it)) << "Invalid Edge after triangulation";
+
+ //check if deletion in the original mesh affects the converted one.
+ mesh_.get_property_handle(doubleHandle,"doubleProp");
+ mesh_.remove_property(doubleHandle);
+ EXPECT_FALSE(mesh_.get_property_handle(doubleHandle,"doubleProp"));
+ EXPECT_TRUE(p.get_property_handle(doubleHandle,"doubleProp"));
+
+}
+
+}