DGtal  0.6.devel
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
FP.ih
1 
30 
31 #include <cstdlib>
33 
35 // IMPLEMENTATION of inline methods.
37 
39 // ----------------------- Standard services ------------------------------
40 
41 
42 template <typename TIterator, typename TInteger, int connectivity>
43 template<typename DSS, typename Adapter>
44 inline
45 bool
48  Adapter* &anAdapter,
49  const typename DSS::ConstIterator& i ) {
50 
51  bool flag;
52  if ( aDSS.getRemainder(i) < (aDSS.getMu()) ) { //concave part
53  flag = false;
54  anAdapter = new Adapter4ConcavePart<DSS>(aDSS);
55  } else { //convex part
56  flag = true;
57  anAdapter = new Adapter4ConvexPart<DSS>(aDSS);
58  }
59  return flag;
60 }
61 
62 template <typename TIterator, typename TInteger, int connectivity>
63 template<typename DSS, typename Adapter>
64 inline
65 void
67 ::mainAlgorithm( DSS &currentDSS, Adapter* adapter,
68  bool isConvex,
69  typename DSS::ConstIterator i,
70  const typename DSS::ConstIterator& end ) throw( InputException ) {
71 
72  ASSERT(adapter != 0);
73 
74  //std::cerr << "first DSS" << std::endl;
75  //std::cerr << currentDSS << std::endl;
76 
77  while (i != end) {
78 
79  //store the last leaning point
80  //if the first and last leaning points
81  //of the MS are not confounded
82  if (adapter->firstLeaningPoint() != adapter->lastLeaningPoint()) {
83  myPolygon.push_back(adapter->lastLeaningPoint());
84  }
85 
86  //removing step
87  while (!currentDSS.isExtendableForward(i)) {
88  //remove a point from the back
89  if ( currentDSS.retractForward() ) {
90  //store the last leaning point
91  if (adapter->lastLeaningPoint() != myPolygon.back()) {
92  myPolygon.push_back(adapter->lastLeaningPoint());
93  }
94  } else {
95  //disconnected digital curve
96  throw InputException();
97  }
98  }
99 
100  //remove the last leaning point
101  //if the first and last leaning points
102  //of the current DSS are not confounded
103  if (adapter->firstLeaningPoint() != adapter->lastLeaningPoint()) {
104  myPolygon.pop_back();
105  }
106 
107  //adding step
108  while ( (i != end)&&(currentDSS.extendForward(i)) ) {
109  //store the first leaning point
110  if (adapter->firstLeaningPoint() != myPolygon.back()) {
111  myPolygon.push_back(adapter->firstLeaningPoint());
112  }
113  ++i; //move forward
114  }
115 
116  //transition step
117  if (i != end) {
118 
119  if ( (isConvex)&&( currentDSS.getRemainder(i) <
120  (currentDSS.getMu()) ) ) {
121  //from convex to concave
122  isConvex = false;
123  delete (adapter);
124  adapter = new Adapter4ConcavePart<DSS>(currentDSS);
125  } else if ( (!isConvex)&&( currentDSS.getRemainder(i) >=
126  (currentDSS.getMu()+currentDSS.getOmega()) ) ) {
127  //from concave to convex
128  isConvex = true;
129  delete (adapter);
130  adapter = new Adapter4ConvexPart<DSS>(currentDSS);
131  }
132  }
133 
134  }
135 
136  //std::cerr << "last DSS" << std::endl;
137  //std::cerr << currentDSS << std::endl;
138 
139  //last removing step
140  while (currentDSS.retractForward()) {
141  //store the last leaning point
142  if (adapter->lastLeaningPoint() != myPolygon.back()) {
143  myPolygon.push_back(adapter->lastLeaningPoint());
144  }
145  }
146 
147 }
148 
149 
150 template <typename TIterator, typename TInteger, int connectivity>
151 inline
153  const TIterator& itb,
154  const TIterator& ite ) throw( InputException )
155 {
156  FP(itb, ite, false);
157 }
158 
159 template <typename TIterator, typename TInteger, int connectivity>
160 inline
162  const TIterator& itb,
163  const TIterator& ite,
164  const bool& isClosed ) throw( InputException )
165  : myFlagIsClosed( isClosed )
166 {
167 
168  TIterator i = itb;
169  if (i != ite)
170  {
171  if (myFlagIsClosed)
172  {
173  //first maximal DSS
174  Circulator<TIterator> citb(i,itb,ite);
175  //DSSComputerInLoop firstMS(citb);
176  DSSComputerInLoop *firstMS=new DSSComputerInLoop(citb); //init
177 
178  ASSERT(firstMS);
179 
180  //backward extension
181  Circulator<TIterator> back( citb );
182  do {
183  --back;
184  } while (firstMS->extendBackward(back));
185  //forward extension
186  Circulator<TIterator> front( citb );
187  do {
188  ++front;
189  } while (firstMS->extendForward(front));
190 
191  //local convexity
192  bool isConvexAtFront;
193  Adapter<DSSComputerInLoop>* adapterAtFront;
194 
195  isConvexAtFront = initConvexityConcavity<DSSComputerInLoop,Adapter<DSSComputerInLoop> >
196  (*firstMS,adapterAtFront,front);
197 
198  bool isConvexAtBack;
199  Adapter<DSSComputerInLoop>* adapterAtBack;
200 
201  isConvexAtBack = initConvexityConcavity<DSSComputerInLoop,Adapter<DSSComputerInLoop> >
202  (*firstMS,adapterAtBack,back);
203 
204  ASSERT(adapterAtFront);
205  ASSERT(adapterAtBack);
206 
207 
208  //first point
209  if (adapterAtFront->firstLeaningPoint() == adapterAtFront->lastLeaningPoint()) {
210  myPolygon.push_back(adapterAtFront->lastLeaningPoint());
211  }
212 
213  //set end iterator
214  typename DSSComputerInLoop::Point leaningPoint;
215  if ( ( (isConvexAtFront)&&(isConvexAtBack) )
216  || ( (!isConvexAtFront)&&(!isConvexAtBack) ) ) {
217  leaningPoint = adapterAtFront->lastLeaningPoint();
218  } else {
219  leaningPoint = adapterAtBack->firstLeaningPoint();
220  }
221  do {
222  ++back;
223  } while (*back != leaningPoint);
224  ++back;
225 
226  //call main algo
227  mainAlgorithm<DSSComputerInLoop,Adapter<DSSComputerInLoop> >
228  (*firstMS,adapterAtFront,isConvexAtFront,front,back);
229 
230  ASSERT(adapterAtFront);
231  ASSERT(adapterAtBack);
232 
233  //delete (adapterAtFront);
234  //delete (adapterAtBack);
235  delete (firstMS);
236  //remove the last point
237  myPolygon.pop_back();
238 
239  }
240  else
241  {
242  //list of successive upper (U) and lower (L)
243  // leaning points.
244  std::list<Point> vTmpU, vTmpL;
245  vTmpU.push_back(*i);
246  vTmpL.push_back(*i);
247 
248  //longest DSS
249  DSSComputer *longestDSS= new DSSComputer(i); //longest DSS
250 
251  ASSERT(longestDSS);
252 
253  ++i; //move forward
254  while ( (i != ite)&&(longestDSS->extendForward(i)) )
255  {
256  //store the first upper leaning point
257  if (longestDSS->getUf() != vTmpU.back()) {
258  vTmpU.push_back(longestDSS->getUf());
259  }
260  //store the first lower leaning point
261  if (longestDSS->getLf() != vTmpL.back()) {
262  vTmpL.push_back(longestDSS->getLf());
263  }
264  ++i; //move forward
265  }
266 
267  bool isConvex; //TRUE if longestDSS begins a convex part, FALSE otherwise
268  Adapter<DSSComputer>* adapter; //adapter for the current DSS
269 
270  if (i != ite)
271  {
272  isConvex = initConvexityConcavity<DSSComputer,Adapter<DSSComputer> >
273  (*longestDSS,adapter,i);
274 
275  ASSERT(adapter);
276 
277  if (isConvex) myPolygon = vTmpU;
278  else myPolygon = vTmpL;
279 
280  //call main algo
281  mainAlgorithm<DSSComputer,Adapter<DSSComputer> >
282  (*longestDSS,adapter,isConvex,i,ite);
283 
284  ASSERT(adapter);
285  //delete (adapter);
286  delete (longestDSS);
287  }
288  else
289  {
290  //the part is assumed to be convex
291  //if it is straight
292  myPolygon = vTmpU;
293  isConvex = true;
294  adapter = new Adapter4ConvexPart<DSSComputer>(*longestDSS);
295  ASSERT(adapter);
296  }
297 
298  }//end closed/open test
299 
300  } //end itb == ite test
301 
302 }
303 
304 template <typename TIterator, typename TInteger, int connectivity>
305 inline
307 {
308 }
309 
311 // Interface - public :
312 
313 template <typename TIterator, typename TInteger, int connectivity>
314 inline
315 bool
317 {
318  return true;
319 }
320 
321 template <typename TIterator, typename TInteger, int connectivity>
322 inline
325 {
326  return myPolygon.size();
327 }
328 
329 
330 template <typename TIterator, typename TInteger, int connectivity>
331 template <typename OutputIterator>
332 inline
333 OutputIterator
335  typename Polygon::const_iterator i = myPolygon.begin();
336  while ( i != myPolygon.end() ) {
337  *result++ = *i++;
338  }
339  return result;
340 }
341 
342 template <typename TIterator, typename TInteger, int connectivity>
343 template <typename OutputIterator>
344 inline
345 OutputIterator
347 
348  unsigned int n = (unsigned int) myPolygon.size();
349  if (n < 3) { //special case < 3 points
350 
351  typename Polygon::const_iterator i = myPolygon.begin();
352  for ( ; i!= myPolygon.end() ; ++i) {
353  *result++ = RealPoint( *i );
354  }
355 
356  } else { //standard case
357 
358  typename Polygon::const_iterator i, j, k;
359  i = myPolygon.begin();
360  j = i; ++j;
361  k = j; ++k;
362 
363  if (myFlagIsClosed) {
364 
365  //first point
366  *result++ = getRealPoint(myPolygon.back(),*i,*j);
367  //middle points
368  while ( k != myPolygon.end() ) {
369  *result++ = getRealPoint(*i,*j,*k);
370  ++i; ++j; ++k;
371  }
372  //last point
373  *result++ = getRealPoint(*i,*j,myPolygon.front());
374 
375  } else {
376 
377  //first point
378  *result++ = RealPoint( myPolygon.front() );
379  //middle points
380  while ( k != myPolygon.end() ) {
381  *result++ = getRealPoint(*i,*j,*k);
382  ++i; ++j; ++k;
383  }
384  //last point
385  *result++ = RealPoint( myPolygon.back() );
386 
387  }
388 
389  }
390  return result;
391 }
392 
393 template <typename TIterator, typename TInteger, int connectivity>
394 inline
397 ::getRealPoint (const Point& a,const Point& b, const Point& c) const {
398 
399  RealVector shift;
400 
401  Vector e1 = b - a; //previous edge
402  Vector e2 = c - b; //next edge
403 
404  if ( (e1[0]*e2[1]-e1[1]*e2[0]) <= 0 ) {
405 
406  //convex turn
407  if ( (quadrant(e1,1))&&(quadrant(e2,1)) ) {
408  shift = RealVector(0.5,-0.5);
409  } else if ( (quadrant(e1,2))&&(quadrant(e2,2)) ) {
410  shift = RealVector(-0.5,-0.5);
411  } else if ( (quadrant(e1,3))&&(quadrant(e2,3)) ) {
412  shift = RealVector(-0.5,0.5);
413  } else if ( (quadrant(e1,4))&&(quadrant(e2,4)) ) {
414  shift = RealVector(0.5,0.5);
415  } else {
416  ASSERT(false && "DGtal::FP<TIterator,TInteger,connectivity>::getRealPoint: not valid polygon" );
417  }
418 
419  } else {
420 
421  //concave turn
422  if ( (quadrant(e1,1))&&(quadrant(e2,1)) ) {
423  shift = RealVector(-0.5,0.5);
424  } else if ( (quadrant(e1,2))&&(quadrant(e2,2)) ) {
425  shift = RealVector(0.5,0.5);
426  } else if ( (quadrant(e1,3))&&(quadrant(e2,3)) ) {
427  shift = RealVector(0.5,-0.5);
428  } else if ( (quadrant(e1,4))&&(quadrant(e2,4)) ) {
429  shift = RealVector(-0.5,-0.5);
430  } else {
431  ASSERT(false && "DGtal::FP<TIterator,TInteger,connectivity>::getRealPoint: not valid polygon" );
432  }
433 
434  }
435 
436  return ( RealPoint(b) + shift );
437 }
438 
439 template <typename TIterator, typename TInteger, int connectivity>
440 inline
441 bool
443 ::quadrant (const Vector& v, const int& q) const {
444 
445  if (q == 1) {
446  return ( (v[0]>=0)&&(v[1]>=0) );
447  } else if (q == 2) {
448  return ( (v[0]>=0)&&(v[1]<=0) );
449  } else if (q == 3) {
450  return ( (v[0]<=0)&&(v[1]<=0) );
451  } else if (q == 4) {
452  return ( (v[0]<=0)&&(v[1]>=0) );
453  } else {
454  ASSERT(false &&
455  "DGtal::FP<TIterator,TInteger,connectivity>::quadrant: quadrant number should be 0,1,2 or 3" );
456  return false;
457  }
458 }
459 
461 // Display :
462 
463 template <typename TIterator, typename TInteger, int connectivity>
464 inline
465 std::string
467 {
468  return "FP";
469 }
470 
471 
472 template <typename TIterator, typename TInteger, int connectivity>
473 inline
474 void
476 {
477  out << "[FP]" << endl;
478  typename Polygon::const_iterator i = myPolygon.begin();
479  for ( ;i != myPolygon.end();++i)
480  {
481  out << "\t " << (*i) << endl;
482  }
483  out << "[end FP]" << endl;
484 }
485 
486 
487 
488 
489 
491 // Implementation of inline functions //
492 
493 template <typename TIterator, typename TInteger, int connectivity>
494 inline
495 std::ostream&
496 DGtal::operator<< ( std::ostream & out,
497  const FP<TIterator,TInteger,connectivity> & object )
498 {
499  object.selfDisplay( out );
500  return out;
501 }
502 
503 // //
505 
506