Gudhi  1.1.0
 All Classes Functions Typedefs Friends Groups Pages
Skeleton_blockers_simplices_iterators.h
1  /* This file is part of the Gudhi Library. The Gudhi library
2  * (Geometric Understanding in Higher Dimensions) is a generic C++
3  * library for computational topology.
4  *
5  * Author(s): David Salinas
6  *
7  * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 #ifndef GUDHI_KELETON_BLOCKERS_SIMPLICES_ITERATORS_H_
23 #define GUDHI_SKELETON_BLOCKERS_SIMPLICES_ITERATORS_H_
24 
25 #include <memory>
26 #include <list>
27 #include <iostream>
28 #include "gudhi/Utils.h"
29 #include "boost/iterator/iterator_facade.hpp"
30 
31 
32 #include "gudhi/Skeleton_blocker_link_complex.h"
33 #include "gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h"
34 
35 
36 
37 
38 namespace Gudhi {
39 
40 
41 namespace skbl {
42 
43 
52 template<typename SkeletonBlockerComplex,typename Link>
54  public boost::iterator_facade < Simplex_around_vertex_iterator<SkeletonBlockerComplex,Link>
55 , typename SkeletonBlockerComplex::Simplex_handle
56 , boost::forward_traversal_tag
57 , typename SkeletonBlockerComplex::Simplex_handle
58 >
59 {
60  friend class boost::iterator_core_access;
61  typedef SkeletonBlockerComplex Complex;
62  typedef typename Complex::Vertex_handle Vertex_handle;
63  typedef typename Complex::Edge_handle Edge_handle;
64  typedef typename Complex::Simplex_handle Simplex_handle;
65 
66 
67  typedef typename Link::Vertex_handle Link_vertex_handle;
68  // Link_vertex_handle == Complex_Vertex_handle but this renaming helps avoiding confusion
69 
70 
71 private:
72 
73  struct Trie{
74  Vertex_handle v;
75  std::vector<std::shared_ptr<Trie> > childs;
76  private:
77  const Trie* parent_;
78  public:
79 
80 
81  //std::list<std::unique_ptr<Trie> > childs; -> use of deleted function
82 
83  Trie():parent_(0){}
84  Trie(Vertex_handle v_):v(v_),parent_(0){
85  }
86 
87  Trie(Vertex_handle v_,Trie* parent):v(v_),parent_(parent){
88  }
89 
90 
91  bool operator==(const Trie& other) const{
92  return (v == other.v) ;
93  }
94 
95  void add_child(Trie* child){
96  if(child){
97  std::shared_ptr<Trie> ptr_to_add(child);
98  childs.push_back(ptr_to_add);
99  child->parent_ = this;
100  }
101  }
102 
103 
104  friend std::ostream& operator<<(std::ostream& stream, const Trie& trie){
105  stream<< "T( "<< trie.v<< " ";
106  for(auto t : trie.childs)
107  stream << *t ;
108  stream<<")";
109  return stream;
110  }
111 
112  // goes to the root in the trie to consitute simplex
113  void add_vertices_up_to_the_root(Simplex_handle& res) const{
114  res.add_vertex(v);
115  if(parent_)
116  parent_->add_vertices_up_to_the_root(res);
117  }
118 
119  Simplex_handle simplex() const{
120  Simplex_handle res;
121  add_vertices_up_to_the_root(res);
122  return res;
123  }
124 
125  bool is_leaf() const{
126  return childs.empty();
127  }
128 
129  bool is_root() const{
130  return parent_==0;
131  }
132 
133  const Trie* parent() {
134  return parent_;
135  }
136 
137  void remove_leaf() {
138  assert(is_leaf);
139  if(!is_root())
140  parent_->childs.erase(this);
141  }
142 
143  private:
144 
145 
146  public:
147 
148  Trie* go_bottom_left(){
149  if(is_leaf())
150  return this;
151  else
152  return (*childs.begin())->go_bottom_left();
153  }
154 
155  };
156 
157 private:
158  const Complex* complex;
159  Vertex_handle v;
160  std::shared_ptr<Link> link_v;
161  std::shared_ptr<Trie> trie;
162  std::list<Trie*> nodes_to_be_seen; // todo regrouper
163 
164 public:
165  Simplex_around_vertex_iterator():complex(0){
166  }
167 
168  Simplex_around_vertex_iterator(const Complex* complex_,Vertex_handle v_):
169  complex(complex_),
170  v(v_),
171  link_v(new Link(*complex_,v_)),
172  trie(new Trie(v_)){
173  compute_trie_and_nodes_to_be_seen();
174  }
175 
176  // todo avoid useless copy
177  // todo currently just work if copy begin iterator
179  complex(other.complex),
180  v(other.v),
181  link_v(other.link_v),
182  trie(other.trie),
183  nodes_to_be_seen(other.nodes_to_be_seen)
184  {
185  if(!other.is_end()){
186  }
187  }
188 
192  Simplex_around_vertex_iterator(const Complex* complex_,Vertex_handle v_,bool end):
193  complex(complex_),
194  v(v_){
195  set_end();
196  }
197 
198 private:
199 
200 
201  void compute_trie_and_nodes_to_be_seen(){
202  // once we go through every simplices passing through v0
203  // we remove v0. That way, it prevents from passing a lot of times
204  // though edges leaving v0.
205  // another solution would have been to provides an adjacency iterator
206  // to superior vertices that avoids lower ones.
207  while(!link_v->empty()){
208  auto v0 = *(link_v->vertex_range().begin());
209  trie->add_child(build_trie(v0,trie.get()));
210  link_v->remove_vertex(v0);
211  }
212  nodes_to_be_seen.push_back(trie.get());
213  }
214 
215  Trie* build_trie(Link_vertex_handle link_vh,Trie* parent){
216  Trie* res = new Trie(parent_vertex(link_vh),parent);
217  for(Link_vertex_handle nv : link_v->vertex_range(link_vh)) {
218  if(link_vh < nv){
219  Simplex_handle simplex_node_plus_nv(res->simplex());
220  simplex_node_plus_nv.add_vertex(parent_vertex(nv));
221  if(complex->contains(simplex_node_plus_nv)){
222  res->add_child(build_trie(nv,res));
223  }
224  }
225  }
226  return res;
227  }
228 
229  bool is_node_in_complex(Trie* trie){
230  return true;
231  }
232 
233  Vertex_handle parent_vertex(Link_vertex_handle link_vh) const{
234  return complex->convert_handle_from_another_complex(*link_v,link_vh);
235  }
236 
237 
238 
239 public:
240 
241  friend std::ostream& operator<<(std::ostream& stream, const Simplex_around_vertex_iterator& savi){
242  stream<< savi.trie<< std::endl; ;
243  stream << "("<<savi.nodes_to_be_seen.size()<<") nodes to see\n";
244  return stream;
245  }
246 
247  bool equal(const Simplex_around_vertex_iterator& other) const{
248  bool same_complex = (complex == other.complex);
249  if(!same_complex)
250  return false;
251 
252  if(!(v == other.v))
253  return false;
254 
255  bool both_empty = nodes_to_be_seen.empty() && other.nodes_to_be_seen.empty();
256  if(both_empty)
257  return true;
258 
259  bool both_non_empty = !nodes_to_be_seen.empty() && !other.nodes_to_be_seen.empty();
260 
261  if(!both_non_empty) return false; //one is empty the other is not
262 
263  bool same_node = (**(nodes_to_be_seen.begin()) == **(other.nodes_to_be_seen.begin()));
264  return same_node;
265  }
266 
267  void increment(){
268  assert(!is_end());
269  Trie* first_node = nodes_to_be_seen.front();
270 
271  nodes_to_be_seen.pop_front();
272 
273  for(auto childs : first_node->childs){
274  nodes_to_be_seen.push_back(childs.get());
275  }
276 
277  }
278 
279  Simplex_handle dereference() const{
280  assert(!nodes_to_be_seen.empty());
281  Trie* first_node = nodes_to_be_seen.front();
282  return first_node->simplex();
283  }
284 
285 private:
286  void set_end(){
287  nodes_to_be_seen.clear();
288  }
289 
290  bool is_end() const{
291  return nodes_to_be_seen.empty();
292  }
293 };
294 
295 
296 
297 template<typename SkeletonBlockerComplex>
298 class Simplex_iterator :
299  public boost::iterator_facade < Simplex_iterator<SkeletonBlockerComplex>
300 , typename SkeletonBlockerComplex::Simplex_handle
301 , boost::forward_traversal_tag
302 , typename SkeletonBlockerComplex::Simplex_handle
303 >
304 {
305  typedef Skeleton_blocker_link_superior<SkeletonBlockerComplex> Link;
306 
307  friend class boost::iterator_core_access;
308 
309  template<class SkBlDS> friend class Skeleton_blocker_complex;
310 
311 
312  typedef SkeletonBlockerComplex Complex;
313  typedef typename Complex::Vertex_handle Vertex_handle;
314  typedef typename Complex::Edge_handle Edge_handle;
315  typedef typename Complex::Simplex_handle Simplex_handle;
316 
317  typedef typename Complex::CVI CVI;
318 
319 
320  typedef typename Link::Vertex_handle Link_vertex_handle;
321 
322 private:
323 
324  const Complex* complex_;
325  CVI current_vertex_;
326 
327  typedef Simplex_around_vertex_iterator<SkeletonBlockerComplex,Link> SAVI;
328  SAVI current_simplex_around_current_vertex_;
329  SAVI simplices_around_current_vertex_end_;
330 
331 
332 public:
333  Simplex_iterator():complex_(0){}
334 
335  // should not be called if the complex is empty
336  Simplex_iterator(const Complex* complex):
337  complex_(complex),
338  current_vertex_(complex->vertex_range().begin()),
339  current_simplex_around_current_vertex_(complex,*current_vertex_),
340  simplices_around_current_vertex_end_(complex,*current_vertex_,true)
341  {
342  assert(!complex->empty());
343  }
344 
345 private:
346  // todo return to private
347  Simplex_iterator(const Complex* complex,bool end):
348  complex_(complex)
349  {
350  set_end();
351  }
352 
353 public:
354 
355  Simplex_iterator(const Simplex_iterator& other)
356  :
357  complex_(other.complex_),
358  current_vertex_(other.current_vertex_),
359  current_simplex_around_current_vertex_(other.current_simplex_around_current_vertex_),
360  simplices_around_current_vertex_end_(other.simplices_around_current_vertex_end_)
361  {
362  }
363 
364  friend Simplex_iterator make_begin_iterator(const Complex* complex){
365  if(complex->empty())
366  return make_end_simplex_iterator(complex);
367  else
368  return Simplex_iterator(complex);
369  }
370 
371  friend Simplex_iterator make_end_simplex_iterator(const Complex* complex){
372  return Simplex_iterator(complex,true);
373  }
374 
375  bool equal(const Simplex_iterator& other) const{
376  if(complex_!=other.complex_) return false;
377  if(current_vertex_!=other.current_vertex_) return false;
378  if(is_end() && other.is_end()) return true;
379  if(current_simplex_around_current_vertex_ != other.current_simplex_around_current_vertex_)
380  return false;
381  return true;
382  }
383 
384  void increment(){
385  if(current_simplex_around_current_vertex_!= simplices_around_current_vertex_end_){
386  current_simplex_around_current_vertex_.increment();
387  if( current_simplex_around_current_vertex_== simplices_around_current_vertex_end_)
388  goto_next_vertex();
389  }
390  else{
391  goto_next_vertex();
392  }
393  }
394 
395  void goto_next_vertex(){
396  current_vertex_.increment();
397  if(!is_end()){
398  current_simplex_around_current_vertex_= SAVI(complex_,*current_vertex_);
399  simplices_around_current_vertex_end_ = SAVI(complex_,*current_vertex_,true);
400  }
401  }
402 
403  Simplex_handle dereference() const{
404  return current_simplex_around_current_vertex_.dereference();
405  }
406 
407 private:
408  void set_end(){
409  current_vertex_ = complex_->vertex_range().end();
410  }
411 
412  bool is_end() const{
413  return (current_vertex_ == complex_->vertex_range().end());
414  }
415 };
416 
417 
418 }
419 
420 } // namespace GUDHI
421 
422 
423 
424 
425 
426 #endif /* SKELETON_BLOCKERS_SIMPLICES_ITERATORS_H_ */
Simplex_around_vertex_iterator(const Complex *complex_, Vertex_handle v_, bool end)
Definition: Skeleton_blockers_simplices_iterators.h:192
Definition: Skeleton_blockers_simplices_iterators.h:53