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;