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
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;
41
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_;
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 // For cython purpose only. The object it initializes should be overwritten ASAP and never used before it is overwritten.
90 : sib_(nullptr),
91 st_(nullptr) {
92 }
93
94// any end() iterator
96 : last_(st->null_vertex()),
97 next_(st->null_vertex()),
98 sib_(nullptr),
99 sh_(st->null_simplex()),
100 st_(st) {
101 }
102
103 template<class SimplexHandle>
104 Simplex_tree_boundary_simplex_iterator(SimplexTree const* st, SimplexHandle sh)
105 : last_(sh->first),
106 next_(st->null_vertex()),
107 sib_(nullptr),
108 sh_(st->null_simplex()),
109 st_(st) {
110 // Only check once at the beginning instead of for every increment, as this is expensive.
112 GUDHI_CHECK(st_->contiguous_vertices(), "The set of vertices is not { 0, ..., n } without holes");
113 Siblings const* sib = st->self_siblings(sh);
114 next_ = sib->parent();
115 sib_ = sib->oncles();
116 if (sib_ != nullptr) {
119 {
120 if (sib_->oncles() == nullptr) // Only relevant for edges
121 sh_ = sib_->members_.begin() + next_;
122 else
123 sh_ = sib_->find(next_);
124 } else {
125 sh_ = sib_->find(next_);
126 }
127 }
128 }
129
130 private:
131 friend class boost::iterator_core_access;
132 // valid when iterating along the SAME boundary.
133 bool equal(Simplex_tree_boundary_simplex_iterator const& other) const {
134 return sh_ == other.sh_;
135 }
136
137 Simplex_handle const& dereference() const {
138 assert(sh_ != st_->null_simplex());
139 return sh_;
140 }
141
142 void increment() {
143 if (sib_ == nullptr) {
144 sh_ = st_->null_simplex();
145 return;
146 }
147
148 Siblings const* for_sib = sib_;
149 Siblings const* new_sib = sib_->oncles();
150 auto rit = suffix_.rbegin();
152 if (new_sib == nullptr) {
153 // We reached the root, use a short-cut to find a vertex.
154 if (rit == suffix_.rend()) {
155 // Segment, this vertex is the last boundary simplex
156 sh_ = for_sib->members_.begin() + last_;
157 sib_ = nullptr;
158 return;
159 } else {
160 // Dim >= 2, initial step of the descent
161 sh_ = for_sib->members_.begin() + *rit;
162 for_sib = sh_->second.children();
163 ++rit;
164 }
165 }
166 }
167
168 for (; rit != suffix_.rend(); ++rit) {
169 sh_ = for_sib->find(*rit);
170 for_sib = sh_->second.children();
171 }
172 sh_ = for_sib->find(last_); // sh_ points to the right simplex now
173 suffix_.push_back(next_);
174 next_ = sib_->parent();
175 sib_ = new_sib;
176 }
177
178 // Most of the storage should be moved to the range, iterators should be light.
179 Vertex_handle last_; // last vertex of the simplex
180 Vertex_handle next_; // next vertex to push in suffix_
181 Static_vertex_vector suffix_;
182 Siblings const* sib_; // where the next search will start from
183 Simplex_handle sh_; // current Simplex_handle in the boundary
184 SimplexTree const* st_; // simplex containing the simplicial complex
185};
186
190template<class SimplexTree>
191class Simplex_tree_boundary_opposite_vertex_simplex_iterator : public boost::iterator_facade<
192 Simplex_tree_boundary_opposite_vertex_simplex_iterator<SimplexTree>,
193 std::pair<typename SimplexTree::Simplex_handle, typename SimplexTree::Vertex_handle> const, boost::forward_traversal_tag> {
194 public:
195 using Simplex_handle = typename SimplexTree::Simplex_handle;
196 using Vertex_handle = typename SimplexTree::Vertex_handle;
197 using Siblings = typename SimplexTree::Siblings;
198 using Static_vertex_vector = typename SimplexTree::Static_vertex_vector;
199
200 // For cython purpose only. The object it initializes should be overwritten ASAP and never used before it is
201 // overwritten.
203 : sib_(nullptr),
204 st_(nullptr) {
205 }
206
207 // any end() iterator
209 : last_(st->null_vertex()),
210 next_(st->null_vertex()),
211 sib_(nullptr),
212 baov_(st->null_simplex(), st->null_vertex()),
213 st_(st) {
214 }
215
216 template<class SimplexHandle>
218 : last_(sh->first),
219 next_(st->null_vertex()),
220 sib_(nullptr),
221 baov_(st->null_simplex(), sh->first),
222 st_(st) {
223 // Only check once at the beginning instead of for every increment, as this is expensive.
225 GUDHI_CHECK(st_->contiguous_vertices(), "The set of vertices is not { 0, ..., n } without holes");
226 Siblings const* sib = st->self_siblings(sh);
227 next_ = sib->parent();
228 sib_ = sib->oncles();
229 if (sib_ != nullptr) {
232 if (sib_->oncles() == nullptr)
233 // Only relevant for edges
234 baov_.first = sib_->members_.begin() + next_;
235 else
236 baov_.first = sib_->find(next_);
237 } else {
238 baov_.first = sib_->find(next_);
239 }
240 }
241 }
242
243 private:
244 friend class boost::iterator_core_access;
245
246 // valid when iterating along the SAME boundary.
247 bool equal(Simplex_tree_boundary_opposite_vertex_simplex_iterator const& other) const {
248 return (baov_.first == other.baov_.first);
249 }
250
251 std::pair<Simplex_handle, Vertex_handle> const& dereference() const {
252 return baov_;
253 }
254
255 void increment() {
256 if (sib_ == nullptr) {
257 baov_.first = st_->null_simplex();
258 return; // ------>>
259 }
260 Siblings const* for_sib = sib_;
261 Siblings const* new_sib = sib_->oncles();
262 auto rit = suffix_.rbegin();
264 if (new_sib == nullptr) {
265 // We reached the root, use a short-cut to find a vertex.
266 if (rit == suffix_.rend()) {
267 baov_.second = baov_.first->first;
268 // Segment, this vertex is the last boundary simplex
269 baov_.first = for_sib->members_.begin() + last_;
270 sib_ = nullptr;
271 return;
272 } else {
273 // Dim >= 2, initial step of the descent
274 baov_.first = for_sib->members_.begin() + *rit;
275 for_sib = baov_.first->second.children();
276 ++rit;
277 }
278 }
279 }
280
281 for (; rit != suffix_.rend(); ++rit) {
282 baov_.first = for_sib->find(*rit);
283 for_sib = baov_.first->second.children();
284 }
285 baov_.first = for_sib->find(last_); // baov_.first points to the right simplex now
286 suffix_.push_back(next_);
287 next_ = sib_->parent();
288 sib_ = new_sib;
289 baov_.second = suffix_.back();
290 }
291
292 // Most of the storage should be moved to the range, iterators should be light.
293 Vertex_handle last_; // last vertex of the simplex
294 Vertex_handle next_; // next vertex to push in suffix_
295 Static_vertex_vector suffix_;
296 Siblings const* sib_; // where the next search will start from
297 std::pair<Simplex_handle, Vertex_handle> baov_; // a pair containing the current Simplex_handle in the boundary and its opposite vertex
298 SimplexTree const* st_; // simplex containing the simplicial complex
299};
300
301/*---------------------------------------------------------------------------*/
305template<class SimplexTree>
306class Simplex_tree_complex_simplex_iterator : public boost::iterator_facade<
307 Simplex_tree_complex_simplex_iterator<SimplexTree>,
308 typename SimplexTree::Simplex_handle const, boost::forward_traversal_tag> {
309 public:
310 typedef typename SimplexTree::Simplex_handle Simplex_handle;
311 typedef typename SimplexTree::Siblings Siblings;
313
314// any end() iterator
316 : sib_(nullptr),
317 st_(nullptr) {
318 }
319
321 : sib_(nullptr),
322 st_(st) {
323 if (st == nullptr || st->root() == nullptr || st->root()->members().empty()) {
324 st_ = nullptr;
325 } else {
326 sh_ = st->root()->members().begin();
327 sib_ = st->root();
328 while (st->has_children(sh_)) {
329 sib_ = sh_->second.children();
330 sh_ = sib_->members().begin();
331 }
332 }
333 }
334 private:
335 friend class boost::iterator_core_access;
336
337// valid when iterating along the SAME boundary.
338 bool equal(Simplex_tree_complex_simplex_iterator const& other) const {
339 if (other.st_ == nullptr) {
340 return (st_ == nullptr);
341 }
342 if (st_ == nullptr) {
343 return false;
344 }
345 return (&(sh_->second) == &(other.sh_->second));
346 }
347
348 Simplex_handle const& dereference() const {
349 return sh_;
350 }
351
352// Depth first traversal.
353 void increment() {
354 ++sh_;
355 if (sh_ == sib_->members().end()) {
356 if (sib_->oncles() == nullptr) {
357 st_ = nullptr;
358 return;
359 } // reach the end
360 sh_ = sib_->oncles()->members().find(sib_->parent());
361 sib_ = sib_->oncles();
362 return;
363 }
364 while (st_->has_children(sh_)) {
365 sib_ = sh_->second.children();
366 sh_ = sib_->members().begin();
367 }
368 }
369
370 Simplex_handle sh_;
371 Siblings const* sib_;
372 SimplexTree const* st_;
373};
374
379template<class SimplexTree>
380class Simplex_tree_skeleton_simplex_iterator : public boost::iterator_facade<
381 Simplex_tree_skeleton_simplex_iterator<SimplexTree>,
382 typename SimplexTree::Simplex_handle const, boost::forward_traversal_tag> {
383 public:
384 typedef typename SimplexTree::Simplex_handle Simplex_handle;
385 typedef typename SimplexTree::Siblings Siblings;
387
388// any end() iterator
390 : sib_(nullptr),
391 st_(nullptr),
392 dim_skel_(0),
393 curr_dim_(0) {
394 }
395
397 : sib_(nullptr),
398 st_(st),
399 dim_skel_(dim_skel),
400 curr_dim_(0) {
401 if (st == nullptr || st->root() == nullptr || st->root()->members().empty()) {
402 st_ = nullptr;
403 } else {
404 sh_ = st->root()->members().begin();
405 sib_ = st->root();
406 while (st->has_children(sh_) && curr_dim_ < dim_skel_) {
407 sib_ = sh_->second.children();
408 sh_ = sib_->members().begin();
409 ++curr_dim_;
410 }
411 }
412 }
413 private:
414 friend class boost::iterator_core_access;
415
416// valid when iterating along the SAME boundary.
417 bool equal(Simplex_tree_skeleton_simplex_iterator const& other) const {
418 if (other.st_ == nullptr) {
419 return (st_ == nullptr);
420 }
421 if (st_ == nullptr) {
422 return false;
423 }
424 return (&(sh_->second) == &(other.sh_->second));
425 }
426
427 Simplex_handle const& dereference() const {
428 return sh_;
429 }
430
431// Depth first traversal of the skeleton.
432 void increment() {
433 ++sh_;
434 if (sh_ == sib_->members().end()) {
435 if (sib_->oncles() == nullptr) {
436 st_ = nullptr;
437 return;
438 } // reach the end
439 sh_ = sib_->oncles()->members().find(sib_->parent());
440 sib_ = sib_->oncles();
441 --curr_dim_;
442 return;
443 }
444 while (st_->has_children(sh_) && curr_dim_ < dim_skel_) {
445 sib_ = sh_->second.children();
446 sh_ = sib_->members().begin();
447 ++curr_dim_;
448 }
449 }
450
451 Simplex_handle sh_;
452 Siblings const* sib_;
453 SimplexTree const* st_;
454 int dim_skel_;
455 int curr_dim_;
456};
457 // end addtogroup simplex_tree
459
460} // namespace Gudhi
461
462#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:193
Iterator over the simplices of the boundary of a simplex.
Definition: Simplex_tree_iterators.h:81
Iterator over the simplices of a simplicial complex.
Definition: Simplex_tree_iterators.h:308
Iterator over the vertices of a simplex in a SimplexTree.
Definition: Simplex_tree_iterators.h:36
Iterator over the simplices of the skeleton of a given dimension of the simplicial complex.
Definition: Simplex_tree_iterators.h:382
Simplex Tree data structure for representing simplicial complexes.
Definition: Simplex_tree.h:98
Siblings const * self_siblings(SimplexHandle sh) const
Definition: Simplex_tree.h:1154
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:773
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:874
Dictionary::const_iterator Simplex_handle
Handle type to a simplex contained in the simplicial complex represented by the simplex tree.
Definition: Simplex_tree.h:192
Simplex_tree_siblings< Simplex_tree, Dictionary > Siblings
Set of nodes sharing a same parent in the simplex tree.
Definition: Simplex_tree.h:136
Options::Vertex_handle Vertex_handle
Type for the vertex handle.
Definition: Simplex_tree.h:119
Siblings * root()
Definition: Simplex_tree.h:1171
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:748
Gudhi namespace.
Definition: SimplicialComplexForAlpha.h:14
static const bool stable_simplex_handles
If true, Simplex_handle will not be invalidated after insertions or removals.
Definition: SimplexTreeOptions.h:41
static constexpr bool contiguous_vertices
If true, the list of vertices present in the complex must always be 0, ..., num_vertices-1,...
Definition: SimplexTreeOptions.h:37
Handle type for the vertices of a cell complex.
Definition: VertexHandle.h:15