cursors.hh 11.6 KB
Newer Older
1
2
#pragma once

Philip Trettner's avatar
Philip Trettner committed
3
4
#include <iostream>

5
6
namespace polymesh
{
Philip Trettner's avatar
Philip Trettner committed
7
8
class Mesh;

9
template <class PropT>
10
struct vertex_attribute;
11
template <class PropT>
12
struct face_attribute;
13
template <class PropT>
14
struct edge_attribute;
15
template <class PropT>
16
struct halfedge_attribute;
17

Philip Trettner's avatar
Philip Trettner committed
18
19
20
21
22
23
struct vertex_handle;
struct face_handle;
struct edge_handle;
struct halfedge_handle;

struct face_vertex_ring;
24
25
26
27
28
29
30
31
32
struct face_edge_ring;
struct face_halfedge_ring;
struct face_face_ring;

struct vertex_halfedge_out_ring;
struct vertex_halfedge_in_ring;
struct vertex_face_ring;
struct vertex_edge_ring;
struct vertex_vertex_ring;
Philip Trettner's avatar
Philip Trettner committed
33

34
35
36
37
38
39
40
41
42
43
// ======================== INDICES ========================

struct face_index
{
    int value = -1;

    face_index() = default;
    explicit face_index(int idx) : value(idx) {}

    bool is_valid() const { return value >= 0; }
44
    bool is_invalid() const { return value < 0; }
45
46
47
48
    static face_index invalid() { return {}; }

    bool operator==(face_index const& rhs) const { return value == rhs.value; }
    bool operator!=(face_index const& rhs) const { return value != rhs.value; }
Philip Trettner's avatar
Philip Trettner committed
49

50
    template <class PropT>
51
    PropT& operator[](face_attribute<PropT>& prop) const;
52
    template <class PropT>
53
    PropT const& operator[](face_attribute<PropT> const& prop) const;
54
55
56
57
    template <class PropT>
    PropT& operator[](face_attribute<PropT>* prop) const;
    template <class PropT>
    PropT const& operator[](face_attribute<PropT> const* prop) const;
58
59
60
61
62
63
64
65
66
67
};

struct vertex_index
{
    int value = -1;

    vertex_index() = default;
    explicit vertex_index(int idx) : value(idx) {}

    bool is_valid() const { return value >= 0; }
68
    bool is_invalid() const { return value < 0; }
69
70
71
72
    static vertex_index invalid() { return {}; }

    bool operator==(vertex_index const& rhs) const { return value == rhs.value; }
    bool operator!=(vertex_index const& rhs) const { return value != rhs.value; }
Philip Trettner's avatar
Philip Trettner committed
73

74
    template <class PropT>
75
    PropT& operator[](vertex_attribute<PropT>& prop) const;
76
    template <class PropT>
77
    PropT const& operator[](vertex_attribute<PropT> const& prop) const;
78
79
80
81
    template <class PropT>
    PropT& operator[](vertex_attribute<PropT>* prop) const;
    template <class PropT>
    PropT const& operator[](vertex_attribute<PropT> const* prop) const;
82
83
84
85
86
87
88
89
90
91
};

struct edge_index
{
    int value = -1;

    edge_index() = default;
    explicit edge_index(int idx) : value(idx) {}

    bool is_valid() const { return value >= 0; }
92
    bool is_invalid() const { return value < 0; }
93
94
95
96
    static edge_index invalid() { return {}; }

    bool operator==(edge_index const& rhs) const { return value == rhs.value; }
    bool operator!=(edge_index const& rhs) const { return value != rhs.value; }
Philip Trettner's avatar
Philip Trettner committed
97

98
    template <class PropT>
99
    PropT& operator[](edge_attribute<PropT>& prop) const;
100
    template <class PropT>
101
    PropT const& operator[](edge_attribute<PropT> const& prop) const;
102
103
104
105
    template <class PropT>
    PropT& operator[](edge_attribute<PropT>* prop) const;
    template <class PropT>
    PropT const& operator[](edge_attribute<PropT> const* prop) const;
106
107
108
109
110
111
112
113
114
115
};

struct halfedge_index
{
    int value = -1;

