46 #include <boost/program_options/options_description.hpp>    47 #include <boost/program_options/parsers.hpp>    48 #include <boost/program_options/variables_map.hpp>    50 #include "DGtal/base/Common.h"    51 #include "DGtal/helpers/StdDefs.h"    53 #include "DGtal/arithmetic/LighterSternBrocot.h"    54 #include "DGtal/arithmetic/Pattern.h"    56 #include "DGtal/io/boards/Board2D.h"    57 #include "DGtal/io/Color.h"    59 using namespace DGtal;
    62 namespace po = boost::program_options;
   109 template <
typename Po
int>
   110 struct OddConvexHullMap {
   113   typedef Point Vector; 
   122   OddConvexHullMap(
const Vector& aShift = Vector(1,-1))
   131   Point operator()(
const Point& aP)
 const   148 template <
typename Po
int>
   149 struct EvenConvexHullMap {
   152   typedef Point Vector; 
   162   EvenConvexHullMap(
const Point& aPoint, 
const Vector& aShift = Vector(1,-1))
   163     : myZn(aPoint), myS(aShift) {}
   171   Point operator()(
const Point& aP)
 const   173     return myZn - aP + myS; 
   194 template <
typename Board, 
typename Po
int>
   195 void drawSegment(Board& aBoard, 
const Point& aP, 
const Point& aQ)
   197   aBoard.drawLine(aP[0], aP[1], aQ[0], aQ[1]);   
   215 template <
typename Board, 
typename Iterator, 
typename Functor>
   216 void drawSegments(Board& aBoard, 
   217                   const Iterator& itb, 
const Iterator& ite, 
   223       Iterator prevIt = it; 
   225       for ( ; it != ite; ++prevIt, ++it) 
   227           drawSegment( aBoard, aF(*prevIt), aF(*it) ); 
   249 template<
typename Fraction, 
typename Container>
   250 void fillConvergents(
const Fraction& aZn, 
   251                 Container& odd, Container& even)
   253   typedef typename Container::value_type Vector; 
   255   for (
typename Fraction::Quotient i = 1; i <= aZn.k(); ++i)
   257       Fraction zk = aZn.reduced(i); 
   258       if (((aZn.k() - i)%2) == 1 )
   260           odd.push_back(Vector(zk.q(),zk.p())); 
   264           even.push_back(Vector(zk.q(),zk.p())); 
   283 template <
typename Pattern, 
typename Integer>
   284 void displayConvexHull(
const Pattern& aP, 
const Integer& aD, 
bool withFDT = 
false)
   286   typedef typename Pattern::Fraction Fraction; 
   287   typedef typename Pattern::Quotient Quotient; 
   288   typedef typename Pattern::Vector2I Vector;  
   289   typedef std::vector<Vector> Convergents; 
   290   typedef typename Pattern::Point2I Point;  
   295   Convergents oddConvergents, evenConvergents;
   298   Fraction zn = aP.slope();
   302       Fraction znm1 = zn.father(); 
   304         oddConvergents.push_back(Vector(znm1.q(),znm1.p())); 
   306         evenConvergents.push_back(Vector(znm1.q(),znm1.p())); 
   309   fillConvergents( zn, oddConvergents, evenConvergents ); 
   312   Point Zn = Point(aD*zn.q(),aD*zn.p()); 
   313   aBoard << Z2i::Domain( Point(0,0), Zn ); 
   314   aBoard << SetMode( Zn.className(), 
"Grid" );
   315   aBoard.setLineStyle(Board2D::Shape::SolidStyle); 
   316   aBoard.setPenColor(DGtal::Color::Black);
   319   OddConvexHullMap<Point> oddH;
   320   drawSegments( aBoard, oddConvergents.begin(), oddConvergents.end(), oddH ); 
   322   EvenConvexHullMap<Point> evenH(Zn);
   323   drawSegments( aBoard, evenConvergents.begin(), evenConvergents.end(), evenH ); 
   326   drawSegment( aBoard, Point(0,0), Zn ); 
   327   if (evenConvergents.size() != 0)
   329       drawSegment( aBoard, evenH(*evenConvergents.rbegin()), Zn ); 
   330       if (oddConvergents.size() != 0)
   332           drawSegment( aBoard, Point(0,0), oddH(*oddConvergents.rbegin()) );
   334                        oddH(*oddConvergents.begin()), 
   335                        evenH(*evenConvergents.begin()) ); 
   339           drawSegment( aBoard, Point(0,0), evenH(*evenConvergents.rbegin()) );
   347       if (evenConvergents.size() != 0)
   350                      evenH(*evenConvergents.rbegin()) ); 
   352       typedef typename Convergents::const_reverse_iterator RI; 
   353       RI oddRit = oddConvergents.rbegin(); 
   354       RI evenRit = evenConvergents.rbegin(); 
   355       bool hasToContinue = 
true; 
   356       while (hasToContinue) 
   358           if (oddRit != oddConvergents.rend())
   365             hasToContinue = 
false; 
   368           if ( (hasToContinue) && (evenRit != evenConvergents.rend()) )
   375             hasToContinue = 
false; 
   379       aBoard.saveEPS(
"FDT.eps");
   383       aBoard.saveEPS(
"CH.eps");
   399 template <
typename Board, 
typename Po
int>
   400 void drawTriangle(Board& aBoard, 
   401                   const Point& aP, 
const Point& aQ, 
const Point& aR)
   403   aBoard.drawTriangle( aP[0], aP[1], aQ[0], aQ[1], aR[0], aR[1] ); 
   415 struct InDirectBezoutComputer
   424   template<
typename Pattern>
   425   typename Pattern::Vector2I
   426   getPositiveBezout(
const Pattern& aP)
 const   438   template<
typename Pattern>
   439   typename Pattern::Vector2I
   440   getNegativeBezout(
const Pattern& aP)
 const   442     return aP.slope().even() 
   443       ? aP.U( 1 ) - aP.previousPattern().U( 1 ) 
   444       : aP.previousPattern().U( 1 );
   458 struct DirectBezoutComputer
   467   template<
typename Pattern>
   468   typename Pattern::Vector2I
   469   getPositiveBezout(
const Pattern& aP)
 const   471     return aP.slope().even() 
   472       ? aP.U( 1 ) - aP.previousPattern().U( 1 ) 
   473       : aP.previousPattern().U( 1 );
   483   template<
typename Pattern>
   484   typename Pattern::Vector2I
   485   getNegativeBezout(
const Pattern& aP)
 const   510 template <
typename Board, 
typename Pattern, 
typename BezoutComputer>
   511 void displayPartialCDT(Board& aBoard, 
   513                        const typename Pattern::Point2I& aStartingPoint,
   514                        const BezoutComputer& aBC )
   516   typedef typename Pattern::Fraction Fraction; 
   517   typedef typename Pattern::Vector2I Vector;  
   518   typedef typename Pattern::Point2I Point;  
   520   Fraction f = aP.slope();
   521   if ( (f.p() >= 1)&&(f.q() >= 1) )
   523       Point O = aStartingPoint; 
   524       Point Zn = aStartingPoint + aP.v();
   525       Vector v1 = aBC.getNegativeBezout(aP); 
   526       Point B = aStartingPoint + v1; 
   527       drawTriangle(aBoard, O, Zn, B); 
   529       if ( (f.p() > 1)||(f.q() > 1) )
   533           displayPartialCDT(aBoard, Pattern(Fraction(v1[1],v1[0])), O, aBC); 
   535           Vector v2 = aBC.getPositiveBezout(aP); 
   536           displayPartialCDT(aBoard, Pattern(Fraction(v2[1],v2[0])), B, aBC); 
   552 template <
typename Pattern, 
typename Integer>
   553 void displayCDT(
const Pattern& aP, 
const Integer& aD)
   557   typedef typename Pattern::Point2I Point;  
   558   typedef typename Pattern::Quotient Quotient;  
   559   typedef typename Pattern::Fraction Fraction;  
   560   Fraction zn = aP.slope(); 
   563   Point Zn = Point(aD*zn.q(),aD*zn.p()); 
   564   aBoard << Z2i::Domain( Point(0,0), Zn ); 
   565   aBoard << SetMode( Zn.className(), 
"Grid" );
   566   aBoard.setLineStyle(Board2D::Shape::SolidStyle); 
   567   aBoard.setPenColor(DGtal::Color::Black);
   570   for (Integer i = 0; i < aD; ++i)
   572       displayPartialCDT( aBoard, aP, Point(i*zn.q(), i*zn.p()), InDirectBezoutComputer() );
   577   typedef typename Pattern::Vector2I Vector;  
   578   typedef std::vector<Vector> Convergents; 
   579   typedef typename std::vector<Vector>::const_reverse_iterator ReverseIterator; 
   580   Convergents oddConvergents, evenConvergents;
   581   fillConvergents( zn, oddConvergents, evenConvergents ); 
   583   Point rPStartingPoint; 
   585   OddConvexHullMap<Point> oddH;
   587     ReverseIterator itb = evenConvergents.rbegin(); 
   588     ReverseIterator ite = evenConvergents.rend(); 
   589     Point aStartingPoint = oddH( *oddConvergents.rbegin() ); 
   591     Point p = aStartingPoint; 
   592     ReverseIterator it = itb; 
   595         for (++it; it != ite; ++it) 
   597             displayPartialCDT( aBoard, Pattern( (*it)[1], (*it)[0] ), p, DirectBezoutComputer() ); 
   604   EvenConvexHullMap<Point> evenH(Zn);
   606     ReverseIterator itb = oddConvergents.rbegin(); 
   607     ReverseIterator ite = oddConvergents.rend(); 
   608     Point aStartingPoint = evenH( *evenConvergents.rbegin() ); 
   610     Point p = aStartingPoint;
   611     ReverseIterator it = itb; 
   612     for ( ; it != ite; ++it) 
   615         displayPartialCDT( aBoard, Pattern( (*it)[1], (*it)[0] ), p, DirectBezoutComputer() ); 
   620     for (Integer i = 0; i < (aD-1); ++i)
   622         Point p = rPStartingPoint + i*aP.v(); 
   623         displayPartialCDT( aBoard, aP, p, DirectBezoutComputer() );
   628   aBoard.saveEPS(
"CDT.eps");
   638 void missingParam(std::string param)
   640   trace.error() << 
" Parameter: " << param << 
" is required...";
   641   trace.info() << std::endl;
   655 int main(
int argc, 
char **argv)
   658   po::options_description general_opt(
"Allowed options are");
   659   general_opt.add_options()
   660     (
"help,h", 
"display this message")
   661     (
"aparam,a",   po::value<int>(), 
"pattern a parameter" )
   662     (
"bparam,b",   po::value<int>(), 
"pattern b parameter" )
   663     (
"delta,d",   po::value<int>()->default_value(1), 
"number of repetitions" )
   664     (
"triangulation,t",   po::value<string>()->default_value(
"CH"), 
"output:\n\tClosest-point Delaunay triangulation {CDT}\n\tFarthest-point Delaunay triangulation {FDT}\n\tConvex hull {CH}" );
   667   po::variables_map vm;
   669     po::store(po::parse_command_line(argc, argv, general_opt), vm);  
   670   }
