iterators.hh 6.59 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
#pragma once

#include <cassert>

#include "cursors.hh"

// For iterator interfaces, see http://anderberg.me/2016/07/04/c-custom-iterators/
// Note: some iterator methods are implemented at the end of Mesh.hh to ensure inlining

namespace polymesh
{
12
13
// ================= ITERATOR =================

Philip Trettner's avatar
Philip Trettner committed
14
15
template <typename tag>
struct valid_primitive_iterator
16
{
Philip Trettner's avatar
Philip Trettner committed
17
    using handle_t = typename primitive<tag>::handle;
18

Philip Trettner's avatar
Philip Trettner committed
19
20
21
    static const bool is_all_iterator = false;
    static const bool is_valid_iterator = true;

Philip Trettner's avatar
Philip Trettner committed
22
    valid_primitive_iterator() = default;
23
    valid_primitive_iterator(handle_t handle) : handle(handle) { this->handle.idx = handle.mesh->next_valid_idx_from(handle.idx); }
24

Philip Trettner's avatar
Philip Trettner committed
25
26
    handle_t operator*() const { return handle; }
    valid_primitive_iterator& operator++()
27
    {
28
        ++handle.idx.value;
Philip Trettner's avatar
Philip Trettner committed
29
30
        handle.idx = handle.mesh->next_valid_idx_from(handle.idx);
        return *this;
31
    }
32
    valid_primitive_iterator operator++(int) const
33
34
35
36
    {
        auto i = *this;
        return ++i;
    }
Philip Trettner's avatar
Philip Trettner committed
37
    bool operator==(valid_primitive_iterator const& rhs) const
38
39
40
41
    {
        assert(handle.mesh == rhs.handle.mesh && "comparing iterators from different meshes");
        return handle.idx == rhs.handle.idx;
    }
Philip Trettner's avatar
Philip Trettner committed
42
    bool operator!=(valid_primitive_iterator const& rhs) const
43
44
45
46
47
    {
        assert(handle.mesh == rhs.handle.mesh && "comparing iterators from different meshes");
        return handle.idx != rhs.handle.idx;
    }

Philip Trettner's avatar
Philip Trettner committed
48
    static int primitive_size(Mesh const& m) { return primitive<tag>::valid_size(m); }
Philip Trettner's avatar
Philip Trettner committed
49

50
private:
Philip Trettner's avatar
Philip Trettner committed
51
    handle_t handle;
52
53
};

Philip Trettner's avatar
Philip Trettner committed
54
55
template <typename tag>
struct all_primitive_iterator
56
{
Philip Trettner's avatar
Philip Trettner committed
57
    using handle_t = typename primitive<tag>::handle;
58

Philip Trettner's avatar
Philip Trettner committed
59
60
61
    static const bool is_all_iterator = true;
    static const bool is_valid_iterator = false;

Philip Trettner's avatar
Philip Trettner committed
62
63
    all_primitive_iterator() = default;
    all_primitive_iterator(handle_t handle) : handle(handle) {}
64

Philip Trettner's avatar
Philip Trettner committed
65
66
    handle_t operator*() const { return handle; }
    all_primitive_iterator& operator++()
67
    {
68
        ++handle.idx.value;
Philip Trettner's avatar
Philip Trettner committed
69
        return *this;
70
    }
71
    all_primitive_iterator operator++(int) const
72
73
74
75
    {
        auto i = *this;
        return ++i;
    }
Philip Trettner's avatar
Philip Trettner committed
76
    bool operator==(all_primitive_iterator const& rhs) const
77
78
79
80
    {
        assert(handle.mesh == rhs.handle.mesh && "comparing iterators from different meshes");
        return handle.idx == rhs.handle.idx;
    }
Philip Trettner's avatar
Philip Trettner committed
81
    bool operator!=(all_primitive_iterator const& rhs) const
82
83
84
85
86
    {
        assert(handle.mesh == rhs.handle.mesh && "comparing iterators from different meshes");
        return handle.idx != rhs.handle.idx;
    }

Philip Trettner's avatar
Philip Trettner committed
87
    static int primitive_size(Mesh const& m) { return primitive<tag>::all_size(m); }
Philip Trettner's avatar
Philip Trettner committed
88

89
private:
Philip Trettner's avatar
Philip Trettner committed
90
    handle_t handle;
91
92
};

93
// ================= CIRCULATOR =================
Philip Trettner's avatar
Philip Trettner committed
94

95
96
97
98
99
100
/// Generic half-edge circulator (via CRTP)
/// implement operator* given the current `handle`
/// implement void advance() to change `handle`
/// inherit ctor's from primitive_circulator
template<typename this_t>
struct primitive_circulator
Philip Trettner's avatar
Philip Trettner committed
101
{
102
103
    primitive_circulator() = default;
    primitive_circulator(halfedge_handle handle, bool not_at_begin) : handle(handle), not_at_begin(not_at_begin) {}
Philip Trettner's avatar
Philip Trettner committed
104

105
    primitive_circulator& operator++()
Philip Trettner's avatar
Philip Trettner committed
106
    {
107
        static_cast<this_t*>(this)->advance();
Philip Trettner's avatar
Philip Trettner committed
108
109
110
        not_at_begin = true;
        return *this;
    }
111
    primitive_circulator operator++(int) const
Philip Trettner's avatar
Philip Trettner committed
112
113
114
115
    {
        auto i = *this;
        return ++i;
    }
116
    bool operator==(primitive_circulator const& rhs) const
Philip Trettner's avatar
Philip Trettner committed
117
118
119
120
    {
        assert(handle.mesh == rhs.handle.mesh && "comparing iterators from different meshes");
        return not_at_begin == rhs.not_at_begin && handle.idx == rhs.handle.idx;
    }
121
    bool operator!=(primitive_circulator const& rhs) const
Philip Trettner's avatar
Philip Trettner committed
122
123
124
125
126
    {
        assert(handle.mesh == rhs.handle.mesh && "comparing iterators from different meshes");
        return not_at_begin != rhs.not_at_begin || handle.idx != rhs.handle.idx;
    }

127
protected:
128
129
130
131
    halfedge_handle handle;
    bool not_at_begin;
};

132
struct face_vertex_circulator : primitive_circulator<face_vertex_circulator>
133
{
134
135
136
137
138
139
140
    using primitive_circulator<face_vertex_circulator>::primitive_circulator;
    vertex_handle operator*() const { return handle.vertex_to(); }
    void advance() { handle = handle.next(); }
};
struct face_halfedge_circulator : primitive_circulator<face_halfedge_circulator>
{
    using primitive_circulator<face_halfedge_circulator>::primitive_circulator;
141
    halfedge_handle operator*() const { return handle; }
142
    void advance() { handle = handle.next(); }
143
};
144
struct face_edge_circulator : primitive_circulator<face_edge_circulator>
145
{
146
    using primitive_circulator<face_edge_circulator>::primitive_circulator;
147
    edge_handle operator*() const { return handle.edge(); }
148
    void advance() { handle = handle.next(); }
149
};
150
struct face_face_circulator : primitive_circulator<face_vertex_circulator>
151
{
152
    using primitive_circulator<face_vertex_circulator>::primitive_circulator;
153
    face_handle operator*() const { return handle.opposite_face(); }
154
    void advance() { handle = handle.next(); }
155
156
};

157
struct vertex_halfedge_out_circulator : primitive_circulator<vertex_halfedge_out_circulator>
158
{
159
    using primitive_circulator<vertex_halfedge_out_circulator>::primitive_circulator;
160
    halfedge_handle operator*() const { return handle; }
161
    void advance() { handle = handle.opposite().next(); }
162
};
163
struct vertex_halfedge_in_circulator : primitive_circulator<vertex_halfedge_in_circulator>
164
{
165
    using primitive_circulator<vertex_halfedge_in_circulator>::primitive_circulator;
166
    halfedge_handle operator*() const { return handle.opposite(); }
167
    void advance() { handle = handle.opposite().next(); }
168
};
169
struct vertex_face_circulator : primitive_circulator<vertex_face_circulator>
170
{
171
    using primitive_circulator<vertex_face_circulator>::primitive_circulator;
172
    face_handle operator*() const { return handle.face(); }
173
    void advance() { handle = handle.opposite().next(); }
174
};
175
struct vertex_vertex_circulator : primitive_circulator<vertex_vertex_circulator>
176
{
177
    using primitive_circulator<vertex_vertex_circulator>::primitive_circulator;
178
    vertex_handle operator*() const { return handle.vertex_to(); }
179
    void advance() { handle = handle.opposite().next(); }
180
};
181
struct vertex_edge_circulator : primitive_circulator<vertex_edge_circulator>
182
{
183
    using primitive_circulator<vertex_edge_circulator>::primitive_circulator;
184
    edge_handle operator*() const { return handle.edge(); }
185
    void advance() { handle = handle.opposite().next(); }
Philip Trettner's avatar
Philip Trettner committed
186
};
Philip Trettner's avatar
Philip Trettner committed
187
188
189
190
191
192
193

struct halfedge_ring_circulator : primitive_circulator<halfedge_ring_circulator>
{
    using primitive_circulator<halfedge_ring_circulator>::primitive_circulator;
    halfedge_handle operator*() const { return handle; }
    void advance() { handle = handle.next(); }
};
194
}