cursors.hh 5.69 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
#include "primitives.hh"
Philip Trettner's avatar
Philip Trettner committed
6
#include "tmp.hh"
Philip Trettner's avatar
Philip Trettner committed
7

8
9
namespace polymesh
{
Philip Trettner's avatar
Philip Trettner committed
10
// ======================== BASE ========================
11

Philip Trettner's avatar
Philip Trettner committed
12
template <class tag>
Philip Trettner's avatar
Philip Trettner committed
13
struct primitive_index
14
{
Philip Trettner's avatar
Philip Trettner committed
15
16
17
18
19
    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;

20
21
    int value = -1;

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

    bool is_valid() const { return value >= 0; }
26
    bool is_invalid() const { return value < 0; }
Philip Trettner's avatar
Philip Trettner committed
27
28
29
30
    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; }
Philip Trettner's avatar
Philip Trettner committed
31
32
    bool operator==(handle_t const& rhs) const { return value == rhs.idx.value; }
    bool operator!=(handle_t const& rhs) const { return value != rhs.idx.value; }
Philip Trettner's avatar
Philip Trettner committed
33

Philip Trettner's avatar
Philip Trettner committed
34
35
    explicit operator int() const { return value; }

Philip Trettner's avatar
Philip Trettner committed
36
37
38
39
40
    /// indexes this primitive by a functor
    /// also works for attributes
    /// - e.g. v[position] or f[area]
    template <class FuncT>
    auto operator[](FuncT&& f) const -> tmp::result_type_of<FuncT, index_t>;
41
42
};

Philip Trettner's avatar
Philip Trettner committed
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
template <class tag>
struct primitive_handle
{
    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;

    Mesh const* mesh = nullptr;
    index_t idx;

    primitive_handle() = default;
    primitive_handle(Mesh const* mesh, index_t idx) : mesh(mesh), idx(idx) {}

    bool operator==(index_t const& rhs) const { return idx == rhs; }
    bool operator!=(index_t const& rhs) const { return idx != rhs; }
    bool operator==(handle_t const& rhs) const { return mesh == rhs.mesh && idx == rhs.idx; }
    bool operator!=(handle_t const& rhs) const { return mesh != rhs.mesh || idx != rhs.idx; }

Philip Trettner's avatar
Philip Trettner committed
62
63
    explicit operator int() const { return (int)idx; }

Philip Trettner's avatar
Philip Trettner committed
64
65
66
67
68
    /// indexes this primitive by a functor
    /// also works for attributes
    /// - e.g. v[position] or f[area]
    template <class FuncT>
    auto operator[](FuncT&& f) const -> tmp::result_type_of<FuncT, handle_t>;
Philip Trettner's avatar
Philip Trettner committed
69
70
71
72
73
74
75

    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
};

// ======================== INDICES ========================

Philip Trettner's avatar
Philip Trettner committed
76
struct face_index : primitive_index<face_tag>
77
{
Philip Trettner's avatar
Philip Trettner committed
78
    using primitive_index::primitive_index;
79
};
Philip Trettner's avatar
Philip Trettner committed
80
struct edge_index : primitive_index<edge_tag>
81
{
Philip Trettner's avatar
Philip Trettner committed
82
    using primitive_index::primitive_index;
83
};
Philip Trettner's avatar
Philip Trettner committed
84
struct halfedge_index : primitive_index<halfedge_tag>
85
{
Philip Trettner's avatar
Philip Trettner committed
86
87
88
89
90
91
    using primitive_index::primitive_index;
};
struct vertex_index : primitive_index<vertex_tag>
{
    using primitive_index::primitive_index;
};
92
93
94

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

Philip Trettner's avatar
Philip Trettner committed
95
struct face_handle : primitive_handle<face_tag>
96
{
Philip Trettner's avatar
Philip Trettner committed
97
    using primitive_handle::primitive_handle;
98

Philip Trettner's avatar
Philip Trettner committed
99
    bool is_removed() const;  ///< marked for deletion (but valid idx)
100
    bool is_boundary() const; ///< true if this face lies at a boundary
Philip Trettner's avatar
Philip Trettner committed
101
102
103
104
105

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

    face_vertex_ring vertices() const;
106
107
    face_edge_ring edges() const;
    face_halfedge_ring halfedges() const;
108
    face_face_ring adjacent_faces() const; ///< includes invalid ones for boundaries!
109
110
};

Philip Trettner's avatar
Philip Trettner committed
111
struct vertex_handle : primitive_handle<vertex_tag>
112
{
Philip Trettner's avatar
Philip Trettner committed
113
    using primitive_handle::primitive_handle;
114

Philip Trettner's avatar
Philip Trettner committed
115
    bool is_removed() const;  ///< marked for deletion (but valid idx)
116
117
    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
118

119
    face_handle any_face() const;                  ///< invalid if at boundary
Philip Trettner's avatar
Philip Trettner committed
120
    face_handle any_valid_face() const;            ///< invalid if isolated (and can be if at boundary)
121
122
123
    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
124
125

    vertex_halfedge_in_ring incoming_halfedges() const;
126
    vertex_halfedge_out_ring outgoing_halfedges() const;
127
128
129
    vertex_edge_ring edges() const;
    vertex_face_ring faces() const; ///< includes invalid ones for boundaries!
    vertex_vertex_ring adjacent_vertices() const;
130
131
};

Philip Trettner's avatar
Philip Trettner committed
132
struct edge_handle : primitive_handle<edge_tag>
133
{
Philip Trettner's avatar
Philip Trettner committed
134
    using primitive_handle::primitive_handle;
135

Philip Trettner's avatar
Philip Trettner committed
136
    bool is_removed() const;  ///< marked for deletion (but valid idx)
137
138
    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
139
140
141

    halfedge_handle halfedgeA() const;
    halfedge_handle halfedgeB() const;
142
143
    vertex_handle vertexA() const;
    vertex_handle vertexB() const;
144
145
    face_handle faceA() const; ///< can be invalid if boundary
    face_handle faceB() const; ///< can be invalid if boundary
146
147
};

Philip Trettner's avatar
Philip Trettner committed
148
struct halfedge_handle : primitive_handle<halfedge_tag>
149
{
Philip Trettner's avatar
Philip Trettner committed
150
    using primitive_handle::primitive_handle;
151

Philip Trettner's avatar
Philip Trettner committed
152
    bool is_removed() const;  ///< marked for deletion (but valid idx)
153
    bool is_boundary() const; ///< true if this half-edge is a boundary (CAUTION: its opposite might not be)
154

Philip Trettner's avatar
Philip Trettner committed
155
156
    vertex_handle vertex_to() const;
    vertex_handle vertex_from() const;
157
    edge_handle edge() const;
158
    face_handle face() const; ///< invalid if boundary
Philip Trettner's avatar
Philip Trettner committed
159
160
161
    halfedge_handle next() const;
    halfedge_handle prev() const;
    halfedge_handle opposite() const;
162
    face_handle opposite_face() const; ///< invalid if opposite boundary
Philip Trettner's avatar
Philip Trettner committed
163

Philip Trettner's avatar
Philip Trettner committed
164
165
    halfedge_ring ring() const; ///< all half-edges along the same ring
};
166
}