2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 * @file ArrayImageIterator.ih
19 * @author Roland Denis (\c roland.denis@univ-smb.fr )
20 * LAboratory of MAthematics - LAMA (CNRS, UMR 5127), University of Savoie, France
24 * This file is part of the DGtal library.
28 //////////////////////////////////////////////////////////////////////////////
29 #include <DGtal/base/Assert.h>
30 //////////////////////////////////////////////////////////////////////////////
32 ///////////////////////////////////////////////////////////////////////////////
33 // IMPLEMENTATION of inline methods.
34 ///////////////////////////////////////////////////////////////////////////////
36 ///////////////////////////////////////////////////////////////////////////////
37 // ----------------------- Standard services ------------------------------
40 //------------------------------------------------------------------------------
41 /// Default constructor.
42 template <typename TIterableClass>
43 DGtal::ArrayImageIterator<TIterableClass>::
45 : myIterableClassPtr(nullptr)
48 //------------------------------------------------------------------------------
49 /// Iterator from a point.
50 template <typename TIterableClass>
51 DGtal::ArrayImageIterator<TIterableClass>::
52 ArrayImageIterator( IterableClass* anIterableClassPtr, Domain const& aFullDomain, Domain const& aViewDomain, Point const& aPoint )
53 : myIterableClassPtr( anIterableClassPtr )
54 , myFullDomain{ aFullDomain }
55 , myViewDomain{ aViewDomain }
56 , myFullExtent( myFullDomain.upperBound() - myFullDomain.lowerBound() + Point::diagonal(1) )
57 , myViewExtent( myViewDomain.upperBound() - myViewDomain.lowerBound() + Point::diagonal(1) )
59 , myFullIndex( Self::Linearizer::getIndex( myPoint - myFullDomain.lowerBound(), myFullExtent ) )
62 myFullDomain.lowerBound().isLower( myViewDomain.lowerBound() )
63 && myFullDomain.upperBound().isUpper( myViewDomain.upperBound() ),
64 "The viewable domain must be included into the full domain."
67 myViewDomain.isInside(aPoint),
68 "The point is outside the viewable domain !"
72 //------------------------------------------------------------------------------
73 /// Iterator pointing to the first value.
74 template <typename TIterableClass>
75 DGtal::ArrayImageIterator<TIterableClass>::
76 ArrayImageIterator( IterableClass* anIterableClassPtr, Domain const& aFullDomain, Domain const& aViewDomain )
77 : ArrayImageIterator{ anIterableClassPtr, aFullDomain, aViewDomain, aViewDomain.lowerBound() }
80 //------------------------------------------------------------------------------
81 /// Iterator pointing to the first value and spanning the whole domain.
82 template <typename TIterableClass>
83 DGtal::ArrayImageIterator<TIterableClass>::
84 ArrayImageIterator( IterableClass* anIterableClassPtr, Domain const& aFullDomain )
85 : ArrayImageIterator{ anIterableClassPtr, aFullDomain, aFullDomain }
88 //------------------------------------------------------------------------------
89 /// Iterator pointing after the last value of the viewable domain.
90 template <typename TIterableClass>
91 DGtal::ArrayImageIterator<TIterableClass>::
92 ArrayImageIterator( IterableClass* anIterableClassPtr, Domain const& aFullDomain, Domain const& aViewDomain, bool /* last */ )
93 : ArrayImageIterator{ anIterableClassPtr, aFullDomain, aViewDomain, aViewDomain.upperBound() }
98 //------------------------------------------------------------------------------
99 /// Iterator pointing after the last value of the whole domain.
100 template <typename TIterableClass>
101 DGtal::ArrayImageIterator<TIterableClass>::
102 ArrayImageIterator( IterableClass* anIterableClassPtr, Domain const& aFullDomain, bool /* last */ )
103 : ArrayImageIterator{ anIterableClassPtr, aFullDomain, aFullDomain, true }
106 //------------------------------------------------------------------------------
107 /// Copy constructor with type interoperability.
108 template <typename TIterableClass>
109 template <typename TOtherIterableClass>
110 DGtal::ArrayImageIterator<TIterableClass>::
112 ArrayImageIterator<TOtherIterableClass> const& other,
113 typename std::enable_if< std::is_convertible<TOtherIterableClass*, IterableClass*>::value >::type*
115 : myIterableClassPtr( other.myIterableClassPtr )
116 , myFullDomain{ other.myFullDomain }
117 , myViewDomain{ other.myViewDomain }
118 , myFullExtent{ other.myFullExtent }
119 , myViewExtent{ other.myViewExtent }
120 , myPoint{ other.myPoint }
121 , myFullIndex{ other.myFullIndex }
124 //------------------------------------------------------------------------------
125 /// Move constructor with type interoperability.
126 template <typename TIterableClass>
127 template <typename TOtherIterableClass>
128 DGtal::ArrayImageIterator<TIterableClass>::
130 ArrayImageIterator<TOtherIterableClass> && other,
131 typename std::enable_if< std::is_convertible<TOtherIterableClass*, IterableClass*>::value >::type*
133 : myIterableClassPtr( std::move(other.myIterableClassPtr) )
134 , myFullDomain{ std::move(other.myFullDomain) }
135 , myViewDomain{ std::move(other.myViewDomain) }
136 , myFullExtent{ std::move(other.myFullExtent) }
137 , myViewExtent{ std::move(other.myViewExtent) }
138 , myPoint{ std::move(other.myPoint) }
139 , myFullIndex{ std::move(other.myFullIndex) }
142 //------------------------------------------------------------------------------
144 template <typename TIterableClass>
145 DGtal::ArrayImageIterator<TIterableClass>::
146 ~ArrayImageIterator()
149 //------------------------------------------------------------------------------
150 /// Copy assignment with type interoperability.
151 template <typename TIterableClass>
152 template <typename TOtherIterableClass>
153 typename std::enable_if<
154 std::is_convertible<TOtherIterableClass*, TIterableClass*>::value,
155 typename DGtal::ArrayImageIterator<TIterableClass>::Self&>::type
156 DGtal::ArrayImageIterator<TIterableClass>::
157 operator= ( ArrayImageIterator<TOtherIterableClass> const& other )
159 myIterableClassPtr = other.myIterableClassPtr;
160 myFullDomain = other.myFullDomain;
161 myViewDomain = other.myViewDomain;
162 myFullExtent = other.myFullExtent;
163 myViewExtent = other.myViewExtent;
164 myPoint = other.myPoint;
165 myFullIndex = other.myFullIndex;
169 //------------------------------------------------------------------------------
170 /// Move assignment constructor with type interoperability.
171 template <typename TIterableClass>
172 template <typename TOtherIterableClass>
173 typename std::enable_if<
174 std::is_convertible<TOtherIterableClass*, TIterableClass*>::value,
175 typename DGtal::ArrayImageIterator<TIterableClass>::Self&>::type
176 DGtal::ArrayImageIterator<TIterableClass>::
177 operator= ( ArrayImageIterator<TOtherIterableClass> && other )
179 myIterableClassPtr = std::move(other.myIterableClassPtr);
180 myFullDomain = std::move(other.myFullDomain);
181 myViewDomain = std::move(other.myViewDomain);
182 myFullExtent = std::move(other.myFullExtent);
183 myViewExtent = std::move(other.myViewExtent);
184 myPoint = std::move(other.myPoint);
185 myFullIndex = std::move(other.myFullIndex);
189 ///////////////////////////////////////////////////////////////////////////////
190 // Interface - public :
192 //------------------------------------------------------------------------------
193 /// Return the point behind this iterator.
194 template <typename TIterableClass>
196 typename DGtal::ArrayImageIterator<TIterableClass>::Point const&
197 DGtal::ArrayImageIterator<TIterableClass>::
198 getPoint() const noexcept
203 //------------------------------------------------------------------------------
204 /// Return the distance from this iterator to a given point.
205 template <typename TIterableClass>
208 DGtal::ArrayImageIterator<TIterableClass>::
209 distance_to( Point const& aPoint ) const noexcept
212 myViewDomain.isInside(aPoint),
213 "The point is outside the viewable domain !"
216 static_cast<std::ptrdiff_t>( Linearizer::getIndex(aPoint, myViewDomain.lowerBound(), myViewExtent) )
217 - static_cast<std::ptrdiff_t>( Linearizer::getIndex(myPoint, myViewDomain.lowerBound(), myViewExtent) );
220 //------------------------------------------------------------------------------
221 /// Writes/Displays the object on an output stream.
222 template <typename TIterableClass>
225 DGtal::ArrayImageIterator<TIterableClass>::
226 selfDisplay ( std::ostream & out ) const
228 out << "[ArrayImageIterator] pointing to " << getPoint();
231 //------------------------------------------------------------------------------
232 ///Checks the validity/consistency of the object.
233 template <typename TIterableClass>
236 DGtal::ArrayImageIterator<TIterableClass>::isValid() const
238 return myIterableClassPtr != nullptr;
242 ///////////////////////////////////////////////////////////////////////////////
245 //------------------------------------------------------------------------------
246 /// Increment of one step.
247 template <typename TIterableClass>
249 DGtal::ArrayImageIterator<TIterableClass>::
254 for ( auto i = 1; i < (int)Domain::dimension && myPoint[i-1] > myViewDomain.upperBound()[i-1]; ++i )
256 myPoint[i-1] = myViewDomain.lowerBound()[i-1];
258 std::size_t cum = myFullExtent[i-1] - myViewExtent[i-1];
259 for ( auto j = 0; j < i-1; ++j )
260 cum *= myFullExtent[j];
266 //------------------------------------------------------------------------------
267 /// Decrement of one step.
268 template <typename TIterableClass>
270 DGtal::ArrayImageIterator<TIterableClass>::
275 for ( Dimension i = 1; i < Domain::dimension && myPoint[i-1] < myViewDomain.lowerBound()[i-1]; ++i )
277 myPoint[i-1] = myViewDomain.upperBound()[i-1];
279 std::size_t accum = myFullExtent[i-1] - myViewExtent[i-1];
280 for ( int j = 0; j < (int)i-1; ++j )
281 accum *= myFullExtent[j];
283 myFullIndex -= accum;
287 //------------------------------------------------------------------------------
289 template <typename TIterableClass>
292 DGtal::ArrayImageIterator<TIterableClass>::
293 equal( Self const& other ) const
295 return myFullIndex == other.myFullIndex;
298 //------------------------------------------------------------------------------
300 template <typename TIterableClass>
302 typename DGtal::ArrayImageIterator<TIterableClass>::Reference
303 DGtal::ArrayImageIterator<TIterableClass>::
306 return myIterableClassPtr->dereference( myPoint, myFullIndex );
309 //------------------------------------------------------------------------------
310 /// Distance to other iterator.
311 template <typename TIterableClass>
314 DGtal::ArrayImageIterator<TIterableClass>::
315 distance_to( Self const& other ) const
317 return distance_to( other.myPoint );
320 //------------------------------------------------------------------------------
321 /// Advance by n steps.
322 template <typename TIterableClass>
324 DGtal::ArrayImageIterator<TIterableClass>::
325 advance( std::ptrdiff_t n )
327 const auto pos = Self::Linearizer::getIndex( myPoint, myViewDomain.lowerBound(), myViewExtent );
328 myPoint = Self::Linearizer::getPoint( pos + n, myViewDomain.lowerBound(), myViewExtent );
329 myFullIndex = Self::Linearizer::getIndex( myPoint, myFullDomain.lowerBound(), myFullExtent );
333 ///////////////////////////////////////////////////////////////////////////////
334 // Implementation of inline functions //
336 template <typename T>
339 DGtal::operator<< ( std::ostream & out,
340 const ArrayImageIterator<T> & object )
342 object.selfDisplay( out );
347 ///////////////////////////////////////////////////////////////////////////////