46#include "DGtal/base/Common.h"
47#include "DGtal/helpers/StdDefs.h"
49#include "DGtal/arithmetic/LighterSternBrocot.h"
50#include "DGtal/arithmetic/Pattern.h"
52#include "DGtal/io/boards/Board2D.h"
53#include "DGtal/io/Color.h"
111template <
typename Po
int>
112struct OddConvexHullMap {
115 typedef Point Vector;
124 OddConvexHullMap(
const Vector& aShift = Vector(1,-1))
133 Point operator()(
const Point& aP)
const
150template <
typename Po
int>
151struct EvenConvexHullMap {
154 typedef Point Vector;
164 EvenConvexHullMap(
const Point& aPoint,
const Vector& aShift = Vector(1,-1))
165 : myZn(aPoint), myS(aShift) {}
173 Point operator()(
const Point& aP)
const
175 return myZn - aP + myS;
196template <
typename Board,
typename Po
int>
197void drawSegment(Board& aBoard,
const Point& aP,
const Point& aQ)
199 aBoard.drawLine(aP[0], aP[1], aQ[0], aQ[1]);
217template <
typename Board,
typename Iterator,
typename Functor>
218void drawSegments(Board& aBoard,
219 const Iterator& itb,
const Iterator& ite,
225 Iterator prevIt = it;
227 for ( ; it != ite; ++prevIt, ++it)
229 drawSegment( aBoard, aF(*prevIt), aF(*it) );
251template<
typename Fraction,
typename Container>
252void fillConvergents(
const Fraction& aZn,
253 Container& odd, Container& even)
255 typedef typename Container::value_type Vector;
257 for (
typename Fraction::Quotient i = 1; i <= aZn.k(); ++i)
259 Fraction zk = aZn.reduced(i);
260 if (((aZn.k() - i)%2) == 1 )
262 odd.push_back(Vector(zk.q(),zk.p()));
266 even.push_back(Vector(zk.q(),zk.p()));
285template <
typename Pattern,
typename Integer>
286void displayConvexHull(
const Pattern& aP,
const Integer& aD,
bool withFDT =
false)
288 typedef typename Pattern::Fraction Fraction;
289 typedef typename Pattern::Vector2I Vector;
290 typedef std::vector<Vector> Convergents;
291 typedef typename Pattern::Point2I Point;
296 Convergents oddConvergents, evenConvergents;
299 Fraction zn = aP.slope();
303 Fraction znm1 = zn.father();
305 oddConvergents.push_back(Vector(znm1.q(),znm1.p()));
307 evenConvergents.push_back(Vector(znm1.q(),znm1.p()));
310 fillConvergents( zn, oddConvergents, evenConvergents );
313 Point Zn = Point(aD*zn.q(),aD*zn.p());
314 aBoard << Z2i::Domain( Point(0,0), Zn );
315 aBoard << SetMode( Zn.className(),
"Grid" );
316 aBoard.setLineStyle(Board2D::Shape::SolidStyle);
317 aBoard.setPenColor(DGtal::Color::Black);
320 OddConvexHullMap<Point> oddH;
321 drawSegments( aBoard, oddConvergents.begin(), oddConvergents.end(), oddH );
323 EvenConvexHullMap<Point> evenH(Zn);
324 drawSegments( aBoard, evenConvergents.begin(), evenConvergents.end(), evenH );
327 drawSegment( aBoard, Point(0,0), Zn );
328 if (evenConvergents.size() != 0)
330 drawSegment( aBoard, evenH(*evenConvergents.rbegin()), Zn );
331 if (oddConvergents.size() != 0)
333 drawSegment( aBoard, Point(0,0), oddH(*oddConvergents.rbegin()) );
335 oddH(*oddConvergents.begin()),
336 evenH(*evenConvergents.begin()) );
340 drawSegment( aBoard, Point(0,0), evenH(*evenConvergents.rbegin()) );
348 if (evenConvergents.size() != 0)
351 evenH(*evenConvergents.rbegin()) );
353 typedef typename Convergents::const_reverse_iterator RI;
354 RI oddRit = oddConvergents.rbegin();
355 RI evenRit = evenConvergents.rbegin();
356 bool hasToContinue =
true;
357 while (hasToContinue)
359 if (oddRit != oddConvergents.rend())
366 hasToContinue =
false;
369 if ( (hasToContinue) && (evenRit != evenConvergents.rend()) )
376 hasToContinue =
false;
380 aBoard.saveEPS(
"FDT.eps");
384 aBoard.saveEPS(
"CH.eps");
400template <
typename Board,
typename Po
int>
401void drawTriangle(Board& aBoard,
402 const Point& aP,
const Point& aQ,
const Point& aR)
404 aBoard.drawTriangle( aP[0], aP[1], aQ[0], aQ[1], aR[0], aR[1] );
416struct InDirectBezoutComputer
425 template<
typename Pattern>
426 typename Pattern::Vector2I
427 getPositiveBezout(
const Pattern& aP)
const
439 template<
typename Pattern>
440 typename Pattern::Vector2I
441 getNegativeBezout(
const Pattern& aP)
const
443 return aP.slope().even()
444 ? aP.U( 1 ) - aP.previousPattern().U( 1 )
445 : aP.previousPattern().U( 1 );
459struct DirectBezoutComputer
468 template<
typename Pattern>
469 typename Pattern::Vector2I
470 getPositiveBezout(
const Pattern& aP)
const
472 return aP.slope().even()
473 ? aP.U( 1 ) - aP.previousPattern().U( 1 )
474 : aP.previousPattern().U( 1 );
484 template<
typename Pattern>
485 typename Pattern::Vector2I
486 getNegativeBezout(
const Pattern& aP)
const
511template <
typename Board,
typename Pattern,
typename BezoutComputer>
512void displayPartialCDT(Board& aBoard,
514 const typename Pattern::Point2I& aStartingPoint,
515 const BezoutComputer& aBC )
517 typedef typename Pattern::Fraction Fraction;
518 typedef typename Pattern::Vector2I Vector;
519 typedef typename Pattern::Point2I Point;
521 Fraction f = aP.slope();
522 if ( (f.p() >= 1)&&(f.q() >= 1) )
524 Point O = aStartingPoint;
525 Point Zn = aStartingPoint + aP.v();
526 Vector v1 = aBC.getNegativeBezout(aP);
527 Point B = aStartingPoint + v1;
528 drawTriangle(aBoard, O, Zn, B);
530 if ( (f.p() > 1)||(f.q() > 1) )
534 displayPartialCDT(aBoard, Pattern(Fraction(v1[1],v1[0])), O, aBC);
536 Vector v2 = aBC.getPositiveBezout(aP);
537 displayPartialCDT(aBoard, Pattern(Fraction(v2[1],v2[0])), B, aBC);
553template <
typename Pattern,
typename Integer>
554void displayCDT(
const Pattern& aP,
const Integer& aD)
558 typedef typename Pattern::Point2I Point;
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");
638void missingParam(std::string param)
640 trace.error() <<
" Parameter: " << param <<
" is required...";
641 trace.info() << std::endl;
655int main(
int argc,
char **argv)
657 typedef DGtal::int32_t Integer;
667 app.description(
"Draw the Delaunay triangulation of a pattern using DGtal library. Example: patternTriangulation -a 5 -b 8 ");
668 app.add_option(
"-a,--aparam",a,
"pattern a parameter")
670 app.add_option(
"-b,--bparam",b,
"pattern b parameter")
672 app.add_option(
"-d,--delta",d,
"number of repetitions");
673 app.add_option(
"--triangulation,-t",type,
"output:\n\tClosest-point Delaunay triangulation {CDT}\n\tFarthest-point Delaunay triangulation {FDT}\n\tConvex hull {CH}");
676 app.get_formatter()->column_width(40);
677 CLI11_PARSE(app, argc, argv);
683 if ( (a < 0) || (b <= 0) )
685 trace.error() <<
" parameters a and b should be strictly positive.";
686 trace.info() << std::endl;
691 trace.error() <<
" parameter a should be strictly less than b.";
692 trace.info() << std::endl;
698 trace.error() <<
" parameter d should be strictly positive";
699 trace.info() << std::endl;
702 trace.info() <<
"a=" << a <<
", b=" << b <<
", d=" << d << std::endl;
704 typedef DGtal::int32_t Quotient;
705 typedef LighterSternBrocot<Integer, Quotient, StdMapRebinder> SB;
706 typedef SB::Fraction Fraction;
707 typedef Pattern<Fraction> Pattern;
709 Pattern pattern( a, b );
713 displayCDT(pattern, d);
715 else if (type ==
"FDT")
717 displayConvexHull(pattern, d,
true);
719 else if (type ==
"CH")
721 displayConvexHull(pattern, d);
725 trace.error() <<
" unknown output type. Try -h option. ";
726 trace.info() << std::endl;