2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 * @file DSLSubsegment.ih
19 * @author Isabelle Sivignon (\c isabelle.sivignon@gipsa-lab.grenoble-inp.fr )
20 * gipsa-lab Grenoble Images Parole Signal Automatique (CNRS, UMR 5216), CNRS, France
24 * Implementation of inline methods defined in DSLSubsegment.h
28 ///////////////////////////////////////////////////////////////////////////////
29 // IMPLEMENTATION of inline methods.
30 ///////////////////////////////////////////////////////////////////////////////
32 //////////////////////////////////////////////////////////////////////////////
34 //////////////////////////////////////////////////////////////////////////////
38 ///////////////////////////////////////////////////////////////////////////////
39 // Implementation of inline methods //
42 template <typename TInteger, typename TNumber>
44 DGtal::DSLSubsegment<TInteger,TNumber>::RayC::RayC()
47 template <typename TInteger, typename TNumber>
49 DGtal::DSLSubsegment<TInteger,TNumber>::RayC::RayC(const Integer x0, const Integer y0)
55 template <typename TInteger, typename TNumber>
57 DGtal::DSLSubsegment<TInteger,TNumber>::RayC::RayC(const Integer p , const Integer q, const Integer r, const Integer slope)
63 template <typename TInteger, typename TNumber>
65 DGtal::DSLSubsegment<TInteger,TNumber>::RayC::~RayC()
70 template <typename TInteger, typename TNumber>
72 typename DGtal::DSLSubsegment<TInteger,TNumber>::Integer DGtal::DSLSubsegment<TInteger,TNumber>::intersectionVertical(Point &P, Vector &v, Integer n)
78 Integer val = (n-P[0])/v[0];
79 if(((n-P[0])<0 || v[0] <0) && !((n-P[0])<0 && v[0] <0))
89 template <typename TInteger, typename TNumber>
91 typename DGtal::DSLSubsegment<TInteger,TNumber>::Integer DGtal::DSLSubsegment<TInteger,TNumber>::intersection(Point &P, Vector &v, Vector &aL, Integer r)
93 Number num = P[1]*aL[0]-aL[1]*P[0]-r;
94 Number denom = aL[1]*v[0]-v[1]*aL[0];
95 // using parametric definition of lines and solving for t -> not more precise than the other computation...
97 Integer val = num/denom;
99 // integer rounding is not equivalent to the floor operation when num/denom is negative
100 if((num<0 ||denom <0) && !(num<0 && denom <0))
109 template <typename TInteger, typename TNumber>
111 typename DGtal::DSLSubsegment<TInteger,TNumber>::Integer DGtal::DSLSubsegment<TInteger,TNumber>::intersection(Point &P, Vector &v, Number s)
113 // vector to be approximated = (1,s)
117 Number val = (s*P[0] - P[1])/(v[1]*s);
118 if(ceil(val)-val <= myPrecision) // val is very close and slightly under an integer -> round to the integer
119 return (Integer) ceil(val);
121 return (Integer) floor(val);
125 Number num = -P[1]*v[0] - P[0]*(v[1] - s*v[0]) + v[1]*P[0];
126 Number denom = v[0]*(v[1] - s*v[0]);
127 Number val = num/denom;
131 Q[0] = P[0] + ceil(val)*v[0];
132 Q[1] = P[1] + ceil(val)*v[1];
134 val3 = (Number) Q[0]*s - (Number) Q[1];
136 if(std::abs(val3) <= myPrecision)
137 return (Integer) ceil(val);
139 return (Integer) floor(val);
146 template <typename TInteger, typename TNumber>
148 void DGtal::DSLSubsegment<TInteger,TNumber>::update(Vector &u, Point& A, Vector &l, Integer r, Vector *v)
152 Integer alpha = intersection(AA,u,l,r);
160 template <typename TInteger, typename TNumber>
162 void DGtal::DSLSubsegment<TInteger,TNumber>::update(Vector &u, Point &A, Number s, Vector *v)
166 Integer alpha = intersection(AA,u,s);
174 template <typename TInteger, typename TNumber>
176 void DGtal::DSLSubsegment<TInteger,TNumber>::convexHullHarPeled(Vector &l, Integer n, Point *inf, Point *sup)
192 Point A = Point(0,1);
193 Point B = Point(1,0);
197 Integer alpha1, alpha2, alpha;
198 DGtal::IntegerComputer<Integer> ic;
204 alpha1 = intersection(A,B,l,0);
205 alpha2 = intersectionVertical(A,B,n);
206 alpha = ic.min(alpha1,alpha2);
208 if(A[0]*l[1]-A[1]*l[0]==0 || alpha == alpha2)
213 alpha1 = intersection(B,A,l,0);
214 alpha2 = intersectionVertical(B,A,n);
215 alpha = ic.min(alpha1,alpha2);
217 if(B[0]*l[1]-B[1]*l[0]==0 || alpha == alpha2)
232 template <typename TInteger, typename TNumber>
234 void DGtal::DSLSubsegment<TInteger,TNumber>::convexHullApprox(Vector &l, Integer r, Integer n, Point *inf, Point *sup)
237 //std::cout << "In Convex hull approx" << std::endl;
239 //std::cout << l << " " << n << std::endl;
255 Point A = Point(0,1);
256 Point B = Point(1,0);
258 Vector u = Vector(1,-1);
259 Vector v = Vector(1,0);
261 Vector normal = Vector(-l[1],l[0]);
268 DGtal::IntegerComputer<TInteger> ic;
272 if(v[0]*normal[0]+v[1]*normal[1] ==0) // should never happen
278 if(v[0]*normal[0]+v[1]*normal[1] < 0)
280 alpha = ic.min(intersection(A,v,l,r), intersectionVertical(A,v,n));
282 if(alpha >= 1 || first)
296 if(v[0]*normal[0]+v[1]*normal[1] > 0)
298 alpha = ic.min(intersection(B,v,l,r),intersectionVertical(B,v,n));
321 assert(A[0] != B[0] || A[1] != B[1]);
326 template <typename TInteger, typename TNumber>
328 void DGtal::DSLSubsegment<TInteger,TNumber>::convexHullApproxTwoPoints(Vector &l, Integer r, Integer n, Point *inf, Point *sup, Point *prevInf, Point *prevSup, bool inv)
353 Vector normal = Vector(-l[1],l[0]);
359 DGtal::IntegerComputer<Integer> ic;
364 if(v[0]*normal[0]+v[1]*normal[1]< 0)
366 alpha = ic.min(intersection(A,v,l,r), intersectionVertical(A,v,n));
368 if(alpha >= 1 || first)
374 //test if A is on the slope
375 if(A[0]*l[1]-A[1]*l[0]+r ==0)
391 if(v[0]*normal[0]+v[1]*normal[1]> 0)
393 alpha = ic.min(intersection(B,v,l,r),intersectionVertical(B,v,n));
400 // test if B is on the slope
401 if(B[0]*l[1]-B[1]*l[0] +r==0 )
421 // if A is on the line, A is a vertex for both the lower and the upper convex hulls
422 if(A[0]*l[1]-A[1]*l[0]+r ==0)
431 if(B[0]*l[1]-B[1]*l[0]+r ==0)
456 if(B[0]*l[1]-B[1]*l[0]+r ==0)
464 if(A[0]*l[1]-A[1]*l[0]+r ==0)
496 template <typename TInteger, typename TNumber>
498 void DGtal::DSLSubsegment<TInteger,TNumber>::convexHullApprox(Number s, Integer n, Point *inf, Point *sup)
500 // slope to be approximated = (1,s)
502 //std::cout << "In Convex hull approx" << std::endl;
504 Point A = Point(0,1);
505 Point B = Point(1,0);
507 Vector u = Vector(1,-1);
508 Vector v = Vector(1,0);
510 VectorF normal = VectorF(-s,1);
517 DGtal::IntegerComputer<Integer> ic;
522 if(std::abs(v[0]*normal[0]+v[1]*normal[1]) <= myPrecision)
528 if(v[0]*normal[0]+v[1]*normal[1] < 0)
530 alpha = ic.min(intersection(A,v,s), intersectionVertical(A,v,n));
536 // test if A is on the slope
537 if(std::abs(A[0]*normal[0]+A[1]*normal[1]) <= myPrecision)
553 if(v[0]*normal[0]+v[1]*normal[1] > 0)
555 alpha = ic.min(intersection(B,v,s),intersectionVertical(B,v,n));
561 // test if B is on the slope
562 if(std::abs(B[0]*normal[0]+B[1]*normal[1]) <= myPrecision)
581 Integer g = ic.gcd(v[0],v[1]);
591 assert(A[0] != B[0] || A[1] != B[1]);
598 // Compute the term following f=p/q in the Farey Series of order n. We
599 // have -q'p+p'q = 1, q' max such that q'<=n
600 // Complexity of extendedEuclid
601 template <typename TInteger, typename TNumber>
603 typename DGtal::DSLSubsegment<TInteger,TNumber>::Point DGtal::DSLSubsegment<TInteger,TNumber>::nextTermInFareySeriesEuclid(Integer fp, Integer fq, Integer n)
608 DGtal::IntegerComputer<Integer> ic;
610 p = ic.extendedEuclid(fp,fq,1);
618 pp = pp + floor((n+u)/fq)*fp;
619 qq = qq + floor((n+u)/fq)*fq;
626 template <typename TInteger, typename TNumber>
628 typename DGtal::DSLSubsegment<TInteger,TNumber>::RayC DGtal::DSLSubsegment<TInteger,TNumber>::rayOfHighestSlope(Integer p, Integer q, Integer r, Integer smallestSlope, Integer n)
630 return RayC(p,q,r,n-(n-smallestSlope)%q);
635 template <typename TInteger, typename TNumber>
637 typename DGtal::DSLSubsegment<TInteger,TNumber>::Integer DGtal::DSLSubsegment<TInteger,TNumber>::slope(Integer p, Integer q, Integer r, Number a, Number b, Number mu)
639 BOOST_CONCEPT_ASSERT((concepts::CInteger<TNumber>));
640 return (Integer) ceil((LongDoubleType) (r*b-mu*q)/(-p*b+a*q));
643 template <typename TInteger, typename TNumber>
645 typename DGtal::DSLSubsegment<TInteger,TNumber>::Integer DGtal::DSLSubsegment<TInteger,TNumber>::slope(Integer p, Integer q, Integer r, Number alpha, Number beta)
648 Number val = (r-beta*q)/(-p+alpha*q);
650 // if the value is very close to a slightly smaller integer, we round to the close integer
651 if(val-floor(val) <= myPrecision)
652 return((Integer) floor(val));
654 return((Integer) ceil(val));
658 template <typename TInteger, typename TNumber>
660 typename DGtal::DSLSubsegment<TInteger,TNumber>::Position DGtal::DSLSubsegment<TInteger,TNumber>::positionWrtRay(RayC &r, Number a, Number b, Number mu)
662 BOOST_CONCEPT_ASSERT((concepts::CInteger<TNumber>));
663 Integer v = -a*r.x + r.y*b - mu;
677 template <typename TInteger, typename TNumber>
679 typename DGtal::DSLSubsegment<TInteger,TNumber>::Position DGtal::DSLSubsegment<TInteger,TNumber>::positionWrtRay(RayC &r, Number alpha, Number beta)
681 Number v = -alpha*r.x + r.y - beta;
683 if(std::abs(v) <= myPrecision )
696 template <typename TInteger, typename TNumber>
698 typename DGtal::DSLSubsegment<TInteger,TNumber>::RayC DGtal::DSLSubsegment<TInteger,TNumber>::smartRayOfSmallestSlope(Integer fp, Integer fq, Integer gp, Integer gq, Integer r)
700 // Version 1: using floor operator
707 // Compute the slope of the line through (f=p/Q,r/q) and
709 Integer x = (r*gq - rr*fq);
711 Integer y = r*gp-rr*fp; // after simplification of the above formula
718 template <typename TInteger, typename TNumber>
720 typename DGtal::DSLSubsegment<TInteger,TNumber>::Integer DGtal::DSLSubsegment<TInteger,TNumber>::smartFirstDichotomy(Integer fp, Integer fq, Integer gp, Integer gq, Number a, Number b, Number mu, Integer n, bool *flagRayFound)
722 BOOST_CONCEPT_ASSERT((concepts::CInteger<Number>));
730 *flagRayFound = false;
732 while((lup>=2 || ldown >=2) && !*flagRayFound)
734 myRay = smartRayOfSmallestSlope(fp,fq,gp,gq,r);
735 myPosition = positionWrtRay(myRay,a,b,mu);
739 // std::cout << "height " << r << " Ray " << myRay.x << " " << myRay.y << std::endl;
740 // std::cout << "myPosition " << myPosition << std::endl;
744 if(myPosition == ONTO)
745 *flagRayFound = true;
747 if(myPosition == ABOVE)
749 r = r + ((lup%2 == 0)?lup/2:(lup-1)/2);
750 ldown = ((lup%2 ==0)?lup/2:(lup-1)/2);
751 lup = ((lup%2==0)?lup/2:(lup+1)/2);
755 r = r - ((ldown%2==0)?ldown/2:(ldown+1)/2);
756 lup = ((ldown%2==0)?ldown/2:(ldown+1)/2);
757 ldown = ((ldown%2==0)?ldown/2:(ldown-1)/2);
763 // If the point is not on a ray of smallest slope
766 myRay = smartRayOfSmallestSlope(fp,fq,gp,gq,r);
767 myPosition = positionWrtRay(myRay,a,b,mu);
769 if(myPosition != ONTO)
771 if(myPosition == ABOVE)
774 RayC SteepestRay = rayOfHighestSlope(fp, fq,r,(smartRayOfSmallestSlope(fp,fq,gp,gq,r)).x,n);
775 Position pos = positionWrtRay(SteepestRay,a,b,mu);
780 *flagRayFound = true;
785 *flagRayFound = true;
790 // std::cout << r << std::endl;
797 template <typename TInteger, typename TNumber>
799 typename DGtal::DSLSubsegment<TInteger,TNumber>::Integer DGtal::DSLSubsegment<TInteger,TNumber>::smartFirstDichotomy(Integer fp, Integer fq, Integer gp, Integer gq, Number alpha, Number beta, Integer n, bool *flagRayFound)
807 *flagRayFound = false;
810 // std::cout << fp << " " << fq << " " << gp << " " << gq << std::endl;
814 while((lup>=2 || ldown >=2) && !*flagRayFound)
816 myRay = smartRayOfSmallestSlope(fp,fq,gp,gq,r);
817 myPosition = positionWrtRay(myRay,alpha,beta);
821 // std::cout << "height " << r << " Ray " << myRay.x << " " << myRay.y << std::endl;
822 // std::cout << "myPosition " << myPosition << std::endl;
826 if(myPosition == ONTO)
827 *flagRayFound = true;
829 if(myPosition == ABOVE)
831 r = r + ((lup%2 == 0)?lup/2:(lup-1)/2);
832 ldown = ((lup%2 ==0)?lup/2:(lup-1)/2);
833 lup = ((lup%2==0)?lup/2:(lup+1)/2);
837 r = r - ((ldown%2==0)?ldown/2:(ldown+1)/2);
838 lup = ((ldown%2==0)?ldown/2:(ldown+1)/2);
839 ldown = ((ldown%2==0)?ldown/2:(ldown-1)/2);
844 // If the point is not on a ray of smallest slope
847 myRay = smartRayOfSmallestSlope(fp,fq,gp,gq,r);
848 myPosition = positionWrtRay(myRay,alpha,beta);
850 if(myPosition != ONTO)
852 if(myPosition == ABOVE)
855 RayC SteepestRay = rayOfHighestSlope(fp, fq,r,(smartRayOfSmallestSlope(fp,fq,gp,gq,r)).x,n);
856 Position pos = positionWrtRay(SteepestRay,alpha,beta);
861 *flagRayFound = true;
865 *flagRayFound = true;
874 template <typename TInteger, typename TNumber>
876 typename DGtal::DSLSubsegment<TInteger,TNumber>::RayC DGtal::DSLSubsegment<TInteger,TNumber>::localizeRay(Integer fp, Integer fq, Integer gp, Integer gq, Integer r, Number a, Number b, Number mu, Integer n)
878 boost::ignore_unused_variable_warning( n );
879 BOOST_CONCEPT_ASSERT((concepts::CInteger<Number>));
880 Number alpha = slope(fp, fq,r,a,b,mu);
883 Integer smallestSlope = smartRayOfSmallestSlope(fp,fq,gp,gq,r).x;
886 if(alpha%(fq) == smallestSlope)
888 return RayC(fp,fq,r,alpha);
891 if(alpha%(fq) < smallestSlope)
893 return RayC(fp,fq,r,alpha + smallestSlope - alpha%(fq));
896 // alphaInt%(f.q()) > smallestSlope
898 return RayC(fp,fq,r,alpha - (alpha%(fq) - smallestSlope) + fq);
903 template <typename TInteger, typename TNumber>
905 typename DGtal::DSLSubsegment<TInteger,TNumber>::RayC DGtal::DSLSubsegment<TInteger,TNumber>::localizeRay(Integer fp, Integer fq, Integer gp, Integer gq, Integer r, Number alpha, Number beta, Integer n)
908 Integer smallestSlope = smartRayOfSmallestSlope(fp,fq,gp,gq,r).x;
910 Integer kmax = floor((n-smallestSlope)/fq) +1;
914 Integer ldown = kmax;
921 while((lup>=2 || ldown >=2) && !found)
923 aRay = RayC(fp,fq,r,smallestSlope+k*fq);
924 myPosition = positionWrtRay(aRay,alpha,beta);
927 std::cout << "k " << k << " Ray " << aRay.x << " " << aRay.y << std::endl;
928 std::cout << "myPosition " << myPosition << std::endl;
931 if(myPosition == ONTO)
934 if(myPosition == ABOVE)
936 k = k - ((lup%2 == 0)?lup/2:(lup-1)/2);
937 ldown = ((lup%2 ==0)?lup/2:(lup-1)/2);
938 lup = ((lup%2==0)?lup/2:(lup+1)/2);
942 k = k + ((ldown%2==0)?ldown/2:(ldown+1)/2);
943 lup = ((ldown%2==0)?ldown/2:(ldown+1)/2);
944 ldown = ((ldown%2==0)?ldown/2:(ldown-1)/2);
950 aRay = RayC(fp,fq,r,smallestSlope+k*fq);
951 myPosition = positionWrtRay(aRay,alpha,beta);
953 if(myPosition == ABOVE || myPosition == ONTO)
956 return RayC(fp,fq,r,smallestSlope+(k+1)*fq);
966 template <typename TInteger, typename TNumber>
968 typename DGtal::DSLSubsegment<TInteger,TNumber>::RayC DGtal::DSLSubsegment<TInteger,TNumber>::raySup(Integer fp, Integer fq, RayC r)
971 // r is the highest ray
984 template <typename TInteger, typename TNumber>
986 void DGtal::DSLSubsegment<TInteger,TNumber>::shortFindSolution(Integer fp, Integer fq, Integer gp, Integer gq, RayC r, Integer n, Integer *resAlphaP, Integer *resAlphaQ, Integer *resBetaP) // resBetaQ = resAlphaQ
988 Point inf, sup , tmpsup, tmpinf;
989 DGtal::IntegerComputer<Integer> ic;
991 //Compute the lower edge of the facet
992 if(fq <= ic.max(r.x,n-r.x))
998 convexHullApprox(Vector(fq,fp),0,ic.max(r.x,n-r.x),&inf,&tmpsup);
1000 if(gq <= ic.max(r.x,n-r.x))
1006 convexHullApprox(Vector(gq,gp),0,ic.max(r.x,n-r.x),&tmpinf,&sup);
1009 if(r.x-inf[0] < 0) // R is the ray of smallest slope in inf
1011 *resAlphaP = inf[1];
1012 *resAlphaQ = inf[0];
1013 *resBetaP = -(*resAlphaP)*r.x+(*resAlphaQ)*r.y;
1016 if(r.x+sup[0] > n) // R is the ray of highest slope in sup
1018 *resAlphaP = sup[1];
1019 *resAlphaQ = sup[0];
1020 *resBetaP = -(*resAlphaP)*r.x+(*resAlphaQ)*r.y;
1022 else //the facet is upper triangular,
1024 Integer g = ic.gcd(inf[1] + sup[1],inf[0]+sup[0]);
1026 *resAlphaP = (inf[1]+sup[1])/g;
1027 *resAlphaQ = (inf[0]+sup[0])/g;
1028 *resBetaP = -(*resAlphaP)*r.x+(*resAlphaQ)*r.y;
1036 template <typename TInteger, typename TNumber>
1038 void DGtal::DSLSubsegment<TInteger,TNumber>::findSolutionWithoutFractions(Integer fp, Integer fq, Integer gp, Integer gq, RayC r, Integer n, Integer *resAlphaP, Integer *resAlphaQ, Integer *resBetaP, bool found) // resBetaQ = resAlphaQ
1041 DGtal::IntegerComputer<Integer> ic;
1046 // r is not the highest ray on A
1049 if(gq <= ic.max(r.x,n-r.x))
1050 { // B is a multiple point, r is the lowest ray on B
1051 // (otherwise, there would be an intersection in [AB]
1052 // between the lowest ray on B and the ray above r on A.
1053 // Thus B is the solution
1056 *resBetaP = -gp*r.x + r.y*gq;
1059 { // compute the ray juste above r
1060 rr = raySup(fp,fq,r);
1061 // compute the fraction following f in the Farey Series
1062 // given by the slope of rr
1063 if(ic.max(rr.x,n-rr.x)>ic.max(r.x,n-r.x))
1065 Point next = nextTermInFareySeriesEuclid(fp,fq,ic.max(rr.x,n-rr.x));
1066 *resAlphaP = next[1];
1067 *resAlphaQ = next[0];
1068 *resBetaP = (Integer) -(*resAlphaP)*r.x+(*resAlphaQ)*r.y;
1072 Point next = nextTermInFareySeriesEuclid(fp,fq,ic.max(r.x,n-r.x));
1073 *resAlphaP = next[1];
1074 *resAlphaQ = next[0];
1075 *resBetaP = (Integer) -(*resAlphaP)*r.x+(*resAlphaQ)*r.y ;
1081 if(fq <= ic.max(r.x,n-r.x))
1082 { // A is a multiple point
1083 // A is the solution
1086 *resBetaP = -fp*r.x +fq*r.y;
1089 if(gq <= ic.max(r.x,n-r.x) && (r.x + gq) >n)
1090 { // B is a multiple point and r is the lowest ray
1091 // B is the solution
1094 *resBetaP = -gp*r.x +gq*r.y;
1098 // A is not a multiple point. Check if the vertex above A
1099 // is a multiple point
1100 Integer h = -fp*r.x + r.y*fq +1;
1101 rr = smartRayOfSmallestSlope(fp,fq,gp,gq,h);
1102 if(fq<=ic.max(rr.x,n-rr.x))
1103 { //the vertex above A is a
1104 // multiple point -> A is the solution
1107 *resBetaP = -fp*r.x +fq*r.y;
1112 convexHullHarPeled(v,ic.max(r.x,n-r.x),&inf,&sup);
1113 // Let C be the point on r with abscissa equal to inf.
1114 rr = raySup(inf[1],inf[0],r); // ray above r passing through C
1115 if(rr.x == r.x) // r is the highest ray passing through C
1116 { // C is the solution
1117 *resAlphaP = inf[1];
1118 *resAlphaQ = inf[0];
1119 *resBetaP = -inf[1]*r.x + inf[0]*r.y;
1123 if(ic.max(rr.x,n-rr.x)>ic.max(r.x,n-r.x))
1125 // the solution is given by the fraction following inf
1126 // in the Farey Series of order
1127 // max(x-inf.q(),n-(x.inf.q())), on the ray rr
1129 // we compute the mediant on inf and sup: if
1130 // the denominator is lower or equal to the
1131 // order given by the ray rr, then the
1132 // mediant is the solution. Otherwise, sup is
1134 Integer g = ic.gcd(inf[1] + sup[1],inf[0]+sup[0]);
1135 if((inf[0]+sup[0])/g <= ic.max(rr.x,n-rr.x))
1137 *resAlphaP = (inf[1]+sup[1])/g;
1138 *resAlphaQ = (inf[0]+sup[0])/g;
1142 *resAlphaP = sup[1];
1143 *resAlphaQ = sup[0];
1145 *resBetaP = -(*resAlphaP)*rr.x+(*resAlphaQ)*rr.y - 1;
1149 *resAlphaP = sup[1];
1150 *resAlphaQ = sup[0];
1151 *resBetaP = -(*resAlphaP)*r.x+(*resAlphaQ)*r.y;
1164 // Constructor in the case of integer input parameters
1165 template <typename TInteger, typename TNumber>
1167 DGtal::DSLSubsegment<TInteger,TNumber>::DSLSubsegment(Number a, Number b, Number mu, Point &A, Point &B, std::string type)
1171 if(type.compare("farey")==0)
1172 this->DSLSubsegmentFareyFan(a,b,mu,A,B);
1174 if(type.compare("localCH")==0)
1175 this->DSLSubsegmentLocalCH(a,b,mu,A,B);
1177 throw std::invalid_argument("ERROR: Unknow string to specify the algorithm. \"farey\" is used hereafter.");
1179 catch(std::invalid_argument & e)
1181 std::cerr << e.what() << std::endl;
1182 this->DSLSubsegmentFareyFan(a,b,mu,A,B);
1188 template <typename TInteger, typename TNumber>
1190 void DGtal::DSLSubsegment<TInteger,TNumber>::DSLSubsegmentFareyFan(Number a, Number b, Number mu, Point &A, Point &B)
1192 Integer n = B[0] - A[0];
1200 //std::cout << "DSS parameters are DSL parameters." << std::endl;
1201 ////std::cout << " " << a << " " << b << " " << mu;
1205 // A becomes the origin // mu must be between 0 and b
1206 mu += a*A[0] - A[1]*b;
1211 Integer fp,fq,gp,gq;
1216 convexHullHarPeled(v,n,&inf,&sup);
1224 Point next = nextTermInFareySeriesEuclid(a,b,n);
1233 // Find the height in the ladder
1234 // Returns the height h such that:
1235 // - param is in between the rays passing through the point (inf =
1237 // ==> found is set to false
1238 // - or param is above the ray of smallest slope passing through
1239 // (inf = p/q, h/q) but below all the rays passing through (p/q,
1240 // h+1/q) ==> found is set to true
1243 Integer h = smartFirstDichotomy(fp,fq,gp,gq,a,b,mu,n,&found);
1250 r = smartRayOfSmallestSlope(fp,fq,gp,gq,h);
1254 r = localizeRay(fp,fq,gp,gq,h,a,b,mu,n);
1257 Integer resAlphaP=0, resAlphaQ=0, resBetaP=0;
1258 findSolutionWithoutFractions(fp,fq, gp, gq, r, n, &resAlphaP, &resAlphaQ, &resBetaP, found);
1262 myMu = resBetaP - myA*A[0] + myB*A[1];
1271 template <typename TInteger, typename TNumber>
1273 void DGtal::DSLSubsegment<TInteger,TNumber>::lowerConvexHull(Vector &l, Integer mu, Point &A, Point &B,
1274 Point *prevInfL, Point *infL, Point *infR, Point *prevInfR)
1277 Integer rA = l[1]*A[0]-l[0]*A[1] + mu;
1278 Integer rB = l[1]*B[0]-l[0]*B[1] + mu;
1280 Point prevSupL,supL,supR,prevSupR;
1282 // from left to right
1283 convexHullApproxTwoPoints(l,rA,B[0]-A[0],infL,&supL,prevInfL,&prevSupL,0); // computation of the left part of the convex hulls
1293 // from right to left
1296 convexHullApproxTwoPoints(l,l[0]-rB,B[0]-A[0],infR,&supR,prevInfR,&prevSupR,1);
1298 Point B1 = B + Point(0,1);
1310 *prevInfR = B1 - *prevInfR;
1311 prevSupR = B1 - prevSupR;
1314 *prevInfR = prevSupR;
1319 convexHullApproxTwoPoints(l,0,B[0]-A[0],infR,&supR,prevInfR,&prevSupR,1);
1330 *prevInfR = B - *prevInfR;
1331 prevSupR = B - prevSupR;
1334 *prevInfR = prevSupR;
1346 // Contructor calling the localConvexHull approx instead of the walk in the Farey Fan -> should be a new class.
1347 template <typename TInteger, typename TNumber>
1349 void DGtal::DSLSubsegment<TInteger,TNumber>::DSLSubsegmentLocalCH(Number a, Number b, Number mu, Point &A, Point &B)
1351 Integer rB = a*B[0]-b*B[1] + mu;
1355 Point infL,supL,infR,supR,prevInfL,prevSupL,prevInfR,prevSupR;
1357 lowerConvexHull(l,mu,A,B,&prevInfL,&infL,&infR,&prevInfR);
1361 lowerConvexHull(l,l[0]-rB-1,pz,BA,&prevSupR, &supR, &supL, &prevSupL);
1363 prevSupR = B+Point(0,1)-prevSupR;
1364 supR = B+Point(0,1)-supR;
1365 prevSupL = B+Point(0,1)-prevSupL;
1366 supL = B+Point(0,1)-supL;
1368 DGtal::IntegerComputer<Integer> ic;
1370 myA=0, myB=0, myMu=0;
1372 // we are left with four possible lines given by the couples (prevInfL, infL=infR) (infL = infR,prevInfR)
1373 // (prevSupL, supL = supR) (supL = supR, prevSupR)
1374 // the solution is given by the slope with bigger b
1396 for(int i=0;i<3;i++)
1398 btmp = inf[i+1][0] - inf[i][0];
1399 atmp = inf[i+1][1] - inf[i][1];
1401 if(atmp==0 || btmp==0)
1402 g = ic.max((Integer) 1,ic.max(atmp,btmp));
1404 g = ic.gcd(btmp,atmp);
1415 for(int i=0;i<3;i++)
1417 btmp = sup[i+1][0] - sup[i][0];
1418 atmp = sup[i+1][1] - sup[i][1];
1420 if(atmp==0 || btmp==0)
1421 g = ic.max((Integer) 1,ic.max(atmp,btmp));
1423 g = ic.gcd(btmp,atmp);
1435 myMu = -myA*infL[0] + myB*infL[1];
1441 template <typename TInteger, typename TNumber>
1443 DGtal::DSLSubsegment<TInteger,TNumber>::DSLSubsegment(Number alpha, Number beta,
1444 Point &A, Point &B, Number precision)
1446 Integer n = B[0] - A[0];
1448 myPrecision = precision;
1450 // A becomes the origin
1452 beta +=alpha*A[0] - A[1];
1455 Integer fp,fq,gp,gq;
1459 std::cout << "\n \nDSLSubsegment with floats, n=" << n << " precision = " << myPrecision << std::endl;
1460 std::cout << std::setprecision(15) << "alpha = " << alpha << " beta = " << beta << std::endl;
1464 convexHullApprox(alpha,n,&inf,&sup);
1472 std::cout << "f and g = " << fp << " " << fq << " " << gp << " " << gq << std::endl;
1476 if(fp == gp && fq == gq)
1478 Point next = nextTermInFareySeriesEuclid(fp,fq,n);
1487 // Find the height in the ladder
1488 // Returns the height h such that:
1489 // - param is in between the rays passing through the point (inf =
1491 // ==> found is set to false
1492 // - or param is above the ray of smallest slope passing through
1493 // (inf = p/q, h/q) but below all the rays passing through (p/q,
1494 // h+1/q) ==> found is set to true
1497 Integer h = smartFirstDichotomy(fp,fq,gp,gq,alpha,beta,n,&found);
1502 r = smartRayOfSmallestSlope(fp,fq,gp,gq,h);
1504 r = localizeRay(fp,fq,gp,gq,h,alpha,beta,n);
1507 Integer resAlphaP=0, resAlphaQ=0, resBetaP=0;
1508 findSolutionWithoutFractions(fp,fq, gp, gq, r, n, &resAlphaP, &resAlphaQ, &resBetaP, found);
1513 myMu = resBetaP - myA*A[0] + myB*A[1];
1519 //------------------------- Accessors --------------------------
1521 template <typename TInteger, typename TNumber>
1524 DGtal::DSLSubsegment<TInteger,TNumber>::getA() const {
1529 template <typename TInteger, typename TNumber>
1532 DGtal::DSLSubsegment<TInteger,TNumber>::getB() const {
1538 template <typename TInteger, typename TNumber>
1541 DGtal::DSLSubsegment<TInteger,TNumber>::getMu() const {