ranges.hh 17.1 KB
Newer Older
1
2
3
#pragma once

#include <cstddef>
4
5
#include <map>
#include <set>
6
7
8
9
10
11
#include <vector>

#include "iterators.hh"

namespace polymesh
{
Philip Trettner's avatar
Philip Trettner committed
12
13
14
15
16
17
template <class T>
struct aabb
{
    T min;
    T max;
};
Philip Trettner's avatar
Philip Trettner committed
18

19
20
21
22
23
24
25
template <class V, class W>
struct weighted_sample
{
    V value;
    W weight;
};

Philip Trettner's avatar
Philip Trettner committed
26
template <class this_t, class ElementT>
Philip Trettner's avatar
Philip Trettner committed
27
28
29
struct smart_range
{
    /// returns the first element in this range
Philip Trettner's avatar
Philip Trettner committed
30
31
32
33
    /// returns invalid on empty ranges (or default ctor'd one)
    ElementT first() const;
    /// returns the last element in this range
    /// returns invalid on empty ranges (or default ctor'd one)
Philip Trettner's avatar
Philip Trettner committed
34
    /// TODO: how to make this O(1)
Philip Trettner's avatar
Philip Trettner committed
35
    ElementT last() const;
Philip Trettner's avatar
Philip Trettner committed
36

37
38
    /// returns true if the range is empty
    bool empty() const;
Philip Trettner's avatar
Philip Trettner committed
39
40
    /// returns true if the range is non-empty
    bool any() const;
41
    /// returns true if any value fulfils p(v)
Philip Trettner's avatar
Philip Trettner committed
42
43
    /// also works for boolean attributes
    template <class PredT>
Philip Trettner's avatar
Philip Trettner committed
44
    bool any(PredT&& p) const;
45
    /// returns true if all values fulfil p(v)
Philip Trettner's avatar
Philip Trettner committed
46
47
    /// also works for boolean attributes
    template <class PredT>
Philip Trettner's avatar
Philip Trettner committed
48
49
50
51
52
53
54
    bool all(PredT&& p) const;

    /// returns the number of elements in this range
    /// NOTE: this is an O(n) operation, prefer size() if available
    /// TODO: maybe SFINAE to implement this via size() if available?
    int count() const;

55
56
57
58
59
    /// calculates min(f(e)) over all elements
    /// undefined behavior if range is empty
    /// works for std::min and everything reachable by ADL (calls min(_, _))
    template <class FuncT>
    auto min(FuncT&& f) const -> tmp::decayed_result_type_of<FuncT, ElementT>;
Philip Trettner's avatar
Philip Trettner committed
60
61
62
63
64
    /// returns e that minimizes f(e)
    /// undefined behavior if range is empty
    /// requires working comparison operators for the result
    template <class FuncT>
    ElementT min_by(FuncT&& f) const;
65
66
67
68
69
    /// calculates max(f(e)) over all elements
    /// undefined behavior if range is empty
    /// works for std::max and everything reachable by ADL (calls max(_, _))
    template <class FuncT>
    auto max(FuncT&& f) const -> tmp::decayed_result_type_of<FuncT, ElementT>;
Philip Trettner's avatar
Philip Trettner committed
70
71
72
73
74
    /// returns e that maximizes f(e)
    /// undefined behavior if range is empty
    /// requires working comparison operators for the result
    template <class FuncT>
    ElementT max_by(FuncT&& f) const;
75
76
77
78
79
80
81
82
83
84
    /// calculates the sum of f(e) over all elements
    /// undefined behavior if range is empty
    /// requires operator+ for the elements
    template <class FuncT>
    auto sum(FuncT&& f) const -> tmp::decayed_result_type_of<FuncT, ElementT>;
    /// calculates the avg of f(e) over all elements
    /// undefined behavior if range is empty
    /// requires operator+ for the elements as well as operator/(ElementT, int)
    template <class FuncT>
    auto avg(FuncT&& f) const -> tmp::decayed_result_type_of<FuncT, ElementT>;
Philip Trettner's avatar
Philip Trettner committed
85

86
87
88
89
90
91
    /// calculates the weighted avg of f(e) with weight w(e) over all elements
    /// undefined behavior if range is empty
    /// requires operator+ for the elements and weights as well as operator/(ElementT, WeightT)
    template <class FuncT, class WeightT>
    auto weighted_avg(FuncT&& f, WeightT&& w) const -> tmp::decayed_result_type_of<FuncT, ElementT>;

92
93
94
95
96
97
98
99
    /// calculates the aabb (min and max) of f(e) over all elements
    /// undefined behavior if range is empty
    /// works for std::min/max and everything reachable by ADL (calls min/max(_, _))
    template <class FuncT>
    auto aabb(FuncT&& f) const -> polymesh::aabb<tmp::decayed_result_type_of<FuncT, ElementT>>;
    /// same as aabb(...)
    template <class FuncT>
    auto minmax(FuncT&& f) const -> polymesh::aabb<tmp::decayed_result_type_of<FuncT, ElementT>>;
Philip Trettner's avatar
Philip Trettner committed
100
101
102
103
104
    /// returns {e_min, e_max} that minimizes/maximizes f(e)
    /// undefined behavior if range is empty
    /// requires working comparison operators for the result
    template <class FuncT>
    polymesh::aabb<ElementT> minmax_by(FuncT&& f) const;
105

106
107
108
109
110
111
112
113
114
115
116
117
118
    /// converts this range to a vector
    std::vector<ElementT> to_vector() const;
    /// converts this range to a set
    std::set<ElementT> to_set() const;
    /// converts this range to a vector containing f(v) entries
    template <class FuncT>
    auto to_vector(FuncT&& f) const -> std::vector<tmp::decayed_result_type_of<FuncT, ElementT>>;
    /// converts this range to a set containing f(v) entries
    template <class FuncT>
    auto to_set(FuncT&& f) const -> std::set<tmp::decayed_result_type_of<FuncT, ElementT>>;
    /// converts this range to a map containing {v, f(v)} entries
    template <class FuncT>
    auto to_map(FuncT&& f) const -> std::map<ElementT, tmp::decayed_result_type_of<FuncT, ElementT>>;
Philip Trettner's avatar
Philip Trettner committed
119

120
    // TODO: (requires new ranges)
Philip Trettner's avatar
Philip Trettner committed
121
122
123
124
    // - filter (or where?)
    // - map
    // - skip
    // - only_valid
125
    // - conversions from vector/set/map
Philip Trettner's avatar
Philip Trettner committed
126
127
};

128
129
// ================= COLLECTION =================

Philip Trettner's avatar
Philip Trettner committed
130
template <class mesh_ptr, class tag, class iterator>
Philip Trettner's avatar
Philip Trettner committed
131
struct smart_collection : smart_range<smart_collection<mesh_ptr, tag, iterator>, typename primitive<tag>::handle>
132
{
Philip Trettner's avatar
Philip Trettner committed
133
    template <class AttrT>
Philip Trettner's avatar
Philip Trettner committed
134
    using attribute = typename primitive<tag>::template attribute<AttrT>;
Philip Trettner's avatar
Philip Trettner committed
135
    using handle = typename primitive<tag>::handle;
136

Philip Trettner's avatar
Philip Trettner committed
137
    /// Number of primitives, INCLUDING those marked for deletion
138
    /// O(1) computation
Philip Trettner's avatar
Philip Trettner committed
139
    int size() const;
Philip Trettner's avatar
Philip Trettner committed
140
141

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

Philip Trettner's avatar
Philip Trettner committed
144
    /// Creates a new primitive attribute
145
146
    template <class AttrT>
    attribute<AttrT> make_attribute() const;
Philip Trettner's avatar
Philip Trettner committed
147
    /// Creates a new primitive attribute with a given default value
148
149
150
151
152
153
154
155
    template <class AttrT>
    attribute<AttrT> make_attribute_with_default(AttrT const& def_value) const;
    /// Creates a new primitive attribute and copies the given data
    template <class AttrT>
    attribute<AttrT> make_attribute_from_data(std::vector<AttrT> const& data) const;
    /// Creates a new primitive attribute and copies the given data
    template <class AttrT>
    attribute<AttrT> make_attribute_from_data(AttrT const* data, int cnt) const;
Philip Trettner's avatar
Philip Trettner committed
156
    /// Creates a new primitive attribute and initializes it with f(h) for each handle h
157
158
    template <class FuncT, class AttrT = tmp::decayed_result_type_of<FuncT, handle>>
    attribute<AttrT> make_attribute(FuncT&& f, AttrT const& def_value = AttrT()) const;
Philip Trettner's avatar
Philip Trettner committed
159
160
161
162
163

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

Philip Trettner's avatar
Philip Trettner committed
164
protected:
Philip Trettner's avatar
Philip Trettner committed
165
    /// Backreference to mesh
Philip Trettner's avatar
Philip Trettner committed
166
    mesh_ptr mesh;
Philip Trettner's avatar
Philip Trettner committed
167
168
169
170

    friend class Mesh;
};

Philip Trettner's avatar
Philip Trettner committed
171
/// Collection of all vertices of a mesh
Philip Trettner's avatar
Philip Trettner committed
172
/// Basically a smart std::vector
Philip Trettner's avatar
Philip Trettner committed
173
174
template <class iterator>
struct vertex_collection : smart_collection<Mesh*, vertex_tag, iterator>
Philip Trettner's avatar
Philip Trettner committed
175
{
176
177
178
179
    /// Adds a new vertex and returns its handle
    /// Does NOT invalidate any iterator!
    vertex_handle add() const;

Philip Trettner's avatar
Philip Trettner committed
180
181
182
183
    /// Collapsed the given vertex by removing it and merging the adjacent faces
    /// Preserves half-edge properties but not face ones
    void collapse(vertex_handle v) const;

184
185
186
    /// 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;
187
188
};

Philip Trettner's avatar
Philip Trettner committed
189
/// Collection of all faces of a mesh
190
/// Basically a smart std::vector
Philip Trettner's avatar
Philip Trettner committed
191
192
template <class iterator>
struct face_collection : smart_collection<Mesh*, face_tag, iterator>
193
194
195
196
197
{
    /// 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
198
    face_handle add(const vertex_handle (&v_handles)[N]) const;
Philip Trettner's avatar
Philip Trettner committed
199
200
201
    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;
202
    face_handle add(vertex_handle const* v_handles, int vcnt) const;
Philip Trettner's avatar
Philip Trettner committed
203
    template <size_t N>
Philip Trettner's avatar
Philip Trettner committed
204
    face_handle add(const halfedge_handle (&half_loop)[N]) const;
Philip Trettner's avatar
Philip Trettner committed
205
206
207
    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;
208
    face_handle add(halfedge_handle const* half_loop, int vcnt) const;
209

Philip Trettner's avatar
Philip Trettner committed
210
211
212
213
214
    /// Splits a face by inserting a vertex (which is returned) and creating triangles towards it
    /// Preserves half-edge attributes
    /// The face itself is deleted and multiple new ones are created
    vertex_handle split(face_handle f) const;

215
216
217
    /// 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;
218
219
};

Philip Trettner's avatar
Philip Trettner committed
220
/// Collection of all edges of a mesh
221
/// Basically a smart std::vector
Philip Trettner's avatar
Philip Trettner committed
222
223
template <class iterator>
struct edge_collection : smart_collection<Mesh*, edge_tag, iterator>
224
{
Philip Trettner's avatar
Philip Trettner committed
225
226
    /// Adds an edge between two existing, distinct vertices
    /// if edge already exists, returns it
Philip Trettner's avatar
Philip Trettner committed
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
    edge_handle add_or_get(vertex_handle v_from, vertex_handle v_to) const;

    /// Returns the edge handle between two vertices (invalid if not found)
    /// O(valence) computation
    edge_handle find(vertex_handle v_from, vertex_handle v_to) const;

    /// Splits this edge in half by inserting a vertex (which is returned)
    /// Preserves face attributes
    /// The edge itself is deleted and two new ones are created
    vertex_handle split(edge_handle e) const;

    /// Moves both half-edges vertices to their next half-edge vertex
    /// Equivalent to an edge flip if both faces are triangular
    /// Preserves all attributes
    /// NOTE: does not work on boundaries!
    /// TODO: image
    void rotate_next(edge_handle e) const;
    /// Same as rotate_next but with the previous half-edge
    void rotate_prev(edge_handle e) const;
Philip Trettner's avatar
Philip Trettner committed
246

247
248
249
    /// 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
250
};
Philip Trettner's avatar
Philip Trettner committed
251

Philip Trettner's avatar
Philip Trettner committed
252
253
/// Collection of all half-edges of a mesh
/// Basically a smart std::vector
Philip Trettner's avatar
Philip Trettner committed
254
255
template <class iterator>
struct halfedge_collection : smart_collection<Mesh*, halfedge_tag, iterator>
Philip Trettner's avatar
Philip Trettner committed
256
257
258
259
{
    /// Adds an half-edge between two existing, distinct vertices
    /// if half-edge already exists, returns it
    /// (always adds opposite half-edge as well)
Philip Trettner's avatar
Philip Trettner committed
260
261
262
263
264
265
    halfedge_handle add_or_get(vertex_handle v_from, vertex_handle v_to) const;

    /// Returns the half-edge handle between two vertices (invalid if not found)
    /// O(valence) computation
    halfedge_handle find(vertex_handle v_from, vertex_handle v_to) const;

Philip Trettner's avatar
Philip Trettner committed
266
267
268
269
270
    /// Collapsed the given half-edge by removing it, keeping the to_vertex, and creating new triangles
    /// Preserves half-edge properties but not face or vertex ones
    /// Similar to a vertex collapse of the `from` vertex with triangulation towards `to`
    void collapse(halfedge_handle h) const;

Philip Trettner's avatar
Philip Trettner committed
271
272
    /// Splits this half-edge in half by inserting a vertex (which is returned)
    /// Preserves face attributes
Philip Trettner's avatar
Philip Trettner committed
273
    /// Contrary to edges().split, the edge is preserved and a single new one is inserted AFTER h
Philip Trettner's avatar
Philip Trettner committed
274
275
276
277
278
279
280
281
282
283
284
    /// (thus h->next() is the newly inserted edge and h->vertex_to() is the returned vertex)
    vertex_handle split(halfedge_handle h) const;

    /// Moves the to-vertex of this half-edge to the same as the next half-edge
    /// Preserves all attributes
    /// NOTE: does not work on boundaries!
    /// NOTE: does not work on triangles!
    /// TODO: image
    void rotate_next(halfedge_handle h) const;
    /// Same as rotate_next but with the previous half-edge
    void rotate_prev(halfedge_handle h) const;
Philip Trettner's avatar
Philip Trettner committed
285
286
287
288

    /// 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;
289
290
};

Philip Trettner's avatar
Philip Trettner committed
291
// vertices
292

Philip Trettner's avatar
Philip Trettner committed
293
294
295
struct all_vertex_collection : vertex_collection<primitive<vertex_tag>::all_iterator>
{
};
296

Philip Trettner's avatar
Philip Trettner committed
297
298
299
struct all_vertex_const_collection : smart_collection<Mesh const*, vertex_tag, primitive<vertex_tag>::all_iterator>
{
};
300

Philip Trettner's avatar
Philip Trettner committed
301
302
struct valid_vertex_collection : vertex_collection<primitive<vertex_tag>::valid_iterator>
{
303
304
};

Philip Trettner's avatar
Philip Trettner committed
305
struct valid_vertex_const_collection : smart_collection<Mesh const*, vertex_tag, primitive<vertex_tag>::valid_iterator>
306
{
Philip Trettner's avatar
Philip Trettner committed
307
};
308

Philip Trettner's avatar
Philip Trettner committed
309
// faces
310

Philip Trettner's avatar
Philip Trettner committed
311
312
struct all_face_collection : face_collection<primitive<face_tag>::all_iterator>
{
313
314
};

Philip Trettner's avatar
Philip Trettner committed
315
struct all_face_const_collection : smart_collection<Mesh const*, face_tag, primitive<face_tag>::all_iterator>
316
{
Philip Trettner's avatar
Philip Trettner committed
317
};
318

Philip Trettner's avatar
Philip Trettner committed
319
320
321
struct valid_face_collection : face_collection<primitive<face_tag>::valid_iterator>
{
};
322

Philip Trettner's avatar
Philip Trettner committed
323
324
325
struct valid_face_const_collection : smart_collection<Mesh const*, face_tag, primitive<face_tag>::valid_iterator>
{
};
Philip Trettner's avatar
Philip Trettner committed
326

Philip Trettner's avatar
Philip Trettner committed
327
// edges
328

Philip Trettner's avatar
Philip Trettner committed
329
330
331
struct all_edge_collection : edge_collection<primitive<edge_tag>::all_iterator>
{
};
Philip Trettner's avatar
Philip Trettner committed
332

Philip Trettner's avatar
Philip Trettner committed
333
334
struct all_edge_const_collection : smart_collection<Mesh const*, edge_tag, primitive<edge_tag>::all_iterator>
{
335
336
};

Philip Trettner's avatar
Philip Trettner committed
337
struct valid_edge_collection : edge_collection<primitive<edge_tag>::valid_iterator>
338
{
Philip Trettner's avatar
Philip Trettner committed
339
};
340

Philip Trettner's avatar
Philip Trettner committed
341
342
343
struct valid_edge_const_collection : smart_collection<Mesh const*, edge_tag, primitive<edge_tag>::valid_iterator>
{
};
344

Philip Trettner's avatar
Philip Trettner committed
345
// half-edges
346

Philip Trettner's avatar
Philip Trettner committed
347
348
struct all_halfedge_collection : halfedge_collection<primitive<halfedge_tag>::all_iterator>
{
349
350
};

Philip Trettner's avatar
Philip Trettner committed
351
struct all_halfedge_const_collection : smart_collection<Mesh const*, halfedge_tag, primitive<halfedge_tag>::all_iterator>
352
{
Philip Trettner's avatar
Philip Trettner committed
353
};
354

Philip Trettner's avatar
Philip Trettner committed
355
356
357
struct valid_halfedge_collection : halfedge_collection<primitive<halfedge_tag>::valid_iterator>
{
};
358

Philip Trettner's avatar
Philip Trettner committed
359
360
struct valid_halfedge_const_collection : smart_collection<Mesh const*, halfedge_tag, primitive<halfedge_tag>::valid_iterator>
{
361
};
Philip Trettner's avatar
Philip Trettner committed
362

363
364
// ================= RINGS =================

Philip Trettner's avatar
Philip Trettner committed
365
template <class this_t, class tag>
Philip Trettner's avatar
Philip Trettner committed
366
struct primitive_ring : smart_range<this_t, typename primitive<tag>::handle>
Philip Trettner's avatar
Philip Trettner committed
367
{
Philip Trettner's avatar
Philip Trettner committed
368
369
    using handle = typename primitive<tag>::handle;

Philip Trettner's avatar
Philip Trettner committed
370
371
    face_handle face;

Philip Trettner's avatar
Philip Trettner committed
372
    /// Number of elements
Philip Trettner's avatar
Philip Trettner committed
373
374
    /// O(result) computation
    int size() const;
375
    /// Returns true if handle is contained in this ring
Philip Trettner's avatar
Philip Trettner committed
376
    bool contains(handle v) const;
Philip Trettner's avatar
Philip Trettner committed
377
378
};

Philip Trettner's avatar
Philip Trettner committed
379
380
template <class tag, class circulator>
struct face_primitive_ring : primitive_ring<face_primitive_ring<tag, circulator>, tag>
381
382
{
    face_handle face;
Philip Trettner's avatar
Philip Trettner committed
383
    face_primitive_ring(face_handle f) { face = f; }
384
385

    // Iteration:
Philip Trettner's avatar
Philip Trettner committed
386
387
    circulator begin() const { return {face.any_halfedge(), false}; }
    circulator end() const { return {face.any_halfedge(), true}; }
388
389
};

Philip Trettner's avatar
Philip Trettner committed
390
391
template <class tag, class circulator>
struct vertex_primitive_ring : primitive_ring<vertex_primitive_ring<tag, circulator>, tag>
392
{
Philip Trettner's avatar
Philip Trettner committed
393
394
    vertex_handle vertex;
    vertex_primitive_ring(vertex_handle v) { vertex = v; }
395
396

    // Iteration:
Philip Trettner's avatar
Philip Trettner committed
397
398
    circulator begin() const { return {vertex.any_outgoing_halfedge(), vertex.is_isolated()}; }
    circulator end() const { return {vertex.any_outgoing_halfedge(), true}; }
399
400
};

Philip Trettner's avatar
Philip Trettner committed
401
402
403
404
405
406
407
408
409
410
411
template <class tag, class circulator>
struct halfedge_primitive_ring : primitive_ring<halfedge_primitive_ring<tag, circulator>, tag>
{
    halfedge_handle halfedge;
    halfedge_primitive_ring(halfedge_handle h) { halfedge = h; }

    // Iteration:
    circulator begin() const { return {halfedge, false}; }
    circulator end() const { return {halfedge, true}; }
};

Philip Trettner's avatar
Philip Trettner committed
412
/// all vertices belonging to a face
Philip Trettner's avatar
Philip Trettner committed
413
struct face_vertex_ring : face_primitive_ring<vertex_tag, face_vertex_circulator>
414
{
Philip Trettner's avatar
Philip Trettner committed
415
    using face_primitive_ring<vertex_tag, face_vertex_circulator>::face_primitive_ring;
Philip Trettner's avatar
Philip Trettner committed
416
};
417

Philip Trettner's avatar
Philip Trettner committed
418
/// all halfedges belonging to a face
Philip Trettner's avatar
Philip Trettner committed
419
struct face_halfedge_ring : face_primitive_ring<halfedge_tag, face_halfedge_circulator>
Philip Trettner's avatar
Philip Trettner committed
420
{
Philip Trettner's avatar
Philip Trettner committed
421
    using face_primitive_ring<halfedge_tag, face_halfedge_circulator>::face_primitive_ring;
422
423
};

Philip Trettner's avatar
Philip Trettner committed
424
/// all edges belonging to a face
Philip Trettner's avatar
Philip Trettner committed
425
struct face_edge_ring : face_primitive_ring<edge_tag, face_edge_circulator>
426
{
Philip Trettner's avatar
Philip Trettner committed
427
    using face_primitive_ring<edge_tag, face_edge_circulator>::face_primitive_ring;
Philip Trettner's avatar
Philip Trettner committed
428
};
429

Philip Trettner's avatar
Philip Trettner committed
430
/// all adjacent faces belonging to a face
Philip Trettner's avatar
Philip Trettner committed
431
struct face_face_ring : face_primitive_ring<face_tag, face_face_circulator>
Philip Trettner's avatar
Philip Trettner committed
432
{
Philip Trettner's avatar
Philip Trettner committed
433
    using face_primitive_ring<face_tag, face_face_circulator>::face_primitive_ring;
Philip Trettner's avatar
Philip Trettner committed
434
};
435

Philip Trettner's avatar
Philip Trettner committed
436
/// all outgoing half-edges from a vertex
Philip Trettner's avatar
Philip Trettner committed
437
struct vertex_halfedge_out_ring : vertex_primitive_ring<halfedge_tag, vertex_halfedge_out_circulator>
Philip Trettner's avatar
Philip Trettner committed
438
{
Philip Trettner's avatar
Philip Trettner committed
439
    using vertex_primitive_ring<halfedge_tag, vertex_halfedge_out_circulator>::vertex_primitive_ring;
440
441
442
};

/// all incoming half-edges from a vertex
Philip Trettner's avatar
Philip Trettner committed
443
struct vertex_halfedge_in_ring : vertex_primitive_ring<halfedge_tag, vertex_halfedge_in_circulator>
444
{
Philip Trettner's avatar
Philip Trettner committed
445
    using vertex_primitive_ring<halfedge_tag, vertex_halfedge_in_circulator>::vertex_primitive_ring;
446
447
448
};

/// all adjacent vertices of a vertex
Philip Trettner's avatar
Philip Trettner committed
449
struct vertex_vertex_ring : vertex_primitive_ring<vertex_tag, vertex_vertex_circulator>
450
{
Philip Trettner's avatar
Philip Trettner committed
451
    using vertex_primitive_ring<vertex_tag, vertex_vertex_circulator>::vertex_primitive_ring;
452
453
454
};

/// all adjacent edges of a vertex
Philip Trettner's avatar
Philip Trettner committed
455
struct vertex_edge_ring : vertex_primitive_ring<edge_tag, vertex_edge_circulator>
456
{
Philip Trettner's avatar
Philip Trettner committed
457
    using vertex_primitive_ring<edge_tag, vertex_edge_circulator>::vertex_primitive_ring;
458
459
460
};

/// all adjacent faces of a vertex (INCLUDES invalid ones for boundaries)
Philip Trettner's avatar
Philip Trettner committed
461
struct vertex_face_ring : vertex_primitive_ring<face_tag, vertex_face_circulator>
462
{
Philip Trettner's avatar
Philip Trettner committed
463
    using vertex_primitive_ring<face_tag, vertex_face_circulator>::vertex_primitive_ring;
464
465
};

Philip Trettner's avatar
Philip Trettner committed
466
467
468
469
470
/// all half-edges along a ring (next -> next -> ...)
struct halfedge_ring : halfedge_primitive_ring<halfedge_tag, halfedge_ring_circulator>
{
    using halfedge_primitive_ring<halfedge_tag, halfedge_ring_circulator>::halfedge_primitive_ring;
};
471
}