DGtal  0.6.devel
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StandardDSLQ0.ih
1 
30 
31 #include <cstdlib>
33 
35 // IMPLEMENTATION of inline methods.
37 
39 // ----------------------- Standard services ------------------------------
40 
41 //-----------------------------------------------------------------------------
42 template <typename TFraction>
43 inline
46 {
47 }
48 //-----------------------------------------------------------------------------
49 template <typename TFraction>
50 inline
53  : myPattern()
54 {
55 }
56 //-----------------------------------------------------------------------------
57 template <typename TFraction>
58 inline
60 StandardDSLQ0 ( const Self & other )
61  : myPattern( other.myPattern ), myMu( other.myMu )
62 {
63 }
64 //-----------------------------------------------------------------------------
65 template <typename TFraction>
66 inline
69 operator= ( const Self & other )
70 {
71  myPattern = other.myPattern;
72  myMu = other.myMu;
73  return *this;
74 }
75 //-----------------------------------------------------------------------------
76 template <typename TFraction>
77 inline
80  : myPattern( aSlope ), myMu( aMu )
81 {
82 }
83 //-----------------------------------------------------------------------------
84 template <typename TFraction>
85 inline
88  : myPattern( a1, b1 ), myMu( mu1 )
89 {
90 }
91 //-----------------------------------------------------------------------------
92 template <typename TFraction>
93 inline
94 bool
96 operator()( const Point & p ) const
97 {
98  if ( slope().null() ) return false;
99  Integer _r = r( p );
100  return ( mu() <= _r ) && ( _r < ( mu() + pattern().length() ) );
101 }
102 //-----------------------------------------------------------------------------
103 template <typename TFraction>
104 inline
107 r( const Point & p ) const
108 {
109  ASSERT( ! slope().null() );
110  return a() * p[ 0 ] - b() * p[ 1 ];
111 }
112 //-----------------------------------------------------------------------------
113 template <typename TFraction>
114 inline
117 slope() const
118 {
119  return pattern().slope();
120 }
121 //-----------------------------------------------------------------------------
122 template <typename TFraction>
123 inline
126 pattern() const
127 {
128  return myPattern;
129 }
130 //-----------------------------------------------------------------------------
131 template <typename TFraction>
132 inline
135 mu() const
136 {
137  return myMu;
138 }
139 //-----------------------------------------------------------------------------
140 template <typename TFraction>
141 inline
144 mup() const
145 {
146  return myMu + pattern().length() - NumberTraits<Integer>::ONE;
147 }
148 //-----------------------------------------------------------------------------
149 template <typename TFraction>
150 inline
153 a() const
154 {
155  return slope().p();
156 }
157 //-----------------------------------------------------------------------------
158 template <typename TFraction>
159 inline
162 b() const
163 {
164  return slope().q();
165 }
166 //-----------------------------------------------------------------------------
167 template <typename TFraction>
168 inline
171 v() const
172 {
173  return pattern().v();
174 }
175 //-----------------------------------------------------------------------------
176 template <typename TFraction>
177 inline
180 U() const
181 {
182  Vector2I u = pattern().bezout();
183  Integer c = ( mu() * u[ 0 ] ) / b();
184  return Point( mu() > NumberTraits<Integer>::ZERO
185  ? v() * ( c + 1 ) - u * mu()
186  : u * mu() - v() * c );
187 }
188 //-----------------------------------------------------------------------------
189 template <typename TFraction>
190 inline
193 L() const
194 {
195  return Point( U() + pattern().L( NumberTraits<Quotient>::ZERO ) );
196 }
197 //-----------------------------------------------------------------------------
198 template <typename TFraction>
199 inline
203 {
204  Integer q = a() * x - mup();
205  return Point( x, ic.ceilDiv( q, b() ) );
206 }
207 //-----------------------------------------------------------------------------
208 template <typename TFraction>
209 inline
213 {
214  Integer q = a() * x - mu();
215  return Point( x, ic.floorDiv( q, b() ) );
216 }
217 //-----------------------------------------------------------------------------
218 template <typename TFraction>
219 inline
223 {
224  Integer q = mu() + b() * y;
225  return Point( ic.ceilDiv( q, a() ), y );
226 }
227 //-----------------------------------------------------------------------------
228 template <typename TFraction>
229 inline
233 {
234  Integer q = mup() + b() * y;
235  return Point( ic.floorDiv( q, a() ), y );
236 }
237 //-----------------------------------------------------------------------------
238 template <typename TFraction>
239 inline
240 bool
242 before( const Point & p1, const Point & p2 ) const
243 {
244  return ( p1[ 0 ] < p2[ 0 ] )
245  || ( ( p1[ 0 ] == p2[ 0 ] ) && ( p1[ 1 ] < p2[ 1 ] ) );
246 }
247 //-----------------------------------------------------------------------------
248 template <typename TFraction>
249 inline
250 bool
252 beforeOrEqual( const Point & p1, const Point & p2 ) const
253 {
254  return ( p1[ 0 ] < p2[ 0 ] )
255  || ( ( p1[ 0 ] == p2[ 0 ] ) && ( p1[ 1 ] <= p2[ 1 ] ) );
256 }
257 //-----------------------------------------------------------------------------
258 template <typename TFraction>
261 begin( Point p ) const
262 {
263  return ConstIterator( *this, p );
264 }
265 //-----------------------------------------------------------------------------
266 template <typename TFraction>
269 end( Point p ) const
270 {
271  ConstIterator it( *this, p );
272  return ++it;
273 }
274 
275 //-----------------------------------------------------------------------------
276 template <typename TFraction>
279 reversedSmartDSS( const Point & A, const Point & B ) const
280 {
281  Point _U = U();
282  Integer cA = ic.floorDiv( A[ 0 ] - _U[ 0 ], v()[ 0 ] );
283  Point U1 = _U + v() * cA;
284  Integer cB = ic.ceilDiv( B[ 0 ] - _U[ 0 ], v()[ 0 ] );
285  Point U2 = _U + v() * cB;
286  if ( before( A, U1 ) ) U1 -= v();
287  if ( before( U2, B ) ) U2 += v();
288  return reversedSmartDSS( U1, U2, A, B );
289 }
290 
291 //-----------------------------------------------------------------------------
292 template <typename TFraction>
296  const Point & A, const Point & B ) const
297 {
298  #ifdef TRACE_DSL
299  std::cerr << "[reversedSmartDSS] " << (*this)
300  << " " << pattern().rE() << std::endl
301  << " +- U1=" << U1 << " A=" << A
302  << " B=" << B << " U2=" << U2 << std::endl
303  << " v()=" << pattern().v()
304  << " u()=" << pattern().bezout()
305  << " r(U())=" << r(U())
306  << " mu=" << mu() << " r(U1)=" << r(U1)
307  << " r(U2)=" << r(U2)
308  << " r(A)=" << r(A)
309  << " r(B)=" << r(B)
310  << " mup=" << mup()
311  << " DSS(A)=" << this->operator()( A )
312  << " DSS(B)=" << this->operator()( B ) << std::endl;
313  #endif
314  ASSERT( ! slope().null() );
315  ASSERT( r( U1 ) == mu() && r( U2 ) == mu()
316  && this->operator()( A ) && this->operator()( B ) );
317  ASSERT( beforeOrEqual( U1, A ) );
318  ASSERT( before( A, B ) );
319  ASSERT( beforeOrEqual( B, U2 ) );
320  if ( A[ 0 ] == B[ 0 ] ) return Self( 1, 0, A[ 0 ] );
321  if ( A[ 1 ] == B[ 1 ] ) return Self( 0, 1, -A[ 1 ] );
322  Integer dU = U2[ 0 ] - U1[ 0 ];
323  ASSERT( dU >= b() );
324 #ifdef TRACE_DSL
325  std::cerr << " +- dU=" << dU << std::endl;
326 #endif
327  if ( ( dU >= (3*b()) )
328  || ( ( dU == (2*b()) ) && ( A == U1 || B == U2 ) )
329  || ( A == U1 && B == U2 ) )
330  {
331 #ifdef TRACE_DSL
332  std::cerr << "[reversedSmartDSS] 3 patterns || ..." << std::endl;
333 #endif
334  return *this;
335  }
336  // [A,B] is included in two patterns of this DSL.
337  if ( dU == (2*b()) )
338  {
339 #ifdef TRACE_DSL
340  std::cerr << "[reversedSmartDSS] 2 patterns" << std::endl;
341 #endif
342  return DSSWithinTwoPatterns( U1, U2, A, B );
343  }
344  // [A,B] is included in one patterns of this DSL.
345  Pattern<Fraction> subpattern;
346  Quotient nb;
347  Vector2I startPos;
348  Integer posA = ( A - U1 ).norm1();
349  Integer posB = ( B - U1 ).norm1();
350 #ifdef TRACE_DSL
351  std::cerr << "[reversedSmartDSS] 1 pattern" << std::endl;
352 #endif
353  bool m = pattern().getSmallestCoveringSubpattern
354  ( subpattern, nb, startPos, posA, posB );
355 #ifdef TRACE_DSL
356  std::cerr << " - smallest:" << subpattern.rE() << " at " << startPos << endl;
357 #endif
358  if ( ! m )
359  { // smallest covering subpattern is the pattern itself.
360  bool n = pattern().getGreatestIncludedSubpattern
361  ( subpattern, nb, startPos, posA, posB );
362 #ifdef TRACE_DSL
363  std::cerr << " - greatest:" << subpattern.rE() << " at " << startPos << endl;
364 #endif
365  ASSERT( n );
366  Point NU( U1 + startPos );
367  Integer nmu = subpattern.slope().p() * NU[ 0 ]
368  - subpattern.slope().q() * NU[ 1 ];
369  return Self( subpattern.slope(), nmu );
370  }
371  // last case, recursive call.
372  Point NU1( U1 + startPos );
373  Point NU2( NU1 + subpattern.v()*nb );
374  Integer nmu = subpattern.slope().p() * NU1[ 0 ]
375  - subpattern.slope().q() * NU1[ 1 ];
376  StandardDSLQ0 ndsl( subpattern.slope(), nmu );
377  return ndsl.reversedSmartDSS( NU1, NU2, A, B );
378 }
379 //-----------------------------------------------------------------------------
380 template <typename TFraction>
384  const Point & A, const Point & B ) const
385 {
386  Integer posA, posB;
387  Point Um = U1 + pattern().v();
388  ASSERT( Um + pattern().v() == U2 );
389  ASSERT( before( A, B ) );
390  ASSERT( before( A, Um ) );
391  ASSERT( before( Um, B ) );
392  ASSERT( r( U1 ) == mu() && r( U2 ) == mu() );
393  bool readyLU = false;
394  bool readyRU = false;
395  bool readyL = false;
396  Point L1 = U1 + pattern().L( 0 );
397  Point L2 = L1 + pattern().v();
398  Pattern<Fraction> subpattern;
399  Pattern<Fraction> patDeepest;
400  Pattern<Fraction> patLU = pattern();
401  Pattern<Fraction> patRU = pattern();
402  Pattern<Fraction> patL = pattern();
403  Quotient nb;
404  Vector2I startPos;
405  #ifdef TRACE_DSL
406  std::cerr << "[DSSWithinTwoPatterns] " << (*this)
407  << " " << pattern().rE() << std::endl
408  << " +- U1=" << U1 << " A=" << A
409  << " B=" << B << " U2=" << U2
410  << " L1=" << L1 << std::endl;
411  #endif
412  while( true ) //for ( Quotient i = NumberTraits<Quotient>::ZERO; i <= pattern().slope().k(); ++i )
413  {
414  if ( ! readyLU )
415  {
416  bool mLU = patLU.getSmallestCoveringSubpattern
417  ( subpattern, nb, startPos,
418  ( A - U1 ).norm1(), ( Um - U1 ).norm1(), false );
419  if ( ! mLU || nb > 1 )
420  {
421  bool n = patLU.getGreatestIncludedSubpattern
422  ( subpattern, nb, startPos,
423  ( A - U1 ).norm1(), ( Um - U1 ).norm1(), false );
424  ASSERT( n );
425  readyLU = true;
426  }
427  patLU = subpattern;
428  U1 += startPos;
429  }
430  if ( ! readyRU )
431  {
432  bool mRU = patRU.getSmallestCoveringSubpattern
433  ( subpattern, nb, startPos,
434  0, ( B - Um ).norm1(), false );
435  if ( ! mRU || nb > 1 )
436  {
437  bool n = patRU.getGreatestIncludedSubpattern
438  ( subpattern, nb, startPos,
439  0, ( B - Um ).norm1(), false );
440  ASSERT( n );
441  readyRU = true;
442  }
443  patRU = subpattern;
444  ASSERT( ! patRU.slope().null() );
445  U2 = Um + patRU.v() * nb;
446  }
447  if ( ! readyL )
448  {
449  posA = L1[ 0 ] <= A[ 0 ] ? ( A - L1 ).norm1() : 0;
450  posB = L2[ 0 ] > B[ 0 ] ? ( B - L1 ).norm1() : patL.length();
451  bool mL = patL.getSmallestCoveringSubpattern
452  ( subpattern, nb, startPos, posA, posB, true );
453  if ( ! mL )
454  {
455  bool n = patL.getGreatestIncludedSubpattern
456  ( subpattern, nb, startPos, posA, posB, true );
457  ASSERT( n );
458  patL = subpattern;
459  readyL = true;
460  }
461  else
462  { // One has to keep the pertinent pattern
463  // It is the reversed pattern around Um.
464  patL = subpattern;
465  L2 = Um + patL.L( 0 );
466  L1 = L2 - patL.v();
467  }
468  // patL = subpattern;
469  // L1 += startPos;
470  // L2 = L1 + patL.v() * nb;
471  }
472 #ifdef TRACE_DSL
473  std::cerr << " (*) " << (readyLU ? '*' : '-')
474  << "LU=" << patLU.rE() << " at " << U1 << std::endl;
475  std::cerr << " (*) " << (readyRU ? '*' : '-')
476  << "RU=" << patRU.rE() << " til " << U2 << std::endl;
477  std::cerr << " (*) " << (readyL ? '*' : '-')
478  << "L =" << patL.rE() << " at " << L1 << std::endl;
479 #endif
480  if ( readyLU || readyRU || readyL )
481  {
482  patDeepest = deepest( patLU.slope(), patRU.slope(), patL.slope() );
483 #ifdef TRACE_DSL
484  std::cerr << " => deepest is " << patDeepest.rE() << std::endl;
485 #endif
486  }
487  if ( ( readyLU && patDeepest.slope().q() == patLU.slope().q() )
488  || ( readyRU && patDeepest.slope().q() == patRU.slope().q() )
489  || ( readyL && patDeepest.slope().q() == patL.slope().q() ) )
490  break;
491  }
492  Integer nmu = patDeepest.slope().p() * Um[ 0 ]
493  - patDeepest.slope().q() * Um[ 1 ];
494  return StandardDSLQ0( patDeepest.slope(), nmu );
495 }
496 //-----------------------------------------------------------------------------
497 template <typename TFraction>
500 smartDSS( const Point & A, const Point & B ) const
501 {
502 #ifdef TRACE_DSL
503  std::cerr << "[smartDSS] " << (*this)
504  << " " << pattern().rE() << std::endl
505  << " A=" << A << " B=" << B << std::endl;
506 #endif
507  ASSERT( ! slope().null() );
508  ASSERT( this->operator()( A ) && this->operator()( B ) );
509  ASSERT( before( A, B ) );
510  Fraction f10( 1, 0 );
511  Pattern<Fraction> p( 0, 1 );
512  bool ulu = true;
513  bool lul = true;
514  Quotient delta = 0;
515  Point2I _U = A;
516  Point2I _L = A;
517  Point2I _Up = _U + Point2I(0,1);
518  Point2I _Lp = _L + Point2I(1,-1);
519  UnsignedInteger AB1 = (B-A).norm1();
520  while ( ( (_Up - A).norm1() <= AB1 )
521  && this->operator()( _Up ) )
522  {
523 #ifdef TRACE_DSL
524  std::cerr << "Vertical" << std::endl;
525 #endif
526  p = Pattern<Fraction>( f10 );
527  _Up += Point2I(0,1);
528  _Lp += Point2I(0,1);
529  ++delta;
530  }
531  if ( delta != 0 )
532  {
533  _Lp += Point2I(0,1);
534  // ulu = false;
535  }
536 
537  while ( p.slope() != this->slope() )
538  {
539 #ifdef TRACE_DSL
540  std::cerr << "[smartDSS] v=" << p.v()
541  << " bez=" << p.bezout()
542  << " U=(" << _U[0] << "," << _U[1] << ")"
543  << " L=(" << _L[0] << "," << _L[1] << ")"
544  << " Up=(" << _Up[0] << "," << _Up[1] << ")"
545  << " Lp=(" << _Lp[0] << "," << _Lp[1] << ")"
546  << std::endl;
547 #endif
548  ASSERT( p.v()[1]*p.bezout()[0] - p.v()[0]*p.bezout()[1] == -1 );
549  if ( ( (_Up - A).norm1() > AB1 ) && ( (_Lp - A).norm1() > AB1 ) ) break;
550  else if ( _Up[ 1 ] <= B[ 1 ] && this->operator()( _Up ) )
551  {
552  Fraction np = p.slope().right();
553  for ( Quotient i = 1; i < delta; ++i )
554  np = np.left();
555  _L = _Lp + p.bezout() - p.v();
556  if ( ! lul ) _L -= p.v();
557  p = Pattern<Fraction>( np );
558  ASSERT( p.v()[1]*p.bezout()[0] - p.v()[0]*p.bezout()[1] == -1 );
559  _Up = _U + p.v() + p.bezout();
560  _Lp = _L + p.v() + p.v() - p.bezout();
561  delta = 1; ulu = true; lul = false;
562  }
563  else if ( _Lp[ 0 ] <= B[ 0 ] && this->operator()( _Lp ) )
564  {
565  Fraction np = p.slope().left();
566  for ( Quotient i = 1; i < delta; ++i )
567  np = np.right();
568  _U = p.slope() == f10 ? _Up - Point2I( 0,1 ) : _Up - p.bezout();
569  if ( ! ulu ) _U -= p.v();
570  p = Pattern<Fraction>( np );
571  ASSERT( p.v()[1]*p.bezout()[0] - p.v()[0]*p.bezout()[1] == -1 );
572  _Up = _U + p.v() + p.bezout();
573  _Lp = _L + p.v() + p.v() - p.bezout();
574  delta = 1; ulu = false; lul = true;
575  }
576  else
577  {
578  ++delta;
579  _Up += p.v();
580  _Lp += p.v();
581  }
582  }
583  Integer nmu = p.slope().p() * _U[ 0 ] - p.slope().q() * _U[ 1 ];
584  return StandardDSLQ0( p.slope(), nmu );
585 }
586 
587 //-----------------------------------------------------------------------------
588 template <typename TFraction>
589 inline
593 {
594  return deepest( f1, deepest( f2, f3 ) );
595 }
596 //-----------------------------------------------------------------------------
597 template <typename TFraction>
598 inline
602 {
603  return ( ( f1.k() > f2.k() )
604  || ( ( f1.k() == f2.k() ) && ( f1.u() >= f2.u() ) ) )
605  ? f1 : f2;
606 }
607 
609 // Interface - public :
610 
615 template <typename TFraction>
616 inline
617 void
619 {
620  out << "[StandardDSLQ0"
621  << " a=" << a() << ", b=" << b() << ", mu=" << mu() << "]";
622 }
623 
628 template <typename TFraction>
629 inline
630 bool
632 {
633  return true;
634 }
635 
636 
637 
639 // Implementation of inline functions //
640 
641 template <typename TFraction>
642 inline
643 std::ostream&
644 DGtal::operator<< ( std::ostream & out,
645  const StandardDSLQ0<TFraction> & object )
646 {
647  object.selfDisplay( out );
648  return out;
649 }
650 
651 // //
653 
654