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 {
122 OddConvexHullMap(
const Vector& aShift = Vector(1,-1))
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) {}
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)
288 typedef std::vector<Vector> Convergents;
294 Convergents oddConvergents, evenConvergents;
297 Fraction zn = aP.
slope();
301 Fraction znm1 = zn.father();
303 oddConvergents.push_back(Vector(znm1.q(),znm1.p()));
305 evenConvergents.push_back(Vector(znm1.q(),znm1.p()));
308 fillConvergents( zn, oddConvergents, evenConvergents );
311 Point Zn = Point(aD*zn.q(),aD*zn.p());
313 aBoard <<
SetMode( Zn.className(),
"Grid" );
318 OddConvexHullMap<Point> oddH;
319 drawSegments( aBoard, oddConvergents.begin(), oddConvergents.end(), oddH );
321 EvenConvexHullMap<Point> evenH(Zn);
322 drawSegments( aBoard, evenConvergents.begin(), evenConvergents.end(), evenH );
325 drawSegment( aBoard, Point(0,0), Zn );
326 if (evenConvergents.size() != 0)
328 drawSegment( aBoard, evenH(*evenConvergents.rbegin()), Zn );
329 if (oddConvergents.size() != 0)
331 drawSegment( aBoard, Point(0,0), oddH(*oddConvergents.rbegin()) );
333 oddH(*oddConvergents.begin()),
334 evenH(*evenConvergents.begin()) );
338 drawSegment( aBoard, Point(0,0), evenH(*evenConvergents.rbegin()) );
346 if (evenConvergents.size() != 0)
349 evenH(*evenConvergents.rbegin()) );
351 typedef typename Convergents::const_reverse_iterator RI;
352 RI oddRit = oddConvergents.rbegin();
353 RI evenRit = evenConvergents.rbegin();
354 bool hasToContinue =
true;
355 while (hasToContinue)
357 if (oddRit != oddConvergents.rend())
364 hasToContinue =
false;
367 if ( (hasToContinue) && (evenRit != evenConvergents.rend()) )
374 hasToContinue =
false;
398 template <
typename Board,
typename Po
int>
399 void drawTriangle(Board& aBoard,
400 const Point& aP,
const Point& aQ,
const Point& aR)
402 aBoard.drawTriangle( aP[0], aP[1], aQ[0], aQ[1], aR[0], aR[1] );
414 struct InDirectBezoutComputer
423 template<
typename Pattern>
425 getPositiveBezout(
const Pattern& aP)
const
437 template<
typename Pattern>
439 getNegativeBezout(
const Pattern& aP)
const
441 return aP.
slope().even()
457 struct DirectBezoutComputer
466 template<
typename Pattern>
468 getPositiveBezout(
const Pattern& aP)
const
470 return aP.
slope().even()
482 template<
typename Pattern>
484 getNegativeBezout(
const Pattern& aP)
const
509 template <
typename Board,
typename Pattern,
typename BezoutComputer>
510 void displayPartialCDT(Board& aBoard,
513 const BezoutComputer& aBC )
519 Fraction f = aP.
slope();
520 if ( (f.p() >= 1)&&(f.q() >= 1) )
522 Point O = aStartingPoint;
523 Point Zn = aStartingPoint + aP.
v();
524 Vector v1 = aBC.getNegativeBezout(aP);
525 Point B = aStartingPoint + v1;
526 drawTriangle(aBoard, O, Zn, B);
528 if ( (f.p() > 1)||(f.q() > 1) )
532 displayPartialCDT(aBoard,
Pattern(Fraction(v1[1],v1[0])), O, aBC);
534 Vector v2 = aBC.getPositiveBezout(aP);
535 displayPartialCDT(aBoard,
Pattern(Fraction(v2[1],v2[0])), B, aBC);
551 template <
typename Pattern,
typename Integer>
552 void displayCDT(
const Pattern& aP,
const Integer& aD)
558 Fraction zn = aP.
slope();
561 Point Zn = Point(aD*zn.q(),aD*zn.p());
563 aBoard <<
SetMode( Zn.className(),
"Grid" );
568 for (Integer i = 0; i < aD; ++i)
570 displayPartialCDT( aBoard, aP, Point(i*zn.q(), i*zn.p()), InDirectBezoutComputer() );
576 typedef std::vector<Vector> Convergents;
577 typedef typename std::vector<Vector>::const_reverse_iterator
ReverseIterator;
578 Convergents oddConvergents, evenConvergents;
579 fillConvergents( zn, oddConvergents, evenConvergents );
581 Point rPStartingPoint;
583 OddConvexHullMap<Point> oddH;
585 ReverseIterator itb = evenConvergents.rbegin();
586 ReverseIterator ite = evenConvergents.rend();
587 Point aStartingPoint = oddH( *oddConvergents.rbegin() );
589 Point p = aStartingPoint;
590 ReverseIterator it = itb;
593 for (++it; it != ite; ++it)
595 displayPartialCDT( aBoard,
Pattern( (*it)[1], (*it)[0] ), p, DirectBezoutComputer() );
602 EvenConvexHullMap<Point> evenH(Zn);
604 ReverseIterator itb = oddConvergents.rbegin();
605 ReverseIterator ite = oddConvergents.rend();
606 Point aStartingPoint = evenH( *evenConvergents.rbegin() );
608 Point p = aStartingPoint;
609 ReverseIterator it = itb;
610 for ( ; it != ite; ++it)
613 displayPartialCDT( aBoard,
Pattern( (*it)[1], (*it)[0] ), p, DirectBezoutComputer() );
618 for (Integer i = 0; i < (aD-1); ++i)
620 Point p = rPStartingPoint + i*aP.
v();
621 displayPartialCDT( aBoard, aP, p, DirectBezoutComputer() );
636 void missingParam(std::string param)
638 trace.
error() <<
" Parameter: " << param <<
" is required...";
653 int main(
int argc,
char **argv)
656 po::options_description general_opt(
"Allowed options are");
657 general_opt.add_options()
658 (
"help,h",
"display this message")
659 (
"aparam,a", po::value<int>(),
"pattern a parameter" )
660 (
"bparam,b", po::value<int>(),
"pattern b parameter" )
661 (
"delta,d", po::value<int>()->default_value(1),
"number of repetitions" )
662 (
"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}" );
665 po::variables_map vm;
667 po::store(po::parse_command_line(argc, argv, general_opt), vm);
668 }
catch(
const std::exception& ex){
670 trace.
info()<<
"Error checking program options: "<< ex.what()<< endl;
674 if(!parseOK || vm.count(
"help")||argc<=1)
676 trace.
info()<<
"Draw the Delaunay triangulation of a pattern using DGtal library" <<std::endl
677 <<
"Basic usage: "<<std::endl
678 <<
"\t" << argv[0] <<
" -a 5 -b 8 "<<std::endl
679 << general_opt <<
"\n";
684 if (!(vm.count(
"aparam"))) missingParam(
"-a");
685 if (!(vm.count(
"bparam"))) missingParam(
"-b");
688 Integer a = vm[
"aparam"].as<
int>();
689 Integer b = vm[
"bparam"].as<
int>();
690 if ( (a < 0) || (b <= 0) )
692 trace.
error() <<
" parameters a and b should be strictly positive.";
698 trace.
error() <<
" parameter a should be strictly less than b.";
702 Integer d = vm[
"delta"].as<
int>();
705 trace.
error() <<
" parameter d should be strictly positive";
709 trace.
info() <<
"a=" << a <<
", b=" << b <<
", d=" << d << std::endl;
713 typedef SB::Fraction Fraction;
716 Pattern pattern( a, b );
718 string type = vm[
"triangulation"].as<
string>();
721 displayCDT(pattern, d);
723 else if (type ==
"FDT")
725 displayConvexHull(pattern, d,
true);
727 else if (type ==
"CH")
729 displayConvexHull(pattern, d);
733 trace.
error() <<
" unknown output type. Try -h option. ";
HyperRectDomain< Space > Domain
Point2I U(Quotient k) const
Board & setLineStyle(Shape::LineStyle style)
Trace trace(traceWriterTerm)
void saveEPS(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
typename Self::Point Point
Board & setPenColor(const DGtal::Color &color)
Pattern previousPattern() const