DGtal 1.4.0
Loading...
Searching...
No Matches
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)
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 <map>
50
52
53#include "DGtal/geometry/curves/SegmentComputerUtils.h"
54
55
56#define PRECISION 0.00000001
57
58namespace DGtal
59{
60
62 // class FrechetShortcut
109 template <typename TIterator,typename TInteger = typename IteratorCirculatorTraits<TIterator>::Value::Coordinate>
111 {
112 // ----------------------- Standard services ------------------------------
113 public:
114
115 //entier
116
118 typedef TInteger Integer;
119
120
121
122 //required types
123 typedef TIterator ConstIterator;
126
127 //2D point and 2D vector
130 typedef typename Vector::Coordinate Coordinate;
131
137 {
138 private:
143
144 protected:
145
154
159 typedef std::map <ConstIterator,occulter_attributes > occulter_list;
160
161 public:
163
164
165 public:
166
167 typedef boost::icl::interval_set<double> IntervalSet;
168
172 int myQuad;
173
178 bool myFlag;
179
181
187
192
197
204
209 Backpath(const Backpath & other);
210
211
217 Backpath& operator=(const Backpath & other);
218
219
224
228 void reset();
229
234
239
247
252
257
258
259 }; // End of class Backpath
260
261
266 class Cone{
267
268 public:
272 double myMin;
273
277 double myMax;
278
282 bool myInf; // true if the cone is infinite (the whole plane)
283
285
291 Cone(double a0, double a1);
292
303 Cone(double x, double y, double x0, double y0, double x1, double y1);
304
309 Cone(const Cone& c) = default;
310
316 Cone& operator=(const Cone& c);
317
322 bool isEmpty() const;
323
329
336
342
347 void selfDisplay ( std::ostream & out) const;
348
349 };
350
351
352
353
354 struct Tools
355 {
365 static bool isBetween(double i, double a, double b, double n)
366 {
367 if(a<=b)
368 return (i>=a && i<=b);
369 else
370 return ((i>=a && i<=n) || (i>=0 && i<=b));
371 }
372
373
374 // Code by Tim Voght
375 // http://local.wasp.uwa.edu.au/~pbourke/geometry/2circle/tvoght.c
376
377 /* circle_circle_intersection() *
378 * Determine the points where 2 circles in a common plane intersect.
379 *
380 * int circle_circle_intersection(
381 * // center and radius of 1st circle
382 * double x0, double y0, double r0,
383 * // center and radius of 2nd circle
384 * double x1, double y1, double r1,
385 * // 1st intersection point
386 * double *xi, double *yi,
387 * // 2nd intersection point
388 * double *xi_prime, double *yi_prime)
389 *
390 * This is a public domain work. 3/26/2005 Tim Voght
391 *
392 */
400 static int circle_circle_intersection(double x0, double y0, double r0,
401 double x1, double y1, double r1,
402 double *xi, double *yi,
403 double *xi_prime, double *yi_prime)
404 {
405 // I. Sivignon 05/2024: fix to handle the case where r0=0 or
406 // r1=0. Enables the case where error=0.
407 // Other special cases where circles are tangent are treated
408 // below.
409 if(r0==0)
410 {
411 *xi = x0; *yi = y0;
412 *xi_prime = x0 ; *yi_prime = y0;
413 return 1;
414 }
415 else
416 if(r1==0)
417 {
418 *xi = x1; *yi = y1;
419 *xi_prime = x1 ; *yi_prime = y1;
420 return 1;
421 }
422
423 double a, dx, dy, d, h, rx, ry;
424 double x2, y2;
425
426 /* dx and dy are the vertical and horizontal distances between
427 * the circle centers.
428 */
429 dx = x1 - x0;
430 dy = y1 - y0;
431
432 /* Determine the straight-line distance between the centers. */
433 //d = sqrt((dy*dy) + (dx*dx));
434 d = hypot(dx,dy); // Suggested by Keith Briggs
435
436 if((r0+r1)*(r0+r1)-((dy*dy)+(dx*dx)) < PRECISION)
437 { // I. Sivignon 05/2024: fix to handle the case where
438 // circles are tangent but radii are non zero.
439
440 double alpha= r0/d;
441 *xi = x0 + dx*alpha;
442 *yi = y0 + dy*alpha;
443 *xi_prime = *xi; *yi_prime = *yi;
444 return 1;
445 }
446
447 /* Check for solvability. */
448 if (d > (r0 + r1))
449 {
450 /* no solution. circles do not intersect. */
451 std::cerr << "Warning : the two circles do not intersect -> should never happen" << std::endl;
452 return 0; //I. Sivignon 05/2010 should never happen for our specific use.
453 }
454 if (d < fabs(r0 - r1))
455 {
456 /* no solution. one circle is contained in the other */
457 return 0;
458 }
459
460 // }
461 /* 'point 2' is the point where the line through the circle
462 * intersection points crosses the line between the circle
463 * centers.
464 */
465
466 /* Determine the distance from point 0 to point 2. */
467 a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ;
468
469 /* Determine the coordinates of point 2. */
470 x2 = x0 + (dx * a/d);
471 y2 = y0 + (dy * a/d);
472
473
474 /* Determine the distance from point 2 to either of the
475 * intersection points.
476 */
477 h = sqrt((r0*r0) - (a*a));
478
479 /* Now determine the offsets of the intersection points from
480 * point 2.
481 */
482 rx = -dy * (h/d);
483 ry = dx * (h/d);
484
485 /* Determine the absolute intersection points. */
486 *xi = x2 + rx;
487 *xi_prime = x2 - rx;
488 *yi = y2 + ry;
489 *yi_prime = y2 - ry;
490
491 return 1;
492 }
493
494
495
515 static int circleTangentPoints(double x, double y, double x1, double y1, double r1, double *xi, double *yi,
516 double *xi_prime, double *yi_prime)
517 {
518 double x0 = (x+x1)/2;
519 double y0 = (y+y1)/2;
520 double r0 = sqrt((x-x1)*(x-x1) + (y-y1)*(y-y1))/2;
521
522 int res =
523 circle_circle_intersection(x0,y0,r0,x1,y1,r1,xi,yi,xi_prime,yi_prime);
524
525
526 return res;
527
528 }
529
530
540 static double computeAngle(double x0, double y0, double x1, double y1)
541 {
542 double x = x1-x0;
543 double y = y1-y0;
544
545 if(x!=0)
546 {
547 double alpha = y/x;
548
549 if(x>0 && y>=0)
550 return atan(alpha);
551 else
552 if(x>0 && y<0)
553 return atan(alpha)+2*M_PI;
554 else
555 if(x<0)
556 return atan(alpha)+M_PI;
557 }
558 else
559 {
560 if(y==0)
561 return 0;
562 else
563 if(y>0)
564 return M_PI_2;
565 else
566 return 3*M_PI_2;
567 }
568 return -1;
569 }
570
571
572
578 static double angleVectVect(Vector u, Vector v)
579 {
581 return acos((double)ic.dotProduct(u,v)/(u.norm()*v.norm()));
582 }
583
589 static int computeChainCode(Point p, Point q)
590 {
591 int d;
592 Coordinate x2 = q[0];
593 Coordinate y2 = q[1];
594 Coordinate x1 = p[0];
595 Coordinate y1 = p[1];
596
597 if(x2-x1==0)
598 if(y2-y1==1)
599 d=2;
600 else
601 d=6;
602 else
603 if(x2-x1==1)
604 if(y2-y1==0)
605 d=0;
606 else
607 if(y2-y1==1)
608 d=1;
609 else
610 d=7;
611 else
612 if(y2-y1==0)
613 d=4;
614 else
615 if(y2-y1==1)
616 d=3;
617 else
618 d=5;
619 return d;
620 }
621
627 static int computeOctant(Point p, Point q)
628 {
629 int d = 0;
630 Coordinate x = q[0]-p[0];
631 Coordinate y = q[1]-p[1];
632
633 if(x>=0)
634 {
635 if(y>=0)
636 {
637 if(x>y)
638 d=0; // 0 <= y < x
639 else
640 if(x!=0)
641 d=1; // 0 <= x <= y
642 }
643 else
644 {
645 if(x>=abs(y))
646 d=7; // 0 < abs(y) <= x
647 else
648 d=6; // 0 <= x < abs(y)
649 }
650 }
651 if(x<=0)
652 {
653 if(y>0)
654 if(abs(x)>=y)
655 d=3; //
656 else
657 d=2;
658 else
659 {
660 if(abs(x)>abs(y))
661 d=4;
662 else
663 if(x!=0)
664 d=5;
665 }
666 }
667 return d;
668
669 }
670
679 static int rot(int d, int quad)
680 {
681 return (d-quad+8)%8;
682 }
683
689 static Vector chainCode2Vect(int d)
690 {
691 Vector v;
692 switch(d){
693
694 case 0:{
695 v[0] = 1;
696 v[1] = 0;
697 break;
698 }
699 case 1:{
700 v[0] = 1;
701 v[1] = 1;
702 break;
703 }
704 case 2:{
705 v[0] = 0;
706 v[1] = 1;
707 break;
708 }
709 case 3:{
710 v[0] = -1;
711 v[1] = 1;
712 break;
713 }
714 case 4:{
715 v[0] = -1;
716 v[1] = 0;
717 break;
718 }
719 case 5:{
720 v[0] = -1;
721 v[1] = -1;
722 break;
723 }
724 case 6:{
725 v[0] = 0;
726 v[1] = -1;
727 break;
728 }
729 case 7:{
730 v[0] = 1;
731 v[1] = -1;
732 break;
733 }
734
735 }
736
737 return v;
738 }
739
740
741 };
742
743
749
754 FrechetShortcut(double error);
755
761 void init(const ConstIterator& it);
762
764
769 FrechetShortcut ( const Self & other );
770
776 FrechetShortcut & operator= ( const Self & other );
777
782
789 bool operator==( const Self & other ) const;
790
797 bool operator!=( const Self & other ) const;
798
799
800
805
806 // ----------------------- Interface --------------------------------------
807public:
808
815
822
823
824 // ---------------------------- Accessors ----------------------------------
825
826
836
837
838 public:
839
843 std::string className() const;
844
845
850 bool isValid() const;
851
852 // ------------------------- Protected Datas ------------------------------
853 protected:
854
858 double myError;
859
864 std::vector <Backpath> myBackpath;
865
870
879
880
881
882 // ------------------------- Private Datas --------------------------------
883 private:
884
885
886
887 // ------------------------- Hidden services ------------------------------
888
889 public:
890
898
905
911
916
920 void resetCone();
921
927
934
940
941
942
943
948 void selfDisplay ( std::ostream & out ) const ;
949
950
951
952 // ------------------------- Internals ------------------------------------
953 private:
954
955 }; // end of class FrechetShortcut
956
957
958 // Utils
959
960
967 template <typename TIterator,typename TInteger>
968 std::ostream&
969 operator<< ( std::ostream & out, const FrechetShortcut<TIterator,TInteger> & object );
970
971
972
973
974
975
976} // namespace DGtal
977
978
980// Includes inline functions.
981#include "DGtal/geometry/curves/FrechetShortcut.ih"
982// //
984
985#endif // !defined FrechetShortcut_h
986
987#undef FrechetShortcut_RECURSES
988#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)
FrechetShortcut< std::reverse_iterator< ConstIterator >, Integer > Reverse
ConstIterator begin() const
IteratorCirculatorTraits< ConstIterator >::Value Point
bool operator!=(const Self &other) const
Vector::Coordinate Coordinate
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
ConstIterator end() const
std::vector< Backpath > myBackpath
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