    halfedge_index() = default;
    explicit halfedge_index(int idx) : value(idx) {}

    bool is_valid() const { return value >= 0; }
116
    bool is_invalid() const { return value < 0; }
117
118
119
120
    static halfedge_index invalid() { return {}; }

    bool operator==(halfedge_index const& rhs) const { return value == rhs.value; }
    bool operator!=(halfedge_index const& rhs) const { return value != rhs.value; }
Philip Trettner's avatar
Philip Trettner committed
121

122
    template <class PropT>
123
    PropT& operator[](halfedge_attribute<PropT>& prop) const;
124
    template <class PropT>
125
    PropT const& operator[](halfedge_attribute<PropT> const& prop) const;
126
127
128
129
    template <class PropT>
    PropT& operator[](halfedge_attribute<PropT>* prop) const;
    template <class PropT>
    PropT const& operator[](halfedge_attribute<PropT> const* prop) const;
130
131
132
133
134
135
};

// ======================== HANDLES ========================

struct face_handle
{
Philip Trettner's avatar
Philip Trettner committed
136
    Mesh const* mesh = nullptr;
137
138
    face_index idx;

Philip Trettner's avatar
Philip Trettner committed
139
    face_handle() = default;
140
141
142
143
144
145
    face_handle(Mesh const* mesh, face_index idx) : mesh(mesh), idx(idx) {}

    bool operator==(face_index const& rhs) const { return idx == rhs; }
    bool operator!=(face_index const& rhs) const { return idx != rhs; }
    bool operator==(face_handle const& rhs) const { return mesh == rhs.mesh && idx == rhs.idx; }
    bool operator!=(face_handle const& rhs) const { return mesh != rhs.mesh || idx != rhs.idx; }
146

147
    template <class PropT>
148
    PropT& operator[](face_attribute<PropT>& prop) const;
149
    template <class PropT>
150
    PropT const& operator[](face_attribute<PropT> const& prop) const;
151
152
153
154
    template <class PropT>
    PropT& operator[](face_attribute<PropT>* prop) const;
    template <class PropT>
    PropT const& operator[](face_attribute<PropT> const* prop) const;
Philip Trettner's avatar
Philip Trettner committed
155

Philip Trettner's avatar
Philip Trettner committed
156
157
158
    bool is_valid() const { return idx.is_valid(); }    ///< valid idx (but could be deleted in some iterators)
    bool is_invalid() const { return !idx.is_valid(); } ///< invalid idx
    bool is_removed() const;                            ///< marked for deletion (but valid idx)
159
160

    bool is_boundary() const; ///< true if this face lies at a boundary
Philip Trettner's avatar
Philip Trettner committed
161
162
163
164
165

    vertex_handle any_vertex() const;
    halfedge_handle any_halfedge() const;

    face_vertex_ring vertices() const;
166
167
    face_edge_ring edges() const;
    face_halfedge_ring halfedges() const;
168
    face_face_ring adjacent_faces() const; ///< includes invalid ones for boundaries!
169
170
171
172
};

struct vertex_handle
{
Philip Trettner's avatar
Philip Trettner committed
173
    Mesh const* mesh = nullptr;
174
175
    vertex_index idx;

Philip Trettner's avatar
Philip Trettner committed
176
    vertex_handle() = default;
177
178
179
180
181
182
    vertex_handle(Mesh const* mesh, vertex_index idx) : mesh(mesh), idx(idx) {}

