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.
42template <typename TIterableClass>
43DGtal::ArrayImageIterator<TIterableClass>::
45 : myIterableClassPtr(nullptr)
48//------------------------------------------------------------------------------
49/// Iterator from a point.
50template <typename TIterableClass>
51DGtal::ArrayImageIterator<TIterableClass>::
52ArrayImageIterator( 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.
74template <typename TIterableClass>
75DGtal::ArrayImageIterator<TIterableClass>::
76ArrayImageIterator( 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.
82template <typename TIterableClass>
83DGtal::ArrayImageIterator<TIterableClass>::
84ArrayImageIterator( IterableClass* anIterableClassPtr, Domain const& aFullDomain )
85 : ArrayImageIterator{ anIterableClassPtr, aFullDomain, aFullDomain }
88//------------------------------------------------------------------------------
89/// Iterator pointing after the last value of the viewable domain.
90template <typename TIterableClass>
91DGtal::ArrayImageIterator<TIterableClass>::
92ArrayImageIterator( 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.
100template <typename TIterableClass>
101DGtal::ArrayImageIterator<TIterableClass>::
102ArrayImageIterator( IterableClass* anIterableClassPtr, Domain const& aFullDomain, bool /* last */ )
103 : ArrayImageIterator{ anIterableClassPtr, aFullDomain, aFullDomain, true }
106//------------------------------------------------------------------------------
107/// Copy constructor with type interoperability.
108template <typename TIterableClass>
109template <typename TOtherIterableClass>
110DGtal::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.
126template <typename TIterableClass>
127template <typename TOtherIterableClass>
128DGtal::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//------------------------------------------------------------------------------
144template <typename TIterableClass>
145DGtal::ArrayImageIterator<TIterableClass>::
149//------------------------------------------------------------------------------
150/// Copy assignment with type interoperability.
151template <typename TIterableClass>
152template <typename TOtherIterableClass>
153typename std::enable_if<
154 std::is_convertible<TOtherIterableClass*, TIterableClass*>::value,
155 typename DGtal::ArrayImageIterator<TIterableClass>::Self&>::type
156DGtal::ArrayImageIterator<TIterableClass>::
157operator= ( 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.
171template <typename TIterableClass>
172template <typename TOtherIterableClass>
173typename std::enable_if<
174 std::is_convertible<TOtherIterableClass*, TIterableClass*>::value,
175 typename DGtal::ArrayImageIterator<TIterableClass>::Self&>::type
176DGtal::ArrayImageIterator<TIterableClass>::
177operator= ( 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.
194template <typename TIterableClass>
196typename DGtal::ArrayImageIterator<TIterableClass>::Point const&
197DGtal::ArrayImageIterator<TIterableClass>::
198 getPoint() const noexcept
203//------------------------------------------------------------------------------
204/// Return the distance from this iterator to a given point.
205template <typename TIterableClass>
208DGtal::ArrayImageIterator<TIterableClass>::
209distance_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.
222template <typename TIterableClass>
225DGtal::ArrayImageIterator<TIterableClass>::
226 selfDisplay ( std::ostream & out ) const
228 out << "[ArrayImageIterator] pointing to " << getPoint();
231//------------------------------------------------------------------------------
232///Checks the validity/consistency of the object.
233template <typename TIterableClass>
236DGtal::ArrayImageIterator<TIterableClass>::isValid() const
238 return myIterableClassPtr != nullptr;
242///////////////////////////////////////////////////////////////////////////////
245//------------------------------------------------------------------------------
246/// Increment of one step.
247template <typename TIterableClass>
249DGtal::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.
268template <typename TIterableClass>
270DGtal::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//------------------------------------------------------------------------------
289template <typename TIterableClass>
292DGtal::ArrayImageIterator<TIterableClass>::
293equal( Self const& other ) const
295 return myFullIndex == other.myFullIndex;
298//------------------------------------------------------------------------------
300template <typename TIterableClass>
302typename DGtal::ArrayImageIterator<TIterableClass>::Reference
303DGtal::ArrayImageIterator<TIterableClass>::
306 return myIterableClassPtr->dereference( myPoint, myFullIndex );
309//------------------------------------------------------------------------------
310/// Distance to other iterator.
311template <typename TIterableClass>
314DGtal::ArrayImageIterator<TIterableClass>::
315distance_to( Self const& other ) const
317 return distance_to( other.myPoint );
320//------------------------------------------------------------------------------
321/// Advance by n steps.
322template <typename TIterableClass>
324DGtal::ArrayImageIterator<TIterableClass>::
325advance( 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 //
339DGtal::operator<< ( std::ostream & out,
340 const ArrayImageIterator<T> & object )
342 object.selfDisplay( out );
347///////////////////////////////////////////////////////////////////////////////