MidpointT.hh 4.2 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
/**
 * Midpoint subdivision algorithm.
 *
Janis Born's avatar
Janis Born committed
16
 * With every step, the set of vertices is replaced by the midpoints of all
17 18 19 20 21 22 23 24 25
 * 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:
Janis Born's avatar
Janis Born committed
30 31 32
    typedef RealType real_t;
    typedef MeshType mesh_t;
    typedef SubdividerT<MeshType, RealType> parent_t;
33

Janis Born's avatar
Janis Born committed
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
Janis Born's avatar
Janis Born committed
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
Janis Born's avatar
Janis Born committed
48
    bool subdivide(mesh_t& _m, size_t _n, const bool _update_points = true)
49
    {
50 51 52 53
        _m.request_halfedge_status();
        _m.request_edge_status();
        _m.request_vertex_status();
        _m.request_face_status();
Janis Born's avatar
Janis Born committed
54 55
        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");
56 57 58 59

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

Janis Born's avatar
Janis Born committed
102
    bool cleanup(mesh_t& _m)
103 104 105 106 107 108 109 110
    {
        return true;
    }
};

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