cursors.hh 10.3 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
9
class Mesh;

template <typename PropT>
10
struct vertex_attribute;
Philip Trettner's avatar
Philip Trettner committed
11
template <typename PropT>
12
struct face_attribute;
Philip Trettner's avatar
Philip Trettner committed
13
template <typename PropT>
14
struct edge_attribute;
Philip Trettner's avatar
Philip Trettner committed
15
template <typename 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 <typename PropT>
51
    PropT& operator[](face_attribute<PropT>& prop) const;
Philip Trettner's avatar
Philip Trettner committed
52
    template <typename PropT>
53
    PropT const& operator[](face_attribute<PropT> const& prop) const;
54
55
56
57
58
59
60
61
62
63
};

struct vertex_index
{
    int value = -1;

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

    bool is_valid() const { return value >= 0; }
64
    bool is_invalid() const { return value < 0; }
65
66
67
68
    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
69
70

    template <typename PropT>
71
    PropT& operator[](vertex_attribute<PropT>& prop) const;
Philip Trettner's avatar
Philip Trettner committed
72
    template <typename PropT>
73
    PropT const& operator[](vertex_attribute<PropT> const& prop) const;
74
75
76
77
78
79
80
81
82
83
};

struct edge_index
{
    int value = -1;

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

    bool is_valid() const { return value >= 0; }
84
    bool is_invalid() const { return value < 0; }
85
86
87
88
    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
89
90

    template <typename PropT>
91
    PropT& operator[](edge_attribute<PropT>& prop) const;
Philip Trettner's avatar
Philip Trettner committed
92
    template <typename PropT>
93
    PropT const& operator[](edge_attribute<PropT> const& prop) const;
94
95
96
97
98
99
100
101
102
103
};

struct halfedge_index
{
    int value = -1;

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

    bool is_valid() const { return value >= 0; }
104
    bool is_invalid() const { return value < 0; }
105
106
107
108
    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
109
110

    template <typename PropT>
111
    PropT& operator[](halfedge_attribute<PropT>& prop) const;
Philip Trettner's avatar
Philip Trettner committed
112
    template <typename PropT>
113
    PropT const& operator[](halfedge_attribute<PropT> const& prop) const;
114
115
116
117
118
119
};

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

struct face_handle
{
Philip Trettner's avatar
Philip Trettner committed
120
    Mesh const* mesh = nullptr;
121
122
    face_index idx;

Philip Trettner's avatar
Philip Trettner committed
123
    face_handle() = default;
124
125
126
127
128
129
    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; }
130

Philip Trettner's avatar
Philip Trettner committed
131
    template <typename PropT>
132
    PropT& operator[](face_attribute<PropT>& prop) const;
Philip Trettner's avatar
Philip Trettner committed
133
    template <typename PropT>
134
    PropT const& operator[](face_attribute<PropT> const& prop) const;
Philip Trettner's avatar
Philip Trettner committed
135

136
137
138
139
140
    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)

    bool is_boundary() const; ///< true if this face lies at a boundary
Philip Trettner's avatar
Philip Trettner committed
141
142
143
144
145

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

    face_vertex_ring vertices() const;
146
147
    face_edge_ring edges() const;
    face_halfedge_ring halfedges() const;
148
    face_face_ring adjacent_faces() const; ///< includes invalid ones for boundaries!
149
150
151
152
};

struct vertex_handle
{
Philip Trettner's avatar
Philip Trettner committed
153
    Mesh const* mesh = nullptr;
154
155
    vertex_index idx;

Philip Trettner's avatar
Philip Trettner committed
156
    vertex_handle() = default;
157
158
159
160
161
162
    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; }
163

Philip Trettner's avatar
Philip Trettner committed
164
    template <typename PropT>
165
    PropT& operator[](vertex_attribute<PropT>& prop) const;
Philip Trettner's avatar
Philip Trettner committed
166
    template <typename PropT>
167
    PropT const& operator[](vertex_attribute<PropT> const& prop) const;
Philip Trettner's avatar
Philip Trettner committed
168

169
170
171
172
173
174
    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)

    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
175

176
    face_handle any_face() const;                  ///< invalid if at boundary
Philip Trettner's avatar
Philip Trettner committed
177
    face_handle any_valid_face() const;            ///< invalid if isolated (and can be if at boundary)
178
179
180
    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
181
182

    vertex_halfedge_in_ring incoming_halfedges() const;
183
    vertex_halfedge_out_ring outgoing_halfedges() const;
184
185
186
    vertex_edge_ring edges() const;
    vertex_face_ring faces() const; ///< includes invalid ones for boundaries!
    vertex_vertex_ring adjacent_vertices() const;
187
188
189
190
};

struct edge_handle
{
Philip Trettner's avatar
Philip Trettner committed
191
    Mesh const* mesh = nullptr;
192
193
    edge_index idx;

Philip Trettner's avatar
Philip Trettner committed
194
    edge_handle() = default;
195
196
197
198
199
200
    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; }
201

Philip Trettner's avatar
Philip Trettner committed
202
    template <typename PropT>
203
    PropT& operator[](edge_attribute<PropT>& prop) const;
Philip Trettner's avatar
Philip Trettner committed
204
    template <typename PropT>
205
    PropT const& operator[](edge_attribute<PropT> const& prop) const;
Philip Trettner's avatar
Philip Trettner committed
206

207
208
209
210
211
212
    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)

    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
213
214
215

    halfedge_handle halfedgeA() const;
    halfedge_handle halfedgeB() const;
216
217
    vertex_handle vertexA() const;
    vertex_handle vertexB() const;
218
219
    face_handle faceA() const; ///< can be invalid if boundary
    face_handle faceB() const; ///< can be invalid if boundary
220
221
222
223
};

struct halfedge_handle
{
Philip Trettner's avatar
Philip Trettner committed
224
    Mesh const* mesh = nullptr;
225
226
    halfedge_index idx;

Philip Trettner's avatar
Philip Trettner committed
227
    halfedge_handle() = default;
228
229
230
231
232
233
    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
234

Philip Trettner's avatar
Philip Trettner committed
235
    template <typename PropT>
236
    PropT& operator[](halfedge_attribute<PropT>& prop) const;
Philip Trettner's avatar
Philip Trettner committed
237
    template <typename PropT>
238
    PropT const& operator[](halfedge_attribute<PropT> const& prop) const;
Philip Trettner's avatar
Philip Trettner committed
239

240
241
242
243
244
    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)

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

Philip Trettner's avatar
Philip Trettner committed
246
247
    vertex_handle vertex_to() const;
    vertex_handle vertex_from() const;
248
    edge_handle edge() const;
249
    face_handle face() const; ///< invalid if boundary
Philip Trettner's avatar
Philip Trettner committed
250
251
252
    halfedge_handle next() const;
    halfedge_handle prev() const;
    halfedge_handle opposite() const;
253
    face_handle opposite_face() const; ///< invalid if opposite boundary
254
};
Philip Trettner's avatar
Philip Trettner committed
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306

/// ======== 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;
}
307
}