Loading [MathJax]/extensions/TeX/AMSsymbols.js
DGtal 2.0.0
FrechetShortcut.h
1
17
18#pragma once
19
31
32#if defined(FrechetShortcut_RECURSES)
33#error Recursive header files inclusion detected in FrechetShortcut.h
34#else // defined(FrechetShortcut_RECURSES)
36#define FrechetShortcut_RECURSES
37
38#if !defined FrechetShortcut_h
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 <boost/iterator/reverse_iterator.hpp>
50#include <map>
51
53
54#include "DGtal/geometry/curves/SegmentComputerUtils.h"
55
56
57#define PRECISION 0.00000001
58
59namespace DGtal
60{
61
63 // class FrechetShortcut
108
109
110 template <typename TIterator,typename TInteger = typename IteratorCirculatorTraits<TIterator>::Value::Coordinate>
112 {
113 // ----------------------- Standard services ------------------------------
114 public:
115
116 //entier
117
119 typedef TInteger Integer;
120
121
122
123 //required types
124 typedef TIterator ConstIterator;
127
128 //2D point and 2D vector
131 typedef typename Vector::Coordinate Coordinate;
132
138 {
139 private:
144
145 protected:
146
155
160 typedef std::map <ConstIterator,occulter_attributes > occulter_list;
161
162 public:
164
165
166 public:
167
168 typedef boost::icl::interval_set<double> IntervalSet;
169
173 int myQuad;
174
179 bool myFlag;
180
182
188
193
198
205
210 Backpath(const Backpath & other);
211
212
218 Backpath& operator=(const Backpath & other);
219
220
225
229 void reset();
230
235
240
248
253
258
259
260 }; // End of class Backpath
261
262
267 class Cone{
268
269 public:
273 double myMin;
274
278 double myMax;
279
283 bool myInf; // true if the cone is infinite (the whole plane)
284
286
292 Cone(double a0, double a1);
293
304 Cone(double x, double y, double x0, double y0, double x1, double y1);
305
310 Cone(const Cone& c) = default;
311
317 Cone& operator=(const Cone& c);
318
323 bool isEmpty() const;
324
330
337
343
348 void selfDisplay ( std::ostream & out) const;
349
350 };
351
352
353
354
355 struct Tools
356 {
366 static bool isBetween(double i, double a, double b, double n)
367 {
368 if(a<=b)
369 return (i>=a && i<=b);
370 else
371 return ((i>=a && i<=n) || (i>=0 && i<=b));
372 }
373
374
375 // Code by Tim Voght
376 // http://local.wasp.uwa.edu.au/~pbourke/geometry/2circle/tvoght.c
377
378 /* circle_circle_intersection() *
379 * Determine the points where 2 circles in a common plane intersect.
380 *
381 * int circle_circle_intersection(
382 * // center and radius of 1st circle
383 * double x0, double y0, double r0,
384 * // center and radius of 2nd circle
385 * double x1, double y1, double r1,
386 * // 1st intersection point
387 * double *xi, double *yi,
388 * // 2nd intersection point
389 * double *xi_prime, double *yi_prime)
390 *
391 * This is a public domain work. 3/26/2005 Tim Voght
392 *
393 */
401 static int circle_circle_intersection(double x0, double y0, double r0,
402 double x1, double y1, double r1,
403 double *xi, double *yi,
404 double *xi_prime, double *yi_prime)
405 {
406 // I. Sivignon 05/2024: fix to handle the case where r0=0 or
407 // r1=0. Enables the case where error=0.
408 // Other special cases where circles are tangent are treated
409 // below.
410 if(r0==0)
411 {
412 *xi = x0; *yi = y0;
413 *xi_prime = x0 ; *yi_prime = y0;
414 return 1;
415 }
416 else
417 if(r1==0)
418 {
419 *xi = x1; *yi = y1;
420 *xi_prime = x1 ; *yi_prime = y1;
421 return 1;
422 }
423
424 double a, dx, dy, d, h, rx, ry;
425 double x2, y2;
426
427 /* dx and dy are the vertical and horizontal distances between
428 * the circle centers.
429 */
430 dx = x1 - x0;
431 dy = y1 - y0;
432
433 /* Determine the straight-line distance between the centers. */
434 //d = sqrt((dy*dy) + (dx*dx));
435 d = hypot(dx,dy); // Suggested by Keith Briggs
436
437 if((r0+r1)*(r0+r1)-((dy*dy)+(dx*dx)) < PRECISION)
438 { // I. Sivignon 05/2024: fix to handle the case where
439 // circles are tangent but radii are non zero.
440
441 double alpha= r0/d;
442 *xi = x0 + dx*alpha;
443 *yi = y0 + dy*alpha;
444 *xi_prime = *xi; *yi_prime = *yi;
445 return 1;
446 }
447
448 /* Check for solvability. */
449 if (d > (r0 + r1))
450 {
451 /* no solution. circles do not intersect. */
452 std::cerr << "Warning : the two circles do not intersect -> should never happen" << std::endl;
453 return 0; //I. Sivignon 05/2010 should never happen for our specific use.
454 }
455 if (d < fabs(r0 - r1))
456 {
457 /* no solution. one circle is contained in the other */
458 return 0;
459 }
460
461 // }
462 /* 'point 2' is the point where the line through the circle
463 * intersection points crosses the line between the circle
464 * centers.
465 */
466
467 /* Determine the distance from point 0 to point 2. */
468 a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ;
469
470 /* Determine the coordinates of point 2. */
471 x2 = x0 + (dx * a/d);
472 y2 = y0 + (dy * a/d);
473
474
475 /* Determine the distance from point 2 to either of the
476 * intersection points.
477 */
478 h = sqrt((r0*r0) - (a*a));
479
480 /* Now determine the offsets of the intersection points from
481 * point 2.
482 */
483 rx = -dy * (h/d);
484 ry = dx * (h/d);
485
486 /* Determine the absolute intersection points. */
487 *xi = x2 + rx;
488 *xi_prime = x2 - rx;
489 *yi = y2 + ry;
490 *yi_prime = y2 - ry;
491
492 return 1;
493 }
494
495
496
516 static int circleTangentPoints(double x, double y, double x1, double y1, double r1, double *xi, double *yi,
517 double *xi_prime, double *yi_prime)
518 {
519 double x0 = (x+x1)/2;
520 double y0 = (y+y1)/2;
521 double r0 = sqrt((x-x1)*(x-x1) + (y-y1)*(y-y1))/2;
522
523 int res =
524 circle_circle_intersection(x0,y0,r0,x1,y1,r1,xi,yi,xi_prime,yi_prime);
525
526
527 return res;
528
529 }
530
531
541 static double computeAngle(double x0, double y0, double x1, double y1)
542 {
543 double x = x1-x0;
544 double y = y1-y0;
545
546 if(x!=0)
547 {
548 double alpha = y/x;
549
550 if(x>0 && y>=0)
551 return atan(alpha);
552 else
553 if(x>0 && y<0)
554 return atan(alpha)+2*M_PI;
555 else
556 if(x<0)
557 return atan(alpha)+M_PI;
558 }
559 else
560 {
561 if(y==0)
562 return 0;
563 else
564 if(y>0)
565 return M_PI_2;
566 else
567 return 3*M_PI_2;
568 }
569 return -1;
570 }
571
572
573
579 static double angleVectVect(Vector u, Vector v)
580 {
582 return acos((double)ic.dotProduct(u,v)/(u.norm()*v.norm()));
583 }
584
590 static int computeChainCode(Point p, Point q)
591 {
592 int d;
593 Coordinate x2 = q[0];
594 Coordinate y2 = q[1];
595 Coordinate x1 = p[0];
596 Coordinate y1 = p[1];
597
598 if(x2-x1==0)
599 if(y2-y1==1)
600 d=2;
601 else
602 d=6;
603 else
604 if(x2-x1==1)
605 if(y2-y1==0)
606 d=0;
607 else
608 if(y2-y1==1)
609 d=1;
610 else
611 d=7;
612 else
613 if(y2-y1==0)
614 d=4;
615 else
616 if(y2-y1==1)
617 d=3;
618 else
619 d=5;
620 return d;
621 }
622
628 static int computeOctant(Point p, Point q)
629 {
630 int d = 0;
631 Coordinate x = q[0]-p[0];
632 Coordinate y = q[1]-p[1];
633
634 if(x>=0)
635 {
636 if(y>=0)
637 {
638 if(x>y)
639 d=0; // 0 <= y < x
640 else
641 if(x!=0)
642 d=1; // 0 <= x <= y
643 }
644 else
645 {
646 if(x>=abs(y))
647 d=7; // 0 < abs(y) <= x
648 else
649 d=6; // 0 <= x < abs(y)
650 }
651 }
652 if(x<=0)
653 {
654 if(y>0)
655 if(abs(x)>=y)
656 d=3; //
657 else
658 d=2;
659 else
660 {
661 if(abs(x)>abs(y))
662 d=4;
663 else
664 if(x!=0)
665 d=5;
666 }
667 }
668 return d;
669
670 }
671
679
680 static int rot(int d, int quad)
681 {
682 return (d-quad+8)%8;
683 }
684
690 static Vector chainCode2Vect(int d)
691 {
692 Vector v;
693 switch(d){
694
695 case 0:{
696 v[0] = 1;
697 v[1] = 0;
698 break;
699 }
700 case 1:{
701 v[0] = 1;
702 v[1] = 1;
703 break;
704 }
705 case 2:{
706 v[0] = 0;
707 v[1] = 1;
708 break;
709 }
710 case 3:{
711 v[0] = -1;
712 v[1] = 1;
713 break;
714 }
715 case 4:{
716 v[0] = -1;
717 v[1] = 0;
718 break;
719 }
720 case 5:{
721 v[0] = -1;
722 v[1] = -1;
723 break;
724 }
725 case 6:{
726 v[0] = 0;
727 v[1] = -1;
728 break;
729 }
730 case 7:{
731 v[0] = 1;
732 v[1] = -1;
733 break;
734 }
735
736 }
737
738 return v;
739 }
740
741
742 };
743
744
750
755 FrechetShortcut(double error);
756
761
762 void init(const ConstIterator& it);
763
765
770 FrechetShortcut ( const Self & other );
771
777 FrechetShortcut & operator= ( const Self & other );
778
783
789
790 bool operator==( const Self & other ) const;
791
798 bool operator!=( const Self & other ) const;
799
800
801
806
807 // ----------------------- Interface --------------------------------------
808public:
809
816
823
824
825 // ---------------------------- Accessors ----------------------------------
826
827
837
838
839 public:
840
844 std::string className() const;
845
846
851 bool isValid() const;
852
853 // ------------------------- Protected Datas ------------------------------
854 protected:
855
859 double myError;
860
865 std::vector <Backpath> myBackpath;
866
870 Cone myCone;
871
880
881
882
883 // ------------------------- Private Datas --------------------------------
884 private:
885
886
887
888 // ------------------------- Hidden services ------------------------------
889
890 public:
891
897
899
906
912
917
921 void resetCone();
922
928
935
941
942
943
944
949 void selfDisplay ( std::ostream & out ) const ;
950
951
952
953 // ------------------------- Internals ------------------------------------
954 private:
955
956 }; // end of class FrechetShortcut
957
958
959 // Utils
960
961
968 template <typename TIterator,typename TInteger>
969 std::ostream&
970 operator<< ( std::ostream & out, const FrechetShortcut<TIterator,TInteger> & object );
971
972
973
974
975
976
977} // namespace DGtal
978
979
981// Includes inline functions.
982#include "DGtal/geometry/curves/FrechetShortcut.ih"
983// //
985
986#endif // !defined FrechetShortcut_h
987
988#undef FrechetShortcut_RECURSES
989#endif // else defined(FrechetShortcut_RECURSES)
const FrechetShortcut< ConstIterator, Integer > * myS
struct DGtal::FrechetShortcut::Backpath::occulter_attributes occulter_attributes
boost::icl::interval_set< double > IntervalSet
void updateBackPathFirstQuad(int d, const ConstIterator &)
std::map< ConstIterator, occulter_attributes > occulter_list
Backpath & operator=(const Backpath &other)
Backpath(const Backpath &other)
Backpath(const FrechetShortcut< ConstIterator, Integer > *s, int q)
Cone & operator=(const Cone &c)
void selfDisplay(std::ostream &out) const
Cone(const Cone &c)=default
Cone(double a0, double a1)
Cone(double x, double y, double x0, double y0, double x1, double y1)
Aim: On-line computation Computation of the longest shortcut according to the Fréchet distance for a ...
std::string className() const
FrechetShortcut & operator=(const Self &other)
ConstIterator begin() const
IteratorCirculatorTraits< ConstIterator >::Value Point
bool operator!=(const Self &other) const
Reverse getReverse() const
IteratorCirculatorTraits< ConstIterator >::Value Vector
FrechetShortcut(const Self &other)
void selfDisplay(std::ostream &out) const
void init(const ConstIterator &it)
FrechetShortcut(double error)
FrechetShortcut getSelf()
BOOST_CONCEPT_ASSERT((concepts::CInteger< TInteger >))
bool operator==(const Self &other) const
FrechetShortcut< boost::reverse_iterator< ConstIterator >, Integer > Reverse
ConstIterator end() const
FrechetShortcut< ConstIterator, Integer > Self
Aim: This class gathers several types and methods to make computation with integers.
Integer dotProduct(const Vector2I &u, const Vector2I &v) const
DGtal is the top-level namespace which contains all DGtal functions and types.
std::ostream & operator<<(std::ostream &out, const ClosedIntegerHalfPlane< TSpace > &object)
static int circle_circle_intersection(double x0, double y0, double r0, double x1, double y1, double r1, double *xi, double *yi, double *xi_prime, double *yi_prime)
static double angleVectVect(Vector u, Vector v)
static Vector chainCode2Vect(int d)
static int circleTangentPoints(double x, double y, double x1, double y1, double r1, double *xi, double *yi, double *xi_prime, double *yi_prime)
static bool isBetween(double i, double a, double b, double n)
static double computeAngle(double x0, double y0, double x1, double y1)
static int rot(int d, int quad)
static int computeChainCode(Point p, Point q)
static int computeOctant(Point p, Point q)
Aim: Concept checking for Integer Numbers. More precisely, this concept is a refinement of both CEucl...
Definition CInteger.h:88