    bool operator==(vertex_index const& rhs) const { return idx == rhs; }
    bool operator!=(vertex_index const& rhs) const { return idx != rhs; }
    bool operator==(vertex_handle const& rhs) const { return mesh == rhs.mesh && idx == rhs.idx; }
    bool operator!=(vertex_handle const& rhs) const { return mesh != rhs.mesh || idx != rhs.idx; }
183

184
    template <class PropT>
185
    PropT& operator[](vertex_attribute<PropT>& prop) const;
186
    template <class PropT>
187
    PropT const& operator[](vertex_attribute<PropT> const& prop) const;
188
189
190
191
    template <class PropT>
    PropT& operator[](vertex_attribute<PropT>* prop) const;
    template <class PropT>
    PropT const& operator[](vertex_attribute<PropT> const* prop) const;
Philip Trettner's avatar
Philip Trettner committed
192

Philip Trettner's avatar
Philip Trettner committed
193
194
195
    bool is_valid() const { return idx.is_valid(); }    ///< valid idx (but could be deleted in some iterators)
    bool is_invalid() const { return !idx.is_valid(); } ///< invalid idx
    bool is_removed() const;                            ///< marked for deletion (but valid idx)
196
197
198

    bool is_isolated() const; ///< true if this vertex is not connected at all
    bool is_boundary() const; ///< true if this vertex lies at a boundary
Philip Trettner's avatar
Philip Trettner committed
199

200
    face_handle any_face() const;                  ///< invalid if at boundary
Philip Trettner's avatar
Philip Trettner committed
201
    face_handle any_valid_face() const;            ///< invalid if isolated (and can be if at boundary)
202
203
204
    halfedge_handle any_outgoing_halfedge() const; ///< invalid if isolated
    halfedge_handle any_incoming_halfedge() const; ///< invalid if isolated
    edge_handle any_edge() const;                  ///< invalid if isolated
205
206

    vertex_halfedge_in_ring incoming_halfedges() const;
207
    vertex_halfedge_out_ring outgoing_halfedges() const;
208
209
210
    vertex_edge_ring edges() const;
    vertex_face_ring faces() const; ///< includes invalid ones for boundaries!
    vertex_vertex_ring adjacent_vertices() const;
211
212
213
214
};

struct edge_handle
{
Philip Trettner's avatar
Philip Trettner committed
215
    Mesh const* mesh = nullptr;
216
217
    edge_index idx;

Philip Trettner's avatar
Philip Trettner committed
218
    edge_handle() = default;
219
220
221
222
223
224
    edge_handle(Mesh const* mesh, edge_index idx) : mesh(mesh), idx(idx) {}

    bool operator==(edge_index const& rhs) const { return idx == rhs; }
    bool operator!=(edge_index const& rhs) const { return idx != rhs; }
    bool operator==(edge_handle const& rhs) const { return mesh == rhs.mesh && idx == rhs.idx; }
    bool operator!=(edge_handle const& rhs) const { return mesh != rhs.mesh || idx != rhs.idx; }
225

226
    template <class PropT>
227
    PropT& operator[](edge_attribute<PropT>& prop) const;
228
    template <class PropT>
229
    PropT const& operator[](edge_attribute<PropT> const& prop) const;
230
231
232
233
    template <class PropT>
    PropT& operator[](edge_attribute<PropT>* prop) const;
    template <class PropT>
    PropT const& operator[](edge_attribute<PropT> const* prop) const;
Philip Trettner's avatar
Philip Trettner committed
234

Philip Trettner's avatar
Philip Trettner committed
235
236
237
    bool is_valid() const { return idx.is_valid(); }    ///< valid idx (but could be deleted in some iterators)
    bool is_invalid() const { return !idx.is_valid(); } ///< invalid idx
    bool is_removed() const;                            ///< marked for deletion (but valid idx)
238
239
240

    bool is_isolated() const; ///< true if this edge has no faces
    bool is_boundary() const; ///< true if this edge is a boundary
Philip Trettner's avatar
Philip Trettner committed
241
242
243

    halfedge_handle halfedgeA() const;
    halfedge_handle halfedgeB() const;
244
245
    vertex_handle vertexA() const;
    vertex_handle vertexB() const;
246
247
    face_handle faceA() const; ///< can be invalid if boundary
    face_handle faceB() const; ///< can be invalid if boundary
248
249
250
251
};

struct halfedge_handle
{
Philip Trettner's avatar
Philip Trettner committed
252
    Mesh const* mesh = nullptr;
253
254
    halfedge_index idx;

Philip Trettner's avatar
Philip Trettner committed
255
    halfedge_handle() = default;
256
257
258
259
260
261
    halfedge_handle(Mesh const* mesh, halfedge_index idx) : mesh(mesh), idx(idx) {}

    bool operator==(halfedge_index const& rhs) const { return idx == rhs; }
    bool operator!=(halfedge_index const& rhs) const { return idx != rhs; }
    bool operator==(halfedge_handle const& rhs) const { return mesh == rhs.mesh && idx == rhs.idx; }
    bool operator!=(halfedge_handle const& rhs) const { return mesh != rhs.mesh || idx != rhs.idx; }
Philip Trettner's avatar
Philip Trettner committed
262

263
    template <class PropT>
264
    PropT& operator[](halfedge_attribute<PropT>& prop) const;
265
    template <class PropT>
266
    PropT const& operator[](halfedge_attribute<PropT> const& prop) const;
267
268
269
270
    template <class PropT>
    PropT& operator[](halfedge_attribute<PropT>* prop) const;
    template <class PropT>
    PropT const& operator[](halfedge_attribute<PropT> const* prop) const;
Philip Trettner's avatar
Philip Trettner committed
271

Philip Trettner's avatar
Philip Trettner committed
272
273
274
    bool is_valid() const { return idx.is_valid(); }    ///< valid idx (but could be deleted in some iterators)
    bool is_invalid() const { return !idx.is_valid(); } ///< invalid idx
    bool is_removed() const;                            ///< marked for deletion (but valid idx)
275
276

    bool is_boundary() const; ///< true if this half-edge is a boundary (CAUTION: its opposite might not be)
277

Philip Trettner's avatar
Philip Trettner committed
278
279
    vertex_handle vertex_to() const;
    vertex_handle vertex_from() const;
280
    edge_handle edge() const;
281
    face_handle face() const; ///< invalid if boundary
Philip Trettner's avatar
Philip Trettner committed
282
283
284
    halfedge_handle next() const;
    halfedge_handle prev() const;
    halfedge_handle opposite() const;
285
    face_handle opposite_face() const; ///< invalid if opposite boundary
286
};
Philip Trettner's avatar
Philip Trettner committed
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338

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

inline std::ostream& operator<<(std::ostream& out, vertex_index v)
{
    out << "vertex " << v.value;
    if (v.is_invalid())
        out << " (invalid)";
    return out;
}
inline std::ostream& operator<<(std::ostream& out, face_index f)
{
    out << "face " << f.value;
    if (f.is_invalid())
        out << " (invalid)";
    return out;
}
inline std::ostream& operator<<(std::ostream& out, edge_index e)
{
    out << "edge " << e.value;
    if (e.is_invalid())
        out << " (invalid)";
    return out;
}
inline std::ostream& operator<<(std::ostream& out, halfedge_index h)
{
    out << "half-edge " << h.value;
    if (h.is_invalid())
        out << " (invalid)";
    return out;
}

inline std::ostream& operator<<(std::ostream& out, vertex_handle v)
{
    out << v.idx;
    return out;
}
inline std::ostream& operator<<(std::ostream& out, face_handle f)
{
    out << f.idx;
    return out;
}
inline std::ostream& operator<<(std::ostream& out, edge_handle e)
{
    out << e.idx;
    return out;
}
inline std::ostream& operator<<(std::ostream& out, halfedge_handle h)
{
    out << h.idx;
    return out;
}
339
}