diff --git a/Doc/subdivider.docu b/Doc/subdivider.docu index e6287ffa..a34d6318 100644 --- a/Doc/subdivider.docu +++ b/Doc/subdivider.docu @@ -14,6 +14,7 @@ subdivision: -# OpenMesh::Subdivider::Uniform::InterpolatingSqrt3LGT -# OpenMesh::Subdivider::Uniform::CompositeT -# OpenMesh::Subdivider::Uniform::CatmullClarkT + -# OpenMesh::Subdivider::Uniform::MidpointT -# Adaptive subdivision -# OpenMesh::Subdivider::Adaptive::CompositeT -# Simple subdivision diff --git a/src/OpenMesh/Core/Mesh/PolyMeshT.hh b/src/OpenMesh/Core/Mesh/PolyMeshT.hh index d514fedc..0554161e 100644 --- a/src/OpenMesh/Core/Mesh/PolyMeshT.hh +++ b/src/OpenMesh/Core/Mesh/PolyMeshT.hh @@ -409,6 +409,22 @@ public: return edge_vec.sqrnorm(); } + /** Calculates the midpoint of the halfedge _heh, defined by the positions of + the two incident vertices */ + Point calc_edge_midpoint(HalfedgeHandle _heh) const + { + VertexHandle vh0 = this->from_vertex_handle(_heh); + VertexHandle vh1 = this->to_vertex_handle(_heh); + return 0.5 * (this->point(vh0) + this->point(vh1)); + } + + /** Calculates the midpoint of the edge _eh, defined by the positions of the + two incident vertices */ + Point calc_edge_midpoint(EdgeHandle _eh) const + { + return calc_edge_midpoint(this->halfedge_handle(_eh, 0)); + } + /** defines a consistent representation of a sector geometry: the halfedge _in_heh defines the sector orientation the vertex pointed by _in_heh defines the sector center diff --git a/src/OpenMesh/Tools/Subdivider/Uniform/CatmullClarkT.hh b/src/OpenMesh/Tools/Subdivider/Uniform/CatmullClarkT.hh index 3ba43902..1afc3687 100644 --- a/src/OpenMesh/Tools/Subdivider/Uniform/CatmullClarkT.hh +++ b/src/OpenMesh/Tools/Subdivider/Uniform/CatmullClarkT.hh @@ -88,7 +88,7 @@ namespace Uniform { // BEGIN_NS_UNIFORM \note Needs a PolyMesh to work on! */ -template +template class CatmullClarkT : public SubdividerT< MeshType, RealType > { public: diff --git a/src/OpenMesh/Tools/Subdivider/Uniform/CompositeLoopT.hh b/src/OpenMesh/Tools/Subdivider/Uniform/CompositeLoopT.hh index b0a68531..ad2f3bf7 100644 --- a/src/OpenMesh/Tools/Subdivider/Uniform/CompositeLoopT.hh +++ b/src/OpenMesh/Tools/Subdivider/Uniform/CompositeLoopT.hh @@ -77,7 +77,7 @@ namespace Uniform { // BEGIN_NS_DECIMATER /** Uniform composite Loop subdivision algorithm */ -template +template class CompositeLoopT : public CompositeT { public: diff --git a/src/OpenMesh/Tools/Subdivider/Uniform/CompositeSqrt3T.hh b/src/OpenMesh/Tools/Subdivider/Uniform/CompositeSqrt3T.hh index aa1f572d..28705938 100644 --- a/src/OpenMesh/Tools/Subdivider/Uniform/CompositeSqrt3T.hh +++ b/src/OpenMesh/Tools/Subdivider/Uniform/CompositeSqrt3T.hh @@ -77,7 +77,7 @@ namespace Uniform { // BEGIN_NS_UNIFORM /** Uniform composite sqrt(3) subdivision algorithm */ -template +template class CompositeSqrt3T : public CompositeT { public: diff --git a/src/OpenMesh/Tools/Subdivider/Uniform/LongestEdgeT.hh b/src/OpenMesh/Tools/Subdivider/Uniform/LongestEdgeT.hh index ab02192b..c689af3f 100644 --- a/src/OpenMesh/Tools/Subdivider/Uniform/LongestEdgeT.hh +++ b/src/OpenMesh/Tools/Subdivider/Uniform/LongestEdgeT.hh @@ -82,7 +82,7 @@ namespace Uniform { // BEGIN_NS_UNIFORM //== CLASS DEFINITION ========================================================= -template +template class CompareLengthFunction { public: diff --git a/src/OpenMesh/Tools/Subdivider/Uniform/LoopT.hh b/src/OpenMesh/Tools/Subdivider/Uniform/LoopT.hh index ea767d5a..7701b000 100644 --- a/src/OpenMesh/Tools/Subdivider/Uniform/LoopT.hh +++ b/src/OpenMesh/Tools/Subdivider/Uniform/LoopT.hh @@ -92,7 +92,7 @@ namespace Uniform { // BEGIN_NS_DECIMATER * M.S. Thesis, Department of Mathematics, University of Utah, August 1987. * */ -template +template class LoopT : public SubdividerT { public: diff --git a/src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh b/src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh new file mode 100644 index 00000000..73b1e9f7 --- /dev/null +++ b/src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh @@ -0,0 +1,105 @@ +#pragma once + +#include +#include +#include + +#include + +namespace OpenMesh { +namespace Subdivider { +namespace Uniform { + +/** + * Midpoint subdivision algorithm. + * + * With every step, the set of vertices is replaced with by the midpoints of all + * current edges. Then, two sets of faces are created to set up the new + * connectivity: From all midpoints of edges surrounding an original face, a new + * face is created. Also, for all midpoints of edges surrounding an original + * vertex, a new face is created. + * + * @note This algorithm ignores the _update_points option. + * @note This algorithm is best suited for closed meshes since boundaries tend + * to fragment into isolated faces after a few iterations. + */ +template +class MidpointT : public SubdividerT +{ +public: + typedef RealType real_t; + typedef MeshType mesh_t; + typedef SubdividerT parent_t; + + // Inherited constructors + MidpointT() : parent_t() {} + MidpointT(mesh_t& _m) : parent_t(_m) {} + + const char* name() const { return "midpoint"; } + +protected: // SubdividerT interface + bool prepare(mesh_t& _m) + { + return true; + } + + //! Performs one step of Midpoint subdivision. + //! @note The _update_points option is ignored + bool subdivide(mesh_t& _m, size_t _n, const bool _update_points = true) + { + PropertyManager, mesh_t> edge_midpoint(_m, "edge_midpoint"); + PropertyManager, mesh_t> is_original_vertex(_m, "is_original_vertex"); + + for (size_t iteration = 0; iteration < _n; ++iteration) { + is_original_vertex.set_range(_m.vertices_begin(), _m.vertices_end(), true); + // Create vertices on edge midpoints + for (typename mesh_t::EdgeIter it = _m.edges_begin(), end = _m.edges_end(); it != end; ++it) { + EdgeHandle eh = *it; + VertexHandle new_vh = _m.new_vertex(_m.calc_edge_midpoint(eh)); + edge_midpoint[eh] = new_vh; + is_original_vertex[new_vh] = false; + } + // Create new faces from original faces + for (typename mesh_t::FaceIter it = _m.faces_begin(), end = _m.faces_end(); it != end; ++it) { + FaceHandle fh = *it; + std::vector new_corners; + for (typename mesh_t::FaceEdgeIter it = _m.fe_begin(fh), end = _m.fe_end(fh); it != end; ++it) { + EdgeHandle eh = *it; + new_corners.push_back(edge_midpoint[eh]); + } + _m.add_face(new_corners); + } + // Create new faces from original vertices + for (typename mesh_t::VertexIter it = _m.vertices_begin(), end = _m.vertices_end(); it != end; ++it) { + VertexHandle vh = *it; + if (is_original_vertex[vh]) { + if (!_m.is_boundary(vh)) { + std::vector new_corners; + for (typename mesh_t::VertexEdgeIter it = _m.ve_begin(vh), end = _m.ve_end(vh); it != end; ++it) { + EdgeHandle eh = *it; + new_corners.push_back(edge_midpoint[eh]); + } + std::reverse(new_corners.begin(), new_corners.end()); + _m.add_face(new_corners); + } + } + } + for (typename mesh_t::VertexIter it = _m.vertices_begin(), end = _m.vertices_end(); it != end; ++it) { + VertexHandle vh = *it; + if (is_original_vertex[vh]) { + _m.delete_vertex(vh); + } + } + } + return true; + } + + bool cleanup(mesh_t& _m) + { + return true; + } +}; + +} // namespace Uniform +} // namespace Subdivider +} // namespace OpenMesh diff --git a/src/OpenMesh/Tools/Subdivider/Uniform/ModifiedButterFlyT.hh b/src/OpenMesh/Tools/Subdivider/Uniform/ModifiedButterFlyT.hh index 425d56f6..5825c9b8 100644 --- a/src/OpenMesh/Tools/Subdivider/Uniform/ModifiedButterFlyT.hh +++ b/src/OpenMesh/Tools/Subdivider/Uniform/ModifiedButterFlyT.hh @@ -95,7 +95,7 @@ namespace Uniform { // BEGIN_NS_UNIFORM * * Clement Courbet - clement.courbet@ecp.fr */ -template +template class ModifiedButterflyT : public SubdividerT { public: diff --git a/src/OpenMesh/Tools/Subdivider/Uniform/Sqrt3InterpolatingSubdividerLabsikGreinerT.hh b/src/OpenMesh/Tools/Subdivider/Uniform/Sqrt3InterpolatingSubdividerLabsikGreinerT.hh index 4266aa81..903b39ba 100644 --- a/src/OpenMesh/Tools/Subdivider/Uniform/Sqrt3InterpolatingSubdividerLabsikGreinerT.hh +++ b/src/OpenMesh/Tools/Subdivider/Uniform/Sqrt3InterpolatingSubdividerLabsikGreinerT.hh @@ -109,7 +109,7 @@ namespace Uniform { // BEGIN_NS_UNIFORM * Clement Courbet - clement.courbet@ecp.fr */ -template +template class InterpolatingSqrt3LGT : public SubdividerT< MeshType, RealType > { public: diff --git a/src/OpenMesh/Tools/Subdivider/Uniform/Sqrt3T.hh b/src/OpenMesh/Tools/Subdivider/Uniform/Sqrt3T.hh index 6ed44f97..77e0e6b0 100644 --- a/src/OpenMesh/Tools/Subdivider/Uniform/Sqrt3T.hh +++ b/src/OpenMesh/Tools/Subdivider/Uniform/Sqrt3T.hh @@ -99,7 +99,7 @@ namespace Uniform { // BEGIN_NS_DECIMATER * * L. Kobbelt, "Sqrt(3) subdivision", Proceedings of SIGGRAPH 2000. */ -template +template class Sqrt3T : public SubdividerT< MeshType, RealType > { public: diff --git a/src/OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh b/src/OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh index e1de8506..ad6d038d 100644 --- a/src/OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh +++ b/src/OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh @@ -79,18 +79,17 @@ namespace OpenMesh { namespace Subdivider { namespace Uniform { - //== CLASS DEFINITION ========================================================= /** Abstract base class for uniform subdivision algorithms. * * A derived class must overload the following functions: - * -# name() - * -# prepare() - * -# subdivide() - * -# cleanup() + * -# const char* name() const + * -# void prepare(MeshType&) + * -# void subdivide(MeshType&, size_t, bool) + * -# void cleanup(MeshType&) */ -template +template class SubdividerT : private Utils::Noncopyable { public: @@ -104,7 +103,7 @@ public: //@{ /// Constructor to be used with interface 2 /// \see attach(), operator()(size_t), detach() - SubdividerT(void) : attached_(NULL) { } + SubdividerT(void) : attached_() { } /// Constructor to be used with interface 1 (calls attach()) /// \see operator()( MeshType&, size_t ) @@ -112,7 +111,7 @@ public: //@} - /// Descructor (calls detach()) + /// Destructor (calls detach()) virtual ~SubdividerT() { detach(); }