DGtal 1.3.0
Loading...
Searching...
No Matches
AlphaThickSegmentComputer.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 AlphaThickSegmentComputer.ih
19 * @author Bertrand Kerautret (\c kerautre@loria.fr )
20 * LORIA (CNRS, UMR 7503), University of Nancy, France
21 * @author Alexandre Faure
22 * @author Fabien Feschet
23 * @author Mohammad Said
24 * @author Jacques-Olivier Lachaud
25 *
26 * @date 2015/01/05
27 *
28 * Implementation of inline methods defined in AlphaThickSegmentComputer.h
29 *
30 * This file is part of the DGtal library.
31 */
32
33///////////////////////////////////////////////////////////////////////////////
34// IMPLEMENTATION of inline methods.
35///////////////////////////////////////////////////////////////////////////////
36
37//////////////////////////////////////////////////////////////////////////////
38#include <cstdlib>
39#include <limits>
40//////////////////////////////////////////////////////////////////////////////
41
42
43
44///////////////////////////////////////////////////////////////////////////////
45// Implementation of inline methods //
46///////////////////////////////////////////////////////////////////////////////
47
48
49
50// ----------------------- Standard services ------------------------------
51
52
53//-----------------------------------------------------------------------------
54template < typename TInputPoint, typename TConstIterator>
55inline
56DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::~AlphaThickSegmentComputer()
57{
58}
59
60//-----------------------------------------------------------------------------
61template < typename TInputPoint, typename TConstIterator>
62inline
63DGtal::AlphaThickSegmentComputer< TInputPoint,
64 TConstIterator>::AlphaThickSegmentComputer(const double maximalThickness,
65 const ThicknessDef &thicknessDefinition,
66 const double thickCompPrecision):
67 myBegin(), myEnd()
68{
69 myThicknessCompPrecision = thickCompPrecision;
70 myMaximalThickness = maximalThickness;
71 myThicknessDefinition = thicknessDefinition;
72 myNbPointsAddedFromIterators = 0;
73}
74
75
76
77//-----------------------------------------------------------------------------
78template < typename TInputPoint, typename TConstIterator>
79inline
80DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::
81AlphaThickSegmentComputer( const AlphaThickSegmentComputer & other ): myBegin(other.myBegin), myEnd(other.myEnd),
82 myPointContainer(other.myPointContainer),
83 myMaximalThickness(other.myMaximalThickness),
84 myThicknessCompPrecision(other.myThicknessCompPrecision),
85 myThicknessDefinition(other.myThicknessDefinition),
86 myState(other.myState),
87 myPreviousState(other.myPreviousState),
88 myIsStoringPoints(other.myIsStoringPoints),
89 myNbPointsAddedFromIterators(other.myNbPointsAddedFromIterators)
90
91{
92}
93
94template < typename TInputPoint, typename TConstIterator>
95inline
96DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator> &
97DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::
98operator= ( const AlphaThickSegmentComputer & other )
99{
100 if ( this != &other )
101 {
102 myThicknessDefinition = other.myThicknessDefinition;
103 myMaximalThickness = other.myMaximalThickness;
104 myThicknessCompPrecision = other.myThicknessCompPrecision;
105 myPointContainer = other.myPointContainer;
106 myState = other.myState;
107 myPreviousState = other.myPreviousState;
108 myIsStoringPoints = other.myIsStoringPoints;
109 myNbPointsAddedFromIterators = other.myNbPointsAddedFromIterators;
110 myBegin = other.myBegin;
111 myEnd = other.myEnd;
112 }
113 return *this;
114}
115
116
117
118
119
120//-----------------------------------------------------------------------------
121template < typename TInputPoint, typename TConstIterator>
122inline
123typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::Self
124DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getSelf() const
125{
126 return Self(myMaximalThickness, myThicknessDefinition, myThicknessCompPrecision);
127}
128
129
130
131//-----------------------------------------------------------------------------
132template < typename TInputPoint, typename TConstIterator>
133inline
134typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::Reverse
135DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getReverse() const
136{
137 return Reverse (myMaximalThickness, myThicknessDefinition, myThicknessCompPrecision);
138}
139
140
141template < typename TInputPoint, typename TConstIterator>
142inline
143bool
144DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::operator==( const AlphaThickSegmentComputer & other ) const{
145 return ( (myBegin == other.myBegin)
146 && (myEnd == other.myEnd) && myState.vertexSh == other.myState.vertexSh
147 && myState.edgePh == other.myState.edgePh && myState.edgeQh == other.myState.edgeQh);
148}
149
150
151template < typename TInputPoint, typename TConstIterator>
152inline
153bool
154DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::operator!=( const AlphaThickSegmentComputer & other ) const{
155 return (!(*this == other));
156}
157
158
159//-----------------------------------------------------------------------------
160template < typename TInputPoint, typename TConstIterator>
161inline
162typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::Size
163DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::size() const
164{
165 return myPointContainer.size();
166}
167
168
169//-----------------------------------------------------------------------------
170template < typename TInputPoint, typename TConstIterator>
171inline
172bool
173DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::empty() const
174{
175 return myPointContainer.empty();
176}
177
178
179//-----------------------------------------------------------------------------
180template < typename TInputPoint, typename TConstIterator>
181inline
182typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::ConstIterator
183DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::begin() const
184{
185 return myBegin;
186}
187
188
189
190//-----------------------------------------------------------------------------
191template < typename TInputPoint, typename TConstIterator>
192inline
193typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::ConstIterator
194DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::end() const
195{
196 return myEnd;
197}
198
199//-----------------------------------------------------------------------------
200template < typename TInputPoint, typename TConstIterator>
201inline
202typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::ContainerConstIterator
203DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::containerBegin() const
204{
205 return myPointContainer.begin();
206}
207
208
209
210//-----------------------------------------------------------------------------
211template < typename TInputPoint, typename TConstIterator>
212inline
213typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::ContainerConstIterator
214DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::containerEnd() const
215{
216 return myPointContainer.end();
217}
218
219
220
221//-----------------------------------------------------------------------------
222template < typename TInputPoint, typename TConstIterator>
223inline
224typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::ConvexhullConstIterator
225DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::convexhullBegin() const
226{
227 return myState.melkmanCH.begin();
228}
229
230
231
232//-----------------------------------------------------------------------------
233template < typename TInputPoint, typename TConstIterator>
234inline
235typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::ConvexhullConstIterator
236DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::convexhullEnd() const
237{
238 return myState.melkmanCH.end();
239}
240
241
242
243
244//-----------------------------------------------------------------------------
245template < typename TInputPoint, typename TConstIterator>
246inline
247typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::Size
248DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::max_size() const
249{
250 return myPointContainer.max_size();
251}
252
253
254
255
256
257//-----------------------------------------------------------------------------
258template < typename TInputPoint, typename TConstIterator>
259inline
260void
261DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::
262init(const ConstIterator &it)
263{
264 myState.melkmanCH.clear();
265 myNbPointsAddedFromIterators = 0;
266 myIsStoringPoints = false;
267 myBegin = it;
268 myEnd = it;
269 extendFront();
270}
271
272
273//-----------------------------------------------------------------------------
274template < typename TInputPoint, typename TConstIterator>
275inline
276bool
277DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::isExtendableFront(const InputPoint &aPoint )
278{
279 myPreviousState = myState;
280 myPointContainer.push_back(aPoint);
281 myState.melkmanCH.add(aPoint);
282 bool aResult = melkmanIsConvexValid();
283 myPointContainer.pop_back();
284 myState = myPreviousState;
285 return aResult;
286}
287
288
289
290//-----------------------------------------------------------------------------
291template < typename TInputPoint, typename TConstIterator>
292inline
293bool
294DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::extendFront(const InputPoint &aPoint)
295{
296 myPreviousState = myState;
297 myPointContainer.push_back(aPoint);
298 myState.melkmanCH.add(aPoint);
299 if (melkmanIsConvexValid()){
300 if (myPointContainer.size()==1){
301 myState.lastBack = aPoint;
302 }
303 myState.lastFront = aPoint;
304 return true;
305 }else{
306 myPointContainer.pop_back();
307 myState = myPreviousState;
308 return false;
309 }
310}
311
312//-----------------------------------------------------------------------------
313template < typename TInputPoint, typename TConstIterator>
314inline
315bool
316DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::isExtendableFront()
317{
318 myPreviousState = myState;
319 myState.melkmanCH.add(*myEnd);
320 bool aResult = melkmanIsConvexValid();
321 myState = myPreviousState;
322 return aResult;
323}
324
325
326
327//-----------------------------------------------------------------------------
328template < typename TInputPoint, typename TConstIterator>
329inline
330bool
331DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::extendFront()
332{
333 myPreviousState = myState;
334 myState.melkmanCH.add(*myEnd);
335
336 if (melkmanIsConvexValid()){
337 if (myEnd==myBegin){
338 myState.lastBack = *myEnd;
339 }
340 myNbPointsAddedFromIterators++;
341 myState.lastFront = *myEnd;
342 ++myEnd;
343 return true;
344 }else{
345 myState = myPreviousState;
346 return false;
347 }
348}
349
350
351
352
353
354
355//-----------------------------------------------------------------------------
356template < typename TInputPoint, typename TConstIterator>
357inline
358typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::Primitive
359DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::primitive() const
360{
361 PointD vectNormal;
362 double mu, nu;
363 computeParallelStripParams(mu, vectNormal, nu);
364 return Primitive(mu,vectNormal,nu);
365}
366
367
368
369
370//-----------------------------------------------------------------------------
371template < typename TInputPoint, typename TConstIterator>
372inline
373void
374DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::selfDisplay(std::ostream & out) const
375{
376 out << "[Alpha Thick Segment Computer]" << std::endl;
377 out << "Inside points: "<< std::endl;
378 for ( ConstIterator it = myPointContainer.begin(); it != myPointContainer.end(); ++it)
379 {
380 out << *it << " ";
381 }
382 out << std::endl << "Segment thickness : " << myState.actualThickness << std::endl;
383 PointD pt1, pt2, pt3, pt4;
384 getBoundingBox(pt1, pt2, pt3, pt4);
385 out << std::endl << "Bounding box:" << pt1 << " " << pt2 << " " << pt3 << " " << pt4 << std::endl;
386
387}
388
389
390
391
392//-----------------------------------------------------------------------------
393template < typename TInputPoint, typename TConstIterator>
394inline
395bool
396DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::isValid() const
397{
398 return isNotEmpty(myBegin,myEnd);
399}
400
401//-----------------------------------------------------------------------------
402template < typename TInputPoint, typename TConstIterator>
403inline
404std::pair<std::pair<TInputPoint, TInputPoint>, TInputPoint>
405DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getAntipodalLeaningPoints() const
406 {
407 std::pair<std::pair<TInputPoint, TInputPoint>, TInputPoint> r;
408 std::pair<TInputPoint, TInputPoint> edgePair;
409 edgePair.first = myState.edgePh;
410 edgePair.second = myState.edgeQh;
411 r.first = edgePair;
412 r.second = myState.vertexSh;
413 return r;
414 }
415
416//-----------------------------------------------------------------------------
417template < typename TInputPoint, typename TConstIterator>
418inline
419std::pair<TInputPoint, TInputPoint >
420DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getExtremityPoints() const
421{
422 std::pair<TInputPoint, TInputPoint> r;
423 r.first = myState.lastBack;
424 r.second = myState.lastFront;
425 computeExtremaPoints(myState.melkmanCH.begin(), myState.melkmanCH.end() , r.first, r.second);
426 return r;
427}
428
429
430
431//-----------------------------------------------------------------------------
432template < typename TInputPoint, typename TConstIterator>
433inline
434double
435DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::updateMainHeightAndAntiPodal()
436{
437 double chThickness = DGtal::functions::Hull2D::computeHullThickness(myState.melkmanCH.begin(),
438 myState.melkmanCH.end(),
439 myThicknessDefinition,
440 myState.edgePh,
441 myState.edgeQh, myState.vertexSh);
442
443 return floor(chThickness / myThicknessCompPrecision + 0.5) * myThicknessCompPrecision;
444
445}
446
447
448
449
450//-----------------------------------------------------------------------------
451template < typename TInputPoint, typename TConstIterator>
452inline
453bool
454DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::melkmanIsConvexValid()
455{
456 myState.actualThickness = updateMainHeightAndAntiPodal();
457 return myState.actualThickness <= myMaximalThickness;
458}
459
460
461template < typename TInputPoint, typename TConstIterator>
462inline
463std::vector<TInputPoint>
464DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getConvexHull() const
465{
466 std::vector<TInputPoint> aResult;
467 for (typename DGtal::MelkmanConvexHull<TInputPoint, Functor>::ConstIterator it = myState.melkmanCH.begin();
468 it != myState.melkmanCH.end(); it++)
469 {
470 aResult.push_back(*it);
471 }
472 return aResult;
473}
474
475
476
477template < typename TInputPoint, typename TConstIterator>
478inline
479void
480DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getBoundingBoxFromExtremPoints(const InputPoint &aFirstPt,
481 const InputPoint &aLastPt,
482 PointD &pt1LongestSegment1,
483 PointD &pt2LongestSegment1,
484 PointD &pt3LongestSegment2,
485 PointD &pt4LongestSegment2,
486 double minVisibleWidthBounds) const
487{
488
489 // Special case, blurred segment composed only of aligned points.
490 // In this cas the bounding box is restrained to a eplison width rectangle.
491 if(myState.actualThickness==0.0)
492 {
493 PointD vectPQ (aFirstPt[0]- aLastPt[0], aFirstPt[1]- aLastPt[1]);
494 double normPQ = vectPQ.norm();
495 PointD vectUnitPerpPQ (-vectPQ[1]/normPQ, vectPQ[0]/normPQ);
496 pt1LongestSegment1[0]= aFirstPt[0]+vectUnitPerpPQ[0]*minVisibleWidthBounds/2.0;
497 pt1LongestSegment1[1]= aFirstPt[1]+vectUnitPerpPQ[1]*minVisibleWidthBounds/2.0;
498
499 pt2LongestSegment1[0]= aLastPt[0]+vectUnitPerpPQ[0]*minVisibleWidthBounds/2.0;
500 pt2LongestSegment1[1]= aLastPt[1]+vectUnitPerpPQ[1]*minVisibleWidthBounds/2.0;
501
502 pt3LongestSegment2[0]= aLastPt[0]-vectUnitPerpPQ[0]*minVisibleWidthBounds/2.0;
503 pt3LongestSegment2[1]= aLastPt[1]-vectUnitPerpPQ[1]*minVisibleWidthBounds/2.0;
504
505 pt4LongestSegment2[0]= aFirstPt[0]-vectUnitPerpPQ[0]*minVisibleWidthBounds/2.0;
506 pt4LongestSegment2[1]= aFirstPt[1]-vectUnitPerpPQ[1]*minVisibleWidthBounds/2.0;
507
508 }
509 else
510 {
511 PointD projF, projL, projS ;
512 projectOnStraightLine<PointD>(myState.edgePh, myState.edgeQh, aFirstPt, projF);
513 projectOnStraightLine<PointD>(myState.edgePh, myState.edgeQh, aLastPt, projL);
514 projectOnStraightLine<PointD>(myState.edgePh, myState.edgeQh, myState.vertexSh, projS);
515
516 // Shift of the projection of PQ to define the other part of bounds.
517 PointD dep (myState.vertexSh[0]-projS[0], myState.vertexSh[1]-projS[1]);
518 PointD projF2(projF[0]+dep[0], projF[1]+dep[1] );
519 PointD projL2(projL[0]+dep[0], projL[1]+dep[1] );
520
521 pt1LongestSegment1[0]=projF[0];
522 pt1LongestSegment1[1]=projF[1];
523
524 pt2LongestSegment1[0]=projL[0];
525 pt2LongestSegment1[1]=projL[1];
526
527 pt3LongestSegment2[0]=projL2[0];
528 pt3LongestSegment2[1]=projL2[1];
529
530 pt4LongestSegment2[0]=projF2[0];
531 pt4LongestSegment2[1]=projF2[1];
532 }
533 // check orientation of resulting sequence of vertex
534 PointD v1 = pt1LongestSegment1 - pt2LongestSegment1;
535 PointD v2 = pt3LongestSegment2 - pt2LongestSegment1;
536 double orient = v1[0]*v2[1]-v1[1]*v2[0];
537 if (orient < 0)
538 {
539 std::swap(pt1LongestSegment1, pt4LongestSegment2);
540 std::swap(pt2LongestSegment1, pt3LongestSegment2);
541 }
542
543
544
545}
546
547
548
549
550
551
552template < typename TInputPoint, typename TConstIterator>
553inline
554void
555DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getBoundingBox(PointD &pt1LongestSegment1,
556 PointD &pt2LongestSegment1,
557 PointD &pt3LongestSegment2,
558 PointD &pt4LongestSegment2 ) const
559{
560 // handle special case with only one point
561 if (getNumberSegmentPoints() == 1)
562 {
563 TInputPoint p = myState.lastFront;
564 pt1LongestSegment1[0]= p[0]+myMaximalThickness/2.0;
565 pt1LongestSegment1[1]= p[1]+myMaximalThickness/2.0;
566 pt2LongestSegment1[0]= p[0]+myMaximalThickness/2.0;
567 pt2LongestSegment1[1]= p[1]-myMaximalThickness/2.0;
568 pt3LongestSegment2[0]= p[0]-myMaximalThickness/2.0;
569 pt3LongestSegment2[1]= p[1]-myMaximalThickness/2.0;
570 pt4LongestSegment2[0]= p[0]-myMaximalThickness/2.0;
571 pt4LongestSegment2[1]= p[1]+myMaximalThickness/2.0;
572 return;
573 }
574 InputPoint fp = myState.lastBack;
575 InputPoint lp = myState.lastFront;
576 getBoundingBoxFromExtremPoints(fp, lp, pt1LongestSegment1, pt2LongestSegment1,
577 pt3LongestSegment2, pt4LongestSegment2, myMaximalThickness);
578
579 if(myState.actualThickness==0.0)
580 {
581 return;
582 }
583
584 InputPoint extremF = myState.lastFront;
585 InputPoint extremL = myState.lastBack;
586
587 computeExtremaPoints(myState.melkmanCH.begin(), myState.melkmanCH.end() , extremL, extremF);
588 getBoundingBoxFromExtremPoints(extremF, extremL, pt1LongestSegment1, pt2LongestSegment1,
589 pt3LongestSegment2, pt4LongestSegment2, myMaximalThickness);
590}
591
592
593
594template < typename TInputPoint, typename TConstIterator>
595inline
596std::string
597DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::className() const
598{
599 return "AlphaThickSegment";
600}
601
602
603
604template < typename TInputPoint, typename TConstIterator>
605inline
606double
607DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getSegmentLength() const
608{
609 PointD pt1, pt2, pt3, pt4;
610 getBoundingBox(pt1, pt2, pt3, pt4);
611 return (pt2-pt1).norm();
612}
613
614
615
616template < typename TInputPoint, typename TConstIterator>
617inline
618void
619DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::computeParallelStripParams(double &mu,
620 PointD &N,
621 double &nu) const
622{
623 PointD dirSeg = myState.edgeQh - myState.edgePh;
624 N[0] = -dirSeg[1];
625 N[1] = dirSeg[0];
626 mu = (N[0]*myState.edgePh[0]+N[1]*myState.edgePh[1]);
627 nu = N[0]*myState.vertexSh[0]+N[1]*myState.vertexSh[1] - mu;
628}
629
630
631template < typename TInputPoint, typename TConstIterator>
632inline
633double
634DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getThickness() const
635{
636 return myState.actualThickness;
637}
638
639
640template < typename TInputPoint, typename TConstIterator>
641inline
642typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::PointD
643DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getNormal() const
644{
645 return primitive().normal();
646}
647
648
649template < typename TInputPoint, typename TConstIterator>
650inline
651double
652DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getMu() const
653{
654 return primitive().mu();
655}
656
657
658template < typename TInputPoint, typename TConstIterator>
659inline
660double
661 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getNu() const
662{
663 return primitive().nu();
664}
665
666
667template < typename TInputPoint, typename TConstIterator>
668inline
669bool
670DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::isStoringSegmentPoints() const
671{
672 return myIsStoringPoints;
673}
674
675
676
677template < typename TInputPoint, typename TConstIterator>
678inline
679unsigned int
680DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getNumberSegmentPoints() const
681{
682 return static_cast<unsigned int>(myNbPointsAddedFromIterators+myPointContainer.size());
683}
684
685
686
687template < typename TInputPoint, typename TConstIterator>
688template<typename TPoint, typename TPointD>
689inline
690bool
691DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::projectOnStraightLine(const TPoint & ptA,
692 const TPoint & ptB,
693 const TPoint & ptC,
694 TPointD & ptProjected) const
695{
696 if (ptA==ptC)
697 {
698 ptProjected=ptA;
699 return true;
700 }
701 if (ptB==ptC)
702 {
703 ptProjected=ptB;
704 return true ;
705 }
706
707 TPointD vAB (ptB[0]- ptA[0], ptB[1]- ptA[1]);
708 PointD vABn ((double)vAB[0], (double)vAB[1]);
709 vABn = vABn/vABn.norm();
710 PointD vAC (ptC[0]-ptA[0], ptC[1]-ptA[1]);
711 double distPtA_Proj = vAC.dot(vABn);
712
713 ptProjected[0]= ptA[0]+vABn[0]*(distPtA_Proj);
714 ptProjected[1] = ptA[1]+vABn[1]*(distPtA_Proj);
715
716 return distPtA_Proj>=0 && ((ptA[0]<ptB[0] && ptProjected[0]<=ptB[0] ) ||
717 (ptA[0]>ptB[0] && ptProjected[0]>=ptB[0] ) ||
718 (ptA[0]==ptB[0] && ptA[1]<ptB[1] && ptProjected[1]<=ptB[1]) ||
719 (ptA[0]==ptB[0] && ptA[1]>=ptB[1] && ptProjected[1]>=ptB[1]));
720}
721
722
723
724template< typename TInputPoint, typename TConstIterator>
725template<typename TConstIteratorG>
726void
727DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::
728computeExtremaPoints(const TConstIteratorG & itBegin,
729 const TConstIteratorG & itEnd,
730 InputPoint & aFirstExtrPt,
731 InputPoint & aLastExtrPt) const
732{
733 // To be changed with saved point added by push front/push back
734 InputPoint extremF = myState.lastBack;
735 InputPoint extremL = myState.lastFront;
736
737 PointD projExtremF;
738 PointD projExtremL;
739
740 projectOnStraightLine(myState.edgePh, myState.edgeQh, extremF, projExtremF);
741 projectOnStraightLine(myState.edgePh, myState.edgeQh, extremL, projExtremL);
742
743 InputPoint peF = InputPoint(projExtremF, functors::Round<>());
744 InputPoint peL = InputPoint(projExtremL, functors::Round<>());
745
746 for(TConstIteratorG it = itBegin; it != itEnd; it++)
747 {
748 InputPoint p = *it;
749 PointD projPointEnvConv;
750 bool isNewExtrema = !projectOnStraightLine(peF, peL, p, projPointEnvConv);
751 if(isNewExtrema)
752 {
753 double distFirst = (projPointEnvConv-projExtremF).norm();
754 double distLast = (projPointEnvConv- projExtremL).norm();
755 if(distFirst>= distLast)
756 {
757 aLastExtrPt = p;
758 peL = InputPoint( projPointEnvConv, functors::Round<>());
759 }
760 else
761 {
762 aFirstExtrPt = p;
763 peF = InputPoint( projPointEnvConv, functors::Round<>());
764 }
765 }
766 }
767
768}
769
770
771///////////////////////////////////////////////////////////////////////////////
772// Implementation of inline functions and external operators //
773
774/**
775 * Overloads 'operator<<' for displaying objects of class 'AlphaThickSegmentComputer'.
776 * @param out the output stream where the object is written.
777 * @param object the object of class 'AlphaThickSegmentComputer' to write.
778 * @return the output stream after the writing.
779 */
780template < typename TInputPoint, typename TConstIterator>
781inline
782std::ostream&
783DGtal::operator<< ( std::ostream & out,
784 const AlphaThickSegmentComputer< TInputPoint, TConstIterator> & object )
785{
786 object.selfDisplay ( out );
787 return out;
788}
789
790// //
791///////////////////////////////////////////////////////////////////////////////
792
793