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

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

Philip Trettner's avatar
Philip Trettner committed
5
6
#include "primitives.hh"

7
8
9
10
namespace polymesh
{
// ======================== INDICES ========================

Philip Trettner's avatar
Philip Trettner committed
11
12
template <typename tag>
struct primitive_index
13
{
Philip Trettner's avatar
Philip Trettner committed
14
15
16
17
18
    template <class AttrT>
    using attribute = typename primitive<tag>::template attribute<AttrT>;
    using index_t = typename primitive<tag>::index;
    using handle_t = typename primitive<tag>::handle;

19
20
    int value = -1;

Philip Trettner's avatar
Philip Trettner committed
21
22
    primitive_index() = default;
    explicit primitive_index(int idx) : value(idx) {}
23
24

    bool is_valid() const { return value >= 0; }
25
    bool is_invalid() const { return value < 0; }
Philip Trettner's avatar
Philip Trettner committed
26
27
28
29
30
31
32
33
34
35
36
37
38
    static index_t invalid() { return {}; }

    bool operator==(index_t const& rhs) const { return value == rhs.value; }
    bool operator!=(index_t const& rhs) const { return value != rhs.value; }

    template <class AttrT>
    AttrT& operator[](attribute<AttrT>& prop) const;
    template <class AttrT>
    AttrT const& operator[](attribute<AttrT> const& prop) const;
    template <class AttrT>
    AttrT& operator[](attribute<AttrT>* prop) const;
    template <class AttrT>
    AttrT const& operator[](attribute<AttrT> const* prop) const;
39
40
};

Philip Trettner's avatar
Philip Trettner committed
41
struct face_index : primitive_index<face_tag>
42
{
Philip Trettner's avatar
Philip Trettner committed
43
44
    using primitive_index::primitive_index;
    using primitive_index::operator=;
45
};
Philip Trettner's avatar
Philip Trettner committed
46
struct edge_index : primitive_index<edge_tag>
47
{
Philip Trettner's avatar
Philip Trettner committed
48
49
    using primitive_index::primitive_index;
    using primitive_index::operator=;
50
};
Philip Trettner's avatar
Philip Trettner committed
51
struct halfedge_index : primitive_index<halfedge_tag>
52
{
Philip Trettner's avatar
Philip Trettner committed
53
54
55
56
57
58
59
60
    using primitive_index::primitive_index;
    using primitive_index::operator=;
};
struct vertex_index : primitive_index<vertex_tag>
{
    using primitive_index::primitive_index;
    using primitive_index::operator=;
};
61
62


Philip Trettner's avatar
Philip Trettner committed
63
64
65
// ===========================================
// OLD CODE:

66
67
68
69
70

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

struct face_handle
{
Philip Trettner's avatar
Philip Trettner committed
71
    Mesh const* mesh = nullptr;
72
73
    face_index idx;

Philip Trettner's avatar
Philip Trettner committed
74
    face_handle() = default;
75
76
77
78
79
80
    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; }
81

Philip Trettner's avatar
Philip Trettner committed
82
83
84
85
86
87
88
89
    template <class AttrT>
    AttrT& operator[](face_attribute<AttrT>& prop) const;
    template <class AttrT>
    AttrT const& operator[](face_attribute<AttrT> const& prop) const;
    template <class AttrT>
    AttrT& operator[](face_attribute<AttrT>* prop) const;
    template <class AttrT>
    AttrT const& operator[](face_attribute<AttrT> const* prop) const;
Philip Trettner's avatar
Philip Trettner committed
90

Philip Trettner's avatar
Philip Trettner committed
91
92
93
    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)
94
95

    bool is_boundary() const; ///< true if this face lies at a boundary
Philip Trettner's avatar
Philip Trettner committed
96
97
98
99
100

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

    face_vertex_ring vertices() const;
101
102
    face_edge_ring edges() const;
    face_halfedge_ring halfedges() const;
103
    face_face_ring adjacent_faces() const; ///< includes invalid ones for boundaries!
104
105
106
107
};

struct vertex_handle
{
Philip Trettner's avatar
Philip Trettner committed
108
    Mesh const* mesh = nullptr;
109
110
    vertex_index idx;

Philip Trettner's avatar
Philip Trettner committed
111
    vertex_handle() = default;
112
113
114
115
116
117
    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; }
