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"
58 using namespace DGtal;
110 template <
typename Po
int>
111 struct OddConvexHullMap {
114 typedef Point Vector;
123 OddConvexHullMap(
const Vector& aShift = Vector(1,-1))
132 Point operator()(
const Point& aP)
const
149 template <
typename Po
int>
150 struct EvenConvexHullMap {
153 typedef Point Vector;
163 EvenConvexHullMap(
const Point& aPoint,
const Vector& aShift = Vector(1,-1))
164 : myZn(aPoint), myS(aShift) {}
172 Point operator()(
const Point& aP)
const
174 return myZn - aP + myS;
195 template <
typename Board,
typename Po
int>
196 void drawSegment(Board& aBoard,
const Point& aP,
const Point& aQ)
198 aBoard.drawLine(aP[0], aP[1], aQ[0], aQ[1]);
216 template <
typename Board,
typename Iterator,
typename Functor>
217 void drawSegments(Board& aBoard,
218 const Iterator& itb,
const Iterator& ite,
224 Iterator prevIt = it;
226 for ( ; it != ite; ++prevIt, ++it)
228 drawSegment( aBoard, aF(*prevIt), aF(*it) );
250 template<
typename Fraction,
typename Container>
251 void fillConvergents(
const Fraction& aZn,
252 Container& odd, Container& even)
254 typedef typename Container::value_type Vector;
256 for (
typename Fraction::Quotient i = 1; i <= aZn.k(); ++i)
258 Fraction zk = aZn.reduced(i);
259 if (((aZn.k() - i)%2) == 1 )
261 odd.push_back(Vector(zk.q(),zk.p()));
265 even.push_back(Vector(zk.q(),zk.p()));
284 template <
typename Pattern,
typename Integer>
285 void displayConvexHull(
const Pattern& aP,
const Integer& aD,
bool withFDT =
false)
287 typedef typename Pattern::Fraction Fraction;
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::Fraction Fraction;
559 Fraction zn = aP.slope();
562 Point Zn = Point(aD*zn.q(),aD*zn.p());
563 aBoard << Z2i::Domain( Point(0,0), Zn );
564 aBoard << SetMode( Zn.className(),
"Grid" );
565 aBoard.setLineStyle(Board2D::Shape::SolidStyle);
566 aBoard.setPenColor(DGtal::Color::Black);
569 for (Integer i = 0; i < aD; ++i)
571 displayPartialCDT( aBoard, aP, Point(i*zn.q(), i*zn.p()), InDirectBezoutComputer() );
576 typedef typename Pattern::Vector2I Vector;
577 typedef std::vector<Vector> Convergents;
578 typedef typename std::vector<Vector>::const_reverse_iterator ReverseIterator;
579 Convergents oddConvergents, evenConvergents;
580 fillConvergents( zn, oddConvergents, evenConvergents );
582 Point rPStartingPoint;
584 OddConvexHullMap<Point> oddH;
586 ReverseIterator itb = evenConvergents.rbegin();
587 ReverseIterator ite = evenConvergents.rend();
588 Point aStartingPoint = oddH( *oddConvergents.rbegin() );
590 Point p = aStartingPoint;
591 ReverseIterator it = itb;
594 for (++it; it != ite; ++it)
596 displayPartialCDT( aBoard, Pattern( (*it)[1], (*it)[0] ), p, DirectBezoutComputer() );
603 EvenConvexHullMap<Point> evenH(Zn);
605 ReverseIterator itb = oddConvergents.rbegin();
606 ReverseIterator ite = oddConvergents.rend();
607 Point aStartingPoint = evenH( *evenConvergents.rbegin() );
609 Point p = aStartingPoint;
610 ReverseIterator it = itb;
611 for ( ; it != ite; ++it)
614 displayPartialCDT( aBoard, Pattern( (*it)[1], (*it)[0] ), p, DirectBezoutComputer() );
619 for (Integer i = 0; i < (aD-1); ++i)
621 Point p = rPStartingPoint + i*aP.v();
622 displayPartialCDT( aBoard, aP, p, DirectBezoutComputer() );
627 aBoard.saveEPS(
"CDT.eps");
637 void missingParam(std::string param)
639 trace.error() <<
" Parameter: " << param <<
" is required...";
640 trace.info() << std::endl;
654 int main(
int argc,
char **argv)
656 typedef DGtal::int32_t Integer;
666 app.description(
"Draw the Delaunay triangulation of a pattern using DGtal library. Example: patternTriangulation -a 5 -b 8 ");
667 app.add_option(
"-a,--aparam",a,
"pattern a parameter")
669 app.add_option(
"-b,--bparam",b,
"pattern b parameter")
671 app.add_option(
"-d,--delta",d,
"number of repetitions");
672 app.add_option(
"--triangulation,-t",type,
"output:\n\tClosest-point Delaunay triangulation {CDT}\n\tFarthest-point Delaunay triangulation {FDT}\n\tConvex hull {CH}",
true);
675 app.get_formatter()->column_width(40);
676 CLI11_PARSE(app, argc, argv);
682 if ( (a < 0) || (b <= 0) )
684 trace.error() <<
" parameters a and b should be strictly positive.";
685 trace.info() << std::endl;
690 trace.error() <<
" parameter a should be strictly less than b.";
691 trace.info() << std::endl;
697 trace.error() <<
" parameter d should be strictly positive";
698 trace.info() << std::endl;
701 trace.info() <<
"a=" << a <<
", b=" << b <<
", d=" << d << std::endl;
703 typedef DGtal::int32_t Quotient;
704 typedef LighterSternBrocot<Integer, Quotient, StdMapRebinder> SB;
705 typedef SB::Fraction Fraction;
706 typedef Pattern<Fraction> Pattern;
708 Pattern pattern( a, b );
712 displayCDT(pattern, d);
714 else if (type ==
"FDT")
716 displayConvexHull(pattern, d,
true);
718 else if (type ==
"CH")
720 displayConvexHull(pattern, d);
724 trace.error() <<
" unknown output type. Try -h option. ";
725 trace.info() << std::endl;