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 {

Janis Born's avatar
Janis Born committed
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:
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;
    }

Janis Born's avatar
Janis Born committed
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
    {
Janis Born's avatar
Janis Born committed
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
Janis Born's avatar
Janis Born committed
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
Janis Born's avatar
Janis Born committed
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;
Janis Born's avatar
Janis Born committed
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
Janis Born's avatar
Janis Born committed
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;
Janis Born's avatar
Janis Born committed
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]);
                        }
Janis Born's avatar
Janis Born committed
82
                        std::reverse(new_corners.begin(), new_corners.end());
83
84
85
86
                        _m.add_face(new_corners);
                    }
                }
            }
Janis Born's avatar
Janis Born committed
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;
    }

Janis Born's avatar
Janis Born committed
97
    bool cleanup(mesh_t& _m)
98
99
100
101
102
103
104
105
    {
        return true;
    }
};

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