118

Philip Trettner's avatar
Philip Trettner committed
119
120
121
122
123
124
125
126
    template <class AttrT>
    AttrT& operator[](vertex_attribute<AttrT>& prop) const;
    template <class AttrT>
    AttrT const& operator[](vertex_attribute<AttrT> const& prop) const;
    template <class AttrT>
    AttrT& operator[](vertex_attribute<AttrT>* prop) const;
    template <class AttrT>
    AttrT const& operator[](vertex_attribute<AttrT> const* prop) const;
Philip Trettner's avatar
Philip Trettner committed
127

Philip Trettner's avatar
Philip Trettner committed
128
129
130
    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)
131
132
133

    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
134

135
    face_handle any_face() const;                  ///< invalid if at boundary
Philip Trettner's avatar
Philip Trettner committed
136
    face_handle any_valid_face() const;            ///< invalid if isolated (and can be if at boundary)
137
138
139
    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
140
141

    vertex_halfedge_in_ring incoming_halfedges() const;
142
    vertex_halfedge_out_ring outgoing_halfedges() const;
143
144
145
    vertex_edge_ring edges() const;
    vertex_face_ring faces() const; ///< includes invalid ones for boundaries!
    vertex_vertex_ring adjacent_vertices() const;
146
147
148
149
};

struct edge_handle
{
Philip Trettner's avatar
Philip Trettner committed
150
    Mesh const* mesh = nullptr;
151
152
    edge_index idx;

Philip Trettner's avatar
Philip Trettner committed
153
    edge_handle() = default;
154
155
156
157
158
159
    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; }
160

Philip Trettner's avatar
Philip Trettner committed
161
162
163
164
165
166
167
168
    template <class AttrT>
    AttrT& operator[](edge_attribute<AttrT>& prop) const;
    template <class AttrT>
    AttrT const& operator[](edge_attribute<AttrT> const& prop) const;
    template <class AttrT>
    AttrT& operator[](edge_attribute<AttrT>* prop) const;
    template <class AttrT>
    AttrT const& operator[](edge_attribute<AttrT> const* prop) const;
Philip Trettner's avatar
Philip Trettner committed
169

Philip Trettner's avatar
Philip Trettner committed
170
171
172
    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)
173
174
175

    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
176
177
178

    halfedge_handle halfedgeA() const;
    halfedge_handle halfedgeB() const;
179
180
    vertex_handle vertexA() const;
    vertex_handle vertexB() const;
181
182
    face_handle faceA() const; ///< can be invalid if boundary
    face_handle faceB() const; ///< can be invalid if boundary
183
184
185
186
};

struct halfedge_handle
{
Philip Trettner's avatar
Philip Trettner committed
187
    Mesh const* mesh = nullptr;
188
189
    halfedge_index idx;

Philip Trettner's avatar
Philip Trettner committed
190
    halfedge_handle() = default;
191
192
193
194
195
196
    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
197

Philip Trettner's avatar
Philip Trettner committed
198
199
200
201
202
203
204
205
    template <class AttrT>
    AttrT& operator[](halfedge_attribute<AttrT>& prop) const;
    template <class AttrT>
    AttrT const& operator[](halfedge_attribute<AttrT> const& prop) const;
    template <class AttrT>
    AttrT& operator[](halfedge_attribute<AttrT>* prop) const;
    template <class AttrT>
    AttrT const& operator[](halfedge_attribute<AttrT> const* prop) const;
Philip Trettner's avatar
Philip Trettner committed
206

Philip Trettner's avatar
Philip Trettner committed
207
208
209
    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)
210
211

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

Philip Trettner's avatar
Philip Trettner committed
213
214
    vertex_handle vertex_to() const;
    vertex_handle vertex_from() const;
215
    edge_handle edge() const;
216
    face_handle face() const; ///< invalid if boundary
Philip Trettner's avatar
Philip Trettner committed
217
218
219
    halfedge_handle next() const;
    halfedge_handle prev() const;
    halfedge_handle opposite() const;
220
    face_handle opposite_face() const; ///< invalid if opposite boundary
221
};
Philip Trettner's avatar
Philip Trettner committed
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273

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