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 <utility> // for std::pair
20
21namespace Gudhi {
22
27
32template<class SimplexTree>
33class Simplex_tree_simplex_vertex_iterator : public boost::iterator_facade<
34 Simplex_tree_simplex_vertex_iterator<SimplexTree>,
35 typename SimplexTree::Vertex_handle const, boost::forward_traversal_tag,
36 typename SimplexTree::Vertex_handle const> {
37 public:
38 typedef typename SimplexTree::Simplex_handle Simplex_handle;
39 typedef typename SimplexTree::Siblings Siblings;
40 typedef typename SimplexTree::Vertex_handle Vertex_handle;
41
42 explicit Simplex_tree_simplex_vertex_iterator(SimplexTree const* st)
43 : // any end() iterator
44 sib_(nullptr),
45 v_(st->null_vertex()) {
46 }
47
48 Simplex_tree_simplex_vertex_iterator(SimplexTree const* st, Simplex_handle sh)
49 : sib_(st->self_siblings(sh)),
50 v_(sh->first) {
51 }
52
53 private:
54 friend class boost::iterator_core_access;
55
56 bool equal(Simplex_tree_simplex_vertex_iterator const &other) const {
57 return sib_ == other.sib_ && v_ == other.v_;
58 }
59
60 Vertex_handle const& dereference() const {
61 return v_;
62 }
63
64 void increment() {
65 v_ = sib_->parent();
66 sib_ = sib_->oncles();
67 }
68
69 Siblings const* sib_;
70 Vertex_handle v_;
71};
72
73/*---------------------------------------------------------------------------*/
78template<class SimplexTree>
79class Simplex_tree_boundary_simplex_iterator : public boost::iterator_facade<
80 Simplex_tree_boundary_simplex_iterator<SimplexTree>,
81 typename SimplexTree::Simplex_handle const, boost::forward_traversal_tag> {
82 public:
83 using Simplex_handle = typename SimplexTree::Simplex_handle;
84 using Vertex_handle = typename SimplexTree::Vertex_handle;
85 using Siblings = typename SimplexTree::Siblings;
86 using Static_vertex_vector = typename SimplexTree::Static_vertex_vector;
87
88// any end() iterator
89 explicit Simplex_tree_boundary_simplex_iterator(SimplexTree const* st)
90 : last_(st->null_vertex()),
91 next_(st->null_vertex()),
92 sib_(nullptr),
93 sh_(st->null_simplex()),
94 st_(st) {
95 }
96
97 template<class SimplexHandle>
98 Simplex_tree_boundary_simplex_iterator(SimplexTree const* st, SimplexHandle sh)
99 : last_(sh->first),
100 next_(st->null_vertex()),
101 sib_(nullptr),
102 sh_(st->null_simplex()),
103 st_(st) {
104 // Only check once at the beginning instead of for every increment, as this is expensive.
105 if constexpr (SimplexTree::Options::contiguous_vertices)
106 GUDHI_CHECK(st_->contiguous_vertices(), "The set of vertices is not { 0, ..., n } without holes");
107 Siblings const* sib = st->self_siblings(sh);
108 next_ = sib->parent();
109 sib_ = sib->oncles();
110 if (sib_ != nullptr) {
111 if constexpr (SimplexTree::Options::contiguous_vertices &&
112 !SimplexTree::Options::stable_simplex_handles)
113 {
114 if (sib_->oncles() == nullptr) // Only relevant for edges
115 sh_ = sib_->members_.begin() + next_;
116 else
117 sh_ = sib_->find(next_);
118 } else {
119 sh_ = sib_->find(next_);
120 }
121 }
122 }
123
124 private:
125 friend class boost::iterator_core_access;
126 // valid when iterating along the SAME boundary.
127 bool equal(Simplex_tree_boundary_simplex_iterator const& other) const {
128 return sh_ == other.sh_;
129 }
130
131 Simplex_handle const& dereference() const {
132 assert(sh_ != st_->null_simplex());
133 return sh_;
134 }
135
136 void increment() {
137 if (sib_ == nullptr) {
138 sh_ = st_->null_simplex();
139 return;
140 }
141
142 Siblings const* for_sib = sib_;
143 Siblings const* new_sib = sib_->oncles();
144 auto rit = suffix_.rbegin();
145 if constexpr (SimplexTree::Options::contiguous_vertices && !SimplexTree::Options::stable_simplex_handles) {
146 if (new_sib == nullptr) {
147 // We reached the root, use a short-cut to find a vertex.
148 if (rit == suffix_.rend()) {
149 // Segment, this vertex is the last boundary simplex
150 sh_ = for_sib->members_.begin() + last_;
151 sib_ = nullptr;
152 return;
153 } else {
154 // Dim >= 2, initial step of the descent
155 sh_ = for_sib->members_.begin() + *rit;
156 for_sib = sh_->second.children();
157 ++rit;
158 }
159 }
160 }
161
162 for (; rit != suffix_.rend(); ++rit) {
163 sh_ = for_sib->find(*rit);
164 for_sib = sh_->second.children();
165 }
166 sh_ = for_sib->find(last_); // sh_ points to the right simplex now
167 suffix_.push_back(next_);
168 next_ = sib_->parent();
169 sib_ = new_sib;
170 }
171
172 // Most of the storage should be moved to the range, iterators should be light.
173 Vertex_handle last_; // last vertex of the simplex
174 Vertex_handle next_; // next vertex to push in suffix_
175 Static_vertex_vector suffix_;
176 Siblings const* sib_; // where the next search will start from
177 Simplex_handle sh_; // current Simplex_handle in the boundary
178 SimplexTree const* st_; // simplex containing the simplicial complex
179};
180
184template<class SimplexTree>
185class Simplex_tree_boundary_opposite_vertex_simplex_iterator : public boost::iterator_facade<
186 Simplex_tree_boundary_opposite_vertex_simplex_iterator<SimplexTree>,
187 std::pair<typename SimplexTree::Simplex_handle, typename SimplexTree::Vertex_handle> const, boost::forward_traversal_tag> {
188 public:
189 using Simplex_handle = typename SimplexTree::Simplex_handle;
190 using Vertex_handle = typename SimplexTree::Vertex_handle;
191 using Siblings = typename SimplexTree::Siblings;
192 using Static_vertex_vector = typename SimplexTree::Static_vertex_vector;
193
194 // any end() iterator
195 explicit Simplex_tree_boundary_opposite_vertex_simplex_iterator(SimplexTree const* st)
196 : last_(st->null_vertex()),
197 next_(st->null_vertex()),
198 sib_(nullptr),
199 baov_(st->null_simplex(), st->null_vertex()),
200 st_(st) {
201 }
202
203 template<class SimplexHandle>
204 Simplex_tree_boundary_opposite_vertex_simplex_iterator(SimplexTree const* st, SimplexHandle sh)
205 : last_(sh->first),
206 next_(st->null_vertex()),
207 sib_(nullptr),
208 baov_(st->null_simplex(), sh->first),
209 st_(st) {
210 // Only check once at the beginning instead of for every increment, as this is expensive.
211 if constexpr (SimplexTree::Options::contiguous_vertices)
212 GUDHI_CHECK(st_->contiguous_vertices(), "The set of vertices is not { 0, ..., n } without holes");
213 Siblings const* sib = st->self_siblings(sh);
214 next_ = sib->parent();
215 sib_ = sib->oncles();
216 if (sib_ != nullptr) {
217 if constexpr (SimplexTree::Options::contiguous_vertices &&
218 !SimplexTree::Options::stable_simplex_handles) {
219 if (sib_->oncles() == nullptr)
220 // Only relevant for edges
221 baov_.first = sib_->members_.begin() + next_;
222 else
223 baov_.first = sib_->find(next_);
224 } else {
225 baov_.first = sib_->find(next_);
226 }
227 }
228 }
229
230 private:
231 friend class boost::iterator_core_access;
232
233 // valid when iterating along the SAME boundary.
234 bool equal(Simplex_tree_boundary_opposite_vertex_simplex_iterator const& other) const {
235 return (baov_.first == other.baov_.first);
236 }
237
238 std::pair<Simplex_handle, Vertex_handle> const& dereference() const {
239 return baov_;
240 }
241
242 void increment() {
243 if (sib_ == nullptr) {
244 baov_.first = st_->null_simplex();
245 return; // ------>>
246 }
247 Siblings const* for_sib = sib_;
248 Siblings const* new_sib = sib_->oncles();
249 auto rit = suffix_.rbegin();
250 if constexpr (SimplexTree::Options::contiguous_vertices && !SimplexTree::Options::stable_simplex_handles) {
251 if (new_sib == nullptr) {
252 // We reached the root, use a short-cut to find a vertex.
253 if (rit == suffix_.rend()) {
254 baov_.second = baov_.first->first;
255 // Segment, this vertex is the last boundary simplex
256 baov_.first = for_sib->members_.begin() + last_;
257 sib_ = nullptr;
258 return;
259 } else {
260 // Dim >= 2, initial step of the descent
261 baov_.first = for_sib->members_.begin() + *rit;
262 for_sib = baov_.first->second.children();
263 ++rit;
264 }
265 }
266 }
267
268 for (; rit != suffix_.rend(); ++rit) {
269 baov_.first = for_sib->find(*rit);
270 for_sib = baov_.first->second.children();
271 }
272 baov_.first = for_sib->find(last_); // baov_.first points to the right simplex now
273 suffix_.push_back(next_);
274 next_ = sib_->parent();
275 sib_ = new_sib;
276 baov_.second = suffix_.back();
277 }
278
279 // Most of the storage should be moved to the range, iterators should be light.
280 Vertex_handle last_; // last vertex of the simplex
281 Vertex_handle next_; // next vertex to push in suffix_
282 Static_vertex_vector suffix_;
283 Siblings const* sib_; // where the next search will start from
284 std::pair<Simplex_handle, Vertex_handle> baov_; // a pair containing the current Simplex_handle in the boundary and its opposite vertex
285 SimplexTree const* st_; // simplex containing the simplicial complex
286};
287
288/*---------------------------------------------------------------------------*/
292template<class SimplexTree>
293class Simplex_tree_complex_simplex_iterator : public boost::iterator_facade<
294 Simplex_tree_complex_simplex_iterator<SimplexTree>,
295 typename SimplexTree::Simplex_handle const, boost::forward_traversal_tag> {
296 public:
297 typedef typename SimplexTree::Simplex_handle Simplex_handle;
298 typedef typename SimplexTree::Siblings Siblings;
299 typedef typename SimplexTree::Vertex_handle Vertex_handle;
300
301// any end() iterator
302 Simplex_tree_complex_simplex_iterator()
303 : sib_(nullptr),
304 st_(nullptr) {
305 }
306
307 explicit Simplex_tree_complex_simplex_iterator(SimplexTree const* st)
308 : sib_(nullptr),
309 st_(st) {
310 if (st == nullptr || st->root() == nullptr || st->root()->members().empty()) {
311 st_ = nullptr;
312 } else {
313 sh_ = st->root()->members().begin();
314 sib_ = st->root();
315 while (st->has_children(sh_)) {
316 sib_ = sh_->second.children();
317 sh_ = sib_->members().begin();
318 }
319 }
320 }
321 private:
322 friend class boost::iterator_core_access;
323
324// valid when iterating along the SAME boundary.
325 bool equal(Simplex_tree_complex_simplex_iterator const& other) const {
326 if (other.st_ == nullptr) {
327 return (st_ == nullptr);
328 }
329 if (st_ == nullptr) {
330 return false;
331 }
332 return (&(sh_->second) == &(other.sh_->second));
333 }
334
335 Simplex_handle const& dereference() const {
336 return sh_;
337 }
338
339// Depth first traversal.
340 void increment() {
341 ++sh_;
342 if (sh_ == sib_->members().end()) {
343 if (sib_->oncles() == nullptr) {
344 st_ = nullptr;
345 return;
346 } // reach the end
347 sh_ = sib_->oncles()->members().find(sib_->parent());
348 sib_ = sib_->oncles();
349 return;
350 }
351 while (st_->has_children(sh_)) {
352 sib_ = sh_->second.children();
353 sh_ = sib_->members().begin();
354 }
355 }
356
357 Simplex_handle sh_;
358 Siblings const* sib_;
359 SimplexTree const* st_;
360};
361
366template<class SimplexTree>
367class Simplex_tree_skeleton_simplex_iterator : public boost::iterator_facade<
368 Simplex_tree_skeleton_simplex_iterator<SimplexTree>,
369 typename SimplexTree::Simplex_handle const, boost::forward_traversal_tag> {
370 public:
371 typedef typename SimplexTree::Simplex_handle Simplex_handle;
372 typedef typename SimplexTree::Siblings Siblings;
373 typedef typename SimplexTree::Vertex_handle Vertex_handle;
374
375// any end() iterator
376 Simplex_tree_skeleton_simplex_iterator()
377 : sib_(nullptr),
378 st_(nullptr),
379 dim_skel_(0),
380 curr_dim_(0) {
381 }
382
383 Simplex_tree_skeleton_simplex_iterator(SimplexTree const* st, int dim_skel)
384 : sib_(nullptr),
385 st_(st),
386 dim_skel_(dim_skel),
387 curr_dim_(0) {
388 if (st == nullptr || st->root() == nullptr || st->root()->members().empty()) {
389 st_ = nullptr;
390 } else {
391 sh_ = st->root()->members().begin();
392 sib_ = st->root();
393 while (st->has_children(sh_) && curr_dim_ < dim_skel_) {
394 sib_ = sh_->second.children();
395 sh_ = sib_->members().begin();
396 ++curr_dim_;
397 }
398 }
399 }
400 private:
401 friend class boost::iterator_core_access;
402
403// valid when iterating along the SAME boundary.
404 bool equal(Simplex_tree_skeleton_simplex_iterator const& other) const {
405 if (other.st_ == nullptr) {
406 return (st_ == nullptr);
407 }
408 if (st_ == nullptr) {
409 return false;
410 }
411 return (&(sh_->second) == &(other.sh_->second));
412 }
413
414 Simplex_handle const& dereference() const {
415 return sh_;
416 }
417
418// Depth first traversal of the skeleton.
419 void increment() {
420 ++sh_;
421 if (sh_ == sib_->members().end()) {
422 if (sib_->oncles() == nullptr) {
423 st_ = nullptr;
424 return;
425 } // reach the end
426 sh_ = sib_->oncles()->members().find(sib_->parent());
427 sib_ = sib_->oncles();
428 --curr_dim_;
429 return;
430 }
431 while (st_->has_children(sh_) && curr_dim_ < dim_skel_) {
432 sib_ = sh_->second.children();
433 sh_ = sib_->members().begin();
434 ++curr_dim_;
435 }
436 }
437
438 Simplex_handle sh_;
439 Siblings const* sib_;
440 SimplexTree const* st_;
441 int dim_skel_;
442 int curr_dim_;
443};
444
448template<class SimplexTree>
449class Simplex_tree_dimension_simplex_iterator : public boost::iterator_facade<
450 Simplex_tree_dimension_simplex_iterator<SimplexTree>,
451 typename SimplexTree::Simplex_handle const, boost::forward_traversal_tag> {
452 public:
453 typedef typename SimplexTree::Simplex_handle Simplex_handle;
454 typedef typename SimplexTree::Siblings Siblings;
455 typedef typename SimplexTree::Vertex_handle Vertex_handle;
456
457// any end() iterator
458 Simplex_tree_dimension_simplex_iterator()
459 : sib_(nullptr),
460 st_(nullptr),
461 dim_(0),
462 curr_dim_(0) {
463 }
464
465 Simplex_tree_dimension_simplex_iterator(SimplexTree const* st, int dim)
466 : sib_(nullptr),
467 st_(st),
468 dim_(dim),
469 curr_dim_(0) {
470 if (st == nullptr || st->root() == nullptr || st->root()->members().empty() ||
471 st->upper_bound_dimension() < dim || dim < 0) {
472 st_ = nullptr;
473 } else {
474 sh_ = st->root()->members().begin();
475 sib_ = st->root();
476 until_leaf_or_dim();
477 // if we reached a leaf that does not respect the required dimension - call increment
478 if (curr_dim_ != dim_)
479 increment();
480 }
481 }
482 private:
483 friend class boost::iterator_core_access;
484
485// valid when iterating along the SAME boundary.
486 bool equal(Simplex_tree_dimension_simplex_iterator const& other) const {
487 if (other.st_ == nullptr) {
488 return (st_ == nullptr);
489 }
490 if (st_ == nullptr) {
491 return false;
492 }
493 return (&(sh_->second) == &(other.sh_->second));
494 }
495
496 Simplex_handle const& dereference() const {
497 return sh_;
498 }
499
500 void until_leaf_or_dim() {
501 while (st_->has_children(sh_) && curr_dim_ != dim_) {
502 sib_ = sh_->second.children();
503 sh_ = sib_->members().begin();
504 ++curr_dim_;
505 }
506#ifdef DEBUG_TRACES
507 std::clog << "Simplex_tree::dimension_simplex_range until_leaf_or_dim reached (";
508 for (auto vertex : st_->simplex_vertex_range(sh_)) {
509 std::clog << vertex << ",";
510 }
511 std::clog << ")\n";
512#endif // DEBUG_TRACES
513 }
514 // Depth first traversal of the tree structure. Returns when reaching a simplex with a given dimension
515 void increment() {
516 ++sh_;
517 while (sh_ == sib_->members().end()) {
518 if (sib_->oncles() == nullptr) {
519 st_ = nullptr;
520 return;
521 } // reach the end
522 sh_ = sib_->oncles()->members().find(sib_->parent());
523 sib_ = sib_->oncles();
524 --curr_dim_;
525 ++sh_;
526 until_leaf_or_dim();
527 }
528 // It seems we do it twice here, but necessary when coming from the constructor
529 until_leaf_or_dim();
530 // if we reached a leaf that does not respect the dimension - recall increment
531 if (curr_dim_ != dim_)
532 increment();
533 }
534
535 Simplex_handle sh_;
536 Siblings const* sib_;
537 SimplexTree const* st_;
538 int dim_;
539 int curr_dim_;
540};
541 // end addtogroup simplex_tree
543
544} // namespace Gudhi
545
546#endif // SIMPLEX_TREE_SIMPLEX_TREE_ITERATORS_H_
Siblings const * self_siblings(SimplexHandle sh) const
Definition Simplex_tree.h:1390
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:811
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:912
Dictionary::const_iterator Simplex_handle
Handle type to a simplex contained in the simplicial complex represented by the simplex tree.
Definition Simplex_tree.h:212
Simplex_tree_siblings< Simplex_tree, Dictionary > Siblings
Set of nodes sharing a same parent in the simplex tree.
Definition Simplex_tree.h:139
Options::Vertex_handle Vertex_handle
Type for the vertex handle.
Definition Simplex_tree.h:122
int upper_bound_dimension() const
Returns an upper bound on the dimension of the simplicial complex.
Definition Simplex_tree.h:893
Siblings * root()
Definition Simplex_tree.h:1407
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:786
Gudhi namespace.
Definition SimplicialComplexForAlpha.h:14