Loading...
Searching...
No Matches
Simplex_tree_iterators.h
1/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
2 * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
3 * Author(s): Clément Maria
4 *
5 * Copyright (C) 2014 Inria
6 *
7 * Modification(s):
8 * - 2022/04 Vincent Rouvreau: Add Simplex_tree_boundary_opposite_vertex_simplex_iterator for alpha and cech purpose
9 * - YYYY/MM Author: Description of the modification
10 */
11
12#ifndef SIMPLEX_TREE_SIMPLEX_TREE_ITERATORS_H_
13#define SIMPLEX_TREE_SIMPLEX_TREE_ITERATORS_H_
14
15#include <gudhi/Debug_utils.h>
16
17#include <boost/iterator/iterator_facade.hpp>
18
19#include <vector>
20#include <utility> // for std::pair
21
22namespace Gudhi {
23
33template<class SimplexTree>
34class Simplex_tree_simplex_vertex_iterator : public boost::iterator_facade<
35 Simplex_tree_simplex_vertex_iterator<SimplexTree>,
36 typename SimplexTree::Vertex_handle const, boost::forward_traversal_tag,
37 typename SimplexTree::Vertex_handle const> {
38 public:
39 typedef typename SimplexTree::Simplex_handle Simplex_handle;
40 typedef typename SimplexTree::Siblings Siblings;
42
44 : // any end() iterator
45 sib_(nullptr),
46 v_(st->null_vertex()) {
47 }
48
49 Simplex_tree_simplex_vertex_iterator(SimplexTree const* st, Simplex_handle sh)
50 : sib_(st->self_siblings(sh)),
51 v_(sh->first) {
52 }
53
54 private:
55 friend class boost::iterator_core_access;
56
57 bool equal(Simplex_tree_simplex_vertex_iterator const &other) const {
58 return sib_ == other.sib_ && v_ == other.v_;
59 }
60
61 Vertex_handle const& dereference() const {
62 return v_;
63 }
64
65 void increment() {
66 v_ = sib_->parent();
67 sib_ = sib_->oncles();
68 }
69
70 Siblings * sib_;
72};
73
74/*---------------------------------------------------------------------------*/
79template<class SimplexTree>
80class Simplex_tree_boundary_simplex_iterator : public boost::iterator_facade<
81 Simplex_tree_boundary_simplex_iterator<SimplexTree>,
82 typename SimplexTree::Simplex_handle const, boost::forward_traversal_tag> {
83 public:
84 using Simplex_handle = typename SimplexTree::Simplex_handle;
85 using Vertex_handle = typename SimplexTree::Vertex_handle;
86 using Siblings = typename SimplexTree::Siblings;
87 using Static_vertex_vector = typename SimplexTree::Static_vertex_vector;
88
89 // For cython purpose only. The object it initializes should be overwritten ASAP and never used before it is overwritten.
91 : sib_(nullptr),
92 st_(nullptr) {
93 }
94
95// any end() iterator
97 : last_(st->null_vertex()),
98 next_(st->null_vertex()),
99 sib_(nullptr),
100 sh_(st->null_simplex()),
101 st_(st) {
102 }
103
104 template<class SimplexHandle>
106 : last_(sh->first),
107 next_(st->null_vertex()),
108 sib_(nullptr),
109 sh_(st->null_simplex()),
110 st_(st) {
111 // Only check once at the beginning instead of for every increment, as this is expensive.
112 if constexpr (SimplexTree::Options::contiguous_vertices)
113 GUDHI_CHECK(st_->contiguous_vertices(), "The set of vertices is not { 0, ..., n } without holes");
114 Siblings * sib = st->self_siblings(sh);
115 next_ = sib->parent();
116 sib_ = sib->oncles();
117 if (sib_ != nullptr) {
118 if constexpr (SimplexTree::Options::contiguous_vertices &&
119 !SimplexTree::Options::stable_simplex_handles)
120 {
121 if (sib_->oncles() == nullptr) // Only relevant for edges
122 sh_ = sib_->members_.begin() + next_;
123 else
124 sh_ = sib_->find(next_);
125 } else {
126 sh_ = sib_->find(next_);
127 }
128 }
129 }
130
131 private:
132 friend class boost::iterator_core_access;
133 // valid when iterating along the SAME boundary.
134 bool equal(Simplex_tree_boundary_simplex_iterator const& other) const {
135 return sh_ == other.sh_;
136 }
137
138 Simplex_handle const& dereference() const {
139 assert(sh_ != st_->null_simplex());
140 return sh_;
141 }
142
143 void increment() {
144 if (sib_ == nullptr) {
145 sh_ = st_->null_simplex();
146 return;
147 }
148
149 Siblings * for_sib = sib_;
150 Siblings * new_sib = sib_->oncles();
151 auto rit = suffix_.rbegin();
152 if constexpr (SimplexTree::Options::contiguous_vertices && !SimplexTree::Options::stable_simplex_handles) {
153 if (new_sib == nullptr) {
154 // We reached the root, use a short-cut to find a vertex.
155 if (rit == suffix_.rend()) {
156 // Segment, this vertex is the last boundary simplex
157 sh_ = for_sib->members_.begin() + last_;
158 sib_ = nullptr;
159 return;
160 } else {
161 // Dim >= 2, initial step of the descent
162 sh_ = for_sib->members_.begin() + *rit;
163 for_sib = sh_->second.children();
164 ++rit;
165 }
166 }
167 }
168
169 for (; rit != suffix_.rend(); ++rit) {
170 sh_ = for_sib->find(*rit);
171 for_sib = sh_->second.children();
172 }
173 sh_ = for_sib->find(last_); // sh_ points to the right simplex now
174 suffix_.push_back(next_);
175 next_ = sib_->parent();
176 sib_ = new_sib;
177 }
178
179 // Most of the storage should be moved to the range, iterators should be light.
180 Vertex_handle last_; // last vertex of the simplex
181 Vertex_handle next_; // next vertex to push in suffix_
182 Static_vertex_vector suffix_;
183 Siblings * sib_; // where the next search will start from
184 Simplex_handle sh_; // current Simplex_handle in the boundary
185 SimplexTree * st_; // simplex containing the simplicial complex
186};
187
191template<class SimplexTree>
192class Simplex_tree_boundary_opposite_vertex_simplex_iterator : public boost::iterator_facade<
193 Simplex_tree_boundary_opposite_vertex_simplex_iterator<SimplexTree>,
194 std::pair<typename SimplexTree::Simplex_handle, typename SimplexTree::Vertex_handle> const, boost::forward_traversal_tag> {
195 public:
196 using Simplex_handle = typename SimplexTree::Simplex_handle;
197 using Vertex_handle = typename SimplexTree::Vertex_handle;
198 using Siblings = typename SimplexTree::Siblings;
199 using Static_vertex_vector = typename SimplexTree::Static_vertex_vector;
200
201 // For cython purpose only. The object it initializes should be overwritten ASAP and never used before it is
202 // overwritten.
204 : sib_(nullptr),
205 st_(nullptr) {
206 }
207
208 // any end() iterator
210 : last_(st->null_vertex()),
211 next_(st->null_vertex()),
212 sib_(nullptr),
213 baov_(st->null_simplex(), st->null_vertex()),
214 st_(st) {
215 }
216
217 template<class SimplexHandle>
219 : last_(sh->first),
220 next_(st->null_vertex()),
221 sib_(nullptr),
222 baov_(st->null_simplex(), sh->first),
223 st_(st) {
224 // Only check once at the beginning instead of for every increment, as this is expensive.
225 if constexpr (SimplexTree::Options::contiguous_vertices)
226 GUDHI_CHECK(st_->contiguous_vertices(), "The set of vertices is not { 0, ..., n } without holes");
227 Siblings * sib = st->self_siblings(sh);
228 next_ = sib->parent();
229 sib_ = sib->oncles();
230 if (sib_ != nullptr) {
231 if constexpr (SimplexTree::Options::contiguous_vertices &&
232 !SimplexTree::Options::stable_simplex_handles) {
233 if (sib_->oncles() == nullptr)
234 // Only relevant for edges
235 baov_.first = sib_->members_.begin() + next_;
236 else
237 baov_.first = sib_->find(next_);
238 } else {
239 baov_.first = sib_->find(next_);
240 }
241 }
242 }
243
244 private:
245 friend class boost::iterator_core_access;
246
247 // valid when iterating along the SAME boundary.
248 bool equal(Simplex_tree_boundary_opposite_vertex_simplex_iterator const& other) const {
249 return (baov_.first == other.baov_.first);
250 }
251
252 std::pair<Simplex_handle, Vertex_handle> const& dereference() const {
253 return baov_;
254 }
255
256 void increment() {
257 if (sib_ == nullptr) {
258 baov_.first = st_->null_simplex();
259 return; // ------>>
260 }
261 Siblings * for_sib = sib_;
262 Siblings * new_sib = sib_->oncles();
263 auto rit = suffix_.rbegin();
264 if constexpr (SimplexTree::Options::contiguous_vertices && !SimplexTree::Options::stable_simplex_handles) {
265 if (new_sib == nullptr) {
266 // We reached the root, use a short-cut to find a vertex.
267 if (rit == suffix_.rend()) {
268 baov_.second = baov_.first->first;
269 // Segment, this vertex is the last boundary simplex
270 baov_.first = for_sib->members_.begin() + last_;
271 sib_ = nullptr;
272 return;
273 } else {
274 // Dim >= 2, initial step of the descent
275 baov_.first = for_sib->members_.begin() + *rit;
276 for_sib = baov_.first->second.children();
277 ++rit;
278 }
279 }
280 }
281
282 for (; rit != suffix_.rend(); ++rit) {
283 baov_.first = for_sib->find(*rit);
284 for_sib = baov_.first->second.children();
285 }
286 baov_.first = for_sib->find(last_); // baov_.first points to the right simplex now
287 suffix_.push_back(next_);
288 next_ = sib_->parent();
289 sib_ = new_sib;
290 baov_.second = suffix_.back();
291 }
292
293 // Most of the storage should be moved to the range, iterators should be light.
294 Vertex_handle last_; // last vertex of the simplex
295 Vertex_handle next_; // next vertex to push in suffix_
296 Static_vertex_vector suffix_;
297 Siblings * sib_; // where the next search will start from
298 std::pair<Simplex_handle, Vertex_handle> baov_; // a pair containing the current Simplex_handle in the boundary and its opposite vertex
299 SimplexTree * st_; // simplex containing the simplicial complex
300};
301
302/*---------------------------------------------------------------------------*/
306template<class SimplexTree>
307class Simplex_tree_complex_simplex_iterator : public boost::iterator_facade<
308 Simplex_tree_complex_simplex_iterator<SimplexTree>,
309 typename SimplexTree::Simplex_handle const, boost::forward_traversal_tag> {
310 public:
311 typedef typename SimplexTree::Simplex_handle Simplex_handle;
312 typedef typename SimplexTree::Siblings Siblings;
314
315// any end() iterator
317 : sib_(nullptr),
318 st_(nullptr) {
319 }
320
322 : sib_(nullptr),
323 st_(st) {
324 if (st == nullptr || st->root() == nullptr || st->root()->members().empty()) {
325 st_ = nullptr;
326 } else {
327 sh_ = st->root()->members().begin();
328 sib_ = st->root();
329 while (st->has_children(sh_)) {
330 sib_ = sh_->second.children();
331 sh_ = sib_->members().begin();
332 }
333 }
334 }
335 private:
336 friend class boost::iterator_core_access;
337
338// valid when iterating along the SAME boundary.
339 bool equal(Simplex_tree_complex_simplex_iterator const& other) const {
340 if (other.st_ == nullptr) {
341 return (st_ == nullptr);
342 }
343 if (st_ == nullptr) {
344 return false;
345 }
346 return (&(sh_->second) == &(other.sh_->second));
347 }
348
349 Simplex_handle const& dereference() const {
350 return sh_;
351 }
352
353// Depth first traversal.
354 void increment() {
355 ++sh_;
356 if (sh_ == sib_->members().end()) {
357 if (sib_->oncles() == nullptr) {
358 st_ = nullptr;
359 return;
360 } // reach the end
361 sh_ = sib_->oncles()->members().find(sib_->parent());
362 sib_ = sib_->oncles();
363 return;
364 }
365 while (st_->has_children(sh_)) {
366 sib_ = sh_->second.children();
367 sh_ = sib_->members().begin();
368 }
369 }
370
371 Simplex_handle sh_;
372 Siblings * sib_;
373 SimplexTree * st_;
374};
375
380template<class SimplexTree>
381class Simplex_tree_skeleton_simplex_iterator : public boost::iterator_facade<
382 Simplex_tree_skeleton_simplex_iterator<SimplexTree>,
383 typename SimplexTree::Simplex_handle const, boost::forward_traversal_tag> {
384 public:
385 typedef typename SimplexTree::Simplex_handle Simplex_handle;
386 typedef typename SimplexTree::Siblings Siblings;
388
389// any end() iterator
391 : sib_(nullptr),
392 st_(nullptr),
393 dim_skel_(0),
394 curr_dim_(0) {
395 }
396
398 : sib_(nullptr),
399 st_(st),
400 dim_skel_(dim_skel),
401 curr_dim_(0) {
402 if (st == nullptr || st->root() == nullptr || st->root()->members().empty()) {
403 st_ = nullptr;
404 } else {
405 sh_ = st->root()->members().begin();
406 sib_ = st->root();
407 while (st->has_children(sh_) && curr_dim_ < dim_skel_) {
408 sib_ = sh_->second.children();
409 sh_ = sib_->members().begin();
410 ++curr_dim_;
411 }
412 }
413 }
414 private:
415 friend class boost::iterator_core_access;
416
417// valid when iterating along the SAME boundary.
418 bool equal(Simplex_tree_skeleton_simplex_iterator const& other) const {
419 if (other.st_ == nullptr) {
420 return (st_ == nullptr);
421 }
422 if (st_ == nullptr) {
423 return false;
424 }
425 return (&(sh_->second) == &(other.sh_->second));
426 }
427
428 Simplex_handle const& dereference() const {
429 return sh_;
430 }
431
432// Depth first traversal of the skeleton.
433 void increment() {
434 ++sh_;
435 if (sh_ == sib_->members().end()) {
436 if (sib_->oncles() == nullptr) {
437 st_ = nullptr;
438 return;
439 } // reach the end
440 sh_ = sib_->oncles()->members().find(sib_->parent());
441 sib_ = sib_->oncles();
442 --curr_dim_;
443 return;
444 }
445 while (st_->has_children(sh_) && curr_dim_ < dim_skel_) {
446 sib_ = sh_->second.children();
447 sh_ = sib_->members().begin();
448 ++curr_dim_;
449 }
450 }
451
452 Simplex_handle sh_;
453 Siblings * sib_;
454 SimplexTree * st_;
455 int dim_skel_;
456 int curr_dim_;
457};
458 // end addtogroup simplex_tree
460
461} // namespace Gudhi
462
463#endif // SIMPLEX_TREE_SIMPLEX_TREE_ITERATORS_H_
Iterator over the simplices of the boundary of a simplex and their opposite vertices.
Definition: Simplex_tree_iterators.h:194
Iterator over the simplices of the boundary of a simplex.
Definition: Simplex_tree_iterators.h:82
Iterator over the simplices of a simplicial complex.
Definition: Simplex_tree_iterators.h:309
Iterator over the vertices of a simplex in a SimplexTree.
Definition: Simplex_tree_iterators.h:37
Iterator over the simplices of the skeleton of a given dimension of the simplicial complex.
Definition: Simplex_tree_iterators.h:383
Simplex Tree data structure for representing simplicial complexes.
Definition: Simplex_tree.h:95
static Siblings * self_siblings(SimplexHandle sh)
Definition: Simplex_tree.h:1023
Dictionary::iterator Simplex_handle
Handle type to a simplex contained in the simplicial complex represented by the simplex tree.
Definition: Simplex_tree.h:175
Vertex_handle null_vertex() const
Returns a Vertex_handle different from all Vertex_handles associated to the vertices of the simplicia...
Definition: Simplex_tree.h:646
bool has_children(SimplexHandle sh) const
Returns true if the node in the simplex tree pointed by the given simplex handle has children.
Definition: Simplex_tree.h:742
Simplex_tree_siblings< Simplex_tree, Dictionary > Siblings
Set of nodes sharing a same parent in the simplex tree.
Definition: Simplex_tree.h:127
Options::Vertex_handle Vertex_handle
Type for the vertex handle.
Definition: Simplex_tree.h:110
Siblings * root()
Definition: Simplex_tree.h:1032
static Simplex_handle null_simplex()
Returns a Simplex_handle different from all Simplex_handles associated to the simplices in the simpli...
Definition: Simplex_tree.h:635
Handle type for the vertices of a cell complex.
Definition: VertexHandle.h:15