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/>.
19 * @author Jacques-Olivier Lachaud (\c jacques-olivier.lachaud@univ-savoie.fr )
20 * Laboratory of Mathematics (CNRS, UMR 5807), University of Savoie, France
24 * Implementation of inline methods defined in Expander.h
26 * This file is part of the DGtal library.
30 //////////////////////////////////////////////////////////////////////////////
32 //////////////////////////////////////////////////////////////////////////////
34 ///////////////////////////////////////////////////////////////////////////////
35 // IMPLEMENTATION of inline methods.
36 ///////////////////////////////////////////////////////////////////////////////
38 ///////////////////////////////////////////////////////////////////////////////
39 // ----------------------- Standard services ------------------------------
44 template <typename TObject>
46 DGtal::Expander<TObject>::~Expander()
51 * Constructor from a point. This point provides the initial core
54 * @param object the digital object in which the expander expands.
55 * @param p any point in the given object.
57 template <typename TObject>
59 DGtal::Expander<TObject>
60 ::Expander( ConstAlias<Object> object, const Point & p )
61 : myEmbeddingDomain( (&object)->pointSet().domain() ),
63 myObjectDomain( myObject.pointSet() ),
64 myObjectAdjacency( myObjectDomain, myObject.adjacency() ),
65 myCore( myEmbeddingDomain ),
66 myLayer( myEmbeddingDomain ),
67 myDistance( 0 ), myFinished( false ),
68 myNotInCorePred( myCore )
70 ASSERT( myObjectDomain.isInside( p ) );
71 myCore.insertNew( p );
72 computeNextLayer( myCore );
76 * Constructor from iterators. All points visited between the
77 * iterators should be distinct two by two. The so specified set
78 * of points provides the initial core of the expander.
80 * @tparam PointInputIterator the type of an InputIterator pointing on a Point.
82 * @param object the digital object in which the expander expands.
83 * @param b the begin point in a set.
84 * @param e the end point in a set.
86 template <typename TObject>
87 template <typename PointInputIterator>
89 DGtal::Expander<TObject>
90 ::Expander( ConstAlias<Object> object,
91 PointInputIterator b, PointInputIterator e )
92 : myEmbeddingDomain( (&object)->pointSet().domain() ),
94 myObjectDomain( myObject.pointSet() ),
95 myObjectAdjacency( myObjectDomain, myObject.adjacency() ),
96 myCore( myEmbeddingDomain ),
97 myLayer( myEmbeddingDomain ),
98 myDistance( 0 ), myFinished( false ),
99 myNotInCorePred( myCore )
101 myCore.insertNew( b, e );
102 computeNextLayer( myCore );
107 * @return 'true' if all possible elements have been visited.
109 template <typename TObject>
112 DGtal::Expander<TObject>::finished() const
118 * @return the current distance to the initial core, or
119 * equivalently the index of the current layer.
121 template <typename TObject>
123 typename DGtal::Expander<TObject>::Size
124 DGtal::Expander<TObject>::distance() const
131 * Extract next layer. You might used begin() and end() to access
132 * all the elements of the new layer.
134 * @return 'true' if there was another layer, or 'false' if it was the
135 * last (ie. reverse of finished() ).
137 template <typename TObject>
140 DGtal::Expander<TObject>
144 computeNextLayer( myLayer );
149 * Push the layer into the current core. Must be called before
152 template <typename TObject>
155 DGtal::Expander<TObject>
158 myCore.insertNew( myLayer.begin(), myLayer.end() );
162 * Computes the next layer just around [src]. The member 'm_core' must
163 * be up to date (i.e, [src] is a subset of 'm_core'). 'm_layer' is
164 * cleared in this method. At first call, [src] should be 'm_core',
165 * then [src] should be 'm_layer'.
167 * @param src the set around which the new layer is computed.
169 template <typename TObject>
172 DGtal::Expander<TObject>
173 ::computeNextLayer( const DigitalSet & src )
175 if ( finished() ) return;
177 ConstIterator p = src.begin();
178 ConstIterator pEnd = src.end();
179 typedef std::set<Point> SetContainer;
180 typedef std::insert_iterator< SetContainer > Inserter;
181 SetContainer newLayer;
182 Inserter inserter( newLayer, newLayer.begin() );
184 // const ObjectDomainPredicate & objectPred = myObjectDomain.predicate();
185 typedef typename ObjectDomain::Predicate ObjectDomainPredicate;
186 typedef functors::BinaryPointPredicate< ObjectDomainPredicate,
187 NotInCoreDomainPredicate > Predicate;
189 Predicate cPred( myObjectDomain.predicate(),
192 // Computes the 1-neighborhood of the core.
193 for ( ; p != pEnd; ++p )
195 myObjectAdjacency.writeNeighbors
196 ( inserter, *p, cPred );
198 // for ( unsigned int i = 0; i < v.size(); ++i )
200 // std::cerr << " " << v[ i ];
201 // newLayer.insert( v[ i ] );
203 // std::cerr << std::endl;
206 // std::cerr << "Core.size=" << myCore.size()
207 // << " prevLayer.size=" << src.size()
208 // << " nextLayer.size=" << newLayer.size()
211 if ( newLayer.empty() )
217 myLayer.insertNew( newLayer.begin(), newLayer.end() );
223 * @return the iterator on the first element of the layer.
225 template <typename TObject>
227 const typename DGtal::Expander<TObject>::DigitalSet &
228 DGtal::Expander<TObject>
235 * @return a const reference on the (current) layer set of points.
237 template <typename TObject>
239 const typename DGtal::Expander<TObject>::DigitalSet &
240 DGtal::Expander<TObject>
247 * @return the iterator on the first element of the layer.
249 template <typename TObject>
251 typename DGtal::Expander<TObject>::ConstIterator
252 DGtal::Expander<TObject>
255 return myLayer.begin();
259 * @return the iterator after the last element of the layer.
261 template <typename TObject>
263 typename DGtal::Expander<TObject>::ConstIterator
264 DGtal::Expander<TObject>
267 return myLayer.end();
271 ///////////////////////////////////////////////////////////////////////////////
272 // Interface - public :
275 * Writes/Displays the object on an output stream.
276 * @param out the output stream where the object is written.
278 template <typename TObject>
281 DGtal::Expander<TObject>::selfDisplay ( std::ostream & out ) const
283 out << "[Expander layer=" << myDistance
284 << " layer.size=" << myLayer.size()
285 << " finished=" << myFinished
290 * Checks the validity/consistency of the object.
291 * @return 'true' if the object is valid, 'false' otherwise.
293 template <typename TObject>
296 DGtal::Expander<TObject>::isValid() const
303 ///////////////////////////////////////////////////////////////////////////////
304 // Implementation of inline functions //
306 template <typename TObject>
309 DGtal::operator<< ( std::ostream & out,
310 const Expander<TObject> & object )
312 object.selfDisplay( out );
317 ///////////////////////////////////////////////////////////////////////////////