OpenMesh

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CirculatorsT.hh
1 /*===========================================================================*\
2 * *
3 * OpenMesh *
4 * Copyright (C) 2001-2014 by Computer Graphics Group, RWTH Aachen *
5 * www.openmesh.org *
6 * *
7 *---------------------------------------------------------------------------*
8 * This file is part of OpenMesh. *
9 * *
10 * OpenMesh is free software: you can redistribute it and/or modify *
11 * it under the terms of the GNU Lesser General Public License as *
12 * published by the Free Software Foundation, either version 3 of *
13 * the License, or (at your option) any later version with the *
14 * following exceptions: *
15 * *
16 * If other files instantiate templates or use macros *
17 * or inline functions from this file, or you compile this file and *
18 * link it with other files to produce an executable, this file does *
19 * not by itself cause the resulting executable to be covered by the *
20 * GNU Lesser General Public License. This exception does not however *
21 * invalidate any other reasons why the executable file might be *
22 * covered by the GNU Lesser General Public License. *
23 * *
24 * OpenMesh is distributed in the hope that it will be useful, *
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
27 * GNU Lesser General Public License for more details. *
28 * *
29 * You should have received a copy of the GNU LesserGeneral Public *
30 * License along with OpenMesh. If not, *
31 * see <http://www.gnu.org/licenses/>. *
32 * *
33 \*===========================================================================*/
34
35 /*===========================================================================*\
36 * *
37 * $Revision: 990 $ *
38 * $Date: 2014-02-05 10:01:07 +0100 (Mi, 05. Feb 2014) $ *
39 * *
40 \*===========================================================================*/
41
42 #ifndef OPENMESH_CIRCULATORS_HH
43 #define OPENMESH_CIRCULATORS_HH
44 //=============================================================================
45 //
46 // Vertex and Face circulators for PolyMesh/TriMesh
47 //
48 //=============================================================================
49
50
51
52 //== INCLUDES =================================================================
53
54 #include <OpenMesh/Core/System/config.h>
55 #include <cassert>
56 #include <cstddef>
57 #include <iterator>
58
59 //== NAMESPACES ===============================================================
60
61 namespace OpenMesh {
62 namespace Iterators {
63
64 template<class Mesh, class CenterEntityHandle>
65 class GenericCirculator_CenterEntityFnsT {
66 public:
67 static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter);
68 static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter);
69 };
70
71 template<class Mesh>
72 class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::VertexHandle> {
73 public:
74 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
75 heh = mesh->cw_rotated_halfedge_handle(heh);
76 if (heh == start) ++lap_counter;
77 }
78 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
79 if (heh == start) --lap_counter;
80 heh = mesh->ccw_rotated_halfedge_handle(heh);
81 }
82 };
83
84 template<class Mesh>
85 class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::FaceHandle> {
86 public:
87 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
88 heh = mesh->next_halfedge_handle(heh);
89 if (heh == start) ++lap_counter;
90 }
91 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
92 if (heh == start) --lap_counter;
93 heh = mesh->prev_halfedge_handle(heh);
94 }
95 };
96
97 template<class Mesh, class CenterEntityHandle, class ValueHandle>
98 class GenericCirculator_DereferenciabilityCheckT {
99 public:
100 //inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int &lap_counter);
101 };
102
103 template<class Mesh>
104 class GenericCirculator_DereferenciabilityCheckT<Mesh, typename Mesh::FaceHandle, typename Mesh::FaceHandle> {
105 public:
106 inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh) {
107 return mesh->face_handle(mesh->opposite_halfedge_handle(heh)).is_valid();
108 }
109 };
110
111 template<class Mesh>
112 class GenericCirculator_DereferenciabilityCheckT<Mesh, typename Mesh::VertexHandle, typename Mesh::FaceHandle> {
113 public:
114 inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh) {
115 return mesh->face_handle(heh).is_valid();
116 }
117 };
118
119 template<class Mesh, class CenterEntityHandle, class ValueHandle>
120 class GenericCirculator_ValueHandleFnsT {
121 public:
122 inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int &lap_counter) {
123 return heh.is_valid() && ((start != heh) || (lap_counter == 0));
124 }
125 inline static void init(const Mesh*, typename Mesh::HalfedgeHandle&, typename Mesh::HalfedgeHandle&, int&) {};
126 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
127 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle>::increment(mesh, heh, start, lap_counter);
128 }
129 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
130 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle>::decrement(mesh, heh, start, lap_counter);
131 }
132 };
133
134 template<class Mesh, class CenterEntityHandle>
135 class GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, typename Mesh::FaceHandle> {
136 public:
137 typedef GenericCirculator_DereferenciabilityCheckT<Mesh, CenterEntityHandle, typename Mesh::FaceHandle> GenericCirculator_DereferenciabilityCheck;
138
139 inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int &lap_counter) {
140 return heh.is_valid() && ((start != heh) || (lap_counter == 0));
141 }
142 inline static void init(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
143 if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0)
144 increment(mesh, heh, start, lap_counter);
145 };
146 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
147 do {
148 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle>::increment(mesh, heh, start, lap_counter);
149 } while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
150 }
151 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
152 do {
153 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle>::decrement(mesh, heh, start, lap_counter);
154 } while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
155 }
156 };
157
158 template<class Mesh>
159 class GenericCirculatorBaseT {
160 public:
161 typedef const Mesh* mesh_ptr;
162 typedef const Mesh& mesh_ref;
163
164 public:
165 GenericCirculatorBaseT() : mesh_(0), lap_counter_(0) {}
166
167 GenericCirculatorBaseT(mesh_ref mesh, HalfedgeHandle heh, bool end = false) :
168 mesh_(&mesh), start_(heh), heh_(heh), lap_counter_(static_cast<int>(end)) {}
169
170 GenericCirculatorBaseT(const GenericCirculatorBaseT &rhs) :
171 mesh_(rhs.mesh_), start_(rhs.start_), heh_(rhs.heh_), lap_counter_(rhs.lap_counter_) {}
172
173 inline typename Mesh::FaceHandle toFaceHandle() const {
174 return mesh_->face_handle(heh_);
175 }
176
177 inline typename Mesh::FaceHandle toOppositeFaceHandle() const {
178 return mesh_->face_handle(toOppositeHalfedgeHandle());
179 }
180
181 inline typename Mesh::EdgeHandle toEdgeHandle() const {
182 return mesh_->edge_handle(heh_);
183 }
184
185 inline typename Mesh::HalfedgeHandle toHalfedgeHandle() const {
186 return heh_;
187 }
188
189 inline typename Mesh::HalfedgeHandle toOppositeHalfedgeHandle() const {
190 return mesh_->opposite_halfedge_handle(heh_);
191 }
192
193 inline typename Mesh::VertexHandle toVertexHandle() const {
194 return mesh_->to_vertex_handle(heh_);
195 }
196
197 inline GenericCirculatorBaseT &operator=(const GenericCirculatorBaseT &rhs) {
198 mesh_ = rhs.mesh_;
199 start_ = rhs.start_;
200 heh_ = rhs.heh_;
201 lap_counter_ = rhs.lap_counter_;
202 return *this;
203 }
204
205 inline bool operator==(const GenericCirculatorBaseT &rhs) const {
206 return mesh_ == rhs.mesh_ && start_ == rhs.start_ && heh_ == rhs.heh_ && lap_counter_ == rhs.lap_counter_;
207 }
208
209 inline bool operator!=(const GenericCirculatorBaseT &rhs) const {
210 return !operator==(rhs);
211 }
212
213 protected:
214 mesh_ptr mesh_;
215 typename Mesh::HalfedgeHandle start_, heh_;
216 int lap_counter_;
217 };
218
219 template<class Mesh, class CenterEntityHandle, class ValueHandle,
220 ValueHandle (GenericCirculatorBaseT<Mesh>::*Handle2Value)() const>
221 class GenericCirculatorT : protected GenericCirculatorBaseT<Mesh> {
222 public:
223 typedef std::ptrdiff_t difference_type;
224 typedef ValueHandle value_type;
225 typedef const value_type& reference;
226 typedef const value_type* pointer;
227 typedef std::bidirectional_iterator_tag iterator_category;
228
229 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
230 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
231 typedef GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, ValueHandle> GenericCirculator_ValueHandleFns;
232
233 public:
234 GenericCirculatorT() {}
235 GenericCirculatorT(mesh_ref mesh, CenterEntityHandle start, bool end = false) :
236 GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end) {
237
238 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
239 }
240 GenericCirculatorT(mesh_ref mesh, HalfedgeHandle heh, bool end = false) :
241 GenericCirculatorBaseT<Mesh>(mesh, heh, end) {
242
243 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
244 }
245 GenericCirculatorT(const GenericCirculatorT &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {}
246
247 GenericCirculatorT& operator++() {
248 assert(this->mesh_);
249 GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
250 return *this;
251 }
252 GenericCirculatorT& operator--() {
253 assert(this->mesh_);
254 GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
255 return *this;
256 }
257
259 GenericCirculatorT operator++(int) {
260 assert(this->mesh_);
261 GenericCirculatorT cpy(*this);
262 ++(*this);
263 return cpy;
264 }
265
267 GenericCirculatorT operator--(int) {
268 assert(this->mesh_);
269 GenericCirculatorT cpy(*this);
270 --(*this);
271 return cpy;
272 }
273
275 value_type operator*() const {
276 #ifndef NDEBUG
277 assert(this->heh_.is_valid());
278 value_type res = (this->*Handle2Value)();
279 assert(res.is_valid());
280 return res;
281 #else
282 return (this->*Handle2Value)();
283 #endif
284 }
285
294 pointer operator->() const {
295 pointer_deref_value = **this;
296 return &pointer_deref_value;
297 }
298
299 GenericCirculatorT &operator=(const GenericCirculatorT &rhs) {
300 GenericCirculatorBaseT<Mesh>::operator=(rhs);
301 return *this;
302 };
303
304 bool operator==(const GenericCirculatorT &rhs) const {
305 return GenericCirculatorBaseT<Mesh>::operator==(rhs);
306 }
307
308 bool operator!=(const GenericCirculatorT &rhs) const {
309 return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
310 }
311
312 bool is_valid() const {
313 return GenericCirculator_ValueHandleFns::is_valid(this->heh_, this->start_, this->lap_counter_);
314 }
315
316 DEPRECATED("current_halfedge_handle() is an implementation detail and should not be accessed from outside the iterator class.")
322 const HalfedgeHandle &current_halfedge_handle() const {
323 return this->heh_;
324 }
325
326 DEPRECATED("Do not use this error prone implicit cast. Compare to end-iterator or use is_valid(), instead.")
332 operator bool() const {
333 return is_valid();
334 }
335
341 DEPRECATED("This function clutters your code. Use dereferencing operators -> and * instead.")
342 value_type handle() const {
343 return **this;
344 }
345
352 DEPRECATED("Implicit casts of iterators are unsafe. Use dereferencing operators -> and * instead.")
353 operator value_type() const {
354 return **this;
355 }
356
357 template<typename STREAM>
358 friend STREAM &operator<< (STREAM &s, const GenericCirculatorT &self) {
359 return s << self.mesh_ << ", " << self.start_.idx() << ", " << self.heh_.idx() << ", " << self.lap_counter_;
360 }
361
362 private:
363 mutable value_type pointer_deref_value;
364 };
365
366 } // namespace Iterators
367 } // namespace OpenMesh
368
369 #endif
OpenMesh::Iterators::GenericCirculatorT::operator*
value_type operator*() const
Standard dereferencing operator.
Definition: CirculatorsT.hh:275
OpenMesh::Iterators::GenericCirculatorBaseT
Definition: CirculatorsT.hh:159
OpenMesh::Iterators::GenericCirculatorT::operator--
GenericCirculatorT operator--(int)
Post-decrement.
Definition: CirculatorsT.hh:267
OpenMesh::BaseHandle::is_valid
bool is_valid() const
The handle is valid iff the index is not equal to -1.
Definition: Handles.hh:70
OpenMesh::FaceHandle
Handle for a face entity.
Definition: Handles.hh:135
OpenMesh::operator<<
std::ostream & operator<<(std::ostream &_os, const BaseHandle &_hnd)
Write handle _hnd to stream _os.
Definition: Handles.hh:104
OpenMesh::VertexHandle
Handle for a vertex entity.
Definition: Handles.hh:114
OpenMesh::Iterators::GenericCirculator_DereferenciabilityCheckT
Definition: CirculatorsT.hh:98
OpenMesh::Iterators::GenericCirculatorT::operator++
GenericCirculatorT operator++(int)
Post-increment.
Definition: CirculatorsT.hh:259
OpenMesh::Iterators::GenericCirculator_ValueHandleFnsT
Definition: CirculatorsT.hh:120
OpenMesh::Iterators::GenericCirculatorT
Definition: CirculatorsT.hh:221
OpenMesh::HalfedgeHandle
Handle for a halfedge entity.
Definition: Handles.hh:121
OpenMesh::Iterators::GenericCirculator_CenterEntityFnsT
Definition: CirculatorsT.hh:65
OpenMesh::Iterators::GenericCirculatorT::operator->
pointer operator->() const
Pointer dereferentiation.
Definition: CirculatorsT.hh:294