Commit f8eb2730 authored by Jan Möbius's avatar Jan Möbius
Browse files

Merge branch 'featureMeshConversion' into 'master'

Feature mesh conversion

implements a cast from polyMesh to Mesh and vice versa using  static_cast<Mesh>(polymeshInstance) or static_cast<PolyMesh>(trimeshInstance)
as mentioned in #23 .

Copy constructors for respective mesh types were added as well as a function to copy all properties from one mesh to another.
Unittest for mesh conversions were added checking the number of vertices / faces as well as custom double vertex properties and edge properties.

Note: The used triangulation only works for convex polygons, it should be replaced by the earclipping triangulation mentioned in #33

See merge request !110
parents 46c87795 104635d5
Pipeline #3981 passed with stage
in 40 minutes and 56 seconds
......@@ -10,6 +10,7 @@
<b>Core</b>
<ul>
<li>Implemented a cast from polyMesh to Mesh and vice versa using static_cast(polymeshInstance) or static_cast(trimeshInstance)</li>
<li>make all negative handles invalid, not just -1</li>
<li>Several warnings fixed (Including the checked iterators)</li>
</ul>
......
......@@ -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
......
......@@ -186,6 +186,8 @@ public:
// --- constructor/destructor
PolyMeshT() {}
template<typename T>
explicit PolyMeshT(const T& t) : Kernel(t) {}
virtual ~PolyMeshT() {}
/** Uses default copy and assignment operator.
......
......@@ -74,7 +74,8 @@
namespace OpenMesh {
template<class Traits>
class TriMesh_ArrayKernelT;
//== CLASS DEFINITION =========================================================
/// Helper class to build a PolyMesh-type
......@@ -97,7 +98,18 @@ struct PolyMesh_ArrayKernel_GeneratorT
template <class Traits = DefaultTraits>
class PolyMesh_ArrayKernelT
: public PolyMesh_ArrayKernel_GeneratorT<Traits>::Mesh
{};
{
public:
PolyMesh_ArrayKernelT() {}
template<class OtherTraits>
PolyMesh_ArrayKernelT( const TriMesh_ArrayKernelT<OtherTraits> & t)
{
//assign the connectivity (add vertices)
this->assign(t);
//copy properties from triMesh
this->copy_all_kernel_properties(t);
}
};
//=============================================================================
......
......@@ -169,6 +169,10 @@ public:
/// Default constructor
TriMeshT() : PolyMesh() {}
explicit TriMeshT(PolyMesh rhs) : PolyMesh((rhs.triangulate(), rhs))
{
}
/// Destructor
virtual ~TriMeshT() {}
......
......@@ -74,7 +74,8 @@
namespace OpenMesh {
template<class Traits>
class PolyMesh_ArrayKernelT;
//== CLASS DEFINITION =========================================================
......@@ -97,7 +98,18 @@ struct TriMesh_ArrayKernel_GeneratorT
template <class Traits = DefaultTraits>
class TriMesh_ArrayKernelT
: public TriMesh_ArrayKernel_GeneratorT<Traits>::Mesh
{};
{
public:
TriMesh_ArrayKernelT() {}
template<class OtherTraits>
TriMesh_ArrayKernelT( const PolyMesh_ArrayKernelT<OtherTraits> & t)
{
//assign the connectivity (add vertices)
this->assign(t);
//copy properties from polyMesh
this->copy_all_kernel_properties(t);
}
};
//=============================================================================
......
#include <gtest/gtest.h>
#include <Unittests/unittests_common.hh>
#include <OpenMesh/Core/Utils/PropertyManager.hh>
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<Mesh::VertexHandle> 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<Mesh::VertexHandle> 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<PolyMesh>(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<double> 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<PolyMesh>(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>(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<double> 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>(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<double> 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>(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"));
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment