ranges.hh 18.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
    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;
54
55
56
    /// returns the number of elements fulfilling p(v) in this range
    template <class PredT>
    int count(PredT&& p) const;
Philip Trettner's avatar
Philip Trettner committed
57

58
59
60
61
62
    /// 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
63
64
65
66
67
    /// 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;
68
69
70
71
72
    /// 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
73
74
75
76
77
    /// 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;
78
79
80
81
82
83
84
85
86
87
    /// 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
88

89
90
91
92
93
94
    /// 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>;

95
96
97
98
99
100
101
102
    /// 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
103
104
105
106
107
    /// 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;
108

109
110
111
112
113
114
115
116
117
118
119
120
121
    /// 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
122

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

131
132
// ================= COLLECTION =================

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

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

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

Philip Trettner's avatar
Philip Trettner committed
147
    /// Creates a new primitive attribute
148
149
    template <class AttrT>
    attribute<AttrT> make_attribute() const;
Philip Trettner's avatar
Philip Trettner committed
150
    /// Creates a new primitive attribute with a given default value
151
152
153
154
155
156
157
158
    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
159
    /// Creates a new primitive attribute and initializes it with f(h) for each handle h
160
161
    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
162
163
164
165
166

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

Philip Trettner's avatar
Philip Trettner committed
167
protected:
Philip Trettner's avatar
Philip Trettner committed
168
    /// Backreference to mesh
Philip Trettner's avatar
Philip Trettner committed
169
    mesh_ptr mesh;
Philip Trettner's avatar
Philip Trettner committed
170
171
172
173

    friend class Mesh;
};

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

Philip Trettner's avatar
Philip Trettner committed
183
184
185
186
    /// 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;

187
188
189
    /// 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;
190
191
192
193
194

    /// applies an index remapping to all vertex indices
    /// p[curr_idx] = new_idx
    /// NOTE: invalidates all affected handles/iterators
    void permute(std::vector<int> const& p) const;
195
196
};

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

Philip Trettner's avatar
Philip Trettner committed
218
219
220
221
222
    /// 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;

223
224
225
226
    /// Fills the half-edge ring of a given boundary half-edge
    /// Returns the new face
    face_handle fill(halfedge_handle h) const;

227
228
229
    /// 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;
230
231
232
233
234

    /// applies an index remapping to all face indices
    /// p[curr_idx] = new_idx
    /// NOTE: invalidates all affected handles/iterators
    void permute(std::vector<int> const& p) const;
235
236
};

Philip Trettner's avatar
Philip Trettner committed
237
/// Collection of all edges of a mesh
238
/// Basically a smart std::vector
Philip Trettner's avatar
Philip Trettner committed
239
240
template <class iterator>
struct edge_collection : smart_collection<Mesh*, edge_tag, iterator>
241
{
Philip Trettner's avatar
Philip Trettner committed
242
243
    /// Adds an edge between two existing, distinct vertices
    /// if edge already exists, returns it
Philip Trettner's avatar
Philip Trettner committed
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
    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
263

264
265
266
    /// 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;
267
268
269
270
271

    /// applies an index remapping to all edge indices
    /// p[curr_idx] = new_idx
    /// NOTE: invalidates all affected handles/iterators
    void permute(std::vector<int> const& p) const;
Philip Trettner's avatar
Philip Trettner committed
272
};
Philip Trettner's avatar
Philip Trettner committed
273

Philip Trettner's avatar
Philip Trettner committed
274
275
/// Collection of all half-edges of a mesh
/// Basically a smart std::vector
Philip Trettner's avatar
Philip Trettner committed
276
277
template <class iterator>
struct halfedge_collection : smart_collection<Mesh*, halfedge_tag, iterator>
Philip Trettner's avatar
Philip Trettner committed
278
279
280
281
{
    /// 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
282
283
284
285
286
287
    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
288
289
290
291
292
    /// 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
293
294
    /// Splits this half-edge in half by inserting a vertex (which is returned)
    /// Preserves face attributes
Philip Trettner's avatar
Philip Trettner committed
295
    /// Contrary to edges().split, the edge is preserved and a single new one is inserted AFTER h
Philip Trettner's avatar
Philip Trettner committed
296
297
298
    /// (thus h->next() is the newly inserted edge and h->vertex_to() is the returned vertex)
    vertex_handle split(halfedge_handle h) const;

299
300
301
    /// Given an isolated vertex v, inserts a self-adjacent edge at the to-vertex to v
    void attach(halfedge_handle h, vertex_handle v) const;

Philip Trettner's avatar
Philip Trettner committed
302
303
304
305
306
307
308
309
    /// 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
310
311
312
313

    /// 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;
314
315
};

Philip Trettner's avatar
Philip Trettner committed
316
// vertices
317

Philip Trettner's avatar
Philip Trettner committed
318
319
320
struct all_vertex_collection : vertex_collection<primitive<vertex_tag>::all_iterator>
{
};
321

Philip Trettner's avatar
Philip Trettner committed
322
323
324
struct all_vertex_const_collection : smart_collection<Mesh const*, vertex_tag, primitive<vertex_tag>::all_iterator>
{
};
325

Philip Trettner's avatar
Philip Trettner committed
326
327
struct valid_vertex_collection : vertex_collection<primitive<vertex_tag>::valid_iterator>
{
328
329
};

Philip Trettner's avatar
Philip Trettner committed
330
struct valid_vertex_const_collection : smart_collection<Mesh const*, vertex_tag, primitive<vertex_tag>::valid_iterator>
331
{
Philip Trettner's avatar
Philip Trettner committed
332
};
333

Philip Trettner's avatar
Philip Trettner committed
334
// faces
335

Philip Trettner's avatar
Philip Trettner committed
336
337
struct all_face_collection : face_collection<primitive<face_tag>::all_iterator>
{
338
339
};

Philip Trettner's avatar
Philip Trettner committed
340
struct all_face_const_collection : smart_collection<Mesh const*, face_tag, primitive<face_tag>::all_iterator>
341
{
Philip Trettner's avatar
Philip Trettner committed
342
};
343

Philip Trettner's avatar
Philip Trettner committed
344
345
346
struct valid_face_collection : face_collection<primitive<face_tag>::valid_iterator>
{
};
347

Philip Trettner's avatar
Philip Trettner committed
348
349
350
struct valid_face_const_collection : smart_collection<Mesh const*, face_tag, primitive<face_tag>::valid_iterator>
{
};
Philip Trettner's avatar
Philip Trettner committed
351

Philip Trettner's avatar
Philip Trettner committed
352
// edges
353

Philip Trettner's avatar
Philip Trettner committed
354
355
356
struct all_edge_collection : edge_collection<primitive<edge_tag>::all_iterator>
{
};
Philip Trettner's avatar
Philip Trettner committed
357

Philip Trettner's avatar
Philip Trettner committed
358
359
struct all_edge_const_collection : smart_collection<Mesh const*, edge_tag, primitive<edge_tag>::all_iterator>
{
360
361
};

Philip Trettner's avatar
Philip Trettner committed
362
struct valid_edge_collection : edge_collection<primitive<edge_tag>::valid_iterator>
363
{
Philip Trettner's avatar
Philip Trettner committed
364
};
365

Philip Trettner's avatar
Philip Trettner committed
366
367
368
struct valid_edge_const_collection : smart_collection<Mesh const*, edge_tag, primitive<edge_tag>::valid_iterator>
{
};
369

Philip Trettner's avatar
Philip Trettner committed
370
// half-edges
371

Philip Trettner's avatar
Philip Trettner committed
372
373
struct all_halfedge_collection : halfedge_collection<primitive<halfedge_tag>::all_iterator>
{
374
375
};

Philip Trettner's avatar
Philip Trettner committed
376
struct all_halfedge_const_collection : smart_collection<Mesh const*, halfedge_tag, primitive<halfedge_tag>::all_iterator>
377
{
Philip Trettner's avatar
Philip Trettner committed
378
};
379

Philip Trettner's avatar
Philip Trettner committed
380
381
382
struct valid_halfedge_collection : halfedge_collection<primitive<halfedge_tag>::valid_iterator>
{
};
383

Philip Trettner's avatar
Philip Trettner committed
384
385
struct valid_halfedge_const_collection : smart_collection<Mesh const*, halfedge_tag, primitive<halfedge_tag>::valid_iterator>
{
386
};
Philip Trettner's avatar
Philip Trettner committed
387

388
389
// ================= RINGS =================

Philip Trettner's avatar
Philip Trettner committed
390
template <class this_t, class tag>
Philip Trettner's avatar
Philip Trettner committed
391
struct primitive_ring : smart_range<this_t, typename primitive<tag>::handle>
Philip Trettner's avatar
Philip Trettner committed
392
{
Philip Trettner's avatar
Philip Trettner committed
393
394
    using handle = typename primitive<tag>::handle;

Philip Trettner's avatar
Philip Trettner committed
395
396
    face_handle face;

Philip Trettner's avatar
Philip Trettner committed
397
    /// Number of elements
Philip Trettner's avatar
Philip Trettner committed
398
399
    /// O(result) computation
    int size() const;
400
    /// Returns true if handle is contained in this ring
Philip Trettner's avatar
Philip Trettner committed
401
    bool contains(handle v) const;
Philip Trettner's avatar
Philip Trettner committed
402
403
};

Philip Trettner's avatar
Philip Trettner committed
404
405
template <class tag, class circulator>
struct face_primitive_ring : primitive_ring<face_primitive_ring<tag, circulator>, tag>
406
407
{
    face_handle face;
Philip Trettner's avatar
Philip Trettner committed
408
    face_primitive_ring(face_handle f) { face = f; }
409
410

    // Iteration:
Philip Trettner's avatar
Philip Trettner committed
411
412
    circulator begin() const { return {face.any_halfedge(), false}; }
    circulator end() const { return {face.any_halfedge(), true}; }
413
414
};

Philip Trettner's avatar
Philip Trettner committed
415
416
template <class tag, class circulator>
struct vertex_primitive_ring : primitive_ring<vertex_primitive_ring<tag, circulator>, tag>
417
{
Philip Trettner's avatar
Philip Trettner committed
418
419
    vertex_handle vertex;
    vertex_primitive_ring(vertex_handle v) { vertex = v; }
420
421

    // Iteration:
Philip Trettner's avatar
Philip Trettner committed
422
423
    circulator begin() const { return {vertex.any_outgoing_halfedge(), vertex.is_isolated()}; }
    circulator end() const { return {vertex.any_outgoing_halfedge(), true}; }
424
425
};

Philip Trettner's avatar
Philip Trettner committed
426
427
428
429
430
431
432
433
434
435
436
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
437
/// all vertices belonging to a face
Philip Trettner's avatar
Philip Trettner committed
438
struct face_vertex_ring : face_primitive_ring<vertex_tag, face_vertex_circulator>
439
{
Philip Trettner's avatar
Philip Trettner committed
440
    using face_primitive_ring<vertex_tag, face_vertex_circulator>::face_primitive_ring;
Philip Trettner's avatar
Philip Trettner committed
441
};
442

Philip Trettner's avatar
Philip Trettner committed
443
/// all halfedges belonging to a face
Philip Trettner's avatar
Philip Trettner committed
444
struct face_halfedge_ring : face_primitive_ring<halfedge_tag, face_halfedge_circulator>
Philip Trettner's avatar
Philip Trettner committed
445
{
Philip Trettner's avatar
Philip Trettner committed
446
    using face_primitive_ring<halfedge_tag, face_halfedge_circulator>::face_primitive_ring;
447
448
};

Philip Trettner's avatar
Philip Trettner committed
449
/// all edges belonging to a face
Philip Trettner's avatar
Philip Trettner committed
450
struct face_edge_ring : face_primitive_ring<edge_tag, face_edge_circulator>
451
{
Philip Trettner's avatar
Philip Trettner committed
452
    using face_primitive_ring<edge_tag, face_edge_circulator>::face_primitive_ring;
Philip Trettner's avatar
Philip Trettner committed
453
};
454

Philip Trettner's avatar
Philip Trettner committed
455
/// all adjacent faces belonging to a face
Philip Trettner's avatar
Philip Trettner committed
456
struct face_face_ring : face_primitive_ring<face_tag, face_face_circulator>
Philip Trettner's avatar
Philip Trettner committed
457
{
Philip Trettner's avatar
Philip Trettner committed
458
    using face_primitive_ring<face_tag, face_face_circulator>::face_primitive_ring;
Philip Trettner's avatar
Philip Trettner committed
459
};
460

Philip Trettner's avatar
Philip Trettner committed
461
/// all outgoing half-edges from a vertex
Philip Trettner's avatar
Philip Trettner committed
462
struct vertex_halfedge_out_ring : vertex_primitive_ring<halfedge_tag, vertex_halfedge_out_circulator>
Philip Trettner's avatar
Philip Trettner committed
463
{
Philip Trettner's avatar
Philip Trettner committed
464
    using vertex_primitive_ring<halfedge_tag, vertex_halfedge_out_circulator>::vertex_primitive_ring;
465
466
467
};

/// all incoming half-edges from a vertex
Philip Trettner's avatar
Philip Trettner committed
468
struct vertex_halfedge_in_ring : vertex_primitive_ring<halfedge_tag, vertex_halfedge_in_circulator>
469
{
Philip Trettner's avatar
Philip Trettner committed
470
    using vertex_primitive_ring<halfedge_tag, vertex_halfedge_in_circulator>::vertex_primitive_ring;
471
472
473
};

/// all adjacent vertices of a vertex
Philip Trettner's avatar
Philip Trettner committed
474
struct vertex_vertex_ring : vertex_primitive_ring<vertex_tag, vertex_vertex_circulator>
475
{
Philip Trettner's avatar
Philip Trettner committed
476
    using vertex_primitive_ring<vertex_tag, vertex_vertex_circulator>::vertex_primitive_ring;
477
478
479
};

/// all adjacent edges of a vertex
Philip Trettner's avatar
Philip Trettner committed
480
struct vertex_edge_ring : vertex_primitive_ring<edge_tag, vertex_edge_circulator>
481
{
Philip Trettner's avatar
Philip Trettner committed
482
    using vertex_primitive_ring<edge_tag, vertex_edge_circulator>::vertex_primitive_ring;
483
484
485
};

/// all adjacent faces of a vertex (INCLUDES invalid ones for boundaries)
Philip Trettner's avatar
Philip Trettner committed
486
struct vertex_face_ring : vertex_primitive_ring<face_tag, vertex_face_circulator>
487
{
Philip Trettner's avatar
Philip Trettner committed
488
    using vertex_primitive_ring<face_tag, vertex_face_circulator>::vertex_primitive_ring;
489
490
};

Philip Trettner's avatar
Philip Trettner committed
491
492
493
494
495
/// 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;
};
496
}