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 tristan.roussillon@liris.cnrs.fr )
20 * Laboratoire d'InfoRmatique en Image et Systèmes d'information - LIRIS (CNRS, UMR 5205), CNRS, France
24 * @brief Implementation of inline methods defined in Preimage2D.h
26 * This file is part of the DGtal library.
30//////////////////////////////////////////////////////////////////////////////
32//////////////////////////////////////////////////////////////////////////////
34///////////////////////////////////////////////////////////////////////////////
35// IMPLEMENTATION of inline methods.
36///////////////////////////////////////////////////////////////////////////////
38///////////////////////////////////////////////////////////////////////////////
39// ----------------------- Standard services ------------------------------
42template <typename Shape>
44DGtal::Preimage2D<Shape>::Preimage2D(
45 const Point & firstPoint,
46 const Point & secondPoint,
47 const Shape & aShape ): myShape(aShape)
49 myPHull.push_front(firstPoint);
50 myQHull.push_front(secondPoint);
55template <typename Shape>
57DGtal::Preimage2D<Shape>::~Preimage2D()
61template <typename Shape>
63DGtal::Preimage2D<Shape>::Preimage2D( const Preimage2D & other ): myShape(other.myShape)
65 myPHull = other.myPHull;
66 myQHull = other.myQHull;
69template <typename Shape>
71DGtal::Preimage2D<Shape>&
72DGtal::Preimage2D<Shape>::operator=( const Preimage2D & other )
76 myShape = other.myShape;
77 myPHull = other.myPHull;
78 myQHull = other.myQHull;
83template <typename Shape>
86DGtal::Preimage2D<Shape>::operator==( const Preimage2D & other ) const
88 if ( (std::equal(myPHull.begin(),myPHull.end(),other.myPHull.begin())
89 &&std::equal(myQHull.begin(),myQHull.end(),other.myQHull.begin()))
90 || (std::equal(myPHull.begin(),myPHull.end(),other.myPHull.rbegin())
91 &&std::equal(myQHull.begin(),myQHull.end(),other.myQHull.rbegin()))
98template <typename Shape>
101DGtal::Preimage2D<Shape>::operator!=( const Preimage2D & other ) const
103 return !(*this == other);
106template <typename Shape>
109DGtal::Preimage2D<Shape>::isLeftExteriorAtTheFront(
111 const Point & /*aQ*/)
114 BackwardIterator PHullBack = myPHull.rbegin();
115 ForwardIterator QHullFront = myQHull.begin();
117 //predicates definition from critical shapes
118 myShape.init(*PHullBack, *QHullFront);
119 PHullBackQHullFrontPred p1( myShape );
124template <typename Shape>
127DGtal::Preimage2D<Shape>::isLeftExteriorAtTheBack(
128 const Point & /*aP*/,
132 ForwardIterator QHullFront = myQHull.begin();
133 BackwardIterator PHullBack = myPHull.rbegin();
135 //predicates definition from critical shapes
136 myShape.init(*QHullFront, *PHullBack);
137 QHullFrontPHullBackPred p2( myShape );
142template <typename Shape>
145DGtal::Preimage2D<Shape>::isRightExteriorAtTheFront(
146 const Point & /*aP*/,
150 BackwardIterator QHullBack = myQHull.rbegin();
151 ForwardIterator PHullFront = myPHull.begin();
153 //predicates definition from critical shapes
154 myShape.init(*QHullBack, *PHullFront);
155 QHullBackPHullFrontPred p2( myShape );
160template <typename Shape>
163DGtal::Preimage2D<Shape>::isRightExteriorAtTheBack(
165 const Point & /*aQ*/)
168 ForwardIterator PHullFront = myPHull.begin();
169 BackwardIterator QHullBack = myQHull.rbegin();
171 //predicates definition from critical shapes
172 myShape.init(*PHullFront, *QHullBack);
173 PHullFrontQHullBackPred p1( myShape );
178template <typename Shape>
181DGtal::Preimage2D<Shape>::canBeAddedAtTheFront(
186 BackwardIterator PHullBack = myPHull.rbegin();
187 ForwardIterator QHullFront = myQHull.begin();
188 BackwardIterator QHullBack = myQHull.rbegin();
189 ForwardIterator PHullFront = myPHull.begin();
191 //predicates definition from critical shapes
192 myShape.init(*PHullBack, *QHullFront);
193 PHullBackQHullFrontPred p1( myShape );
194 myShape.init(*QHullBack, *PHullFront);
195 QHullBackPHullFrontPred p2( myShape );
197 return ( p1(aP) && p2(aQ) );
200template <typename Shape>
203DGtal::Preimage2D<Shape>::canBeAddedAtTheBack(
209 ForwardIterator PHullFront = myPHull.begin();
210 BackwardIterator QHullBack = myQHull.rbegin();
211 ForwardIterator QHullFront = myQHull.begin();
212 BackwardIterator PHullBack = myPHull.rbegin();
214 //predicates definition from critical shapes
215 myShape.init(*PHullFront, *QHullBack);
216 PHullFrontQHullBackPred p1( myShape );
217 myShape.init(*QHullFront, *PHullBack);
218 QHullFrontPHullBackPred p2( myShape );
220 return ( p1(aP) && p2(aQ) );
224template <typename Shape>
227DGtal::Preimage2D<Shape>::addFront(
232 bool isEmpty = false;
235 BackwardIterator PHullBack = myPHull.rbegin();
236 ForwardIterator QHullFront = myQHull.begin();
237 BackwardIterator QHullBack = myQHull.rbegin();
238 ForwardIterator PHullFront = myPHull.begin();
240 //predicates definition from critical shapes
241 myShape.init(*PHullBack, *QHullFront);
242 PHullBackQHullFrontPred p1( myShape );
243 myShape.init(*QHullBack, *PHullFront);
244 QHullBackPHullFrontPred p2( myShape );
246 if ( p1(aP) && p2(aQ) ) {
247 if ( p2(aP) ) { //constraint involved by aP
250 update<ForwardIterator,FrontPHullUpdatePred>
251 (aP, myPHull, PHullFront, myPHull.end());
254 if (aP != *myPHull.begin()) myPHull.push_front(aP);
257 update<BackwardIterator,FrontQHullUpdatePred>
258 (aP, myQHull, QHullBack, myQHull.rend());
260 } //else nothing to do
262 if ( p1(aQ) ) { //constraint involved by aQ
265 update<ForwardIterator,FrontQHullUpdatePred>
266 (aQ, myQHull, QHullFront, myQHull.end());
269 if (aQ != *myQHull.begin()) myQHull.push_front(aQ);
272 update<BackwardIterator,FrontPHullUpdatePred>
273 (aQ, myPHull, PHullBack, myPHull.rend());
275 } //else nothing to do
277 } else isEmpty = true;
282template <typename Shape>
285DGtal::Preimage2D<Shape>::addBack(
290 bool isEmpty = false;
293 ForwardIterator PHullFront = myPHull.begin();
294 BackwardIterator QHullBack = myQHull.rbegin();
295 ForwardIterator QHullFront = myQHull.begin();
296 BackwardIterator PHullBack = myPHull.rbegin();
298 //predicates definition from critical shapes
299 myShape.init(*PHullFront, *QHullBack);
300 PHullFrontQHullBackPred p1( myShape );
301 myShape.init(*QHullFront, *PHullBack);
302 QHullFrontPHullBackPred p2( myShape );
304 if ( p1(aP) && p2(aQ) ) {
305 if ( p2(aP) ) { //constraint involved by aP
308 update<BackwardIterator,BackPHullUpdatePred>
309 (aP, myPHull, PHullBack, myPHull.rend());
312 if (aP != *myPHull.rbegin()) myPHull.push_back(aP);
315 update<ForwardIterator,BackQHullUpdatePred>
316 (aP, myQHull, QHullFront, myQHull.end());
319 } //else nothing to do
321 if ( p1(aQ) ) { //constraint involved by aQ
324 update<BackwardIterator,BackQHullUpdatePred>
325 (aQ, myQHull, QHullBack, myQHull.rend());
328 if (aQ != *myQHull.rbegin()) myQHull.push_back(aQ);
331 update<ForwardIterator,BackPHullUpdatePred>
332 (aQ, myPHull, PHullFront, myPHull.end());
334 } //else nothing to do
336 } else isEmpty = true;
342template <typename Shape>
343template <typename Iterator, typename Predicate>
346DGtal::Preimage2D<Shape>::update(
347 const Point & aPoint,
348 Container & aContainer,
349 Iterator & anIterator,
350 const Iterator & anEndIterator)
356 if (anIterator != anEndIterator) {
359 Predicate pred( myShape );
361 while ( (anIterator != anEndIterator) &&
368 DGtal::OpInSTLContainers<Container,Iterator>
369 ::erase(aContainer, anIterator);
374 if (anIterator != anEndIterator) {
377 pred = Predicate( myShape );
383///////////////////////////////////////////////////////////////////////////////
384// Interface - public :
386template <typename Shape>
389DGtal::Preimage2D<Shape>::className() const
394template <typename Shape>
397DGtal::Preimage2D<Shape>::selfDisplay ( std::ostream & out ) const
399 out << "[Preimage2D]\n";
400 out << "first part: \n";
401 for (ConstForwardIterator i = myPHull.begin();
402 i != myPHull.end(); ++i) {
406 out << "second part: \n";
407 for (ConstForwardIterator i = myQHull.begin();
408 i != myQHull.end(); ++i) {
414template <typename Shape>
417DGtal::Preimage2D<Shape>::isValid() const
422template <typename Shape>
424typename DGtal::Preimage2D<Shape>::Point
425DGtal::Preimage2D<Shape>::Uf() const
427 return *myPHull.rbegin();
430template <typename Shape>
432typename DGtal::Preimage2D<Shape>::Point
433DGtal::Preimage2D<Shape>::Ul() const
435 return *myPHull.begin();
438template <typename Shape>
440typename DGtal::Preimage2D<Shape>::Point
441DGtal::Preimage2D<Shape>::Lf() const
443 return *myQHull.rbegin();
446template <typename Shape>
448typename DGtal::Preimage2D<Shape>::Point
449DGtal::Preimage2D<Shape>::Ll() const
451 return *myQHull.begin();
454template <typename Shape>
457DGtal::Preimage2D<Shape>::getSeparatingStraightLine(
463 Point localUf = Uf();
464 Point localUl = Ul();
465 Point localLf = Lf();
466 Point localLl = Ll();
469 typedef typename Point::Coordinate Coordinate;
471 double a = -NumberTraits<Coordinate>::castToDouble(localLl[1]-localUf[1]);
472 double b = NumberTraits<Coordinate>::castToDouble(localLl[0]-localUf[0]);
473 double c = -NumberTraits<Coordinate>::castToDouble(localUf[0])*a
474 -NumberTraits<Coordinate>::castToDouble(localUf[1])*b;
476 double ap = -NumberTraits<Coordinate>::castToDouble(localUl[1]-localLf[1]);
477 double bp = NumberTraits<Coordinate>::castToDouble(localUl[0]-localLf[0]);
478 double cp = -NumberTraits<Coordinate>::castToDouble(localLf[0])*ap
479 -NumberTraits<Coordinate>::castToDouble(localLf[1])*bp;
482 double det = (ap*b-bp*a);
486 x = -(b*cp-bp*c)/det;
487 y = -(a*cp-ap*c)/(-det);
488 //normalisation of (ap,bp) with respect to (a,b)
489 double l = std::sqrt(a*a + b*b);
490 double lp = std::sqrt(ap*ap + bp*bp);
491 double apn = ap/lp*l;
492 double bpn = bp/lp*l;
493 //slope bisector of (UfLl) and (UlLf)
497 gamma = -alpha*x - beta*y;
508///////////////////////////////////////////////////////////////////////////////
509// Implementation of inline functions //
511template <typename Shape>
514DGtal::operator<< ( std::ostream & out,
515 const Preimage2D<Shape> & object )
517 object.selfDisplay( out );
522///////////////////////////////////////////////////////////////////////////////