From 3b906e51199363e33299a3f9bf3b96b0a3dc8de1 Mon Sep 17 00:00:00 2001 From: Janis Born Date: Wed, 11 Jan 2017 17:26:28 +0100 Subject: [PATCH 1/7] use double as default RealType for subdividers --- .../Tools/Subdivider/Uniform/CatmullClarkT.hh | 2 +- .../Tools/Subdivider/Uniform/CompositeLoopT.hh | 2 +- .../Tools/Subdivider/Uniform/CompositeSqrt3T.hh | 2 +- .../Tools/Subdivider/Uniform/LongestEdgeT.hh | 2 +- src/OpenMesh/Tools/Subdivider/Uniform/LoopT.hh | 2 +- .../Subdivider/Uniform/ModifiedButterFlyT.hh | 2 +- ...qrt3InterpolatingSubdividerLabsikGreinerT.hh | 2 +- src/OpenMesh/Tools/Subdivider/Uniform/Sqrt3T.hh | 2 +- .../Tools/Subdivider/Uniform/SubdividerT.hh | 17 ++++++++--------- 9 files changed, 16 insertions(+), 17 deletions(-) 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/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..aa6bc331 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,15 +103,15 @@ public: //@{ /// Constructor to be used with interface 2 /// \see attach(), operator()(size_t), detach() - SubdividerT(void) : attached_(NULL) { } + SubdividerT(void) : attached_(nullptr) { } /// Constructor to be used with interface 1 (calls attach()) /// \see operator()( MeshType&, size_t ) - SubdividerT( MeshType &_m ) : attached_(NULL) { attach(_m); } + SubdividerT( MeshType &_m ) : attached_(nullptr) { attach(_m); } //@} - /// Descructor (calls detach()) + /// Destructor (calls detach()) virtual ~SubdividerT() { detach(); } From 3179316c829b3e34ae8ca08ce16c05a6a762c532 Mon Sep 17 00:00:00 2001 From: Janis Born Date: Wed, 11 Jan 2017 17:27:11 +0100 Subject: [PATCH 2/7] add calc_edge_midpoint methods for meshes --- src/OpenMesh/Core/Mesh/PolyMeshT.hh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/OpenMesh/Core/Mesh/PolyMeshT.hh b/src/OpenMesh/Core/Mesh/PolyMeshT.hh index d514fedc..bccabcd6 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 + { + auto vh0 = this->from_vertex_handle(_heh); + auto 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 From 50e3887abe143714ffd4541865ac366db70c7c58 Mon Sep 17 00:00:00 2001 From: Janis Born Date: Wed, 11 Jan 2017 17:27:44 +0100 Subject: [PATCH 3/7] add Midpoint uniform subdivision scheme --- .../Tools/Subdivider/Uniform/MidpointT.hh | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh diff --git a/src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh b/src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh new file mode 100644 index 00000000..99875135 --- /dev/null +++ b/src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh @@ -0,0 +1,82 @@ +#pragma once + +#include +#include +#include + +#include + +namespace OpenMesh { +namespace Subdivider { +namespace Uniform { + +template +class MidpointT : public SubdividerT +{ +public: + using real_t = RealType; + using mesh_t = MeshType; + using parent_t = SubdividerT; + + using parent_t::parent_t; + + const char* name() const { return "midpoint"; } + +protected: // SubdividerT interface + bool prepare(mesh_t& _m) override + { + return true; + } + + bool subdivide(mesh_t& _m, size_t _n, const bool _update_points = true) override + { + auto edge_midpoint = makePropertyManagerFromNew>(_m, "edge_midpoint"); + auto is_original_vertex = makePropertyManagerFromNew>(_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 (const auto& eh : _m.edges()) { + auto 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 (const auto& fh : _m.faces()) { + std::vector new_corners; + for (const auto& eh : _m.fe_range(fh)) { + new_corners.push_back(edge_midpoint[eh]); + } + _m.add_face(new_corners); + } + // Create new faces from original vertices + for (const auto& vh : _m.vertices()) { + if (is_original_vertex[vh]) { + if (!_m.is_boundary(vh)) { + std::vector new_corners; + for (const auto& eh : _m.ve_range(vh)) { + new_corners.push_back(edge_midpoint[eh]); + } + std::reverse(begin(new_corners), end(new_corners)); + _m.add_face(new_corners); + } + } + } + for (const auto& vh : _m.vertices()) { + if (is_original_vertex[vh]) { + _m.delete_vertex(vh); + } + } + } + return true; + } + + bool cleanup(mesh_t& _m) override + { + return true; + } +}; + +} // namespace Uniform +} // namespace Subdivider +} // namespace OpenMesh From 3d1bf65c9338300b67ef1cf19f47aacae710c885 Mon Sep 17 00:00:00 2001 From: Janis Born Date: Thu, 12 Jan 2017 13:38:57 +0100 Subject: [PATCH 4/7] =?UTF-8?q?port=20MidpointT=20back=20to=20C++98=20?= =?UTF-8?q?=F0=9F=98=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Tools/Subdivider/Uniform/MidpointT.hh | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh b/src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh index 99875135..bb80618e 100644 --- a/src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh +++ b/src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh @@ -14,55 +14,63 @@ template class MidpointT : public SubdividerT { public: - using real_t = RealType; - using mesh_t = MeshType; - using parent_t = SubdividerT; + typedef RealType real_t; + typedef MeshType mesh_t; + typedef SubdividerT parent_t; - using parent_t::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) override + bool prepare(mesh_t& _m) { return true; } - bool subdivide(mesh_t& _m, size_t _n, const bool _update_points = true) override + bool subdivide(mesh_t& _m, size_t _n, const bool _update_points = true) { - auto edge_midpoint = makePropertyManagerFromNew>(_m, "edge_midpoint"); - auto is_original_vertex = makePropertyManagerFromNew>(_m, "is_original_vertex"); + 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 (const auto& eh : _m.edges()) { - auto new_vh = _m.new_vertex(_m.calc_edge_midpoint(eh)); + 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 (const auto& fh : _m.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 (const auto& eh : _m.fe_range(fh)) { + 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 (const auto& vh : _m.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 (const auto& eh : _m.ve_range(vh)) { + 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(begin(new_corners), end(new_corners)); + std::reverse(new_corners.begin(), new_corners.end()); _m.add_face(new_corners); } } } - for (const auto& vh : _m.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]) { _m.delete_vertex(vh); } @@ -71,7 +79,7 @@ protected: // SubdividerT interface return true; } - bool cleanup(mesh_t& _m) override + bool cleanup(mesh_t& _m) { return true; } From 949e7050822c9d4d218a98bbdd815d5b0ea50cf2 Mon Sep 17 00:00:00 2001 From: Janis Born Date: Thu, 12 Jan 2017 13:41:08 +0100 Subject: [PATCH 5/7] more C++98 compatibility --- src/OpenMesh/Core/Mesh/PolyMeshT.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenMesh/Core/Mesh/PolyMeshT.hh b/src/OpenMesh/Core/Mesh/PolyMeshT.hh index bccabcd6..0554161e 100644 --- a/src/OpenMesh/Core/Mesh/PolyMeshT.hh +++ b/src/OpenMesh/Core/Mesh/PolyMeshT.hh @@ -413,8 +413,8 @@ public: the two incident vertices */ Point calc_edge_midpoint(HalfedgeHandle _heh) const { - auto vh0 = this->from_vertex_handle(_heh); - auto vh1 = this->to_vertex_handle(_heh); + VertexHandle vh0 = this->from_vertex_handle(_heh); + VertexHandle vh1 = this->to_vertex_handle(_heh); return 0.5 * (this->point(vh0) + this->point(vh1)); } From ecb15612f1f42d0648e35840b5a9101bbfcb10cd Mon Sep 17 00:00:00 2001 From: Janis Born Date: Thu, 12 Jan 2017 15:19:18 +0100 Subject: [PATCH 6/7] even more C++98 compatibility --- src/OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh b/src/OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh index aa6bc331..ad6d038d 100644 --- a/src/OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh +++ b/src/OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh @@ -103,11 +103,11 @@ public: //@{ /// Constructor to be used with interface 2 /// \see attach(), operator()(size_t), detach() - SubdividerT(void) : attached_(nullptr) { } + SubdividerT(void) : attached_() { } /// Constructor to be used with interface 1 (calls attach()) /// \see operator()( MeshType&, size_t ) - SubdividerT( MeshType &_m ) : attached_(nullptr) { attach(_m); } + SubdividerT( MeshType &_m ) : attached_(NULL) { attach(_m); } //@} From e8247d6440c17f7029b9bfc9239dd87337a2dc52 Mon Sep 17 00:00:00 2001 From: Janis Born Date: Thu, 12 Jan 2017 17:09:27 +0100 Subject: [PATCH 7/7] add documentation for MidpointT --- Doc/subdivider.docu | 1 + .../Tools/Subdivider/Uniform/MidpointT.hh | 15 +++++++++++++++ 2 files changed, 16 insertions(+) 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/Tools/Subdivider/Uniform/MidpointT.hh b/src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh index bb80618e..73b1e9f7 100644 --- a/src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh +++ b/src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh @@ -10,6 +10,19 @@ 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 { @@ -30,6 +43,8 @@ protected: // SubdividerT interface 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");