Loading...
Searching...
No Matches
Skeleton_blockers_simplices_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): David Salinas
4 *
5 * Copyright (C) 2014 Inria
6 *
7 * Modification(s):
8 * - YYYY/MM Author: Description of the modification
9 */
10
11#ifndef SKELETON_BLOCKER_ITERATORS_SKELETON_BLOCKERS_SIMPLICES_ITERATORS_H_
12#define SKELETON_BLOCKER_ITERATORS_SKELETON_BLOCKERS_SIMPLICES_ITERATORS_H_
13
14#include <gudhi/Skeleton_blocker_link_complex.h>
15#include <gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h>
16#include <gudhi/Skeleton_blocker/internal/Trie.h>
17#include <gudhi/Debug_utils.h>
18
19#include <boost/iterator/iterator_facade.hpp>
20
21#include <memory>
22#include <list>
23#include <iostream>
24
25namespace Gudhi {
26
27namespace skeleton_blocker {
28
37template<typename SkeletonBlockerComplex, typename Link>
39public boost::iterator_facade < Simplex_around_vertex_iterator<SkeletonBlockerComplex, Link>
40, typename SkeletonBlockerComplex::Simplex
41, boost::forward_traversal_tag
42, typename SkeletonBlockerComplex::Simplex
43> {
44 friend class boost::iterator_core_access;
45 typedef SkeletonBlockerComplex Complex;
46 typedef typename Complex::Vertex_handle Vertex_handle;
47 typedef typename Complex::Edge_handle Edge_handle;
48 typedef typename Complex::Simplex Simplex;
49
50 // Link_vertex_handle == Complex_Vertex_handle but this renaming helps avoiding confusion
51 typedef typename Link::Vertex_handle Link_vertex_handle;
52
53 typedef typename Gudhi::skeleton_blocker::Trie<Simplex> Trie;
54
55 private:
56 const Complex* complex;
58 std::shared_ptr<Link> link_v;
59 std::shared_ptr<Trie> trie;
60 // TODO(DS): use a deque instead
61 std::list<Trie*> nodes_to_be_seen;
62
63 public:
64 Simplex_around_vertex_iterator() : complex(0) { }
65
66 Simplex_around_vertex_iterator(const Complex* complex_, Vertex_handle v_) :
67 complex(complex_),
68 v(v_),
69 link_v(new Link(*complex_, v_)),
70 trie(new Trie(v_)) {
71 compute_trie_and_nodes_to_be_seen();
72 }
73
74 // TODO(DS): avoid useless copy
75 // TODO(DS): currently just work if copy begin iterator
77 complex(other.complex),
78 v(other.v),
79 link_v(other.link_v),
80 trie(other.trie),
81 nodes_to_be_seen(other.nodes_to_be_seen) {
82 if (!other.is_end()) {
83 }
84 }
85
89 Simplex_around_vertex_iterator(const Complex* complex_, Vertex_handle v_, bool end) :
90 complex(complex_),
91 v(v_) {
92 set_end();
93 }
94
95 private:
96 void compute_trie_and_nodes_to_be_seen() {
97 // once we go through every simplices passing through v0
98 // we remove v0. That way, it prevents from passing a lot of times
99 // though edges leaving v0.
100 // another solution would have been to provides an adjacency iterator
101 // to superior vertices that avoids lower ones.
102 while (!link_v->empty()) {
103 auto v0 = *(link_v->vertex_range().begin());
104 trie->add_child(build_trie(v0, trie.get()));
105 link_v->remove_vertex(v0);
106 }
107 nodes_to_be_seen.push_back(trie.get());
108 }
109
110 Trie* build_trie(Link_vertex_handle link_vh, Trie* parent) {
111 Trie* res = new Trie(parent_vertex(link_vh), parent);
112 for (Link_vertex_handle nv : link_v->vertex_range(link_vh)) {
113 if (link_vh < nv) {
114 Simplex simplex_node_plus_nv(res->simplex());
115 simplex_node_plus_nv.add_vertex(parent_vertex(nv));
116 if (complex->contains(simplex_node_plus_nv)) {
117 res->add_child(build_trie(nv, res));
118 }
119 }
120 }
121 return res;
122 }
123
124 bool is_node_in_complex(Trie* trie) {
125 return true;
126 }
127
128 Vertex_handle parent_vertex(Link_vertex_handle link_vh) const {
129 return complex->convert_handle_from_another_complex(*link_v, link_vh);
130 }
131
132 public:
133 friend std::ostream& operator<<(std::ostream& stream, const Simplex_around_vertex_iterator& savi) {
134 stream << savi.trie << std::endl;
135 stream << "(" << savi.nodes_to_be_seen.size() << ") nodes to see\n";
136 return stream;
137 }
138
139 bool equal(const Simplex_around_vertex_iterator& other) const {
140 bool same_complex = (complex == other.complex);
141 if (!same_complex)
142 return false;
143
144 if (!(v == other.v))
145 return false;
146
147 bool both_empty = nodes_to_be_seen.empty() && other.nodes_to_be_seen.empty();
148 if (both_empty)
149 return true;
150
151 bool both_non_empty = !nodes_to_be_seen.empty() && !other.nodes_to_be_seen.empty();
152
153 // one is empty the other is not
154 if (!both_non_empty) return false;
155
156 bool same_node = (**(nodes_to_be_seen.begin()) == **(other.nodes_to_be_seen.begin()));
157 return same_node;
158 }
159
160 void increment() {
161 assert(!is_end());
162 Trie* first_node = nodes_to_be_seen.front();
163
164 nodes_to_be_seen.pop_front();
165
166 for (auto child : first_node->children) {
167 nodes_to_be_seen.push_back(child.get());
168 }
169 }
170
171 Simplex dereference() const {
172 assert(!nodes_to_be_seen.empty());
173 Trie* first_node = nodes_to_be_seen.front();
174 return first_node->simplex();
175 }
176
177 Simplex get_trie_address() const {
178 assert(!nodes_to_be_seen.empty());
179 return nodes_to_be_seen.front();
180 }
181
182 private:
183 void set_end() {
184 nodes_to_be_seen.clear();
185 }
186
187 bool is_end() const {
188 return nodes_to_be_seen.empty();
189 }
190};
191
192template<typename SkeletonBlockerComplex>
193class Simplex_iterator :
194public boost::iterator_facade < Simplex_iterator<SkeletonBlockerComplex>
195, typename SkeletonBlockerComplex::Simplex
196, boost::forward_traversal_tag
197, typename SkeletonBlockerComplex::Simplex
198> {
199 typedef Skeleton_blocker_link_superior<SkeletonBlockerComplex> Link;
200
201 friend class boost::iterator_core_access;
202
203 template<class SkBlDS> friend class Skeleton_blocker_complex;
204
205 typedef SkeletonBlockerComplex Complex;
206 typedef typename Complex::Vertex_handle Vertex_handle;
207 typedef typename Complex::Edge_handle Edge_handle;
208 typedef typename Complex::Simplex Simplex;
209 typedef typename Complex::Complex_vertex_iterator Complex_vertex_iterator;
210 typedef typename Link::Vertex_handle Link_vertex_handle;
211
212 private:
213 const Complex* complex_;
214 Complex_vertex_iterator current_vertex_;
215
216 typedef Simplex_around_vertex_iterator<SkeletonBlockerComplex, Link> SAVI;
217 SAVI current_simplex_around_current_vertex_;
218 SAVI simplices_around_current_vertex_end_;
219
220 public:
221 Simplex_iterator() : complex_(0) { }
222
223 Simplex_iterator(const Complex* complex) :
224 complex_(complex),
225 current_vertex_(complex->vertex_range().begin()),
226 current_simplex_around_current_vertex_(complex, *current_vertex_),
227 simplices_around_current_vertex_end_(complex, *current_vertex_, true) {
228 // should not be called if the complex is empty
229 assert(!complex->empty());
230 }
231
232 private:
233 Simplex_iterator(const Complex* complex, bool end) :
234 complex_(complex) {
235 set_end();
236 }
237
238 public:
239 Simplex_iterator(const Simplex_iterator& other)
240 :
241 complex_(other.complex_),
242 current_vertex_(other.current_vertex_),
243 current_simplex_around_current_vertex_(other.current_simplex_around_current_vertex_),
244 simplices_around_current_vertex_end_(other.simplices_around_current_vertex_end_) { }
245
246 friend Simplex_iterator make_begin_iterator(const Complex* complex) {
247 if (complex->empty())
248 return make_end_simplex_iterator(complex);
249 else
250 return Simplex_iterator(complex);
251 }
252
253 friend Simplex_iterator make_end_simplex_iterator(const Complex* complex) {
254 return Simplex_iterator(complex, true);
255 }
256
257 bool equal(const Simplex_iterator& other) const {
258 if (complex_ != other.complex_) return false;
259 if (current_vertex_ != other.current_vertex_) return false;
260 if (is_end() && other.is_end()) return true;
261 if (current_simplex_around_current_vertex_ != other.current_simplex_around_current_vertex_)
262 return false;
263 return true;
264 }
265
266 void increment() {
267 if (current_simplex_around_current_vertex_ != simplices_around_current_vertex_end_) {
268 current_simplex_around_current_vertex_.increment();
269 if (current_simplex_around_current_vertex_ == simplices_around_current_vertex_end_)
270 goto_next_vertex();
271 } else {
272 goto_next_vertex();
273 }
274 }
275
276 void goto_next_vertex() {
277 current_vertex_.increment();
278 if (!is_end()) {
279 current_simplex_around_current_vertex_ = SAVI(complex_, *current_vertex_);
280 simplices_around_current_vertex_end_ = SAVI(complex_, *current_vertex_, true);
281 }
282 }
283
284 Simplex dereference() const {
285 return current_simplex_around_current_vertex_.dereference();
286 }
287
288 private:
289 void set_end() {
290 current_vertex_ = complex_->vertex_range().end();
291 }
292
293 bool is_end() const {
294 return (current_vertex_ == complex_->vertex_range().end());
295 }
296};
297
301template<typename SkeletonBlockerComplex, typename Link>
303public boost::iterator_facade < Simplex_coboundary_iterator<SkeletonBlockerComplex, Link>
304, typename SkeletonBlockerComplex::Simplex, boost::forward_traversal_tag, typename SkeletonBlockerComplex::Simplex> {
305 friend class boost::iterator_core_access;
306 typedef SkeletonBlockerComplex Complex;
307 typedef typename Complex::Vertex_handle Vertex_handle;
308 typedef typename Complex::Edge_handle Edge_handle;
309 typedef typename Complex::Simplex Simplex;
311
312 // Link_vertex_handle == Complex_Vertex_handle but this renaming helps avoiding confusion
313 typedef typename Link::Vertex_handle Link_vertex_handle;
314
315 private:
316 const Complex* complex;
317 const Simplex& sigma;
318 std::shared_ptr<Link> link;
319 Complex_vertex_iterator current_vertex;
320 Complex_vertex_iterator link_vertex_end;
321
322 public:
323 Simplex_coboundary_iterator() : complex(0) { }
324
325 Simplex_coboundary_iterator(const Complex* complex_, const Simplex& sigma_) :
326 complex(complex_),
327 sigma(sigma_),
328 // need only vertices of the link hence the true flag
329 link(new Link(*complex_, sigma_, false, true)) {
330 auto link_vertex_range = link->vertex_range();
331 current_vertex = link_vertex_range.begin();
332 link_vertex_end = link_vertex_range.end();
333 }
334
336 complex(other.complex),
337 sigma(other.sigma),
338 link(other.link),
339 current_vertex(other.current_vertex),
340 link_vertex_end(other.link_vertex_end) { }
341
342 // returns an iterator to the end
343 Simplex_coboundary_iterator(const Complex* complex_, const Simplex& sigma_, bool end) :
344 complex(complex_),
345 sigma(sigma_) {
346 // to represent an end iterator without having to build a useless link, we use
347 // the convection that link is not initialized.
348 }
349
350 private:
351 Vertex_handle parent_vertex(Link_vertex_handle link_vh) const {
352 return complex->convert_handle_from_another_complex(*link, link_vh);
353 }
354
355 public:
356 friend std::ostream& operator<<(std::ostream& stream, const Simplex_coboundary_iterator& sci) {
357 return stream;
358 }
359
360 // assume that iterator points to the same complex and comes from the same simplex
361 bool equal(const Simplex_coboundary_iterator& other) const {
362 assert(complex == other.complex && sigma == other.sigma);
363 if (is_end()) return other.is_end();
364 if (other.is_end()) return is_end();
365 return *current_vertex == *(other.current_vertex);
366 }
367
368 void increment() {
369 ++current_vertex;
370 }
371
372 Simplex dereference() const {
373 Simplex res(sigma);
374 res.add_vertex(parent_vertex(*current_vertex));
375 return res;
376 }
377
378 private:
379 bool is_end() const {
380 return !link || current_vertex == link_vertex_end;
381 }
382};
383
384} // namespace skeleton_blocker
385
386namespace skbl = skeleton_blocker;
387
388} // namespace Gudhi
389
390#endif // SKELETON_BLOCKER_ITERATORS_SKELETON_BLOCKERS_SIMPLICES_ITERATORS_H_
Definition: Skeleton_blockers_simplices_iterators.h:43
Simplex_around_vertex_iterator(const Complex *complex_, Vertex_handle v_, bool end)
Definition: Skeleton_blockers_simplices_iterators.h:89
Definition: Skeleton_blockers_simplices_iterators.h:304
Complex_vertex_range vertex_range() const
Returns a Complex_vertex_range over all vertices of the complex.
Definition: Skeleton_blocker_complex.h:1282
Class that represents a geometric complex that can be simplified. The class allows access to points o...
Definition: Skeleton_blocker_geometric_complex.h:29
Iterator on the vertices of a simplicial complex.
Definition: Skeleton_blockers_vertices_iterators.h:31
Handle type for the vertices of a cell complex.
Definition: VertexHandle.h:15