From 986f98f0b9d8c9543a8eaa7696bcacba1765917c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20M=C3=B6bius?= Date: Wed, 26 Apr 2017 16:58:38 +0200 Subject: [PATCH] Added Triangle 1 to 4 split --- src/OpenMesh/Core/Mesh/TriMeshT.hh | 58 +++++++++++ src/Unittests/unittests_trimesh_split.cc | 117 +++++++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 src/Unittests/unittests_trimesh_split.cc diff --git a/src/OpenMesh/Core/Mesh/TriMeshT.hh b/src/OpenMesh/Core/Mesh/TriMeshT.hh index bf51e29a..f8eda46c 100644 --- a/src/OpenMesh/Core/Mesh/TriMeshT.hh +++ b/src/OpenMesh/Core/Mesh/TriMeshT.hh @@ -337,6 +337,64 @@ public: inline VertexHandle split_copy(FaceHandle _fh, const Point& _p) { const VertexHandle vh = this->add_vertex(_p); PolyMesh::split_copy(_fh, vh); return vh; } + + /** \brief Face split (= 1-to-4) split, splits edges at midpoints and adds 4 new faces in the interior). + * + * @param _fh Face handle that should be splitted + */ + inline void split(FaceHandle _fh) + { + // Collect halfedges of face + HalfedgeHandle he0 = this->halfedge_handle(_fh); + HalfedgeHandle he1 = this->next_halfedge_handle(he0); + HalfedgeHandle he2 = this->next_halfedge_handle(he1); + + EdgeHandle eh0 = this->edge_handle(he0); + EdgeHandle eh1 = this->edge_handle(he1); + EdgeHandle eh2 = this->edge_handle(he2); + + // Collect points of face + VertexHandle p0 = this->to_vertex_handle(he0); + VertexHandle p1 = this->to_vertex_handle(he1); + VertexHandle p2 = this->to_vertex_handle(he2); + + // Calculate midpoint coordinates + const Point new0 = (this->point(p0) + this->point(p2)) * static_cast< typename Point::value_type >(0.5); + const Point new1 = (this->point(p0) + this->point(p1)) * static_cast< typename Point::value_type >(0.5); + const Point new2 = (this->point(p1) + this->point(p2)) * static_cast< typename Point::value_type >(0.5); + + // Add vertices at midpoint coordinates + VertexHandle v0 = this->add_vertex(new0); + VertexHandle v1 = this->add_vertex(new1); + VertexHandle v2 = this->add_vertex(new2); + + const bool split0 = !this->is_boundary(he0); + const bool split1 = !this->is_boundary(he1); + const bool split2 = !this->is_boundary(he2); + + // delete original face + this->delete_face(_fh); + + // split boundary edges of deleted face ( if not boundary ) + if ( split0 ) { + this->split(eh0,v0); + } + + if ( split1 ) { + this->split(eh1,v1); + } + + if ( split2 ) { + this->split(eh2,v2); + } + + // Retriangulate + this->add_face(v0 , p0, v1); + this->add_face(p2, v0 , v2); + this->add_face(v2,v1,p1); + this->add_face(v2 , v0, v1); + } + /** \brief Face split (= 1-to-3 split, calls corresponding PolyMeshT function). * * The properties of the new faces will be undefined! diff --git a/src/Unittests/unittests_trimesh_split.cc b/src/Unittests/unittests_trimesh_split.cc new file mode 100644 index 00000000..ffc4019e --- /dev/null +++ b/src/Unittests/unittests_trimesh_split.cc @@ -0,0 +1,117 @@ + +#include +#include +#include + +namespace { + +class OpenMeshSplitTriangleMesh : public OpenMeshBase { + + protected: + + // This function is called before each test is run + virtual void SetUp() { + + // Do some initial stuff with the member data here... + } + + // 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 + * ==================================================================== + */ + +/* splits a face that has a property in a triangle mesh with split_copy + * the property should be copied to the new faces + */ +TEST_F(OpenMeshSplitTriangleMesh, Split_Triangle_Mesh_1_4) { + + mesh_.clear(); + + mesh_.request_vertex_status(); + mesh_.request_edge_status(); + mesh_.request_face_status(); + + // Add some vertices + Mesh::VertexHandle vhandle[6]; + + vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 1, 0)); + vhandle[1] = mesh_.add_vertex(Mesh::Point(1, 0, 0)); + vhandle[2] = mesh_.add_vertex(Mesh::Point(2, 1, 0)); + vhandle[3] = mesh_.add_vertex(Mesh::Point(3, 0, 0)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(4, 1, 0)); + vhandle[5] = mesh_.add_vertex(Mesh::Point(2,-1, 0)); + + // Add three faces + std::vector face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[3]); + Mesh::FaceHandle to_split = mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[5]); + face_vhandles.push_back(vhandle[3]); + mesh_.add_face(face_vhandles); + + /* Test setup: + * + * edge x => halfedge x/x+1 + * i.e. edge 0 => halfedge 0/1 + * + * 0 --4--- 2 ------ 4 + * \ / \ / + * 0 0 2 6 2 / + * \ / 1 \ / + * 1 ---8--- 3 + * \ / + * \ 3 / + * \ / + * \ / + * 5 + */ + + EXPECT_EQ(4u, mesh_.n_faces()); + + // split face with new vertex + mesh_.split(to_split); + + mesh_.garbage_collection(); + + EXPECT_EQ(10u, mesh_.n_faces()); + + + +} + +} + + +