ranges.hh 9.28 KB
Newer Older
1
2
3
4
5
6
7
8
9
#pragma once

#include <cstddef>
#include <vector>

#include "iterators.hh"

namespace polymesh
{
10
11
// ================= COLLECTION =================

Philip Trettner's avatar
Philip Trettner committed
12
template <class mesh_ptr, class tag, class iterator>
Philip Trettner's avatar
Philip Trettner committed
13
struct smart_collection
14
{
Philip Trettner's avatar
Philip Trettner committed
15
    template <typename AttrT>
Philip Trettner's avatar
Philip Trettner committed
16
    using attribute = typename primitive<tag>::template attribute<AttrT>;
17

Philip Trettner's avatar
Philip Trettner committed
18
    /// Number of primitives, INCLUDING those marked for deletion
19
    /// O(1) computation
Philip Trettner's avatar
Philip Trettner committed
20
    int size() const;
Philip Trettner's avatar
Philip Trettner committed
21
22

    /// Ensures that a given number of primitives can be stored without reallocation
Philip Trettner's avatar
Philip Trettner committed
23
    void reserve(int capacity) const;
24

Philip Trettner's avatar
Philip Trettner committed
25
26
27
28
29
30
31
32
    /// Creates a new vertex attribute
    template <class PropT>
    attribute<PropT> make_attribute(PropT const& def_value = PropT());

    // Iteration:
    iterator begin() const;
    iterator end() const;

Philip Trettner's avatar
Philip Trettner committed
33
protected:
Philip Trettner's avatar
Philip Trettner committed
34
    /// Backreference to mesh
Philip Trettner's avatar
Philip Trettner committed
35
    mesh_ptr mesh;
Philip Trettner's avatar
Philip Trettner committed
36
37
38
39

    friend class Mesh;
};

Philip Trettner's avatar
Philip Trettner committed
40
/// Collection of all vertices of a mesh
Philip Trettner's avatar
Philip Trettner committed
41
/// Basically a smart std::vector
Philip Trettner's avatar
Philip Trettner committed
42
43
template <class iterator>
struct vertex_collection : smart_collection<Mesh*, vertex_tag, iterator>
Philip Trettner's avatar
Philip Trettner committed
44
{
45
46
47
48
    /// Adds a new vertex and returns its handle
    /// Does NOT invalidate any iterator!
    vertex_handle add() const;

49
50
51
    /// Removes a vertex (and all adjacent faces and edges)
    /// (marks them as removed, compactify mesh to actually remove them)
    void remove(vertex_handle v) const;
52
53
};

Philip Trettner's avatar
Philip Trettner committed
54
/// Collection of all faces of a mesh
55
/// Basically a smart std::vector
Philip Trettner's avatar
Philip Trettner committed
56
57
template <class iterator>
struct face_collection : smart_collection<Mesh*, face_tag, iterator>
58
59
60
61
62
{
    /// Adds a face consisting of N vertices
    /// The vertices must already be sorted in CCW order
    /// (note: trying to add already existing halfedges triggers assertions)
    template <size_t N>
Philip Trettner's avatar
Philip Trettner committed
63
    face_handle add(const vertex_handle (&v_handles)[N]) const;
Philip Trettner's avatar
Philip Trettner committed
64
65
66
    face_handle add(vertex_handle v0, vertex_handle v1, vertex_handle v2) const;
    face_handle add(vertex_handle v0, vertex_handle v1, vertex_handle v2, vertex_handle v3) const;
    face_handle add(std::vector<vertex_handle> const& v_handles) const;
67
    face_handle add(vertex_handle const* v_handles, int vcnt) const;
Philip Trettner's avatar
Philip Trettner committed
68
    template <size_t N>
Philip Trettner's avatar
Philip Trettner committed
69
    face_handle add(const halfedge_handle (&half_loop)[N]) const;
Philip Trettner's avatar
Philip Trettner committed
70
71
72
    face_handle add(halfedge_handle h0, halfedge_handle h1, halfedge_handle h2) const;
    face_handle add(halfedge_handle h0, halfedge_handle h1, halfedge_handle h2, halfedge_handle h3) const;
    face_handle add(std::vector<halfedge_handle> const& half_loop) const;
73
    face_handle add(halfedge_handle const* half_loop, int vcnt) const;
74

75
76
77
    /// Removes a face (adjacent edges and vertices are NOT removed)
    /// (marks it as removed, compactify mesh to actually remove it)
    void remove(face_handle f) const;
78
79
};

Philip Trettner's avatar
Philip Trettner committed
80
/// Collection of all edges of a mesh
81
/// Basically a smart std::vector
Philip Trettner's avatar
Philip Trettner committed
82
83
template <class iterator>
struct edge_collection : smart_collection<Mesh*, edge_tag, iterator>
84
{
Philip Trettner's avatar
Philip Trettner committed
85
86
87
88
    /// Adds an edge between two existing, distinct vertices
    /// if edge already exists, returns it
    edge_handle add_or_get(vertex_handle v_from, vertex_handle v_to);

Philip Trettner's avatar
Philip Trettner committed
89
90
    // TODO: find

91
92
93
    /// Removes an edge (and both adjacent faces, vertices are NOT removed)
    /// (marks them as removed, compactify mesh to actually remove them)
    void remove(edge_handle e) const;
Philip Trettner's avatar
Philip Trettner committed
94
};
Philip Trettner's avatar
Philip Trettner committed
95

Philip Trettner's avatar
Philip Trettner committed
96
97
/// Collection of all half-edges of a mesh
/// Basically a smart std::vector
Philip Trettner's avatar
Philip Trettner committed
98
99
template <class iterator>
struct halfedge_collection : smart_collection<Mesh*, halfedge_tag, iterator>
Philip Trettner's avatar
Philip Trettner committed
100
101
102
103
104
{
    /// Adds an half-edge between two existing, distinct vertices
    /// if half-edge already exists, returns it
    /// (always adds opposite half-edge as well)
    halfedge_handle add_or_get(vertex_handle v_from, vertex_handle v_to);
Philip Trettner's avatar
Philip Trettner committed
105

Philip Trettner's avatar
Philip Trettner committed
106
107
108
109
110
    // TODO: find

    /// Removes the edge and both half-edges belonging to it (and both adjacent faces, vertices are NOT removed)
    /// (marks them as removed, compactify mesh to actually remove them)
    void remove_edge(halfedge_handle h) const;
111
112
};

Philip Trettner's avatar
Philip Trettner committed
113
// vertices
114

Philip Trettner's avatar
Philip Trettner committed
115
116
117
struct all_vertex_collection : vertex_collection<primitive<vertex_tag>::all_iterator>
{
};
118

Philip Trettner's avatar
Philip Trettner committed
119
120
121
struct all_vertex_const_collection : smart_collection<Mesh const*, vertex_tag, primitive<vertex_tag>::all_iterator>
{
};
122

Philip Trettner's avatar
Philip Trettner committed
123
124
struct valid_vertex_collection : vertex_collection<primitive<vertex_tag>::valid_iterator>
{
125
126
};

Philip Trettner's avatar
Philip Trettner committed
127
struct valid_vertex_const_collection : smart_collection<Mesh const*, vertex_tag, primitive<vertex_tag>::valid_iterator>
128
{
Philip Trettner's avatar
Philip Trettner committed
129
};
130

Philip Trettner's avatar
Philip Trettner committed
131
// faces
132

Philip Trettner's avatar
Philip Trettner committed
133
134
struct all_face_collection : face_collection<primitive<face_tag>::all_iterator>
{
135
136
};

Philip Trettner's avatar
Philip Trettner committed
137
struct all_face_const_collection : smart_collection<Mesh const*, face_tag, primitive<face_tag>::all_iterator>
138
{
Philip Trettner's avatar
Philip Trettner committed
139
};
140

Philip Trettner's avatar
Philip Trettner committed
141
142
143
struct valid_face_collection : face_collection<primitive<face_tag>::valid_iterator>
{
};
144

Philip Trettner's avatar
Philip Trettner committed
145
146
147
struct valid_face_const_collection : smart_collection<Mesh const*, face_tag, primitive<face_tag>::valid_iterator>
{
};
Philip Trettner's avatar
Philip Trettner committed
148

Philip Trettner's avatar
Philip Trettner committed
149
// edges
150

Philip Trettner's avatar
Philip Trettner committed
151
152
153
struct all_edge_collection : edge_collection<primitive<edge_tag>::all_iterator>
{
};
Philip Trettner's avatar
Philip Trettner committed
154

Philip Trettner's avatar
Philip Trettner committed
155
156
struct all_edge_const_collection : smart_collection<Mesh const*, edge_tag, primitive<edge_tag>::all_iterator>
{
157
158
};

Philip Trettner's avatar
Philip Trettner committed
159
struct valid_edge_collection : edge_collection<primitive<edge_tag>::valid_iterator>
160
{
Philip Trettner's avatar
Philip Trettner committed
161
};
162

Philip Trettner's avatar
Philip Trettner committed
163
164
165
struct valid_edge_const_collection : smart_collection<Mesh const*, edge_tag, primitive<edge_tag>::valid_iterator>
{
};
166

Philip Trettner's avatar
Philip Trettner committed
167
// half-edges
168

Philip Trettner's avatar
Philip Trettner committed
169
170
struct all_halfedge_collection : halfedge_collection<primitive<halfedge_tag>::all_iterator>
{
171
172
};

Philip Trettner's avatar
Philip Trettner committed
173
struct all_halfedge_const_collection : smart_collection<Mesh const*, halfedge_tag, primitive<halfedge_tag>::all_iterator>
174
{
Philip Trettner's avatar
Philip Trettner committed
175
};
176

Philip Trettner's avatar
Philip Trettner committed
177
178
179
struct valid_halfedge_collection : halfedge_collection<primitive<halfedge_tag>::valid_iterator>
{
};
180

Philip Trettner's avatar
Philip Trettner committed
181
182
struct valid_halfedge_const_collection : smart_collection<Mesh const*, halfedge_tag, primitive<halfedge_tag>::valid_iterator>
{
183
};
Philip Trettner's avatar
Philip Trettner committed
184

185
186
// ================= RINGS =================

Philip Trettner's avatar
Philip Trettner committed
187
188
template <class this_t, class element_handle>
struct primitive_ring
Philip Trettner's avatar
Philip Trettner committed
189
190
191
{
    face_handle face;

Philip Trettner's avatar
Philip Trettner committed
192
    /// Number of elements
Philip Trettner's avatar
Philip Trettner committed
193
194
    /// O(result) computation
    int size() const;
195
    /// Returns true if handle is contained in this ring
Philip Trettner's avatar
Philip Trettner committed
196
    bool contains(element_handle v) const;
Philip Trettner's avatar
Philip Trettner committed
197
198
};

Philip Trettner's avatar
Philip Trettner committed
199
200
template <class element_handle, class circulator>
struct face_primitive_ring : primitive_ring<face_primitive_ring<element_handle, circulator>, element_handle>
201
202
{
    face_handle face;
Philip Trettner's avatar
Philip Trettner committed
203
    face_primitive_ring(face_handle f) { face = f; }
204
205

    // Iteration:
Philip Trettner's avatar
Philip Trettner committed
206
207
    circulator begin() const { return {face.any_halfedge(), false}; }
    circulator end() const { return {face.any_halfedge(), true}; }
208
209
};

Philip Trettner's avatar
Philip Trettner committed
210
211
template <class element_handle, class circulator>
struct vertex_primitive_ring : primitive_ring<vertex_primitive_ring<element_handle, circulator>, element_handle>
212
{
Philip Trettner's avatar
Philip Trettner committed
213
214
    vertex_handle vertex;
    vertex_primitive_ring(vertex_handle v) { vertex = v; }
215
216

    // Iteration:
Philip Trettner's avatar
Philip Trettner committed
217
218
    circulator begin() const { return {vertex.any_outgoing_halfedge(), vertex.is_isolated()}; }
    circulator end() const { return {vertex.any_outgoing_halfedge(), true}; }
219
220
};

Philip Trettner's avatar
Philip Trettner committed
221
222
/// all vertices belonging to a face
struct face_vertex_ring : face_primitive_ring<vertex_handle, face_vertex_circulator>
223
{
Philip Trettner's avatar
Philip Trettner committed
224
225
    using face_primitive_ring<vertex_handle, face_vertex_circulator>::face_primitive_ring;
};
226

Philip Trettner's avatar
Philip Trettner committed
227
228
229
230
/// all halfedges belonging to a face
struct face_halfedge_ring : face_primitive_ring<halfedge_handle, face_halfedge_circulator>
{
    using face_primitive_ring<halfedge_handle, face_halfedge_circulator>::face_primitive_ring;
231
232
};

Philip Trettner's avatar
Philip Trettner committed
233
234
/// all edges belonging to a face
struct face_edge_ring : face_primitive_ring<edge_handle, face_edge_circulator>
235
{
Philip Trettner's avatar
Philip Trettner committed
236
237
    using face_primitive_ring<edge_handle, face_edge_circulator>::face_primitive_ring;
};
238

Philip Trettner's avatar
Philip Trettner committed
239
240
241
242
243
/// all adjacent faces belonging to a face
struct face_face_ring : face_primitive_ring<face_handle, face_face_circulator>
{
    using face_primitive_ring<face_handle, face_face_circulator>::face_primitive_ring;
};
244

Philip Trettner's avatar
Philip Trettner committed
245
246
247
248
/// all outgoing half-edges from a vertex
struct vertex_halfedge_out_ring : vertex_primitive_ring<halfedge_handle, vertex_halfedge_out_circulator>
{
    using vertex_primitive_ring<halfedge_handle, vertex_halfedge_out_circulator>::vertex_primitive_ring;
249
250
251
};

/// all incoming half-edges from a vertex
Philip Trettner's avatar
Philip Trettner committed
252
struct vertex_halfedge_in_ring : vertex_primitive_ring<halfedge_handle, vertex_halfedge_in_circulator>
253
{
Philip Trettner's avatar
Philip Trettner committed
254
    using vertex_primitive_ring<halfedge_handle, vertex_halfedge_in_circulator>::vertex_primitive_ring;
255
256
257
};

/// all adjacent vertices of a vertex
Philip Trettner's avatar
Philip Trettner committed
258
struct vertex_vertex_ring : vertex_primitive_ring<vertex_handle, vertex_vertex_circulator>
259
{
Philip Trettner's avatar
Philip Trettner committed
260
    using vertex_primitive_ring<vertex_handle, vertex_vertex_circulator>::vertex_primitive_ring;
261
262
263
};

/// all adjacent edges of a vertex
Philip Trettner's avatar
Philip Trettner committed
264
struct vertex_edge_ring : vertex_primitive_ring<edge_handle, vertex_edge_circulator>
265
{
Philip Trettner's avatar
Philip Trettner committed
266
    using vertex_primitive_ring<edge_handle, vertex_edge_circulator>::vertex_primitive_ring;
267
268
269
};

/// all adjacent faces of a vertex (INCLUDES invalid ones for boundaries)
Philip Trettner's avatar
Philip Trettner committed
270
struct vertex_face_ring : vertex_primitive_ring<face_handle, vertex_face_circulator>
271
{
Philip Trettner's avatar
Philip Trettner committed
272
    using vertex_primitive_ring<face_handle, vertex_face_circulator>::vertex_primitive_ring;
273
274
};

Philip Trettner's avatar
Philip Trettner committed
275
276
277

/// ======== IMPLEMENTATION ========

Philip Trettner's avatar
Philip Trettner committed
278
279
template <class this_t, class element_handle>
int primitive_ring<this_t, element_handle>::size() const
280
281
{
    auto cnt = 0;
Philip Trettner's avatar
Philip Trettner committed
282
    for (auto v : *static_cast<this_t const*>(this))
283
284
285
286
287
288
289
    {
        (void)v; // unused
        cnt++;
    }
    return cnt;
}

Philip Trettner's avatar
Philip Trettner committed
290
291
template <class this_t, class element_handle>
bool primitive_ring<this_t, element_handle>::contains(element_handle v) const
292
{
Philip Trettner's avatar
Philip Trettner committed
293
    for (auto v2 : *static_cast<this_t const*>(this))
294
295
296
297
        if (v == v2)
            return true;
    return false;
}
298
}