Merge branch 'tri_1_4_split' into 'master'
Triangle Mesh 1->4 split See merge request !132
This commit is contained in:
@@ -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(eh0);
|
||||
const bool split1 = !this->is_boundary(eh1);
|
||||
const bool split2 = !this->is_boundary(eh2);
|
||||
|
||||
// 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!
|
||||
|
||||
194
src/Unittests/unittests_trimesh_split.cc
Normal file
194
src/Unittests/unittests_trimesh_split.cc
Normal file
@@ -0,0 +1,194 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <Unittests/unittests_common.hh>
|
||||
#include <iostream>
|
||||
|
||||
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_center) {
|
||||
|
||||
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<Mesh::VertexHandle> 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 in center (non-boundary case)
|
||||
mesh_.split(to_split);
|
||||
|
||||
mesh_.garbage_collection();
|
||||
|
||||
EXPECT_EQ(10u, mesh_.n_faces());
|
||||
|
||||
}
|
||||
|
||||
/* 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_boundary) {
|
||||
|
||||
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<Mesh::VertexHandle> face_vhandles;
|
||||
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
Mesh::FaceHandle to_split = 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_.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 at boundary
|
||||
mesh_.split(to_split);
|
||||
|
||||
mesh_.garbage_collection();
|
||||
|
||||
EXPECT_EQ(8u, mesh_.n_faces());
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user