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