DGtal  0.6.devel
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
FrechetShortcut.h
1 
18 #pragma once
19 
32 #if defined(FrechetShortcut_RECURSES)
33 #error Recursive header files inclusion detected in FrechetShortcut.h
34 #else // defined(FrechetShortcut_RECURSES)
35 
36 #define FrechetShortcut_RECURSES
37 
38 #if !defined FrechetShortcut_h
39 
40 #define FrechetShortcut_h
41 
43 // Inclusions
44 #include "DGtal/base/Common.h"
45 #include "DGtal/base/ConceptUtils.h"
46 #include "DGtal/kernel/PointVector.h"
47 #include "DGtal/arithmetic/IntegerComputer.h"
48 #include <boost/icl/interval_set.hpp>
49 #include <map>
50 
52 
53 #include "DGtal/geometry/curves/SegmentComputerUtils.h"
54 
55 namespace DGtal
56 {
57 
59  // class FrechetShortcut
106  template <typename TIterator,typename TInteger = typename IteratorCirculatorTraits<TIterator>::Value::Coordinate>
108  {
109  // ----------------------- Standard services ------------------------------
110  public:
111 
112  //entier
113 
115  typedef TInteger Integer;
116 
117 
118 
119  //required types
120  typedef TIterator ConstIterator;
123 
124  //2D point and 2D vector
127  typedef typename Vector::Coordinate Coordinate;
128 
133  class Backpath
134  {
135  private:
140 
141  protected:
142 
147  typedef struct occulter_attributes{
148  double angle_min; //
149  double angle_max; //
151 
156  typedef map <ConstIterator,occulter_attributes > occulter_list;
157 
158  public:
160 
161 
162  public:
163 
167  int myQuad;
168 
173  bool myFlag;
174 
176 
181  boost::icl::interval_set<double> myForbiddenIntervals;
182 
187 
191  Backpath();
192 
199 
204  Backpath(const Backpath & other);
205 
206 
210  ~Backpath();
211 
215  void reset();
216 
220  void addPositivePoint();
221 
225  void addNegativePoint();
226 
233  void updateBackPathFirstQuad(int d, const ConstIterator&);
234 
238  void updateOcculters();
239 
243  void updateIntervals();
244 
245 
246  }; // End of class Backpath
247 
248 
253  class Cone{
254 
255  public:
259  double myMin;
260 
264  double myMax;
265 
269  bool myInf; // true if the cone is infinite (the whole plane)
270 
271  Cone();
272 
277  Cone(double a0, double a1);
278 
284  Cone(double x, double y, double x0, double y0, double x1, double y1);
285 
290  bool isEmpty();
291 
297  Cone& operator=(const Cone& c);
298 
303  void intersectCones(Cone c);
304 
311 
318 
323  void selfDisplay ( std::ostream & out) ;
324 
325 
326  };
327 
328 
329 
330 
331  struct Tools
332  {
339  static bool isBetween(double i, double a, double b, double n)
340  {
341  // if a<=b, a simple comparison enables to conclude
342  if(a<=b)
343  if(i>=a && i<=b)
344  return true;
345  else
346  return false;
347  else
348  {
349  //otherwise, translate the points such that a->0
350  int tmp = a;
351  a = fmod(a+n-tmp,n);
352  b = fmod(b+n-tmp,n);
353  i = fmod(i+n-tmp,n);
354  return isBetween(i,a,b,n);
355  }
356  }
357 
358 
359  // Code by Tim Voght
360  // http://local.wasp.uwa.edu.au/~pbourke/geometry/2circle/tvoght.c
361 
362  /* circle_circle_intersection() *
363  * Determine the points where 2 circles in a common plane intersect.
364  *
365  * int circle_circle_intersection(
366  * // center and radius of 1st circle
367  * double x0, double y0, double r0,
368  * // center and radius of 2nd circle
369  * double x1, double y1, double r1,
370  * // 1st intersection point
371  * double *xi, double *yi,
372  * // 2nd intersection point
373  * double *xi_prime, double *yi_prime)
374  *
375  * This is a public domain work. 3/26/2005 Tim Voght
376  *
377  */
385  static int circle_circle_intersection(double x0, double y0, double r0,
386  double x1, double y1, double r1,
387  double *xi, double *yi,
388  double *xi_prime, double *yi_prime)
389  {
390  double a, dx, dy, d, h, rx, ry;
391  double x2, y2;
392 
393  /* dx and dy are the vertical and horizontal distances between
394  * the circle centers.
395  */
396  dx = x1 - x0;
397  dy = y1 - y0;
398 
399  /* Determine the straight-line distance between the centers. */
400  //d = sqrt((dy*dy) + (dx*dx));
401  d = hypot(dx,dy); // Suggested by Keith Briggs
402 
403  /* Check for solvability. */
404  if (d > (r0 + r1))
405  {
406  /* no solution. circles do not intersect. */
407  std::cerr << "Warning : the two circles do not intersect -> should never happen" << std::endl;
408  return 0; //I. Sivignon 05/2010 should never happen for our specific use.
409  }
410  if (d < fabs(r0 - r1))
411  {
412  /* no solution. one circle is contained in the other */
413  return 0;
414  }
415 
416  /* 'point 2' is the point where the line through the circle
417  * intersection points crosses the line between the circle
418  * centers.
419  */
420 
421  /* Determine the distance from point 0 to point 2. */
422  a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ;
423 
424  /* Determine the coordinates of point 2. */
425  x2 = x0 + (dx * a/d);
426  y2 = y0 + (dy * a/d);
427 
428  /* Determine the distance from point 2 to either of the
429  * intersection points.
430  */
431  h = sqrt((r0*r0) - (a*a));
432 
433  /* Now determine the offsets of the intersection points from
434  * point 2.
435  */
436  rx = -dy * (h/d);
437  ry = dx * (h/d);
438 
439  /* Determine the absolute intersection points. */
440  *xi = x2 + rx;
441  *xi_prime = x2 - rx;
442  *yi = y2 + ry;
443  *yi_prime = y2 - ry;
444 
445  return 1;
446  }
447 
448 
449 
461  static int circleTangentPoints(double x, double y, double x1, double y1, double r1, double *xi, double *yi,
462  double *xi_prime, double *yi_prime)
463  {
464  double x0 = (x+x1)/2;
465  double y0 = (y+y1)/2;
466  double r0 = sqrt((x-x1)*(x-x1) + (y-y1)*(y-y1))/2;
467 
468  int res =
469  circle_circle_intersection(x0,y0,r0,x1,y1,r1,xi,yi,xi_prime,yi_prime);
470 
471  return res;
472 
473  }
474 
475 
482  static double computeAngle(double x0, double y0, double x1, double y1)
483  {
484  double x = x1-x0;
485  double y = y1-y0;
486 
487  if(x!=0)
488  {
489  double alpha = y/x;
490 
491  if(x>0 && y>=0)
492  return atan(alpha);
493  else
494  if(x>0 && y<0)
495  return atan(alpha)+2*M_PI;
496  else
497  if(x<0)
498  return atan(alpha)+M_PI;
499  }
500  else
501  {
502  if(y>0)
503  return M_PI_2;
504  else
505  return 3*M_PI_2;
506  }
507  return -1;
508  }
509 
510 
511 
517  static double angleVectVect(Vector u, Vector v)
518  {
520  return acos((double)ic.dotProduct(u,v)/(u.norm()*v.norm()));
521  }
522 
528  static int computeChainCode(Point p, Point q)
529  {
530  int d;
531  Coordinate x2 = q[0];
532  Coordinate y2 = q[1];
533  Coordinate x1 = p[0];
534  Coordinate y1 = p[1];
535 
536  if(x2-x1==0)
537  if(y2-y1==1)
538  d=2;
539  else
540  d=6;
541  else
542  if(x2-x1==1)
543  if(y2-y1==0)
544  d=0;
545  else
546  if(y2-y1==1)
547  d=1;
548  else
549  d=7;
550  else
551  if(y2-y1==0)
552  d=4;
553  else
554  if(y2-y1==1)
555  d=3;
556  else
557  d=5;
558  return d;
559  }
560 
566  static int computeQuadrant(Point p, Point q)
567  {
568  int d;
569  Coordinate x = q[0]-p[0];
570  Coordinate y = q[1]-p[1];
571 
572  if(x>=0)
573  {
574  if(y>=0)
575  {
576  if(x>y)
577  d=0; // 0 <= y < x
578  else
579  if(x!=0)
580  d=1; // 0 <= x <= y
581  }
582  else
583  {
584  if(x>=abs(y))
585  d=7; // 0 < abs(y) <= x
586  else
587  d=6; // 0 <= x < abs(y)
588  }
589  }
590  if(x<=0)
591  {
592  if(y>0)
593  if(abs(x)>=y)
594  d=3; //
595  else
596  d=2;
597  else
598  {
599  if(abs(x)>abs(y))
600  d=4;
601  else
602  if(x!=0)
603  d=5;
604  }
605  }
606  return d;
607 
608  }
609 
618  static int rot(int d, int quad)
619  {
620  return (d-quad+8)%8;
621  }
622 
628  static Vector chainCode2Vect(int d)
629  {
630  Vector v;
631  switch(d){
632 
633  case 0:{
634  v[0] = 1;
635  v[1] = 0;
636  break;
637  }
638  case 1:{
639  v[0] = 1;
640  v[1] = 1;
641  break;
642  }
643  case 2:{
644  v[0] = 0;
645  v[1] = 1;
646  break;
647  }
648  case 3:{
649  v[0] = -1;
650  v[1] = 1;
651  break;
652  }
653  case 4:{
654  v[0] = -1;
655  v[1] = 0;
656  break;
657  }
658  case 5:{
659  v[0] = -1;
660  v[1] = -1;
661  break;
662  }
663  case 6:{
664  v[0] = 0;
665  v[1] = -1;
666  break;
667  }
668  case 7:{
669  v[0] = 1;
670  v[1] = -1;
671  break;
672  }
673 
674  }
675 
676  return v;
677  }
678 
679 
680  };
681 
682 
687  FrechetShortcut();
688 
693  FrechetShortcut(double error);
694 
700  void init(const ConstIterator& it);
701 
703 
708  FrechetShortcut ( const Self & other );
709 
715  FrechetShortcut & operator= ( const Self & other );
716 
720  Reverse getReverse() const;
721 
728  bool operator==( const Self & other ) const;
729 
736  bool operator!=( const Self & other ) const;
737 
738 
739 
744 
745  // ----------------------- Interface --------------------------------------
746 public:
747 
753  bool isExtendableForward();
754 
760  bool extendForward();
761 
762 
763  // ---------------------------- Accessors ----------------------------------
764 
765 
770  ConstIterator begin() const;
774  ConstIterator end() const;
775 
776 
777 
778 
779  public:
780 
784  std::string className() const;
785 
786 
791  bool isValid() const;
792 
793  // ------------------------- Protected Datas ------------------------------
794  protected:
795 
799  double myError;
800 
805  std::vector <Backpath> myBackpath;
806 
810  Cone myCone;
811 
820 
821 
822 
823  // ------------------------- Private Datas --------------------------------
824  private:
825 
826 
827 
828  // ------------------------- Hidden services ------------------------------
829 
830  public:
831 
838  bool updateBackpath();
839 
845  bool testUpdateBackpath();
846 
851  bool isBackpathOk();
852 
856  void resetBackpath();
857 
861  void resetCone();
862 
867  bool testUpdateWidth();
868 
874  Cone computeNewCone();
875 
880  bool updateWidth();
881 
882 
883 
884 
889  void selfDisplay ( std::ostream & out ) const ;
890 
891 
892 
893  // ------------------------- Internals ------------------------------------
894  private:
895 
896  }; // end of class FrechetShortcut
897 
898 
899  // Utils
900 
901 
908  template <typename TIterator,typename TInteger>
909  std::ostream&
910  operator<< ( std::ostream & out, const FrechetShortcut<TIterator,TInteger> & object );
911 
912 
913 
914 
915 
916 
917 } // namespace DGtal
918 
919 
921 // Includes inline functions.
922 #include "DGtal/geometry/curves/FrechetShortcut.ih"
923 // //
925 
926 #endif // !defined FrechetShortcut_h
927 
928 #undef FrechetShortcut_RECURSES
929 #endif // else defined(FrechetShortcut_RECURSES)