DGtal 1.4.0
Loading...
Searching...
No Matches
Preimage2D.ih
1/**
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.
6 *
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.
11 *
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/>.
14 *
15 **/
16
17/**
18 * @file Preimage2D.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
21 *
22 * @date 2010/10/26
23 *
24 * @brief Implementation of inline methods defined in Preimage2D.h
25 *
26 * This file is part of the DGtal library.
27 */
28
29
30//////////////////////////////////////////////////////////////////////////////
31#include <cstdlib>
32//////////////////////////////////////////////////////////////////////////////
33
34///////////////////////////////////////////////////////////////////////////////
35// IMPLEMENTATION of inline methods.
36///////////////////////////////////////////////////////////////////////////////
37
38///////////////////////////////////////////////////////////////////////////////
39// ----------------------- Standard services ------------------------------
40
41
42template <typename Shape>
43inline
44DGtal::Preimage2D<Shape>::Preimage2D(
45 const Point & firstPoint,
46 const Point & secondPoint,
47 const Shape & aShape ): myShape(aShape)
48{
49 myPHull.push_front(firstPoint);
50 myQHull.push_front(secondPoint);
51}
52
53
54
55template <typename Shape>
56inline
57DGtal::Preimage2D<Shape>::~Preimage2D()
58{
59}
60
61template <typename Shape>
62inline
63DGtal::Preimage2D<Shape>::Preimage2D( const Preimage2D & other ): myShape(other.myShape)
64{
65 myPHull = other.myPHull;
66 myQHull = other.myQHull;
67}
68
69template <typename Shape>
70inline
71DGtal::Preimage2D<Shape>&
72DGtal::Preimage2D<Shape>::operator=( const Preimage2D & other )
73{
74 if ( this != &other )
75 {
76 myShape = other.myShape;
77 myPHull = other.myPHull;
78 myQHull = other.myQHull;
79 }
80 return *this;
81}
82
83template <typename Shape>
84inline
85bool
86DGtal::Preimage2D<Shape>::operator==( const Preimage2D & other ) const
87{
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()))
92 )
93 return true;
94 else
95 return false;
96}
97
98template <typename Shape>
99inline
100bool
101DGtal::Preimage2D<Shape>::operator!=( const Preimage2D & other ) const
102{
103 return !(*this == other);
104}
105
106template <typename Shape>
107inline
108bool
109DGtal::Preimage2D<Shape>::isLeftExteriorAtTheFront(
110 const Point & aP,
111 const Point & /*aQ*/)
112{
113 //critical points
114 BackwardIterator PHullBack = myPHull.rbegin();
115 ForwardIterator QHullFront = myQHull.begin();
116
117 //predicates definition from critical shapes
118 myShape.init(*PHullBack, *QHullFront);
119 PHullBackQHullFrontPred p1( myShape );
120
121 return (!p1(aP));
122}
123
124template <typename Shape>
125inline
126bool
127DGtal::Preimage2D<Shape>::isLeftExteriorAtTheBack(
128 const Point & /*aP*/,
129 const Point & aQ)
130{
131 //critical points
132 ForwardIterator QHullFront = myQHull.begin();
133 BackwardIterator PHullBack = myPHull.rbegin();
134
135 //predicates definition from critical shapes
136 myShape.init(*QHullFront, *PHullBack);
137 QHullFrontPHullBackPred p2( myShape );
138
139 return (!p2(aQ));
140}
141
142template <typename Shape>
143inline
144bool
145DGtal::Preimage2D<Shape>::isRightExteriorAtTheFront(
146 const Point & /*aP*/,
147 const Point & aQ)
148{
149 //critical points
150 BackwardIterator QHullBack = myQHull.rbegin();
151 ForwardIterator PHullFront = myPHull.begin();
152
153 //predicates definition from critical shapes
154 myShape.init(*QHullBack, *PHullFront);
155 QHullBackPHullFrontPred p2( myShape );
156
157 return (!p2(aQ));
158}
159
160template <typename Shape>
161inline
162bool
163DGtal::Preimage2D<Shape>::isRightExteriorAtTheBack(
164 const Point & aP,
165 const Point & /*aQ*/)
166{
167 //critical points
168 ForwardIterator PHullFront = myPHull.begin();
169 BackwardIterator QHullBack = myQHull.rbegin();
170
171 //predicates definition from critical shapes
172 myShape.init(*PHullFront, *QHullBack);
173 PHullFrontQHullBackPred p1( myShape );
174
175 return (!p1(aP));
176}
177
178template <typename Shape>
179inline
180bool
181DGtal::Preimage2D<Shape>::canBeAddedAtTheFront(
182 const Point & aP,
183 const Point & aQ)
184{
185 //critical points
186 BackwardIterator PHullBack = myPHull.rbegin();
187 ForwardIterator QHullFront = myQHull.begin();
188 BackwardIterator QHullBack = myQHull.rbegin();
189 ForwardIterator PHullFront = myPHull.begin();
190
191 //predicates definition from critical shapes
192 myShape.init(*PHullBack, *QHullFront);
193 PHullBackQHullFrontPred p1( myShape );
194 myShape.init(*QHullBack, *PHullFront);
195 QHullBackPHullFrontPred p2( myShape );
196
197 return ( p1(aP) && p2(aQ) );
198}
199
200template <typename Shape>
201inline
202bool
203DGtal::Preimage2D<Shape>::canBeAddedAtTheBack(
204 const Point & aP,
205 const Point & aQ)
206{
207
208 //critical points
209 ForwardIterator PHullFront = myPHull.begin();
210 BackwardIterator QHullBack = myQHull.rbegin();
211 ForwardIterator QHullFront = myQHull.begin();
212 BackwardIterator PHullBack = myPHull.rbegin();
213
214 //predicates definition from critical shapes
215 myShape.init(*PHullFront, *QHullBack);
216 PHullFrontQHullBackPred p1( myShape );
217 myShape.init(*QHullFront, *PHullBack);
218 QHullFrontPHullBackPred p2( myShape );
219
220 return ( p1(aP) && p2(aQ) );
221
222}
223
224template <typename Shape>
225inline
226bool
227DGtal::Preimage2D<Shape>::addFront(
228 const Point & aP,
229 const Point & aQ)
230{
231
232 bool isEmpty = false;
233
234 //critical points
235 BackwardIterator PHullBack = myPHull.rbegin();
236 ForwardIterator QHullFront = myQHull.begin();
237 BackwardIterator QHullBack = myQHull.rbegin();
238 ForwardIterator PHullFront = myPHull.begin();
239
240 //predicates definition from critical shapes
241 myShape.init(*PHullBack, *QHullFront);
242 PHullBackQHullFrontPred p1( myShape );
243 myShape.init(*QHullBack, *PHullFront);
244 QHullBackPHullFrontPred p2( myShape );
245
246 if ( p1(aP) && p2(aQ) ) {
247 if ( p2(aP) ) { //constraint involved by aP
248
249 //update myPHull
250 update<ForwardIterator,FrontPHullUpdatePred>
251 (aP, myPHull, PHullFront, myPHull.end());
252
253 //add aP to myPHull
254 if (aP != *myPHull.begin()) myPHull.push_front(aP);
255
256 //update myQHull
257 update<BackwardIterator,FrontQHullUpdatePred>
258 (aP, myQHull, QHullBack, myQHull.rend());
259
260 } //else nothing to do
261
262 if ( p1(aQ) ) { //constraint involved by aQ
263
264 //update myQHull
265 update<ForwardIterator,FrontQHullUpdatePred>
266 (aQ, myQHull, QHullFront, myQHull.end());
267
268 //add aQ to myQHull
269 if (aQ != *myQHull.begin()) myQHull.push_front(aQ);
270
271 //update myPHull
272 update<BackwardIterator,FrontPHullUpdatePred>
273 (aQ, myPHull, PHullBack, myPHull.rend());
274
275 } //else nothing to do
276
277 } else isEmpty = true;
278
279 return (!isEmpty);
280}
281
282template <typename Shape>
283inline
284bool
285DGtal::Preimage2D<Shape>::addBack(
286 const Point & aP,
287 const Point & aQ)
288{
289
290 bool isEmpty = false;
291
292 //critical points
293 ForwardIterator PHullFront = myPHull.begin();
294 BackwardIterator QHullBack = myQHull.rbegin();
295 ForwardIterator QHullFront = myQHull.begin();
296 BackwardIterator PHullBack = myPHull.rbegin();
297
298 //predicates definition from critical shapes
299 myShape.init(*PHullFront, *QHullBack);
300 PHullFrontQHullBackPred p1( myShape );
301 myShape.init(*QHullFront, *PHullBack);
302 QHullFrontPHullBackPred p2( myShape );
303
304 if ( p1(aP) && p2(aQ) ) {
305 if ( p2(aP) ) { //constraint involved by aP
306
307 //update myPHull
308 update<BackwardIterator,BackPHullUpdatePred>
309 (aP, myPHull, PHullBack, myPHull.rend());
310
311 //add aP to myPHull
312 if (aP != *myPHull.rbegin()) myPHull.push_back(aP);
313
314 //update myQHull
315 update<ForwardIterator,BackQHullUpdatePred>
316 (aP, myQHull, QHullFront, myQHull.end());
317
318
319 } //else nothing to do
320
321 if ( p1(aQ) ) { //constraint involved by aQ
322
323 //update myQHull
324 update<BackwardIterator,BackQHullUpdatePred>
325 (aQ, myQHull, QHullBack, myQHull.rend());
326
327 //add aQ to myQHull
328 if (aQ != *myQHull.rbegin()) myQHull.push_back(aQ);
329
330 //update myPHull
331 update<ForwardIterator,BackPHullUpdatePred>
332 (aQ, myPHull, PHullFront, myPHull.end());
333
334 } //else nothing to do
335
336 } else isEmpty = true;
337
338 return (!isEmpty);
339}
340
341
342template <typename Shape>
343template <typename Iterator, typename Predicate>
344inline
345void
346DGtal::Preimage2D<Shape>::update(
347 const Point & aPoint,
348 Container & aContainer,
349 Iterator & anIterator,
350 const Iterator & anEndIterator)
351{
352
353 Point p, q;
354 q = *anIterator;
355 anIterator++;
356 if (anIterator != anEndIterator) {
357 p = *anIterator;
358 myShape.init(p,q);
359 Predicate pred( myShape );
360
361 while ( (anIterator != anEndIterator) &&
362 (pred(aPoint)) ) {
363
364 //deletion
365 anIterator--;
366
367 anIterator =
368 DGtal::OpInSTLContainers<Container,Iterator>
369 ::erase(aContainer, anIterator);
370
371 //update of pred
372 q = p;
373 anIterator++;
374 if (anIterator != anEndIterator) {
375 p = *anIterator;
376 myShape.init(p,q);
377 pred = Predicate( myShape );
378 }
379 }
380 }
381
382}
383///////////////////////////////////////////////////////////////////////////////
384// Interface - public :
385
386template <typename Shape>
387inline
388std::string
389DGtal::Preimage2D<Shape>::className() const
390{
391 return "Preimage2D";
392}
393
394template <typename Shape>
395inline
396void
397DGtal::Preimage2D<Shape>::selfDisplay ( std::ostream & out ) const
398{
399 out << "[Preimage2D]\n";
400 out << "first part: \n";
401 for (ConstForwardIterator i = myPHull.begin();
402 i != myPHull.end(); ++i) {
403 out << *i << ", ";
404 }
405 out << "\n";
406 out << "second part: \n";
407 for (ConstForwardIterator i = myQHull.begin();
408 i != myQHull.end(); ++i) {
409 out << *i << ", ";
410 }
411 out << "\n";
412}
413
414template <typename Shape>
415inline
416bool
417DGtal::Preimage2D<Shape>::isValid() const
418{
419 return true;
420}
421
422template <typename Shape>
423inline
424typename DGtal::Preimage2D<Shape>::Point
425DGtal::Preimage2D<Shape>::Uf() const
426{
427 return *myPHull.rbegin();
428}
429
430template <typename Shape>
431inline
432typename DGtal::Preimage2D<Shape>::Point
433DGtal::Preimage2D<Shape>::Ul() const
434{
435 return *myPHull.begin();
436}
437
438template <typename Shape>
439inline
440typename DGtal::Preimage2D<Shape>::Point
441DGtal::Preimage2D<Shape>::Lf() const
442{
443 return *myQHull.rbegin();
444}
445
446template <typename Shape>
447inline
448typename DGtal::Preimage2D<Shape>::Point
449DGtal::Preimage2D<Shape>::Ll() const
450{
451 return *myQHull.begin();
452}
453
454template <typename Shape>
455inline
456void
457DGtal::Preimage2D<Shape>::getSeparatingStraightLine(
458 double& alpha,
459 double& beta,
460 double& gamma) const
461{
462 //critical points
463 Point localUf = Uf();
464 Point localUl = Ul();
465 Point localLf = Lf();
466 Point localLl = Ll();
467
468 //parameters
469 typedef typename Point::Coordinate Coordinate;
470
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;
475
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;
480
481 double x, y;
482 double det = (ap*b-bp*a);
483 if (det != 0)
484 {
485 //intersection point
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)
494 alpha = (a+apn)/2.0;
495 beta = (b+bpn)/2.0;
496 //intercept
497 gamma = -alpha*x - beta*y;
498 }
499 else
500 {//parallel case
501 alpha = a;
502 beta = b;
503 gamma = c;
504 }
505}
506
507
508///////////////////////////////////////////////////////////////////////////////
509// Implementation of inline functions //
510
511template <typename Shape>
512inline
513std::ostream&
514DGtal::operator<< ( std::ostream & out,
515 const Preimage2D<Shape> & object )
516{
517 object.selfDisplay( out );
518 return out;
519}
520
521// //
522///////////////////////////////////////////////////////////////////////////////
523
524