DGtal  0.9.2
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 //-----------------------------------------------------------------------------
54 template < typename TInputPoint, typename TConstIterator>
55 inline
56 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::~AlphaThickSegmentComputer()
57 {
58 }
59 
60 //-----------------------------------------------------------------------------
61 template < typename TInputPoint, typename TConstIterator>
62 inline
63 DGtal::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 //-----------------------------------------------------------------------------
78 template < typename TInputPoint, typename TConstIterator>
79 inline
80 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::
81 AlphaThickSegmentComputer( 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 
94 template < typename TInputPoint, typename TConstIterator>
95 inline
96 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator> &
97 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::
98 operator= ( 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 //-----------------------------------------------------------------------------
121 template < typename TInputPoint, typename TConstIterator>
122 inline
123 typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::Self
124 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getSelf() const
125 {
126  return Self(myMaximalThickness, myThicknessDefinition, myThicknessCompPrecision);
127 }
128 
129 
130 
131 //-----------------------------------------------------------------------------
132 template < typename TInputPoint, typename TConstIterator>
133 inline
134 typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::Reverse
135 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getReverse() const
136 {
137  return Reverse (myMaximalThickness, myThicknessDefinition, myThicknessCompPrecision);
138 }
139 
140 
141 template < typename TInputPoint, typename TConstIterator>
142 inline
143 bool
144 DGtal::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 
151 template < typename TInputPoint, typename TConstIterator>
152 inline
153 bool
154 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::operator!=( const AlphaThickSegmentComputer & other ) const{
155  return (!(*this == other));
156 }
157 
158 
159 //-----------------------------------------------------------------------------
160 template < typename TInputPoint, typename TConstIterator>
161 inline
162 typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::Size
163 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::size() const
164 {
165  return myPointContainer.size();
166 }
167 
168 
169 //-----------------------------------------------------------------------------
170 template < typename TInputPoint, typename TConstIterator>
171 inline
172 bool
173 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::empty() const
174 {
175  return myPointContainer.empty();
176 }
177 
178 
179 //-----------------------------------------------------------------------------
180 template < typename TInputPoint, typename TConstIterator>
181 inline
182 typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::ConstIterator
183 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::begin() const
184 {
185  return myBegin;
186 }
187 
188 
189 
190 //-----------------------------------------------------------------------------
191 template < typename TInputPoint, typename TConstIterator>
192 inline
193 typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::ConstIterator
194 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::end() const
195 {
196  return myEnd;
197 }
198 
199 //-----------------------------------------------------------------------------
200 template < typename TInputPoint, typename TConstIterator>
201 inline
202 typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::ContainerConstIterator
203 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::containerBegin() const
204 {
205  return myPointContainer.begin();
206 }
207 
208 
209 
210 //-----------------------------------------------------------------------------
211 template < typename TInputPoint, typename TConstIterator>
212 inline
213 typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::ContainerConstIterator
214 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::containerEnd() const
215 {
216  return myPointContainer.end();
217 }
218 
219 
220 
221 //-----------------------------------------------------------------------------
222 template < typename TInputPoint, typename TConstIterator>
223 inline
224 typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::ConvexhullConstIterator
225 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::convexhullBegin() const
226 {
227  return myState.melkmanCH.begin();
228 }
229 
230 
231 
232 //-----------------------------------------------------------------------------
233 template < typename TInputPoint, typename TConstIterator>
234 inline
235 typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::ConvexhullConstIterator
236 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::convexhullEnd() const
237 {
238  return myState.melkmanCH.end();
239 }
240 
241 
242 
243 
244 //-----------------------------------------------------------------------------
245 template < typename TInputPoint, typename TConstIterator>
246 inline
247 typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::Size
248 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::max_size() const
249 {
250  return myPointContainer.max_size();
251 }
252 
253 
254 
255 
256 
257 //-----------------------------------------------------------------------------
258 template < typename TInputPoint, typename TConstIterator>
259 inline
260 void
261 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::
262 init(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 //-----------------------------------------------------------------------------
274 template < typename TInputPoint, typename TConstIterator>
275 inline
276 bool
277 DGtal::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 //-----------------------------------------------------------------------------
291 template < typename TInputPoint, typename TConstIterator>
292 inline
293 bool
294 DGtal::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 //-----------------------------------------------------------------------------
313 template < typename TInputPoint, typename TConstIterator>
314 inline
315 bool
316 DGtal::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 //-----------------------------------------------------------------------------
328 template < typename TInputPoint, typename TConstIterator>
329 inline
330 bool
331 DGtal::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 //-----------------------------------------------------------------------------
356 template < typename TInputPoint, typename TConstIterator>
357 inline
358 typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::Primitive
359 DGtal::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 //-----------------------------------------------------------------------------
371 template < typename TInputPoint, typename TConstIterator>
372 inline
373 void
374 DGtal::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 //-----------------------------------------------------------------------------
393 template < typename TInputPoint, typename TConstIterator>
394 inline
395 bool
396 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::isValid() const
397 {
398  return isNotEmpty(myBegin,myEnd);
399 }
400 
401 //-----------------------------------------------------------------------------
402 template < typename TInputPoint, typename TConstIterator>
403 inline
404 std::pair<std::pair<TInputPoint, TInputPoint>, TInputPoint>
405 DGtal::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 //-----------------------------------------------------------------------------
417 template < typename TInputPoint, typename TConstIterator>
418 inline
419 std::pair<TInputPoint, TInputPoint >
420 DGtal::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 //-----------------------------------------------------------------------------
432 template < typename TInputPoint, typename TConstIterator>
433 inline
434 double
435 DGtal::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 //-----------------------------------------------------------------------------
451 template < typename TInputPoint, typename TConstIterator>
452 inline
453 bool
454 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::melkmanIsConvexValid()
455 {
456  myState.actualThickness = updateMainHeightAndAntiPodal();
457  return myState.actualThickness <= myMaximalThickness;
458 }
459 
460 
461 template < typename TInputPoint, typename TConstIterator>
462 inline
463 std::vector<TInputPoint>
464 DGtal::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 
477 template < typename TInputPoint, typename TConstIterator>
478 inline
479 void
480 DGtal::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(myState.edgePh, myState.edgeQh, aFirstPt, projF);
513  projectOnStraightLine(myState.edgePh, myState.edgeQh, aLastPt, projL);
514  projectOnStraightLine(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 
552 template < typename TInputPoint, typename TConstIterator>
553 inline
554 void
555 DGtal::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 
594 template < typename TInputPoint, typename TConstIterator>
595 inline
596 std::string
597 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::className() const
598 {
599  return "AlphaThickSegment";
600 }
601 
602 
603 
604 template < typename TInputPoint, typename TConstIterator>
605 inline
606 double
607 DGtal::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 
616 template < typename TInputPoint, typename TConstIterator>
617 inline
618 void
619 DGtal::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 
631 template < typename TInputPoint, typename TConstIterator>
632 inline
633 double
634 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getThickness() const
635 {
636  return myState.actualThickness;
637 }
638 
639 
640 template < typename TInputPoint, typename TConstIterator>
641 inline
642 typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::PointD
643 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getNormal() const
644 {
645  return primitive().normal();
646 }
647 
648 
649 template < typename TInputPoint, typename TConstIterator>
650 inline
651 double
652 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getMu() const
653 {
654  return primitive().mu();
655 }
656 
657 
658 template < typename TInputPoint, typename TConstIterator>
659 inline
660 double
661  DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getNu() const
662 {
663  return primitive().nu();
664 }
665 
666 
667 template < typename TInputPoint, typename TConstIterator>
668 inline
669 bool
670 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::isStoringSegmentPoints() const
671 {
672  return myIsStoringPoints;
673 }
674 
675 
676 
677 template < typename TInputPoint, typename TConstIterator>
678 inline
679 unsigned int
680 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::getNumberSegmentPoints() const
681 {
682  return myNbPointsAddedFromIterators+myPointContainer.size();
683 }
684 
685 
686 
687 template < typename TInputPoint, typename TConstIterator>
688 template<typename TPointD>
689 inline
690 bool
691 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::projectOnStraightLine(const TPointD & ptA,
692  const TPointD & ptB,
693  const TPointD & ptC,
694  PointD & 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 
724 template< typename TInputPoint, typename TConstIterator>
725 template<typename TConstIteratorG>
726 void
727 DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::
728 computeExtremaPoints(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 
744  for(TConstIteratorG it = itBegin; it != itEnd; it++)
745  {
746  InputPoint p = *it;
747  PointD pointEnvConv = PointD(p[0], p[1]);
748  PointD projPointEnvConv;
749  bool isNewExtrema = !projectOnStraightLine(projExtremF, projExtremL, pointEnvConv, projPointEnvConv);
750  if(isNewExtrema)
751  {
752  double distFirst = (projPointEnvConv-projExtremF).norm();
753  double distLast = (projPointEnvConv- projExtremL).norm();
754  if(distFirst>= distLast)
755  {
756  aLastExtrPt = pointEnvConv;
757  projExtremL = projPointEnvConv;
758  }
759  else
760  {
761  aFirstExtrPt = pointEnvConv;
762  projExtremF = projPointEnvConv;
763  }
764  }
765  }
766 
767 }
768 
769 
770 ///////////////////////////////////////////////////////////////////////////////
771 // Implementation of inline functions and external operators //
772 
773 /**
774  * Overloads 'operator<<' for displaying objects of class 'AlphaThickSegmentComputer'.
775  * @param out the output stream where the object is written.
776  * @param object the object of class 'AlphaThickSegmentComputer' to write.
777  * @return the output stream after the writing.
778  */
779 template < typename TInputPoint, typename TConstIterator>
780 inline
781 std::ostream&
782 DGtal::operator<< ( std::ostream & out,
783  const AlphaThickSegmentComputer< TInputPoint, TConstIterator> & object )
784 {
785  object.selfDisplay ( out );
786  return out;
787 }
788 
789 // //
790 ///////////////////////////////////////////////////////////////////////////////
791 
792