1 // This is brl/bbas/imesh/imesh_half_edge.h
2 #ifndef imesh_half_edge_h_
3 #define imesh_half_edge_h_
4 
5 //:
6 // \file
7 // \brief A simple indexed half-edge
8 // \author Matt Leotta (mleotta@lems.brown.edu)
9 // \date May 2, 2008
10 
11 #include <iostream>
12 #include <iterator>
13 #include <vector>
14 #ifdef _MSC_VER
15 #  include <vcl_msvc_warnings.h>
16 #endif
17 #include <cassert>
18 
19 #define imesh_invalid_idx (static_cast<unsigned int>(-1))
20 
21 class imesh_half_edge
22 {
23     friend class imesh_half_edge_set;
24   public:
imesh_half_edge(unsigned int e,unsigned int n,unsigned int v,unsigned int f)25     imesh_half_edge(unsigned int e, unsigned int n, unsigned int v, unsigned int f)
26     : next_(n), edge_(e), vert_(v), face_(f) {}
27 
28     //: return the next half-edge index
next_index()29     unsigned int next_index() const { return next_; }
30     //: return the pair half-edge index
pair_index()31     unsigned int pair_index() const { return edge_^1; }
32 
33     //: return the index of the full edge
edge_index()34     unsigned int edge_index() const { return edge_>>1; }
35     //: return the index of the half-edge
half_edge_index()36     unsigned int half_edge_index() const { return edge_; }
37 
38     //: return the vertex index
vert_index()39     unsigned int vert_index() const { return vert_; }
40     //: return the face index
face_index()41     unsigned int face_index() const { return face_; }
42 
is_boundary()43     bool is_boundary() const { return face_ == imesh_invalid_idx; }
44 
45   private:
46     unsigned int next_;
47     unsigned int edge_;
48 
49     unsigned int vert_;
50     unsigned int face_;
51 };
52 
53 
54 //: A collection of indexed half edges
55 class imesh_half_edge_set
56 {
57   public:
58     //: Default Constructor
59     imesh_half_edge_set() = default;
60     //: Construct from a face index list
61     imesh_half_edge_set(const std::vector<std::vector<unsigned int> >& face_list);
62 
63     //: Build the half edges from an indexed face set
64     void build_from_ifs(const std::vector<std::vector<unsigned int> >& face_list);
65 
66     //: Access by index
67     const imesh_half_edge& operator [] (unsigned int i) const { return half_edges_[i]; }
68     //: Access by index
69     imesh_half_edge& operator [] (unsigned int i)  { return half_edges_[i]; }
70 
71     //: number of half edges
size()72     unsigned int size() const { return half_edges_.size(); }
73 
74     //: clear the edges
clear()75     void clear()
76     {
77       half_edges_.clear();
78       vert_to_he_.clear();
79       face_to_he_.clear();
80     }
81 
82     // forward declare iterators
83     class f_iterator;
84     class f_const_iterator;
85     class v_iterator;
86     class v_const_iterator;
87 
88     //=====================================================
89     // Mesh Face Iterators - each half edge touches the same face
90 
91     //: An iterator of half edges adjacent to a face
92     class f_iterator : public std::iterator<std::forward_iterator_tag,imesh_half_edge>
93     {
94       friend class f_const_iterator;
95       friend class v_iterator;
96       public:
97         //: Constructor
f_iterator(unsigned int hei,imesh_half_edge_set & edge_set)98         f_iterator(unsigned int hei, imesh_half_edge_set& edge_set)
99           :half_edge_index_(hei), edge_set_(edge_set) {}
100 
101         //: Constructor from vertex iterator
f_iterator(const v_iterator & other)102         explicit f_iterator(const v_iterator& other)
103           :half_edge_index_(other.half_edge_index_), edge_set_(other.edge_set_) {}
104 
105         //: Assignment
106         f_iterator& operator = (const f_iterator& other)
107         {
108           if (this != &other){
109             assert(&edge_set_ == &other.edge_set_);
110             half_edge_index_ = other.half_edge_index_;
111           }
112           return *this;
113         }
114 
115         imesh_half_edge & operator*() const { return edge_set_[half_edge_index_]; }
116         imesh_half_edge * operator->() const { return &**this; }
pair()117         imesh_half_edge & pair() const { return edge_set_[half_edge_index_^1]; }
118         f_iterator & operator++ () // pre-inc
119         {
120           half_edge_index_ = edge_set_[half_edge_index_].next_index();
121           return *this;
122         }
123         f_iterator operator++(int) // post-inc
124         {
125           f_iterator old = *this;
126           ++*this;
127           return old;
128         }
129 
130         bool operator == (const f_iterator& other) const
131         {
132           return this->half_edge_index_ == other.half_edge_index_ &&
133                 &(this->edge_set_) == &(other.edge_set_);
134         }
135 
136         bool operator != (const f_iterator& other) const
137         {
138           return !(*this == other);
139         }
140 
141         bool operator == (const f_const_iterator& other) const
142         {
143           return this->half_edge_index_ == other.half_edge_index_ &&
144                 &(this->edge_set_) == &(other.edge_set_);
145         }
146 
147         bool operator != (const f_const_iterator& other) const
148         {
149           return !(*this == other);
150         }
151 
152       private:
153         unsigned int half_edge_index_;
154         imesh_half_edge_set& edge_set_;
155     };
156 
157     //: A const iterator of half edges adjacent to a face
158     class f_const_iterator : public std::iterator<std::forward_iterator_tag,imesh_half_edge>
159     {
160         friend class f_iterator;
161         friend class v_const_iterator;
162       public:
163         //: Constructor
f_const_iterator(unsigned int hei,const imesh_half_edge_set & edge_set)164         f_const_iterator(unsigned int hei, const imesh_half_edge_set& edge_set)
165           :half_edge_index_(hei), edge_set_(edge_set) {}
166 
167         //: Constructor from non-const iterator
f_const_iterator(const f_iterator & other)168         f_const_iterator(const f_iterator& other)
169           :half_edge_index_(other.half_edge_index_), edge_set_(other.edge_set_) {}
170 
171         //: Constructor from vertex iterator
f_const_iterator(const v_const_iterator & other)172         explicit f_const_iterator(const v_const_iterator& other)
173           :half_edge_index_(other.half_edge_index_), edge_set_(other.edge_set_) {}
174 
175         //: Assignment
176         f_const_iterator& operator = (const f_const_iterator& other)
177         {
178           if (this != &other){
179             assert(&edge_set_ == &other.edge_set_);
180             half_edge_index_ = other.half_edge_index_;
181           }
182           return *this;
183         }
184 
185         const imesh_half_edge & operator*() const { return edge_set_[half_edge_index_]; }
186         const imesh_half_edge * operator->() const { return &**this; }
pair()187         const imesh_half_edge & pair() const { return edge_set_[half_edge_index_^1]; }
188         f_const_iterator & operator++ () // pre-inc
189         {
190           half_edge_index_ = edge_set_[half_edge_index_].next_index();
191           return *this;
192         }
193         f_const_iterator operator++(int) // post-inc
194         {
195           f_const_iterator old = *this;
196           ++*this;
197           return old;
198         }
199 
200         bool operator == (const f_const_iterator& other) const
201         {
202           return this->half_edge_index_ == other.half_edge_index_ &&
203                 &(this->edge_set_) == &(other.edge_set_);
204         }
205 
206         bool operator != (const f_const_iterator& other) const
207         {
208           return !(*this == other);
209         }
210 
211       private:
212         unsigned int half_edge_index_;
213         const imesh_half_edge_set& edge_set_;
214     };
215 
216 
217     //=====================================================
218     // Mesh Vertex Iterators - each half edge touches the same vertex
219 
220     //: An iterator of half edges adjacent to a vertex
221     class v_iterator : public std::iterator<std::forward_iterator_tag,imesh_half_edge>
222     {
223         friend class v_const_iterator;
224         friend class f_iterator;
225       public:
226         //: Constructor
v_iterator(unsigned int hei,imesh_half_edge_set & edge_set)227         v_iterator(unsigned int hei, imesh_half_edge_set& edge_set)
228           :half_edge_index_(hei), edge_set_(edge_set) {}
229 
230         //: Constructor from face iterator
v_iterator(const f_iterator & other)231         explicit v_iterator(const f_iterator& other)
232           :half_edge_index_(other.half_edge_index_), edge_set_(other.edge_set_) {}
233 
234         //: Assignment
235         v_iterator& operator = (const v_iterator& other)
236         {
237           if (this != &other){
238             assert(&edge_set_ == &other.edge_set_);
239             half_edge_index_ = other.half_edge_index_;
240           }
241           return *this;
242         }
243 
244         imesh_half_edge & operator*() const { return edge_set_[half_edge_index_]; }
245         imesh_half_edge * operator->() const { return &**this; }
pair()246         imesh_half_edge & pair() const { return edge_set_[half_edge_index_^1]; }
247         v_iterator & operator++ () // pre-inc
248         {
249           half_edge_index_ = half_edge_index_ ^ 1; // pair index
250           half_edge_index_ = edge_set_[half_edge_index_].next_index();
251           return *this;
252         }
253         v_iterator operator++(int) // post-inc
254         {
255           v_iterator old = *this;
256           ++*this;
257           return old;
258         }
259 
260         bool operator == (const v_iterator& other) const
261         {
262           return this->half_edge_index_ == other.half_edge_index_ &&
263                 &(this->edge_set_) == &(other.edge_set_);
264         }
265 
266         bool operator != (const v_iterator& other) const
267         {
268           return !(*this == other);
269         }
270 
271         bool operator == (const v_const_iterator& other) const
272         {
273           return this->half_edge_index_ == other.half_edge_index_ &&
274                 &(this->edge_set_) == &(other.edge_set_);
275         }
276 
277         bool operator != (const v_const_iterator& other) const
278         {
279           return !(*this == other);
280         }
281 
282       private:
283         unsigned int half_edge_index_;
284         imesh_half_edge_set& edge_set_;
285     };
286 
287     //: A const iterator of half edges adjacent to a vertex
288     class v_const_iterator : public std::iterator<std::forward_iterator_tag,imesh_half_edge>
289     {
290         friend class v_iterator;
291         friend class f_const_iterator;
292       public:
293         //: Constructor
v_const_iterator(unsigned int hei,const imesh_half_edge_set & edge_set)294         v_const_iterator(unsigned int hei, const imesh_half_edge_set& edge_set)
295           :half_edge_index_(hei), edge_set_(edge_set) {}
296 
297         //: Constructor from non-const iterator
v_const_iterator(const v_iterator & other)298         v_const_iterator(const v_iterator& other)
299           :half_edge_index_(other.half_edge_index_), edge_set_(other.edge_set_) {}
300 
301         //: Constructor from face iterator
v_const_iterator(const f_const_iterator & other)302         explicit v_const_iterator(const f_const_iterator& other)
303           :half_edge_index_(other.half_edge_index_), edge_set_(other.edge_set_) {}
304 
305         //: Assignment
306         v_const_iterator& operator = (const v_const_iterator& other)
307         {
308           if (this != &other){
309             assert(&edge_set_ == &other.edge_set_);
310             half_edge_index_ = other.half_edge_index_;
311           }
312           return *this;
313         }
314 
315         const imesh_half_edge & operator*() const { return edge_set_[half_edge_index_]; }
316         const imesh_half_edge * operator->() const { return &**this; }
pair()317         const imesh_half_edge & pair() const { return edge_set_[half_edge_index_^1]; }
318         v_const_iterator & operator++ () // pre-inc
319         {
320           half_edge_index_ = half_edge_index_ ^ 1; // pair index
321           half_edge_index_ = edge_set_[half_edge_index_].next_index();
322           return *this;
323         }
324         v_const_iterator operator++(int) // post-inc
325         {
326           v_const_iterator old = *this;
327           ++*this;
328           return old;
329         }
330 
331         bool operator == (const v_const_iterator& other) const
332         {
333           return this->half_edge_index_ == other.half_edge_index_ &&
334                 &(this->edge_set_) == &(other.edge_set_);
335         }
336 
337         bool operator != (const v_const_iterator& other) const
338         {
339           return !(*this == other);
340         }
341 
342       private:
343         unsigned int half_edge_index_;
344         const imesh_half_edge_set& edge_set_;
345     };
346 
347     //: Access a face iterator for face \param f
face_begin(unsigned int f)348     f_const_iterator face_begin(unsigned int f) const { return f_const_iterator(face_to_he_[f],*this); }
face_begin(unsigned int f)349     f_iterator face_begin(unsigned int f) { return f_iterator(face_to_he_[f],*this); }
350 
351     //: Access a vertex iterator for vertex \param v
vertex_begin(unsigned int v)352     v_const_iterator vertex_begin(unsigned int v) const { return v_const_iterator(vert_to_he_[v],*this); }
vertex_begin(unsigned int v)353     v_iterator vertex_begin(unsigned int v) { return v_iterator(vert_to_he_[v],*this); }
354 
355     //: Count the number of vertices pointed to by these edges
356     unsigned int num_verts() const;
357 
358     //: Count the number of faces pointed to by these edges
359     unsigned int num_faces() const;
360 
361   private:
362     std::vector<imesh_half_edge> half_edges_;
363     std::vector<unsigned int> vert_to_he_;
364     std::vector<unsigned int> face_to_he_;
365 };
366 
367 
368 #endif // imesh_half_edge_h_
369