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 Tristan Roussillon (\c
20 * tristan.roussillon@liris.cnrs.fr ) Laboratoire d'InfoRmatique en
21 * Image et Systèmes d'information - LIRIS (CNRS, UMR 5205), CNRS,
27 * @brief Implementation of inline methods defined in FMM.h
29 * This file is part of the DGtal library.
33 //////////////////////////////////////////////////////////////////////////////
35 //////////////////////////////////////////////////////////////////////////////
37 #include "DGtal/topology/SCellsFunctors.h"
39 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
40 const typename DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>::Dimension DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>::dimension = Point::dimension;
43 ///////////////////////////////////////////////////////////////////////////////
44 // IMPLEMENTATION of inline methods.
45 ///////////////////////////////////////////////////////////////////////////////
47 ///////////////////////////////////////////////////////////////////////////////
48 // ----------------------- Standard services ------------------------------
50 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
52 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>
53 ::FMM(Image& aImg, AcceptedPointSet& aSet,
54 ConstAlias<PointPredicate> aPointPredicate)
55 : myImage( aImg ), myAcceptedPoints( aSet ),
56 myPointFunctorPtr( new PointFunctor(aImg, aSet) ),
57 myFlagIsOwning( true ),
58 myPointPredicate( aPointPredicate ),
59 myAreaThreshold( std::numeric_limits<Area>::max() ),
60 myValueThreshold( std::numeric_limits<Value>::max() )
62 if (myAcceptedPoints.size() == 0) throw InputException();
67 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
69 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>
70 ::FMM(Image& aImg, AcceptedPointSet& aSet,
71 ConstAlias<PointPredicate> aPointPredicate,
72 const Area& aAreaThreshold,
73 const Value& aValueThreshold)
74 : myImage( aImg ), myAcceptedPoints( aSet ),
75 myPointFunctorPtr( new PointFunctor(aImg, aSet) ),
76 myFlagIsOwning( true ),
77 myPointPredicate( aPointPredicate ),
78 myAreaThreshold( aAreaThreshold ),
79 myValueThreshold( aValueThreshold )
81 if (myAcceptedPoints.size() == 0) throw InputException();
86 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
88 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>
89 ::FMM(Image& aImg, AcceptedPointSet& aSet,
90 ConstAlias<PointPredicate> aPointPredicate,
91 PointFunctor& aPointFunctor)
92 : myImage( aImg ), myAcceptedPoints( aSet ),
93 myPointFunctorPtr( &aPointFunctor ),
94 myFlagIsOwning( false ),
95 myPointPredicate( aPointPredicate ),
96 myAreaThreshold( std::numeric_limits<Area>::max() ),
97 myValueThreshold( std::numeric_limits<Value>::max() )
99 if (myAcceptedPoints.size() == 0) throw InputException();
104 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
106 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>
107 ::FMM(Image& aImg, AcceptedPointSet& aSet,
108 ConstAlias<PointPredicate> aPointPredicate,
109 const Area& aAreaThreshold,
110 const Value& aValueThreshold,
111 PointFunctor& aPointFunctor)
112 : myImage( aImg ), myAcceptedPoints( aSet ),
113 myPointFunctorPtr( &aPointFunctor ),
114 myFlagIsOwning( false ),
115 myPointPredicate( aPointPredicate ),
116 myAreaThreshold( aAreaThreshold ),
117 myValueThreshold( aValueThreshold )
119 if (myAcceptedPoints.size() == 0) throw InputException();
124 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
126 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>::~FMM()
129 delete myPointFunctorPtr;
132 ///////////////////////////////////////////////////////////////////////////////
133 // Static functions :
136 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
137 template <typename TIteratorOnPoints>
139 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>
140 ::initFromPointsRange(const TIteratorOnPoints& itb, const TIteratorOnPoints& ite,
141 Image& aImg, AcceptedPointSet& aSet,
146 for (TIteratorOnPoints it = itb; it != ite; ++it)
148 insertAndAlwaysSetValue( aImg, aSet, *it, aValue );
152 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
153 template <typename KSpace, typename TIteratorOnBels>
155 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>
156 ::initFromBelsRange(const KSpace& aK,
157 const TIteratorOnBels& itb, const TIteratorOnBels& ite,
158 Image& aImg, AcceptedPointSet& aSet,
160 bool aFlagIsPositive)
163 if (aFlagIsPositive) k = 1;
166 for (TIteratorOnBels it = itb; it != ite; ++it)
168 //getting incident points
169 functors::SCellToIncidentPoints<KSpace> func( aK );
170 typename functors::SCellToIncidentPoints<KSpace>::Output points = func( *it );
172 insertAndAlwaysSetValue( aImg, aSet, points.first, -k*aValue );
173 insertAndAlwaysSetValue( aImg, aSet, points.second, k*aValue );
177 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
178 template <typename KSpace, typename TIteratorOnBels, typename TImplicitFunction>
180 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>
181 ::initFromBelsRange(const KSpace& aK,
182 const TIteratorOnBels& itb, const TIteratorOnBels& ite,
183 const TImplicitFunction& aF,
184 Image& aImg, AcceptedPointSet& aSet,
185 bool aFlagIsPositive)
188 if (aFlagIsPositive) k = 1;
191 typedef typename KSpace::Cell Bel;
192 typedef std::pair<const Bel, Value> BelValue;
193 typedef std::map<Bel, Value> Buffer;
195 typedef typename functors::SCellToIncidentPoints<KSpace>::Output Pair;
196 typedef std::vector<Pair> IncidentPoints;
197 functors::SCellToIncidentPoints<KSpace> getIncidentPoints( aK );
199 /// 1) store a value for each bel
200 /// (== distance of the inner point to the interface)
201 IncidentPoints incidentPoints;
203 for (TIteratorOnBels it = itb; it != ite; ++it)
205 //getting incident points
206 Pair points = getIncidentPoints( *it );
207 incidentPoints.push_back( points );
210 Value vin = aF( points.first );
211 Value vout = aF( points.second );
213 //computing/storing the new value
214 Value e = std::max(vin, vout) - std::min(vin, vout);
215 Value v = (std::abs(vin)/e);
217 buffer.insert( BelValue( aK.unsigns( *it ), v ) );
221 /// 2) for each inner/outer point
222 /// computes its distance from the values of its incident bels
223 typedef L2FirstOrderLocalDistanceFromCells<KSpace, Buffer, false> Computer4InnerPts;
224 typedef L2FirstOrderLocalDistanceFromCells<KSpace, Buffer, true> Computer4OuterPts;
225 Computer4InnerPts computerIn(aK, buffer);
226 Computer4OuterPts computerOut(aK, buffer);
227 for (typename IncidentPoints::const_iterator it = incidentPoints.begin();
228 it != incidentPoints.end(); ++it)
230 //computing the values
231 Value vin = computerIn( it->first );
232 Value vout = computerOut( it->second );
235 insertAndAlwaysSetValue( aImg, aSet, it->first, -k*vin );
236 insertAndAlwaysSetValue( aImg, aSet, it->second, k*vout );
240 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
241 template <typename TIteratorOnPairs>
243 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>
244 ::initFromIncidentPointsRange(const TIteratorOnPairs& itb, const TIteratorOnPairs& ite,
245 Image& aImg, AcceptedPointSet& aSet,
247 bool aFlagIsPositive)
250 if (aFlagIsPositive) k = 1;
253 for (TIteratorOnPairs it = itb; it != ite; ++it)
255 insertAndAlwaysSetValue( aImg, aSet, it->first, -k*aValue );
256 insertAndAlwaysSetValue( aImg, aSet, it->second, k*aValue );
260 ///////////////////////////////////////////////////////////////////////////////
261 // Interface - public :
264 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
267 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>::compute()
269 Point p = Point::diagonal(0);
271 while ( addNewAcceptedPoint( p, d ) )
275 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
278 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>
279 ::computeOneStep(Point& aPoint, Value& aValue)
281 return addNewAcceptedPoint(aPoint, aValue);
284 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
286 typename DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>::Value
287 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>::min() const
292 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
294 typename DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>::Value
295 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>::max() const
300 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
302 typename DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>::Value
303 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>::getMin() const
305 const AcceptedPointSet& set = myAcceptedPoints;
306 ASSERT( set.size() >= 1 );
308 typename AcceptedPointSet::ConstIterator it = set.begin();
309 typename AcceptedPointSet::ConstIterator itEnd = set.end();
310 Value vmin = myImage( *it );
311 for (++it; it != itEnd; ++it)
313 Value v = myImage( *it );
314 if (v < vmin) vmin = v;
319 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
321 typename DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>::Value
322 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>::getMax() const
324 const AcceptedPointSet& set = myAcceptedPoints;
325 ASSERT( set.size() >= 1 );
327 typename AcceptedPointSet::ConstIterator it = set.begin();
328 typename AcceptedPointSet::ConstIterator itEnd = set.end();
329 Value vmax = myImage( *it );
330 for (++it; it != itEnd; ++it)
332 Value v = myImage( *it );
333 if (v > vmax) vmax = v;
338 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
341 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>::isValid() const
344 if ( (myAcceptedPoints.size() <= 0)
345 || (myAcceptedPoints.size() >= myAreaThreshold) ) return false;
348 if ( ( getMin() != min() ) || ( getMax() != max() ) ) return false;
349 if ( (std::abs(getMin()) >= myValueThreshold)
350 || (getMax() >= myValueThreshold) ) return false;
353 bool flagIsOk = true;
354 const AcceptedPointSet& set = myAcceptedPoints;
355 typename AcceptedPointSet::ConstIterator it = set.begin();
356 typename AcceptedPointSet::ConstIterator itEnd = set.end();
357 for ( ; ( (it != itEnd)&&(flagIsOk == true) ); ++it)
359 if (myPointPredicate( *it ) == false) flagIsOk = false;
361 if (!flagIsOk) return false;
366 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
369 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>::selfDisplay ( std::ostream & out ) const
371 out << "[FMM " << dimension << "d] ";
372 out << myAcceptedPoints.size() << " accepted points (< " << myAreaThreshold << ")";
373 out << " and " << myCandidatePoints.size() << " candidates. ";
374 out << "dmin: " << min() << ", dmax: " << max();
375 out << " (abs < " << myValueThreshold << ")";
379 ///////////////////////////////////////////////////////////////////////////////
382 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
385 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>::init()
388 myCandidatePoints.clear();
390 typename AcceptedPointSet::Iterator it = myAcceptedPoints.begin();
391 typename AcceptedPointSet::Iterator itEnd = myAcceptedPoints.end();
392 for ( ; it != itEnd; ++it)
397 myMinValue = getMin();
398 myMaxValue = getMax();
402 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
405 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>
406 ::addNewAcceptedPoint(Point& aPoint, Value& aValue)
409 if ( (myAcceptedPoints.size()+1) < myAreaThreshold )
410 {//if a new point can be accepted
412 bool flagStop = false;
413 typename CandidatePointSet::iterator it = myCandidatePoints.begin();
414 typename CandidatePointSet::iterator itEnd = myCandidatePoints.end();
415 while ( (it != itEnd) && (!flagStop) )
416 { //while there are candidates and no point has been accepted
418 //pair of min distance
419 PointValue minPair = *it;
421 if ( std::abs(minPair.second) < myValueThreshold )
422 { //if distance below a given threshold
424 //the point of min distance is removed from the set of candidates
425 myCandidatePoints.erase(*it);
427 // After erasing, the iterator "it" becomes invalid and the test with "itEnd" won't work
430 //it can be inserted into the set of accepted points
431 if ( insertAndSetValue( myImage, myAcceptedPoints,
432 minPair.first, minPair.second ) )
433 { //if it does not belong to the set
434 //the set of candidates is updated with
435 //the neighbors of the new accepted point
436 aPoint = minPair.first;
437 aValue = minPair.second;
438 if (aValue > myMaxValue) myMaxValue = aValue;
439 if (aValue < myMinValue) myMinValue = aValue;
444 { //otherwise it has already been accepted
445 //with a smaller distance and the next candidate
446 //should be considered
447 it = myCandidatePoints.begin();
450 }//end if distance below a given threshold
453 } //end while there are candidates
455 return flagStop; //true if a point has been accepted
457 } //end if a new point can be accepted
461 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
464 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>::update(const Point& aPoint)
468 Point neighbor = aPoint;
469 for (Dimension k = 0; k < dimension; ++k)
471 typename Point::Coordinate c = neighbor[k];
473 addNewCandidate(neighbor);
475 addNewCandidate(neighbor);
480 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
483 DGtal::FMM<TImage, TSet, TPointPredicate, TPointFunctor>::addNewCandidate(const Point& aPoint)
486 //if it lies within the computation domain
487 //and if it is not already accepted
488 if ( (myPointPredicate(aPoint) )
489 && ( myAcceptedPoints.find(aPoint) == myAcceptedPoints.end() ) )
491 ASSERT( myPointFunctorPtr );
492 Value d = myPointFunctorPtr->operator()( aPoint );
493 PointValue newPair( aPoint, d );
494 //insert the new candidate with its distance
495 myCandidatePoints.insert(newPair);
502 ///////////////////////////////////////////////////////////////////////////////
503 // Implementation of inline functions //
505 template <typename TImage, typename TSet, typename TPointPredicate, typename TPointFunctor >
508 DGtal::operator<< ( std::ostream & out,
509 const FMM<TImage, TSet, TPointPredicate, TPointFunctor> & object )
511 object.selfDisplay( out );
516 ///////////////////////////////////////////////////////////////////////////////