DGtalTools  0.9.2
patternTriangulation.cpp
1 
39 #include <iostream>
40 #include <iterator>
41 #include <cstdio>
42 #include <cmath>
43 #include <fstream>
44 #include <vector>
45 
46 #include <boost/program_options/options_description.hpp>
47 #include <boost/program_options/parsers.hpp>
48 #include <boost/program_options/variables_map.hpp>
49 
50 #include "DGtal/base/Common.h"
51 #include "DGtal/helpers/StdDefs.h"
52 
53 #include "DGtal/arithmetic/LighterSternBrocot.h"
54 #include "DGtal/arithmetic/Pattern.h"
55 
56 #include "DGtal/io/boards/Board2D.h"
57 #include "DGtal/io/Color.h"
58 
59 using namespace DGtal;
60 using namespace std;
61 
62 namespace po = boost::program_options;
64 
109 template <typename Point>
110 struct OddConvexHullMap {
111 
112 public:
113  typedef Point Vector;
114 
115 public:
122  OddConvexHullMap(const Vector& aShift = Vector(1,-1))
123  : myS(aShift) {}
124 
131  Point operator()(const Point& aP) const
132  {
133  return aP + myS;
134  }
135 
136 private:
137  Vector myS;
138 
139 };
140 
148 template <typename Point>
149 struct EvenConvexHullMap {
150 
151 public:
152  typedef Point Vector;
153 
154 public:
162  EvenConvexHullMap(const Point& aPoint, const Vector& aShift = Vector(1,-1))
163  : myZn(aPoint), myS(aShift) {}
164 
171  Point operator()(const Point& aP) const
172  {
173  return myZn - aP + myS;
174  }
175 
176 private:
177  Point myZn;
178  Vector myS;
179 
180 };
181 
183 
194 template <typename Board, typename Point>
195 void drawSegment(Board& aBoard, const Point& aP, const Point& aQ)
196 {
197  aBoard.drawLine(aP[0], aP[1], aQ[0], aQ[1]);
198  aBoard << aP << aQ;
199 }
200 
215 template <typename Board, typename Iterator, typename Functor>
216 void drawSegments(Board& aBoard,
217  const Iterator& itb, const Iterator& ite,
218  const Functor& aF)
219 {
220  Iterator it = itb;
221  if (it != ite)
222  {
223  Iterator prevIt = it;
224  ++it;
225  for ( ; it != ite; ++prevIt, ++it)
226  {
227  drawSegment( aBoard, aF(*prevIt), aF(*it) );
228  }
229  }
230 }
231 
232 
234 
249 template<typename Fraction, typename Container>
250 void fillConvergents(const Fraction& aZn,
251  Container& odd, Container& even)
252 {
253  typedef typename Container::value_type Vector;
254 
255  for (typename Fraction::Quotient i = 1; i <= aZn.k(); ++i)
256  {
257  Fraction zk = aZn.reduced(i);
258  if (((aZn.k() - i)%2) == 1 )
259  { //odd
260  odd.push_back(Vector(zk.q(),zk.p()));
261  }
262  else
263  { //even
264  even.push_back(Vector(zk.q(),zk.p()));
265  }
266  }
267 }
268 
283 template <typename Pattern, typename Integer>
284 void displayConvexHull(const Pattern& aP, const Integer& aD, bool withFDT = false)
285 {
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;
291 
292  Board2D aBoard;
293 
294  //list of convergents
295  Convergents oddConvergents, evenConvergents;
296 
297  //fill the lists
298  Fraction zn = aP.slope();
299  // aD > 1
300  if (aD > 1)
301  {
302  Fraction znm1 = zn.father();
303  if (zn.odd())
304  oddConvergents.push_back(Vector(znm1.q(),znm1.p()));
305  else
306  evenConvergents.push_back(Vector(znm1.q(),znm1.p()));
307  }
308  // aD >= 1
309  fillConvergents( zn, oddConvergents, evenConvergents );
310 
311  //display the domain
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);
317 
318  //display the two main lists
319  OddConvexHullMap<Point> oddH;
320  drawSegments( aBoard, oddConvergents.begin(), oddConvergents.end(), oddH );
321 
322  EvenConvexHullMap<Point> evenH(Zn);
323  drawSegments( aBoard, evenConvergents.begin(), evenConvergents.end(), evenH );
324 
325  //display the four last segments
326  drawSegment( aBoard, Point(0,0), Zn );
327  if (evenConvergents.size() != 0)
328  {
329  drawSegment( aBoard, evenH(*evenConvergents.rbegin()), Zn );
330  if (oddConvergents.size() != 0)
331  {
332  drawSegment( aBoard, Point(0,0), oddH(*oddConvergents.rbegin()) );
333  drawSegment( aBoard,
334  oddH(*oddConvergents.begin()),
335  evenH(*evenConvergents.begin()) );
336  }
337  else
338  {
339  drawSegment( aBoard, Point(0,0), evenH(*evenConvergents.rbegin()) );
340  }
341  }
342 
343  if (withFDT)
344  {//display internal edges
345 
346  //first internal edge
347  if (evenConvergents.size() != 0)
348  drawSegment( aBoard,
349  Point(0,0),
350  evenH(*evenConvergents.rbegin()) );
351  //other internal edges
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)
357  {
358  if (oddRit != oddConvergents.rend())
359  {
360  drawSegment( aBoard,
361  oddH(*oddRit),
362  evenH(*evenRit) );
363  }
364  else
365  hasToContinue = false;
366  ++evenRit;
367 
368  if ( (hasToContinue) && (evenRit != evenConvergents.rend()) )
369  {
370  drawSegment( aBoard,
371  oddH(*oddRit),
372  evenH(*evenRit) );
373  }
374  else
375  hasToContinue = false;
376  ++oddRit;
377  }
378 
379  aBoard.saveEPS("FDT.eps");
380  }
381  else
382  {
383  aBoard.saveEPS("CH.eps");
384  }
385 }
386 
388 
399 template <typename Board, typename Point>
400 void drawTriangle(Board& aBoard,
401  const Point& aP, const Point& aQ, const Point& aR)
402 {
403  aBoard.drawTriangle( aP[0], aP[1], aQ[0], aQ[1], aR[0], aR[1] );
404 }
405 
415 struct InDirectBezoutComputer
416 {
424  template<typename Pattern>
425  typename Pattern::Vector2I
426  getPositiveBezout(const Pattern& aP) const
427  {
428  return aP.bezout();
429  }
430 
438  template<typename Pattern>
439  typename Pattern::Vector2I
440  getNegativeBezout(const Pattern& aP) const
441  {
442  return aP.slope().even()
443  ? aP.U( 1 ) - aP.previousPattern().U( 1 )
444  : aP.previousPattern().U( 1 );
445  }
446 
447 };
448 
458 struct DirectBezoutComputer
459 {
467  template<typename Pattern>
468  typename Pattern::Vector2I
469  getPositiveBezout(const Pattern& aP) const
470  {
471  return aP.slope().even()
472  ? aP.U( 1 ) - aP.previousPattern().U( 1 )
473  : aP.previousPattern().U( 1 );
474  }
475 
483  template<typename Pattern>
484  typename Pattern::Vector2I
485  getNegativeBezout(const Pattern& aP) const
486  {
487  return aP.bezout();
488  }
489 
490 };
491 
510 template <typename Board, typename Pattern, typename BezoutComputer>
511 void displayPartialCDT(Board& aBoard,
512  const Pattern& aP,
513  const typename Pattern::Point2I& aStartingPoint,
514  const BezoutComputer& aBC )
515 {
516  typedef typename Pattern::Fraction Fraction;
517  typedef typename Pattern::Vector2I Vector;
518  typedef typename Pattern::Point2I Point;
519 
520  Fraction f = aP.slope();
521  if ( (f.p() >= 1)&&(f.q() >= 1) )
522  {
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);
528 
529  if ( (f.p() > 1)||(f.q() > 1) )
530  {
531  //recursive calls
532  // - first pattern
533  displayPartialCDT(aBoard, Pattern(Fraction(v1[1],v1[0])), O, aBC);
534  // - second pattern
535  Vector v2 = aBC.getPositiveBezout(aP);
536  displayPartialCDT(aBoard, Pattern(Fraction(v2[1],v2[0])), B, aBC);
537  }
538  }
539 }
540 
552 template <typename Pattern, typename Integer>
553 void displayCDT(const Pattern& aP, const Integer& aD)
554 {
555  Board2D aBoard;
556 
557  typedef typename Pattern::Point2I Point;
558  typedef typename Pattern::Quotient Quotient;
559  typedef typename Pattern::Fraction Fraction;
560  Fraction zn = aP.slope();
561 
562  //display the domain
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);
568 
569  //display the upper part of the triangulation
570  for (Integer i = 0; i < aD; ++i)
571  {
572  displayPartialCDT( aBoard, aP, Point(i*zn.q(), i*zn.p()), InDirectBezoutComputer() );
573  }
574 
575  //display the lower parts of the triangulation
576  // - getting the reversed patterns
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 );
582  // - displaying the reversed patterns...
583  Point rPStartingPoint;
584  // - of odd slope:
585  OddConvexHullMap<Point> oddH;
586  {
587  ReverseIterator itb = evenConvergents.rbegin();
588  ReverseIterator ite = evenConvergents.rend();
589  Point aStartingPoint = oddH( *oddConvergents.rbegin() );
590  //
591  Point p = aStartingPoint;
592  ReverseIterator it = itb;
593  if (it != ite)
594  {
595  for (++it; it != ite; ++it)
596  {
597  displayPartialCDT( aBoard, Pattern( (*it)[1], (*it)[0] ), p, DirectBezoutComputer() );
598  p += *it;
599  }
600  }
601  rPStartingPoint = p;
602  }
603  // - of even slope:
604  EvenConvexHullMap<Point> evenH(Zn);
605  {
606  ReverseIterator itb = oddConvergents.rbegin();
607  ReverseIterator ite = oddConvergents.rend();
608  Point aStartingPoint = evenH( *evenConvergents.rbegin() );
609  //
610  Point p = aStartingPoint;
611  ReverseIterator it = itb;
612  for ( ; it != ite; ++it)
613  {
614  p -= *it;
615  displayPartialCDT( aBoard, Pattern( (*it)[1], (*it)[0] ), p, DirectBezoutComputer() );
616  }
617  }
618  // - of same slope:
619  {
620  for (Integer i = 0; i < (aD-1); ++i)
621  {
622  Point p = rPStartingPoint + i*aP.v();
623  displayPartialCDT( aBoard, aP, p, DirectBezoutComputer() );
624  }
625  }
626 
627 
628  aBoard.saveEPS("CDT.eps");
629 }
630 
631 
633 
638 void missingParam(std::string param)
639 {
640  trace.error() << " Parameter: " << param << " is required...";
641  trace.info() << std::endl;
642  exit(1);
643 }
644 
645 
647 
655 int main(int argc, char **argv)
656 {
657  // parse command line ----------------------------------------------
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}" );
665 
666  bool parseOK=true;
667  po::variables_map vm;
668  try{
669  po::store(po::parse_command_line(argc, argv, general_opt), vm);
670  }catch(const std::exception& ex){
671  parseOK=false;
672  trace.info()<< "Error checking program options: "<< ex.what()<< endl;
673  }
674 
675  po::notify(vm);
676  if(!parseOK || vm.count("help")||argc<=1)
677  {
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";
682  return 0;
683  }
684 
685 
686  if (!(vm.count("aparam"))) missingParam("-a");
687  if (!(vm.count("bparam"))) missingParam("-b");
688 
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) )
693  {
694  trace.error() << " parameters a and b should be strictly positive.";
695  trace.info() << std::endl;
696  return 0;
697  }
698  if (a >= b)
699  {
700  trace.error() << " parameter a should be strictly less than b.";
701  trace.info() << std::endl;
702  return 0;
703  }
704  Integer d = vm["delta"].as<int>();
705  if (d <= 0)
706  {
707  trace.error() << " parameter d should be strictly positive";
708  trace.info() << std::endl;
709  return 0;
710  }
711  trace.info() << "a=" << a << ", b=" << b << ", d=" << d << std::endl;
712 
713  typedef DGtal::int32_t Quotient;
714  typedef LighterSternBrocot<Integer, Quotient, StdMapRebinder> SB;
715  typedef SB::Fraction Fraction; // the type for fractions
716  typedef Pattern<Fraction> Pattern; // the type for patterns
717 
718  Pattern pattern( a, b );
719 
720  string type = vm["triangulation"].as<string>();
721  if (type == "CDT")
722  {
723  displayCDT(pattern, d);
724  }
725  else if (type == "FDT")
726  {
727  displayConvexHull(pattern, d, true);
728  }
729  else if (type == "CH")
730  {
731  displayConvexHull(pattern, d);
732  }
733  else
734  {
735  trace.error() << " unknown output type. Try -h option. ";
736  trace.info() << std::endl;
737  return 0;
738  }
739 
740  return 1;
741 }
STL namespace.