Skeleton_blockers_triangles_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_TRIANGLES_ITERATORS_H_
12 #define SKELETON_BLOCKER_ITERATORS_SKELETON_BLOCKERS_TRIANGLES_ITERATORS_H_
13 
14 #include <boost/iterator/iterator_facade.hpp>
15 #include <memory>
16 
17 namespace Gudhi {
18 
19 namespace skeleton_blocker {
20 
26 template<typename Complex, typename LinkType>
27 class Triangle_around_vertex_iterator : public boost::iterator_facade
28 < Triangle_around_vertex_iterator <Complex, LinkType>
29 , typename Complex::Simplex const
30 , boost::forward_traversal_tag
31 , typename Complex::Simplex const> {
32  friend class boost::iterator_core_access;
33  template<typename T> friend class Triangle_iterator;
34  private:
35  typedef typename LinkType::Vertex_handle Vertex_handle;
36  typedef typename LinkType::Root_vertex_handle Root_vertex_handle;
37  typedef typename LinkType::Simplex Simplex;
39 
40  const Complex* complex_;
41  Vertex_handle v_;
42  std::shared_ptr<LinkType> link_;
43  Complex_edge_iterator_ current_edge_;
44  bool is_end_;
45 
46  public:
47  Triangle_around_vertex_iterator(const Complex* complex, Vertex_handle v) :
48  complex_(complex), v_(v), link_(new LinkType(*complex, v_)),
49  current_edge_(link_->edge_range().begin()),
50  is_end_(current_edge_ == link_->edge_range().end()) { }
51 
55  Triangle_around_vertex_iterator(const Complex* complex, Vertex_handle v, bool is_end) :
56  complex_(complex), v_(v), link_(0), is_end_(true) { }
57 
62  complex_(0), v_(-1), link_(0), is_end_(true) { }
63 
65  v_ = other.v_;
66  complex_ = other.complex_;
67  is_end_ = other.is_end_;
68 
69  if (!is_end_) {
70  link_ = other.link_;
71  current_edge_ = other.current_edge_;
72  }
73  }
74 
75  bool equal(const Triangle_around_vertex_iterator& other) const {
76  return (complex_ == other.complex_) && ((finished() && other.finished()) || current_edge_ == other.current_edge_);
77  }
78 
79  Simplex dereference() const {
80  Root_vertex_handle v1 = (*link_)[*current_edge_].first();
81  Root_vertex_handle v2 = (*link_)[*current_edge_].second();
82  return Simplex(v_, *(complex_->get_address(v1)), *(complex_->get_address(v2)));
83  }
84 
85  void increment() {
86  ++current_edge_;
87  }
88 
89  private:
90  bool finished() const {
91  return is_end_ || (current_edge_ == link_->edge_range().end());
92  }
93 };
94 
101 template<typename SkeletonBlockerComplex>
102 class Triangle_iterator : public boost::iterator_facade<
103 Triangle_iterator <SkeletonBlockerComplex>,
104 typename SkeletonBlockerComplex::Simplex const
105 , boost::forward_traversal_tag
106 , typename SkeletonBlockerComplex::Simplex const> {
107  friend class boost::iterator_core_access;
108  private:
109  typedef typename SkeletonBlockerComplex::Vertex_handle Vertex_handle;
110  typedef typename SkeletonBlockerComplex::Root_vertex_handle Root_vertex_handle;
111  typedef typename SkeletonBlockerComplex::Simplex Simplex;
112  typedef typename SkeletonBlockerComplex::Superior_triangle_around_vertex_iterator STAVI;
113  typedef typename SkeletonBlockerComplex::Complex_vertex_iterator Complex_vertex_iterator;
114 
115  const SkeletonBlockerComplex* complex_;
116  Complex_vertex_iterator current_vertex_;
117  STAVI current_triangle_;
118  bool is_end_;
119 
120  public:
121  /*
122  * @remark assume that the complex is non-empty
123  */
124  Triangle_iterator(const SkeletonBlockerComplex* complex) :
125  complex_(complex),
126  current_vertex_(complex->vertex_range().begin()),
127  current_triangle_(complex, *current_vertex_), // this line is problematic is the complex is empty
128  is_end_(false) {
129  assert(!complex->empty());
130  gotoFirstTriangle();
131  }
132 
133  private:
134  // goto to the first triangle or to the end if none
135  void gotoFirstTriangle() {
136  if (!is_finished() && current_triangle_.finished()) {
137  goto_next_vertex();
138  }
139  }
140 
141  public:
146  Triangle_iterator(const SkeletonBlockerComplex* complex, bool is_end) :
147  complex_(complex),
148  current_vertex_(complex->vertex_range().end()),
149  current_triangle_(), // xxx this line is problematic is the complex is empty
150  is_end_(true) { }
151 
152  Triangle_iterator& operator=(const Triangle_iterator & other) {
153  complex_ = other.complex_;
154  Complex_vertex_iterator current_vertex_;
155  STAVI current_triangle_;
156  return *this;
157  }
158 
159  bool equal(const Triangle_iterator& other) const {
160  bool both_are_finished = is_finished() && other.is_finished();
161  bool both_arent_finished = !is_finished() && !other.is_finished();
162  // if the two iterators are not finished, they must have the same state
163  return (complex_ == other.complex_) && (both_are_finished || ((both_arent_finished) &&
164  current_vertex_ == other.current_vertex_ &&
165  current_triangle_ == other.current_triangle_));
166  }
167 
168  Simplex dereference() const {
169  return *current_triangle_;
170  }
171 
172  private:
173  // goto the next vertex that has a triangle pending or the
174  // end vertex iterator if none exists
175  void goto_next_vertex() {
176  // we must have consume all triangles passing through the vertex
177  assert(current_triangle_.finished());
178  // we must not be done
179  assert(!is_finished());
180 
181  ++current_vertex_;
182 
183  if (!is_finished()) {
184  current_triangle_ = STAVI(complex_, *current_vertex_);
185  if (current_triangle_.finished())
186  goto_next_vertex();
187  }
188  }
189 
190  public:
191  void increment() {
192  if (!current_triangle_.finished()) {
193  ++current_triangle_; // problem here
194  if (current_triangle_.finished())
195  goto_next_vertex();
196  } else {
197  assert(!is_finished());
198  goto_next_vertex();
199  }
200  }
201 
202  private:
203  bool is_finished() const {
204  return is_end_ || current_vertex_ == complex_->vertex_range().end();
205  }
206 };
207 
208 } // namespace skeleton_blocker
209 
210 namespace skbl = skeleton_blocker;
211 
212 } // namespace Gudhi
213 
214 #endif // SKELETON_BLOCKER_ITERATORS_SKELETON_BLOCKERS_TRIANGLES_ITERATORS_H_
Iterator on the edges of a simplicial complex.
Definition: Skeleton_blockers_edges_iterators.h:88
virtual boost::optional< Vertex_handle > get_address(Root_vertex_handle id) const
Given an Id return the address of the vertex having this Id in the complex.
Definition: Skeleton_blocker_complex.h:432
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 over the triangles that are adjacent to a vertex of the simplicial complex.
Definition: Skeleton_blockers_triangles_iterators.h:31
Triangle_around_vertex_iterator(const Complex *complex, Vertex_handle v, bool is_end)
ugly hack to get an iterator to the end
Definition: Skeleton_blockers_triangles_iterators.h:55
Triangle_around_vertex_iterator()
ugly hack to get an iterator to the end
Definition: Skeleton_blockers_triangles_iterators.h:61
Iterator over the triangles of the simplicial complex.
Definition: Skeleton_blockers_triangles_iterators.h:106
Triangle_iterator(const SkeletonBlockerComplex *complex, bool is_end)
ugly hack to get an iterator to the end
Definition: Skeleton_blockers_triangles_iterators.h:146
Gudhi namespace.
Definition: SimplicialComplexForAlpha.h:14
Root_vertex_handle and Vertex_handle are similar to global and local vertex descriptor used in boost ...
Definition: SkeletonBlockerDS.h:47