From 39f1eecc829f7ee7761aa72adc2ab5b34e01f89a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20M=C3=B6bius?= Date: Fri, 1 Jul 2011 07:10:15 +0000 Subject: [PATCH] Added is_collapse_ok and split_edge for polymeshes git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@396 fdac6126-5c0c-442c-9429-916003d36597 --- src/OpenMesh/Core/Mesh/PolyConnectivity.cc | 192 +++++++++++++++++++++ src/OpenMesh/Core/Mesh/PolyConnectivity.hh | 10 ++ src/OpenMesh/Core/Mesh/PolyMeshT.hh | 5 +- 3 files changed, 205 insertions(+), 2 deletions(-) diff --git a/src/OpenMesh/Core/Mesh/PolyConnectivity.cc b/src/OpenMesh/Core/Mesh/PolyConnectivity.cc index 512419c2..0b17ecd5 100644 --- a/src/OpenMesh/Core/Mesh/PolyConnectivity.cc +++ b/src/OpenMesh/Core/Mesh/PolyConnectivity.cc @@ -287,6 +287,140 @@ PolyConnectivity::add_face(const VertexHandle* _vertex_handles, uint _vhs_size) return fh; } + + +//----------------------------------------------------------------------------- +bool PolyConnectivity::is_collapse_ok(HalfedgeHandle v0v1) +{ + HalfedgeHandle v1v0(opposite_halfedge_handle(v0v1)); + VertexHandle v0(to_vertex_handle(v1v0)); + VertexHandle v1(to_vertex_handle(v0v1)); + + bool v0v1_triangle = false; + bool v1v0_triangle = false; + + if (!is_boundary(v0v1)) + v0v1_triangle = valence(face_handle(v0v1)) == 3; + + if (!is_boundary(v1v0)) + v1v0_triangle = valence(face_handle(v1v0)) == 3; + + //in a quadmesh we dont have the "next" or "previous" vhandle, so we need to look at previous and next on both sides + VertexHandle v_01_p = from_vertex_handle(prev_halfedge_handle(v0v1)); + VertexHandle v_01_n = to_vertex_handle(next_halfedge_handle(v0v1)); + + VertexHandle v_10_p = from_vertex_handle(prev_halfedge_handle(v1v0)); + VertexHandle v_10_n = to_vertex_handle(next_halfedge_handle(v1v0)); + + //is edge already deleteed? + if (status(edge_handle(v0v1)).deleted()) + { + return false; + } + + //are the vertices already deleted ? + if (status(v0).deleted() || status(v1).deleted()) + { + return false; + } + + //the edges v1-vl and vl-v0 must not be both boundary edges + //this test makes only sense in a polymesh if the side face is a triangle + if (!is_boundary(v0v1)) + { + if (v0v1_triangle) + { + VertexHandle vl = to_vertex_handle(next_halfedge_handle(v0v1)); + + HalfedgeHandle h1 = next_halfedge_handle(v0v1); + HalfedgeHandle h2 = next_halfedge_handle(h1); + if (is_boundary(opposite_halfedge_handle(h1)) && is_boundary(opposite_halfedge_handle(h2))) + return false; + } + } + + //the edges v0-vr and vr-v1 must not be both boundary edges + //this test makes only sense in a polymesh if the side face is a triangle + if (!is_boundary(v1v0)) + { + if (v1v0_triangle) + { + VertexHandle vr = to_vertex_handle(next_halfedge_handle(v1v0)); + + HalfedgeHandle h1 = next_halfedge_handle(v1v0); + HalfedgeHandle h2 = next_halfedge_handle(h1); + if (is_boundary(opposite_halfedge_handle(h1)) && is_boundary(opposite_halfedge_handle(h2))) + return false; + } + } + + // edge between two boundary vertices should be a boundary edge + if ( is_boundary(v0) && is_boundary(v1) && !is_boundary(v0v1) && !is_boundary(v1v0)) + return false; + + VertexVertexIter vv_it; + // test intersection of the one-rings of v0 and v1 + for (vv_it = vv_iter(v0); vv_it; ++vv_it) + { + status(vv_it).set_tagged(false); + } + + for (vv_it = vv_iter(v1); vv_it; ++vv_it) + { + status(vv_it).set_tagged(true); + } + + for (vv_it = vv_iter(v0); vv_it; ++vv_it) + { + if (status(vv_it).tagged() && + !(vv_it.handle() == v_01_n && v0v1_triangle) && + !(vv_it.handle() == v_10_n && v1v0_triangle) + ) + { + return false; + } + } + + //test for a face on the backside/other side that might degenerate + if (v0v1_triangle) + { + HalfedgeHandle one, two; + one = next_halfedge_handle(v0v1); + two = next_halfedge_handle(one); + + one = opposite_halfedge_handle(one); + two = opposite_halfedge_handle(two); + + if (face_handle(one) == face_handle(two) && valence(face_handle(one)) != 3) + { + return false; + } + } + + if (v1v0_triangle) + { + HalfedgeHandle one, two; + one = next_halfedge_handle(v1v0); + two = next_halfedge_handle(one); + + one = opposite_halfedge_handle(one); + two = opposite_halfedge_handle(two); + + if (face_handle(one) == face_handle(two) && valence(face_handle(one)) != 3) + { + return false; + } + } + + if (status(vv_it).tagged() && v_01_n == v_10_n && v0v1_triangle && v1v0_triangle) + { + return false; + } + + // passed all tests + return true; +} + //----------------------------------------------------------------------------- void PolyConnectivity::delete_vertex(VertexHandle _vh, bool _delete_isolated_vertices) @@ -850,5 +984,63 @@ uint PolyConnectivity::valence(FaceHandle _fh) const return count; } +//----------------------------------------------------------------------------- +void PolyConnectivity::split_edge(EdgeHandle _eh, VertexHandle _vh) +{ + HalfedgeHandle h0 = halfedge_handle(_eh, 0); + HalfedgeHandle h1 = halfedge_handle(_eh, 1); + + VertexHandle vfrom = from_vertex_handle(h0); + + HalfedgeHandle ph0 = prev_halfedge_handle(h0); + HalfedgeHandle ph1 = prev_halfedge_handle(h1); + + HalfedgeHandle nh0 = next_halfedge_handle(h0); + HalfedgeHandle nh1 = next_halfedge_handle(h1); + + bool boundary0 = is_boundary(h0); + bool boundary1 = is_boundary(h1); + + //add the new edge + HalfedgeHandle new_e = new_edge(from_vertex_handle(h0), _vh); + + //fix the vertex of the opposite halfedge + set_vertex_handle(h1, _vh); + + //fix the halfedge connectivity + set_next_halfedge_handle(new_e, h0); + set_next_halfedge_handle(h1, opposite_halfedge_handle(new_e)); + + set_next_halfedge_handle(ph0, new_e); + set_next_halfedge_handle(opposite_halfedge_handle(new_e), nh1); + + set_prev_halfedge_handle(new_e, ph0); + set_prev_halfedge_handle(opposite_halfedge_handle(new_e), h1); + + set_prev_halfedge_handle(nh1, opposite_halfedge_handle(new_e)); + set_prev_halfedge_handle(h0, new_e); + + if (!boundary0) + { + set_face_handle(new_e, face_handle(h0)); + } else + { + set_boundary(new_e); + } + + if (!boundary1) + { + set_face_handle(opposite_halfedge_handle(new_e), face_handle(h1)); + } + { + set_boundary(opposite_halfedge_handle(new_e)); + } + + if (halfedge_handle(vfrom) == h0) + { + set_halfedge_handle(vfrom, new_e); + } +} + }//namespace OpenMesh diff --git a/src/OpenMesh/Core/Mesh/PolyConnectivity.hh b/src/OpenMesh/Core/Mesh/PolyConnectivity.hh index d4d14d42..30aaf583 100644 --- a/src/OpenMesh/Core/Mesh/PolyConnectivity.hh +++ b/src/OpenMesh/Core/Mesh/PolyConnectivity.hh @@ -236,6 +236,13 @@ public: /// \name Deleting mesh items and other connectivity/topology modifications //@{ + /** Returns whether collapsing halfedge _heh is ok or would lead to + topological inconsistencies. + \attention This method need the Attributes::Status attribute and + changes the \em tagged bit. */ + bool is_collapse_ok(HalfedgeHandle _he); + + /** Mark vertex and all incident edges and faces deleted. Items marked deleted will be removed by garbageCollection(). \attention Needs the Attributes::Status attribute for vertices, @@ -657,6 +664,9 @@ public: /// triangulate the entire mesh void triangulate(); + /// Edge split (inserts a vertex on the edge only) + void split_edge(EdgeHandle _eh, VertexHandle _vh); + /** \name Generic handle derefertiation. Calls the respective vertex(), halfedge(), edge(), face() diff --git a/src/OpenMesh/Core/Mesh/PolyMeshT.hh b/src/OpenMesh/Core/Mesh/PolyMeshT.hh index fd13dbb4..113b405c 100644 --- a/src/OpenMesh/Core/Mesh/PolyMeshT.hh +++ b/src/OpenMesh/Core/Mesh/PolyMeshT.hh @@ -430,10 +430,11 @@ public: { Kernel::split(_fh, _vh); } inline void split(EdgeHandle _eh, const Point& _p) - { Kernel::split(_eh, add_vertex(_p)); } + { Kernel::split_edge(_eh, add_vertex(_p)); } inline void split(EdgeHandle _eh, VertexHandle _vh) - { Kernel::split(_eh, _vh); } + { Kernel::split_edge(_eh, _vh); } + };