catch(
const std::exception& ex){
   672     trace.info()<< 
"Error checking program options: "<< ex.what()<< endl;
   676   if(!parseOK || vm.count(
"help")||argc<=1)
   678       trace.info()<< 
"Draw the Delaunay triangulation of a pattern using DGtal library" <<std::endl 
   679                   << 
"Basic usage: "<<std::endl
   680                   << 
"\t" << argv[0] << 
" -a 5 -b 8 "<<std::endl
   681                   << general_opt << 
"\n";
   686   if (!(vm.count(
"aparam"))) missingParam(
"-a");
   687   if (!(vm.count(
"bparam"))) missingParam(
"-b");
   689   typedef DGtal::int32_t Integer;
   690   Integer a = vm[
"aparam"].as<
int>();
   691   Integer b = vm[
"bparam"].as<
int>();
   692   if ( (a < 0) || (b <= 0) )
   694       trace.error() << 
" parameters a and b should be strictly positive.";
   695       trace.info() << std::endl;
   700       trace.error() << 
" parameter a should be strictly less than b.";
   701       trace.info() << std::endl;
   704   Integer d = vm[
"delta"].as<
int>(); 
   707       trace.error() << 
" parameter d should be strictly positive";
   708       trace.info() << std::endl;
   711   trace.info() << 
"a=" << a << 
", b=" << b << 
", d=" << d << std::endl; 
   713   typedef DGtal::int32_t Quotient;
   714   typedef LighterSternBrocot<Integer, Quotient, StdMapRebinder> SB;
   715   typedef SB::Fraction Fraction; 
   716   typedef Pattern<Fraction> Pattern; 
   718   Pattern pattern( a, b );
   720   string type = vm[
"triangulation"].as<
string>();
   723       displayCDT(pattern, d); 
   725   else if (type == 
"FDT")
   727       displayConvexHull(pattern, d, 
true); 
   729   else if (type == 
"CH")
   731       displayConvexHull(pattern, d); 
   735       trace.error() << 
" unknown output type. Try -h option. ";
   736       trace.info() << std::endl;