MidpointT.hh 4.03 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
#pragma once

#include <OpenMesh/Core/Mesh/BaseKernel.hh>
#include <OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh>
#include <OpenMesh/Core/Utils/PropertyManager.hh>

#include <algorithm>

namespace OpenMesh {
namespace Subdivider {
namespace Uniform {

13 14 15 16 17 18 19 20 21 22 23 24 25
/**
 * 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.
 */
26 27 28 29
template<typename MeshType, typename RealType = double>
class MidpointT : public SubdividerT<MeshType, RealType>
{
public:
30 31 32
    typedef RealType real_t;
    typedef MeshType mesh_t;
    typedef SubdividerT<MeshType, RealType> parent_t;
33

34 35 36
    // Inherited constructors
    MidpointT() : parent_t() {}
    MidpointT(mesh_t& _m) : parent_t(_m) {}
37 38 39 40

    const char* name() const { return "midpoint"; }

protected: // SubdividerT interface
41
    bool prepare(mesh_t& _m)
42 43 44 45
    {
        return true;
    }

46 47
    //! Performs one step of Midpoint subdivision.
    //! @note The _update_points option is ignored
48
    bool subdivide(mesh_t& _m, size_t _n, const bool _update_points = true)
49
    {
50 51
        PropertyManager<EPropHandleT<typename mesh_t::VertexHandle>, mesh_t> edge_midpoint(_m, "edge_midpoint");
        PropertyManager<VPropHandleT<bool>, mesh_t> is_original_vertex(_m, "is_original_vertex");
52 53 54 55

        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
56 57 58
            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));
59 60 61 62
                edge_midpoint[eh] = new_vh;
                is_original_vertex[new_vh] = false;
            }
            // Create new faces from original faces
63 64
            for (typename mesh_t::FaceIter it = _m.faces_begin(), end = _m.faces_end(); it != end; ++it) {
                FaceHandle fh = *it;
65
                std::vector<typename mesh_t::VertexHandle> new_corners;
66 67
                for (typename mesh_t::FaceEdgeIter it = _m.fe_begin(fh), end = _m.fe_end(fh); it != end; ++it) {
                    EdgeHandle eh = *it;
68 69 70 71 72
                    new_corners.push_back(edge_midpoint[eh]);
                }
                _m.add_face(new_corners);
            }
            // Create new faces from original vertices
73 74
            for (typename mesh_t::VertexIter it = _m.vertices_begin(), end = _m.vertices_end(); it != end; ++it) {
                VertexHandle vh = *it;
75 76 77
                if (is_original_vertex[vh]) {
                    if (!_m.is_boundary(vh)) {
                        std::vector<typename mesh_t::VertexHandle> new_corners;
78 79
                        for (typename mesh_t::VertexEdgeIter it = _m.ve_begin(vh), end = _m.ve_end(vh); it != end; ++it) {
                            EdgeHandle eh = *it;
80 81
                            new_corners.push_back(edge_midpoint[eh]);
                        }
82
                        std::reverse(new_corners.begin(), new_corners.end());
83 84 85 86
                        _m.add_face(new_corners);
                    }
                }
            }
87 88
            for (typename mesh_t::VertexIter it = _m.vertices_begin(), end = _m.vertices_end(); it != end; ++it) {
                VertexHandle vh = *it;
89 90 91 92 93 94 95 96
                if (is_original_vertex[vh]) {
                    _m.delete_vertex(vh);
                }
            }
        }
        return true;
    }

97
    bool cleanup(mesh_t& _m)
98 99 100 101 102 103 104 105
    {
        return true;
    }
};

} // namespace Uniform
} // namespace Subdivider
} // namespace OpenMesh