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 StabbingCircleComputer.ih
19 * @author Tristan Roussillon (\c tristan.roussillon@liris.cnrs.fr )
20 * Laboratoire d'InfoRmatique en Image et Systèmes d'information - LIRIS (CNRS, UMR 5205), CNRS, France
24 * Implementation of inline methods defined in StabbingCircleComputer.h
26 * This file is part of the DGtal library.
30//////////////////////////////////////////////////////////////////////////////
32//////////////////////////////////////////////////////////////////////////////
34///////////////////////////////////////////////////////////////////////////////
35// IMPLEMENTATION of inline methods.
36///////////////////////////////////////////////////////////////////////////////
38///////////////////////////////////////////////////////////////////////////////
39// ----------------------- Standard services ------------------------------
41template <typename TConstIterator>
43DGtal::StabbingCircleComputer<TConstIterator>::StabbingCircleComputer()
44 :myBegin(), myEnd(), mySegPtr(new StabbingLineComputer<ConstIterator>()),
45 myCircle(), myFlagIsInit(false)
49template <typename TConstIterator>
51DGtal::StabbingCircleComputer<TConstIterator>::StabbingCircleComputer( const Self& other )
52 :myBegin(other.myBegin), myEnd(other.myEnd), mySegPtr(other.mySegPtr),
53 myCircle(other.myCircle), myFlagIsInit(other.myFlagIsInit)
57template <typename TConstIterator>
59typename DGtal::StabbingCircleComputer<TConstIterator>::Self&
60DGtal::StabbingCircleComputer<TConstIterator>::operator= ( const Self& other )
64 myBegin = other.myBegin;
66 mySegPtr = other.mySegPtr;
67 myCircle = other.myCircle;
68 myFlagIsInit = other.myFlagIsInit;
73template <typename TConstIterator>
75DGtal::StabbingCircleComputer<TConstIterator>::~StabbingCircleComputer()
79template <typename TConstIterator>
82DGtal::StabbingCircleComputer<TConstIterator>::operator==( const Self& other ) const
84 if (isValid()&&other.isValid())
88 ConstIterator first1 (myBegin);
89 ConstIterator first2 (other.myBegin);
90 while ( ( ( first1 != myEnd )
91 ||( first2 != other.myEnd ) )
94 Pair pair1( *first1 );
95 Pair pair2( *first2 );
96 if ( (pair1.first != pair2.first)||(pair1.second != pair2.second) ) flag1 = false;
99 if ( (first1 != myEnd) || (first2 != other.myEnd) ) flag1 = false;
103 std::reverse_iterator<ConstIterator> rfirst1(myEnd);
104 ConstIterator first2 = other.myBegin;
105 while ( ( ( rfirst1 != std::reverse_iterator<ConstIterator>(myBegin) )
106 ||( first2 != other.myEnd ) )
109 Pair pair1( *rfirst1 );
110 Pair pair2( *first2 );
111 if ( (pair1.first != pair2.first)||(pair1.second != pair2.second) ) flag2 = false;
114 if ( (rfirst1 != std::reverse_iterator<ConstIterator>(myBegin))
115 || (first2 != other.myEnd) ) flag2 = false;
118 return ( flag1 || flag2 );
122 return ( (!isValid()) && (!other.isValid()) );
126template <typename TConstIterator>
129DGtal::StabbingCircleComputer<TConstIterator>::operator!=( const Self& other ) const
131 return !(*this == other);
134template <typename TConstIterator>
136typename DGtal::StabbingCircleComputer<TConstIterator>::Reverse
137DGtal::StabbingCircleComputer<TConstIterator>::getReverse() const
143template <typename TConstIterator>
145typename DGtal::StabbingCircleComputer<TConstIterator>::Self
146DGtal::StabbingCircleComputer<TConstIterator>::getSelf() const
153///////////////////////////////////////////////////////////////////////////////
154// Interface - public :
156template <typename TConstIterator>
159DGtal::StabbingCircleComputer<TConstIterator>::isValid() const
161 if ( mySegPtr.get() != 0 )
163 return mySegPtr->isValid();
171template <typename TConstIterator>
173typename DGtal::StabbingCircleComputer<TConstIterator>::ConstIterator
174DGtal::StabbingCircleComputer<TConstIterator>::begin() const
179template <typename TConstIterator>
181typename DGtal::StabbingCircleComputer<TConstIterator>::ConstIterator
182DGtal::StabbingCircleComputer<TConstIterator>::end() const
187template <typename TConstIterator>
190DGtal::StabbingCircleComputer<TConstIterator>::isStraight() const
192 return !myFlagIsInit;
195template <typename TConstIterator>
197typename DGtal::StabbingCircleComputer<TConstIterator>::StabbingLineComputerPtr
198DGtal::StabbingCircleComputer<TConstIterator>::getStabbingLineComputerPtr() const
203template <typename TConstIterator>
205typename DGtal::StabbingCircleComputer<TConstIterator>::Circle
206DGtal::StabbingCircleComputer<TConstIterator>::getSeparatingCircle() const
211///////////////////////////////////////////////////////////////////////////////
212// Growth operations //
214template <typename TConstIterator>
215template <typename TIterator>
218DGtal::StabbingCircleComputer<TConstIterator>::isCircularlySeparable(
219 const TIterator& itb, const TIterator& ite,
221 Point& Pf, Point& Pl, Point& Qf, Point& Ql)
223 ASSERT( itb != ite );
225 Pair currentPair( *it );
227 //preimage of circles passing through aPole
228 CircleFrom2Points<Point> aCircle( aPole );
229 Preimage2D<CircleFrom2Points<Point> >
230 thePreimage( currentPair.first, currentPair.second, aCircle );
235 { //if more than one pair
237 if ( thePreimage.addFront(currentPair.first, currentPair.second) )
240 while ( (it != ite)&&(isOK) )
243 isOK = thePreimage.addFront(currentPair.first, currentPair.second);
247 else if ( thePreimage.addBack(currentPair.first, currentPair.second) )
250 while ( (it != ite)&&(isOK) )
253 isOK = thePreimage.addBack(currentPair.first, currentPair.second);
258 } //if only one pair => circularly separable
262 Pf = thePreimage.Uf();
263 Pl = thePreimage.Ul();
264 Qf = thePreimage.Lf();
265 Ql = thePreimage.Ll();
270template <typename TConstIterator>
273DGtal::StabbingCircleComputer<TConstIterator>::init(const ConstIterator& anIt)
275 myFlagIsInit = false;
277 //initialize the iterators
282 //...the geometrical DSS
283 mySegPtr->init( anIt );
285 //...the circle as degenerated
287 myCircle = Circle(aPair.first, aPair.first, aPair.first);
290template <typename TConstIterator>
293DGtal::StabbingCircleComputer<TConstIterator>::isExtendableFront()
295 ASSERT( mySegPtr.get() != 0 );
296 Pair aPair( *myEnd );
297 Point aP( aPair.first );
298 Point aQ( aPair.second );
305 PInCirclePred p1( myCircle );
306 QInCirclePred p2( myCircle );
308 if ( p1(aP)&&p2(aQ) )
311 { //checks if the separating circle can be updated
314 Point Pf, Pl, Qf, Ql;
315 if (isCircularlySeparable(myBegin,myEnd,aP,Pf,Pl,Qf,Ql))
320 Point Pf, Pl, Qf, Ql;
321 if (isCircularlySeparable(myBegin,myEnd,aQ,Pf,Pl,Qf,Ql))
324 else ASSERT( false && ("DGtal::StabbingCircleComputer<TConstIterator>::isExtendableFront(): impossible case") );
328 { //not initialized yet
330 if ( mySegPtr->extendFront() ) isOK = true;
333 Point Pf, Pl, Qf, Ql;
334 if (mySegPtr->isConvex())
336 if (isCircularlySeparable(myBegin,myEnd,aQ,Pf,Pl,Qf,Ql))
339 else if (mySegPtr->isConcave())
341 if (isCircularlySeparable(myBegin,myEnd,aP,Pf,Pl,Qf,Ql))
344 else ASSERT( false && ("DGtal::StabbingCircleComputer<TConstIterator>::isExtendableFront(): impossible case") );
351template <typename TConstIterator>
354DGtal::StabbingCircleComputer<TConstIterator>::extendFront()
356 ASSERT( mySegPtr.get() != 0 );
357 Pair aPair( *myEnd );
358 Point aP( aPair.first );
359 Point aQ( aPair.second );
366 PInCirclePred p1( myCircle );
367 QInCirclePred p2( myCircle );
369 if ( p1(aP)&&p2(aQ) )
372 { //update separating circle
375 Point Pf, Pl, Qf, Ql;
376 if (isCircularlySeparable(myBegin,myEnd,aP,Pf,Pl,Qf,Ql))
378 myCircle.init(Pf,Ql,aP);
384 Point Pf, Pl, Qf, Ql;
385 if (isCircularlySeparable(myBegin,myEnd,aQ,Pf,Pl,Qf,Ql))
387 myCircle.init(Qf,Pl,aQ);
391 else ASSERT( false && ("DGtal::StabbingCircleComputer<TConstIterator>::extendFront(): impossible case") );
395 { //not initialized yet
397 if ( mySegPtr->extendFront() ) isOK = true;
400 Point Pf, Pl, Qf, Ql;
401 if (mySegPtr->isConvex())
404 if (isCircularlySeparable(myBegin,myEnd,aQ,Pf,Pl,Qf,Ql))
406 myCircle.init(Qf,Pl,aQ);
411 else if (mySegPtr->isConcave())
414 if (isCircularlySeparable(myBegin,myEnd,aP,Pf,Pl,Qf,Ql))
416 myCircle.init(Pf,Ql,aP);
421 else ASSERT( false && ("DGtal::StabbingCircleComputer<TConstIterator>::extendFront(): impossible case") );
432template <typename TConstIterator>
435DGtal::StabbingCircleComputer<TConstIterator>::isExtendableBack()
437 ASSERT( mySegPtr.get() != 0 );
438 ConstIterator it( myBegin );
441 Point aP( aPair.first );
442 Point aQ( aPair.second );
449 PInCirclePred p1( myCircle );
450 QInCirclePred p2( myCircle );
452 if ( p1(aP)&&p2(aQ) )
455 { //update separating circle
458 Point Pf, Pl, Qf, Ql;
459 std::reverse_iterator<ConstIterator> ritb(myEnd);
460 std::reverse_iterator<ConstIterator> rite(myBegin);
461 if (isCircularlySeparable(ritb,rite,aP,Pf,Pl,Qf,Ql))
466 Point Pf, Pl, Qf, Ql;
467 std::reverse_iterator<ConstIterator> ritb(myEnd);
468 std::reverse_iterator<ConstIterator> rite(myBegin);
469 if (isCircularlySeparable(ritb,rite,aQ,Pf,Pl,Qf,Ql))
472 else ASSERT( false && ("DGtal::StabbingCircleComputer<TConstIterator>::extendBack(): impossible case") );
476 { //not initialized yet
478 if ( mySegPtr->extendBack() ) isOK = true;
481 Point Pf, Pl, Qf, Ql;
482 std::reverse_iterator<ConstIterator> ritb(myEnd);
483 std::reverse_iterator<ConstIterator> rite(myBegin);
484 if (mySegPtr->isOppositeEndConvex())
486 if (isCircularlySeparable(ritb,rite,aQ,Pf,Pl,Qf,Ql))
489 else if (mySegPtr->isOppositeEndConcave())
491 if (isCircularlySeparable(ritb,rite,aP,Pf,Pl,Qf,Ql))
494 else ASSERT( false && ("DGtal::StabbingCircleComputer<TConstIterator>::extendBack(): impossible case") );
501template <typename TConstIterator>
504DGtal::StabbingCircleComputer<TConstIterator>::extendBack()
506 ASSERT( mySegPtr.get() != 0 );
507 ConstIterator it( myBegin );
510 Point aP( aPair.first );
511 Point aQ( aPair.second );
518 PInCirclePred p1( myCircle );
519 QInCirclePred p2( myCircle );
521 if ( p1(aP)&&p2(aQ) )
524 { //update separating circle
527 Point Pf, Pl, Qf, Ql;
528 std::reverse_iterator<ConstIterator> ritb(myEnd);
529 std::reverse_iterator<ConstIterator> rite(myBegin);
530 if (isCircularlySeparable(ritb,rite,aP,Pf,Pl,Qf,Ql))
532 myCircle.init(aP,Pf,Ql);
538 Point Pf, Pl, Qf, Ql;
539 std::reverse_iterator<ConstIterator> ritb(myEnd);
540 std::reverse_iterator<ConstIterator> rite(myBegin);
541 if (isCircularlySeparable(ritb,rite,aQ,Pf,Pl,Qf,Ql))
543 myCircle.init(aQ,Qf,Pl);
547 else ASSERT( false && ("DGtal::StabbingCircleComputer<TConstIterator>::extendBack(): impossible case") );
551 { //not initialized yet
553 if ( mySegPtr->extendBack() ) isOK = true;
556 Point Pf, Pl, Qf, Ql;
557 std::reverse_iterator<ConstIterator> ritb(myEnd);
558 std::reverse_iterator<ConstIterator> rite(myBegin);
559 if (mySegPtr->isOppositeEndConvex())
562 if (isCircularlySeparable(ritb,rite,aQ,Pf,Pl,Qf,Ql))
564 myCircle.init(aQ,Qf,Pl);
569 else if (mySegPtr->isOppositeEndConcave())
572 if (isCircularlySeparable(ritb,rite,aP,Pf,Pl,Qf,Ql))
574 myCircle.init(aP,Pf,Ql);
579 else ASSERT( false && ("DGtal::StabbingCircleComputer<TConstIterator>::extendBack(): impossible case") );
590///////////////////////////////////////////////////////////////////////////////
593template <typename TConstIterator>
596DGtal::StabbingCircleComputer<TConstIterator>::selfDisplay ( std::ostream & out ) const
599 out << "[StabbingCircleComputer]" << std::endl;
602 Pair firstPair( *myBegin );
603 out << "\t From " << firstPair.first << firstPair.second << std::endl;
604 ConstIterator it (myEnd);
606 Pair lastPair( *it );
607 out << "\t To " << lastPair.first << lastPair.second << std::endl;
609 out << myCircle << std::endl;
611 out << "infinite radius" << std::endl;
615 out << "\t not valid" << std::endl;
617 out << "[end of StabbingCircleComputer]" << std::endl;
620template <typename TConstIterator>
623DGtal::StabbingCircleComputer<TConstIterator>::className() const
625 return "StabbingCircleComputer";
629///////////////////////////////////////////////////////////////////////////////
630// Implementation of inline functions //
632template <typename TConstIterator>
635DGtal::operator<< ( std::ostream & out,
636 const StabbingCircleComputer<TConstIterator> & object )
638 object.selfDisplay( out );
643///////////////////////////////////////////////////////////////////////////////