2 *  This program is free software: you can redistribute it and/or modify
 
    3 *  it under the terms of the GNU Lesser General Public License as
 
    4 *  published by the Free Software Foundation, either version 3 of the
 
    5 *  License, or  (at your option) any later version.
 
    7 *  This program is distributed in the hope that it will be useful,
 
    8 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
    9 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
   10 *  GNU General Public License for more details.
 
   12 *  You should have received a copy of the GNU General Public License
 
   13 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
   18 * @file   Display2DFactory.ih
 
   19 * @author Martial Tola <http://liris.cnrs.fr/martial.tola/>
 
   20 * @date   mercredi 28 septembre 2011
 
   24 * Implementation of inline methods defined in Display2DFactory.h
 
   26 * This file is part of the DGtal library.
 
   29#include <DGtal/io/Style2DFactory.h>
 
   30#include <DGtal/io/colormaps/GradientColorMap.h>
 
   31#include <DGtal/topology/CanonicSCellEmbedder.h>
 
   33///////////////////////////////////////////////////////////////////////////////
 
   34// Implementation of inline methods                                          //
 
   37///////////////////////////////////////////////////////////////////////////////
 
   38// Implementation of inline functions and external operators                 //
 
   39template <DGtal::Dimension dim, typename TInteger>
 
   42DGtal::Display2DFactory::drawDECSignedKhalimskyCell(DGtal::Board2D& board, const DGtal::SignedKhalimskyCell<dim, TInteger>& sk)
 
   44  drawDECSignedKhalimskyCell( board, sk.preCell() );
 
   47template <DGtal::Dimension dim, typename TInteger>
 
   50DGtal::Display2DFactory::drawDECSignedKhalimskyCell(DGtal::Board2D& board, const DGtal::SignedKhalimskyPreCell<dim, TInteger>& sk)
 
   52    FATAL_ERROR( dim == 2 );
 
   54    using KPS = DGtal::Z2i::KPreSpace;
 
   57    //FIXME: as for Display3D models, embedder should be factorized
 
   58    //and not instantiated at each call.
 
   59    using Embedder = DGtal::CanonicSCellEmbedder<KPS>;
 
   60    const Embedder embedder( K );
 
   62    const Embedder::RealPoint coords = embedder( sk );
 
   63    const double x = coords[0];
 
   64    const double y = coords[1];
 
   65    const double retract = 0.1f;
 
   66    const bool xodd = ( KPS::sKCoord(sk, 0) & 1 );
 
   67    const bool yodd = ( KPS::sKCoord(sk, 1) & 1 );
 
   68    board.setLineWidth( .5 );
 
   69    board.setPenColor( DGtal::Color::Black );
 
   70    board.setLineStyle( Board2D::Shape::SolidStyle );
 
   73        if ( KPS::sSign(sk) == KPS::NEG ) DGtal::trace.warning() << "negative khalimsky 0-cell" << std::endl;
 
   74        board.drawCircle(x, y, retract);
 
   79        if ( KPS::sSign(sk) == KPS::NEG ) board.drawTriangle(x-.5f, y-retract, x-.5f, y+retract, x+.5f, y);
 
   80        else board.drawTriangle(x+.5f, y+retract, x+.5f, y-retract, x-.5f, y);
 
   85        if ( KPS::sSign(sk) == KPS::NEG ) board.drawTriangle(x-retract, y-.5f, x+retract, y-.5f, x, y+.5);
 
   86        else board.drawTriangle(x+retract, y+.5f, x-retract, y+.5f, x, y-.5);
 
   89    if ( KPS::sSign(sk) == KPS::NEG ) DGtal::trace.warning() << "negative khalimsky 2-cell" << std::endl;
 
   90    board.drawRectangle(x-.5, y+.5, 1, 1);
 
   93// DiscreteExteriorCalculus
 
   94template <DGtal::Dimension dimEmbedded, DGtal::Dimension dimAmbient, typename TLinearAlgebraBackend, typename TInteger>
 
   97DGtal::Display2DFactory::draw(DGtal::Board2D& board, const DGtal::DiscreteExteriorCalculus<dimEmbedded, dimAmbient, TLinearAlgebraBackend, TInteger>& calculus)
 
   99    BOOST_STATIC_ASSERT(( dimAmbient == 2 ));
 
  101    typedef DiscreteExteriorCalculus<dimEmbedded, dimAmbient, TLinearAlgebraBackend, TInteger> Calculus;
 
  102    typedef typename Calculus::ConstIterator ConstIterator;
 
  103    typedef typename Calculus::Cell Cell;
 
  104    typedef typename Calculus::SCell SCell;
 
  105    typedef typename Calculus::KSpace KSpace;
 
  107    board.setFillColor( DGtal::Color(128,128,128) );
 
  108    for (int kk=2; kk>=0; kk--)
 
  109        for (ConstIterator ci=calculus.begin(), cie=calculus.end(); ci!=cie; ci++)
 
  111            const Cell& cell = ci->first;
 
  112            if (calculus.myKSpace.uDim(cell) != static_cast<DGtal::Dimension>(kk)) continue;
 
  114            const bool& flipped = ci->second.flipped;
 
  115            const SCell displayed_cell = calculus.myKSpace.signs(cell, flipped ? KSpace::NEG : KSpace::POS);
 
  117            drawDECSignedKhalimskyCell(board, displayed_cell);
 
  120// DiscreteExteriorCalculus
 
  123template <typename TCalculus, DGtal::Order order, DGtal::Duality duality>
 
  126DGtal::Display2DFactory::draw(DGtal::Board2D& board, const DGtal::KForm<TCalculus, order, duality>& kform)
 
  128    BOOST_STATIC_ASSERT(( TCalculus::dimensionAmbient == 2 ));
 
  129    ASSERT( kform.myCalculus );
 
  131    typedef typename TCalculus::Scalar Scalar;
 
  132    typedef typename TCalculus::Index Index;
 
  136    DGtal::ColorGradientPreset cmap_preset = CMAP_JET;
 
  140        const DGtal::KFormStyle2D* style = dynamic_cast<const DGtal::KFormStyle2D*>(board.myStyles["KForm"].get());
 
  143            cmap_min = style->cmap_min;
 
  144            cmap_max = style->cmap_max;
 
  145            cmap_preset = style->cmap_preset;
 
  146            cmap_repeat = style->cmap_repeat;
 
  150    if (cmap_min == 0 && cmap_max == 0)
 
  153        for (Index index=0; index<kform.myContainer.rows(); index++)
 
  155            const Scalar value = kform.myContainer(index);
 
  156            if (!std::isfinite(value)) continue;
 
  157            if (first || cmap_min > value) cmap_min = value;
 
  158            if (first || cmap_max < value) cmap_max = value;
 
  163    if (cmap_min == cmap_max) cmap_max += 1;
 
  165    board.setLineWidth( .5 );
 
  167    if (cmap_repeat < 1 && cmap_preset == DGtal::CMAP_JET)
 
  169        typedef typename DGtal::GradientColorMap<Scalar, DGtal::CMAP_JET> ColorMap;
 
  170        const ColorMap colormap(cmap_min, cmap_max);
 
  171        drawWithColorMap(board, kform, colormap);
 
  175    if (cmap_repeat < 1 && cmap_preset == DGtal::CMAP_GRAYSCALE)
 
  177        typedef typename DGtal::GradientColorMap<Scalar, DGtal::CMAP_GRAYSCALE> ColorMap;
 
  178        const ColorMap colormap(cmap_min, cmap_max);
 
  179        drawWithColorMap(board, kform, colormap);
 
  183    // @todo FIXME add other colomaps
 
  186        typedef typename DGtal::GradientColorMap<Scalar, DGtal::CMAP_HOT> ColorMap;
 
  187        const ColorMap colormap(cmap_min, cmap_max);
 
  188        drawWithColorMap(board, kform, colormap);
 
  192    ASSERT(cmap_repeat >= 1);
 
  193    typedef typename DGtal::HueShadeColorMap<Scalar, DGtal::CMAP_HOT> ColorMap;
 
  194    const ColorMap colormap(cmap_min, cmap_max, cmap_repeat);
 
  195    drawWithColorMap(board, kform, colormap);
 
  198template <typename TCalculus, DGtal::Order order, DGtal::Duality duality, typename TColorMap>
 
  201DGtal::Display2DFactory::drawWithColorMap(DGtal::Board2D& board, const DGtal::KForm<TCalculus, order, duality>& kform, const TColorMap& colormap)
 
  203    typedef typename TCalculus::Scalar Scalar;
 
  204    typedef typename TCalculus::SCell SCell;
 
  206    for (typename TCalculus::Index index=0; index<kform.length(); index++)
 
  208        const SCell displayed_cell = kform.getSCell(index);
 
  209        const Scalar displayed_value = kform.myContainer(index);
 
  211        if (std::isfinite(displayed_value)) board.setFillColor( colormap(displayed_value) );
 
  214        drawDECSignedKhalimskyCell(board, displayed_cell);
 
  220template <typename TCalculus, DGtal::Duality duality>
 
  222DGtal::Display2DFactory::draw(DGtal::Board2D& board, const DGtal::VectorField<TCalculus, duality>& vector_field)
 
  224    BOOST_STATIC_ASSERT(( TCalculus::dimensionAmbient == 2 ));
 
  225    ASSERT( vector_field.myCalculus );
 
  227    typedef typename DGtal::VectorField<TCalculus, duality>::Vector Vector;
 
  229    typename TCalculus::Scalar scale = .25;
 
  230    typename TCalculus::Scalar epsilon = 1e-8;
 
  233        const DGtal::VectorFieldStyle2D* style = dynamic_cast<const DGtal::VectorFieldStyle2D*>(board.myStyles["VectorField"].get());
 
  236            scale = style->scale;
 
  237            epsilon = style->epsilon;
 
  241    for (typename TCalculus::Index index=0; index<vector_field.length(); index++)
 
  243        const typename TCalculus::SCell& cell = vector_field.getSCell(index);
 
  244        const DGtal::Z2i::RealPoint origin = DGtal::Z2i::RealPoint(cell.preCell().coordinates[0]-1, cell.preCell().coordinates[1]-1)/2.;
 
  246        Vector vector = vector_field.getVector(index);
 
  249        if (!std::isfinite(vector[0]) || !std::isfinite(vector[1])) continue;
 
  250        const typename TCalculus::Scalar& norm = vector.norm();
 
  251        if (norm <= epsilon) continue;
 
  252        if (norm <= .5) vector *= .5/norm;
 
  254        board.drawArrow(origin[0],origin[1],origin[0]+vector[0],origin[1]+vector[1]);
 
  260// AngleLinearMinimizer
 
  262void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
 
  263           const DGtal::AngleLinearMinimizer & a )
 
  266  board.setLineWidth(3.0);
 
  267  board.setPenColor(Color(20,20,200));
 
  269  for(int i=0; i< (int)a.size(); i++){
 
  270    board.drawArc(0.0, 0.0, distance, a.ro(i).min, a.ro(i).max, false, 1);
 
  271    board.drawDot(cos(a.ro(i).value)*distance, sin(a.ro(i).value)*distance );
 
  272    distance+=a.ro(i).distToNext;
 
  277  for(int i=0; i< (int) (a.size()-1); i++){
 
  278    distanceNext= distance+ a.ro(i).distToNext;
 
  279    board.setPenColor(Color(200,20,20));
 
  280    board.drawLine(cos(a.ro(i).value)*distance, sin(a.ro(i).value)*distance,
 
  281                   cos(a.ro(i+1).value)*distanceNext, sin(a.ro(i+1).value)*distanceNext);
 
  282    distance=distanceNext;
 
  285// AngleLinearMinimizer
 
  288template <typename TCoordinate, typename TInteger, unsigned short adjacency>
 
  290void DGtal::Display2DFactory::drawAsBoundingBox( DGtal::Board2D & aBoard,
 
  291     const DGtal::ArithmeticalDSS<TCoordinate,TInteger,adjacency> & a )
 
  293  typedef typename DGtal::ArithmeticalDSS<TCoordinate,TInteger,adjacency>::PointD PointD;
 
  296  PointD topLeft = a.project(a.back(), a.Uf());
 
  297  PointD bottomLeft = a.project(a.back(), a.Lf());
 
  298  PointD bottomRight = a.project(a.front(), a.Lf());
 
  299  PointD topRight = a.project(a.front(), a.Uf());
 
  301  LibBoard::Point topLeftBoard(topLeft[0],topLeft[1]);
 
  302  LibBoard::Point bottomLeftBoard(bottomLeft[0],bottomLeft[1]);
 
  303  LibBoard::Point bottomRightBoard(bottomRight[0],bottomRight[1]);
 
  304  LibBoard::Point topRightBoard(topRight[0],topRight[1]);
 
  306  std::vector<LibBoard::Point> bb;
 
  307  bb.push_back(topLeftBoard);
 
  308  bb.push_back(bottomLeftBoard);
 
  309  bb.push_back(bottomRightBoard);
 
  310  bb.push_back(topRightBoard);
 
  312  aBoard.drawClosedPolyline(bb);
 
  315template <typename TCoordinate, typename TInteger, unsigned short adjacency>
 
  317void DGtal::Display2DFactory::drawAsDigitalPoints( DGtal::Board2D & aBoard,
 
  318     const DGtal::ArithmeticalDSS<TCoordinate,TInteger,adjacency> & a )
 
  320  typedef typename DGtal::ArithmeticalDSS<TCoordinate,TInteger,adjacency>::ConstIterator ConstIterator;
 
  321  typedef typename IteratorCirculatorTraits<ConstIterator>::Value Point;
 
  323  // Draw a linking polygonal line if the pixels are drawn as points.
 
  324  if(aBoard.getMode("PointVector")=="Grid" || aBoard.getMode("PointVector")=="")
 
  326      std::vector<LibBoard::Point> contour;
 
  327      for (ConstIterator it = a.begin(), itEnd = a.end();
 
  331    double xp = NumberTraits<TInteger>::castToDouble(p[0]);
 
  332    double yp = NumberTraits<TInteger>::castToDouble(p[1]);
 
  333    contour.push_back(LibBoard::Point(xp,yp));
 
  335      aBoard.drawPolyline(contour);
 
  339  for (ConstIterator it = a.begin(), itEnd = a.end();
 
  347template <typename TCoordinate, typename TInteger, unsigned short adjacency>
 
  349void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
 
  350     const DGtal::ArithmeticalDSS<TCoordinate,TInteger,adjacency> & a )
 
  352  std::string mode = board.getMode( a.className() );
 
  353  if ( mode == "BoundingBox" )
 
  354    drawAsBoundingBox( board, a );
 
  355  else if ( mode == "Points" )
 
  356    drawAsDigitalPoints( board, a );
 
  357  else if ( ( mode == "" ) )
 
  359      auto style = new DefaultDrawStyleBB_ArithmeticalDSS();
 
  360      drawAsDigitalPoints( board, a );
 
  361      Style2DFactory::draw( board,  style);
 
  362      drawAsBoundingBox( board, a );
 
  366    ASSERT(false && ("draw( DGtal::Board2D & board, const DGtal::ArithmeticalDSS<TCoordinate,TInteger,adjacency> & a ): Unknown mode "+mode)==""  );
 
  370// ArithmeticalDSSComputer
 
  371template <typename TIterator, typename TInteger, int connectivity>
 
  373void DGtal::Display2DFactory::drawAsBoundingBox( DGtal::Board2D & aBoard,
 
  374           const DGtal::ArithmeticalDSSComputer<TIterator,TInteger,connectivity> & a )
 
  376  typedef DGtal::PointVector<2,double> PointD;
 
  379  PointD topLeft = a.project(*a.myF, a.myUf);
 
  380  PointD bottomLeft = a.project(*a.myF, a.myLf);
 
  381  PointD bottomRight = a.project(*a.myL, a.myLf);
 
  382  PointD topRight = a.project(*a.myL, a.myUf);
 
  385  LibBoard::Point topLeftBoard(topLeft[0],topLeft[1]);
 
  386  LibBoard::Point bottomLeftBoard(bottomLeft[0],bottomLeft[1]);
 
  387  LibBoard::Point bottomRightBoard(bottomRight[0],bottomRight[1]);
 
  388  LibBoard::Point topRightBoard(topRight[0],topRight[1]);
 
  390  std::vector<LibBoard::Point> bb;
 
  391  bb.push_back(topLeftBoard);
 
  392  bb.push_back(bottomLeftBoard);
 
  393  bb.push_back(bottomRightBoard);
 
  394  bb.push_back(topRightBoard);
 
  396  aBoard.drawClosedPolyline(bb);
 
  399template <typename TIterator, typename TInteger, int connectivity>
 
  401void DGtal::Display2DFactory::drawAsDigitalPoints( DGtal::Board2D & aBoard,
 
  402           const DGtal::ArithmeticalDSSComputer<TIterator,TInteger,connectivity> & a )
 
  404  typedef TIterator ConstIterator;
 
  405  typedef typename IteratorCirculatorTraits<ConstIterator>::Value Point;
 
  407  ConstIterator itend = a.myL; ++itend;
 
  409  // Draw a linking polygonal line if the pixels are drawn as points.
 
  410  if(aBoard.getMode("PointVector")=="Grid" || aBoard.getMode("PointVector")=="")
 
  412      std::vector<LibBoard::Point> contour;
 
  413      for (ConstIterator i = a.myF; i != itend; ++i) {
 
  415        double xp = NumberTraits<TInteger>::castToDouble(p[0]);
 
  416        double yp = NumberTraits<TInteger>::castToDouble(p[1]);
 
  417        contour.push_back(LibBoard::Point(xp,yp));
 
  419      aBoard.drawPolyline(contour);
 
  423  for (ConstIterator i = a.myF; i != itend; ++i) {
 
  429template <typename TIterator, typename TInteger, int connectivity>
 
  431void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
 
  432     const DGtal::ArithmeticalDSSComputer<TIterator,TInteger,connectivity> & a )
 
  434  std::string mode = board.getMode( a.className() );
 
  435  if ( mode == "BoundingBox" )
 
  436    drawAsBoundingBox( board, a );
 
  437  else if ( mode == "Points" )
 
  438    drawAsDigitalPoints( board, a );
 
  439  else if ( ( mode == "" ) )
 
  441      drawAsDigitalPoints( board, a );
 
  442      drawAsBoundingBox( board, a );
 
  445    FATAL_ERROR_MSG(false, "draw( DGtal::Board2D & board, const DGtal::ArithmeticalDSSComputer<TIterator,TInteger,connectivity> & a ): Unknown mode "+mode);
 
  448// ArithmeticalDSSComputer
 
  451// AlphaThickSegmentComputer
 
  452template <typename TInputPoint,  typename TConstIterator>
 
  453void DGtal::Display2DFactory::drawAsBoundingBox( DGtal::Board2D & aBoard,
 
  454                                                 const DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>  & anAlphaThickSegment){
 
  455  typedef DGtal::PointVector<2,double> PointD;
 
  457  PointD topLeft, topRight, bottomRight, bottomLeft;
 
  458  anAlphaThickSegment.getBoundingBox(topLeft, topRight, bottomRight, bottomLeft);
 
  460  aBoard.drawLine(topLeft[0],topLeft[1],topRight[0],topRight[1]);
 
  461  aBoard.drawLine(topRight[0],topRight[1],bottomRight[0], bottomRight[1] );
 
  462  aBoard.drawLine(bottomRight[0], bottomRight[1], bottomLeft[0], bottomLeft[1]);
 
  463  aBoard.drawLine(bottomLeft[0], bottomLeft[1],topLeft[0],topLeft[1]);
 
  467template < typename TInputPoint, typename TConstIterator>
 
  468void DGtal::Display2DFactory::drawAsDigitalPoints( DGtal::Board2D & aBoard,
 
  469                                                   const DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator> & anAlphaThickSegment){
 
  470  typedef typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::ContainerConstIterator ContConstIterator;
 
  471  typedef TConstIterator ConstIterator;
 
  472  typedef TInputPoint Point;
 
  473  // Draw a linking polygonal line if the pixels are drawn as points.
 
  474  if(aBoard.getMode("PointVector")=="Grid" || aBoard.getMode("PointVector")=="")
 
  476      std::vector<LibBoard::Point> contour;
 
  477      if (anAlphaThickSegment.isStoringSegmentPoints()){
 
  478        for (ContConstIterator it = anAlphaThickSegment.containerBegin();
 
  479             it != anAlphaThickSegment.containerEnd(); it++) {
 
  481          double xp = NumberTraits<typename TInputPoint::Component>::castToDouble(p[0]);
 
  482          double yp = NumberTraits<typename TInputPoint::Component>::castToDouble(p[1]);
 
  483          contour.push_back(LibBoard::Point(xp,yp));
 
  487        for (ConstIterator it = anAlphaThickSegment.begin(); it != anAlphaThickSegment.end(); it++) {
 
  489          double xp = NumberTraits<typename TInputPoint::Component>::castToDouble(p[0]);
 
  490          double yp = NumberTraits<typename TInputPoint::Component>::castToDouble(p[1]);
 
  491          contour.push_back(LibBoard::Point(xp,yp));
 
  494      if(contour.size()>0){
 
  495        aBoard.drawPolyline(contour);
 
  499  if (anAlphaThickSegment.isStoringSegmentPoints()){
 
  500    for (ContConstIterator it = anAlphaThickSegment.containerBegin();
 
  501         it != anAlphaThickSegment.containerEnd(); it++) {
 
  506    for (ConstIterator it = anAlphaThickSegment.begin(); it != anAlphaThickSegment.end(); it++) {
 
  513template < typename TInputPoint,  typename TConstIterator>
 
  514void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
 
  515                                    const DGtal::AlphaThickSegmentComputer< TInputPoint,  TConstIterator>  & anAlphaThickSegment ){
 
  516  std::string mode = aBoard.getMode( anAlphaThickSegment.className() );
 
  517  if ( mode == "BoundingBox" )
 
  518    drawAsBoundingBox( aBoard, anAlphaThickSegment );
 
  519  else if ( mode == "Points" )
 
  520    drawAsDigitalPoints( aBoard, anAlphaThickSegment );
 
  521  else if ( ( mode == "" ) )
 
  523      drawAsDigitalPoints( aBoard, anAlphaThickSegment );
 
  524      drawAsBoundingBox( aBoard, anAlphaThickSegment );
 
  527    FATAL_ERROR_MSG(false, "draw( DGtal::Board2D & board, const DGtal::ArithmeticalDSSComputer<TIterator,TInteger,connectivity> & a ): Unknown mode "+mode);
 
  529// AlphaThickSegmentComputer
 
  533template <typename TPoint>
 
  535void DGtal::Display2DFactory::draw(Board2D & aBoard, const DGtal::CircleFrom2Points<TPoint> & cf2p)
 
  538    CircleFrom3Points<TPoint> c(cf2p.pole(),cf2p.p(),cf2p.q());
 
  539    drawArc(aBoard,c,cf2p.p(),cf2p.q(),true);
 
  545template <typename Point>
 
  547void DGtal::Display2DFactory::drawArc(Board2D & aBoard, const DGtal::CircleFrom3Points<Point> & cf3p, const Point& aPoint1, const Point& aPoint2, bool anOrientation)
 
  549  typedef typename Point::Coordinate Coordinate;
 
  550  typedef Point Vector;
 
  552  double cx = 0, cy = 0, radius = 1;
 
  556    cf3p.getParameters(cx, cy, radius);
 
  558    double alpha1 = std::atan2( NumberTraits<Coordinate>::castToDouble(aPoint1[1])-cy,
 
  559                                NumberTraits<Coordinate>::castToDouble(aPoint1[0])-cx );
 
  560    alpha1 = (alpha1<0)?(alpha1+2.0*M_PI):alpha1;
 
  561    double alpha2 = std::atan2( NumberTraits<Coordinate>::castToDouble(aPoint2[1])-cy,
 
  562                                NumberTraits<Coordinate>::castToDouble(aPoint2[0])-cx );
 
  563    alpha2 = (alpha2<0)?(alpha2+2.0*M_PI):alpha2;
 
  565    Vector u(cf3p.p() - cf3p.q());
 
  566    Vector v(cf3p.r() - cf3p.p());
 
  567    bool orientation = ( ( (u[0] * v[1]) - (u[1] * v[0]) ) < 0 )?(!anOrientation):anOrientation;
 
  569    aBoard.drawArc (cx, cy, radius, alpha1, alpha2, orientation);
 
  571  catch ( InfiniteNumberException& e )
 
  573    aBoard.drawLine( NumberTraits<Coordinate>::castToDouble(aPoint1[0]),
 
  574                     NumberTraits<Coordinate>::castToDouble(aPoint1[1]),
 
  575                     NumberTraits<Coordinate>::castToDouble(aPoint2[0]),
 
  576                     NumberTraits<Coordinate>::castToDouble(aPoint2[1]) );
 
  580template <typename Point>
 
  582void DGtal::Display2DFactory::drawSector(Board2D & aBoard, const DGtal::CircleFrom3Points<Point> & cf3p, const Point& aPoint1, const Point& aPoint2, bool anOrientation)
 
  584  typedef typename Point::Coordinate Coordinate;
 
  585  typedef Point Vector;
 
  587  double cx = 0, cy = 0, radius = 1;
 
  591    cf3p.getParameters(cx, cy, radius);
 
  593    double alpha1 = std::atan2( NumberTraits<Coordinate>::castToDouble(aPoint1[1])-cy,
 
  594                                NumberTraits<Coordinate>::castToDouble(aPoint1[0])-cx );
 
  595    alpha1 = (alpha1<0)?(alpha1+2.0*M_PI):alpha1;
 
  596    double alpha2 = std::atan2( NumberTraits<Coordinate>::castToDouble(aPoint2[1])-cy,
 
  597                                NumberTraits<Coordinate>::castToDouble(aPoint2[0])-cx );
 
  598    alpha2 = (alpha2<0)?(alpha2+2.0*M_PI):alpha2;
 
  600    Vector u(cf3p.p() - cf3p.q());
 
  601    Vector v(cf3p.r() - cf3p.p());
 
  602    bool orientation = ( ( (u[0] * v[1]) - (u[1] * v[0]) ) < 0 )?(!anOrientation):anOrientation;
 
  604    aBoard.drawArc (cx, cy, radius, alpha1, alpha2, orientation);
 
  605    //draw the segments tied to the center
 
  606    double fx = cx + radius*std::cos(alpha1);
 
  607    double fy = cy + radius*std::sin(alpha1);
 
  608    double lx = cx + radius*std::cos(alpha2);
 
  609    double ly = cy + radius*std::sin(alpha2);
 
  610    aBoard.drawLine(fx, fy, cx, cy );
 
  611    aBoard.drawLine(lx, ly, cx, cy );
 
  614  catch ( InfiniteNumberException& e )
 
  616    aBoard.drawLine( NumberTraits<Coordinate>::castToDouble(aPoint1[0]),
 
  617                     NumberTraits<Coordinate>::castToDouble(aPoint1[1]),
 
  618                     NumberTraits<Coordinate>::castToDouble(aPoint2[0]),
 
  619                     NumberTraits<Coordinate>::castToDouble(aPoint2[1]) );
 
  623template <typename Point>
 
  625void DGtal::Display2DFactory::drawAnnulus(Board2D & aBoard, const DGtal::CircleFrom3Points<Point> & cf3p,
 
  626                                          const Point& aPoint1, const Point& aPoint2, bool anOrientation, const double& w)
 
  628  typedef typename Point::Coordinate Coordinate;
 
  629  typedef Point Vector;
 
  631  double cx = 0, cy = 0, radius = 1;
 
  635    cf3p.getParameters(cx, cy, radius);
 
  637    double alpha1 = std::atan2( NumberTraits<Coordinate>::castToDouble(aPoint1[1])-cy,
 
  638                                NumberTraits<Coordinate>::castToDouble(aPoint1[0])-cx );
 
  639    alpha1 = (alpha1<0)?(alpha1+2.0*M_PI):alpha1;
 
  640    double alpha2 = std::atan2( NumberTraits<Coordinate>::castToDouble(aPoint2[1])-cy,
 
  641                                NumberTraits<Coordinate>::castToDouble(aPoint2[0])-cx );
 
  642    alpha2 = (alpha2<0)?(alpha2+2.0*M_PI):alpha2;
 
  644    Vector u(cf3p.p() - cf3p.q());
 
  645    Vector v(cf3p.r() - cf3p.p());
 
  646    bool orientation = ( ( (u[0] * v[1]) - (u[1] * v[0]) ) < 0 )?(!anOrientation):anOrientation;
 
  648    aBoard.drawArc (cx, cy, radius-w, alpha1, alpha2, orientation);
 
  650    aBoard.drawArc (cx, cy, radius+w, alpha1, alpha2, orientation);
 
  652    double ifx = cx + (radius-w)*std::cos(alpha1);
 
  653    double ify = cy + (radius-w)*std::sin(alpha1);
 
  654    double ofx = cx + (radius+w)*std::cos(alpha1);
 
  655    double ofy = cy + (radius+w)*std::sin(alpha1);
 
  656    aBoard.drawLine(ifx, ify, ofx, ofy);
 
  658    double ilx = cx + (radius-w)*std::cos(alpha2);
 
  659    double ily = cy + (radius-w)*std::sin(alpha2);
 
  660    double olx = cx + (radius+w)*std::cos(alpha2);
 
  661    double oly = cy + (radius+w)*std::sin(alpha2);
 
  662    aBoard.drawLine(ilx, ily, olx, oly);
 
  664  catch ( InfiniteNumberException& e )
 
  666    aBoard.drawLine( NumberTraits<Coordinate>::castToDouble(aPoint1[0]),
 
  667                     NumberTraits<Coordinate>::castToDouble(aPoint1[1]),
 
  668                     NumberTraits<Coordinate>::castToDouble(aPoint2[0]),
 
  669                     NumberTraits<Coordinate>::castToDouble(aPoint2[1]) );
 
  673template <typename Point>
 
  675void DGtal::Display2DFactory::draw(Board2D & aBoard, const DGtal::CircleFrom3Points<Point> & cf3p, const Point& aPoint1, const Point& aPoint2, bool anOrientation)
 
  677  std::string mode = aBoard.getMode( cf3p.className() );
 
  678  FATAL_ERROR( (mode=="Arc" || mode=="" || mode=="Sector"|| mode=="Annulus") ||
 
  679    ("draw(Board2D & aBoard, const DGtal::CircleFrom3Points<Point> & cf3p, const Point& aPoint1, const Point& aPoint2): Unknown mode "+mode)==""  );
 
  681  if ( mode == "Arc"  || ( mode == "" )  )
 
  682    drawArc( aBoard, cf3p, aPoint1, aPoint2, anOrientation);
 
  683  else if ( mode == "Sector" )
 
  684    drawSector( aBoard, cf3p, aPoint1, aPoint2, anOrientation);
 
  685  else if ( mode == "Annulus" )
 
  686    drawAnnulus( aBoard, cf3p, aPoint1, aPoint2, anOrientation);
 
  689template <typename TPoint>
 
  691void DGtal::Display2DFactory::draw(Board2D & aBoard, const DGtal::CircleFrom3Points<TPoint> & cf3p)
 
  693  typedef typename TPoint::Coordinate Coordinate;
 
  695  double cx = 0, cy = 0, radius = 1;
 
  698    cf3p.getParameters(cx,cy,radius);
 
  699    aBoard.drawCircle (cx,cy,radius);
 
  701  catch ( InfiniteNumberException& e )
 
  703    aBoard.drawLine( NumberTraits<Coordinate>::castToDouble(cf3p.myP[0]),
 
  704                     NumberTraits<Coordinate>::castToDouble(cf3p.myP[1]),
 
  705                     NumberTraits<Coordinate>::castToDouble(cf3p.myR[0]),
 
  706                     NumberTraits<Coordinate>::castToDouble(cf3p.myR[1]) );
 
  713template<typename Domain, typename Compare>
 
  715void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
 
  716           const DGtal::DigitalSetBySTLSet<Domain, Compare> & s )
 
  718  typedef typename Domain::Point Point;
 
  719  typedef typename std::set<Point>::const_iterator ConstIterator;
 
  721  BOOST_STATIC_ASSERT(Domain::Space::dimension == 2);
 
  722  for(ConstIterator it =  s.begin(); it != s.end(); ++it)
 
  728// DigitalSetByAssociativeContainer
 
  729template<typename Domain, typename Container>
 
  731void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
 
  732                                    const DGtal::DigitalSetByAssociativeContainer<Domain,Container> & s )
 
  734  typedef typename DigitalSetByAssociativeContainer<Domain,Container>::ConstIterator ConstIterator;
 
  736  BOOST_STATIC_ASSERT(Domain::Space::dimension == 2);
 
  737  for(ConstIterator it =  s.begin(); it != s.end(); ++it)
 
  740// DigitalSetByAssociativeContainer
 
  743// DigitalSetBySTLVector
 
  744template<typename Domain>
 
  746void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
 
  747           const DGtal::DigitalSetBySTLVector<Domain> & v )
 
  749  typedef typename Domain::Point Point;
 
  750  typedef typename std::vector<Point>::const_iterator ConstIterator;
 
  752  if (Domain::dimension == 2)
 
  754    for(ConstIterator it =  v.begin(); it != v.end(); ++it)
 
  758    FATAL_ERROR_MSG(false, "draw-NOT-YET-IMPLEMENTED-in-ND");
 
  760// DigitalSetBySTLVector
 
  764template <typename TIterator, typename TInteger, int connectivity>
 
  766void DGtal::Display2DFactory::drawAsPolygon( DGtal::Board2D & aBoard,
 
  767           const DGtal::FP<TIterator,TInteger,connectivity> & fp )
 
  769  typedef DGtal::PointVector<2,TInteger> Point;
 
  770  typedef std::list<Point> Polygon;
 
  772  typedef typename Polygon::const_iterator ConstIterator;
 
  775  std::vector<LibBoard::Point> polyline;
 
  778  ConstIterator i = fp.polygon().begin();
 
  779  for ( ;i != fp.polygon().end();++i) {
 
  781      double xp = (double)NumberTraits<TInteger>::castToInt64_t(p[0]);
 
  782      double yp = (double)NumberTraits<TInteger>::castToInt64_t(p[1]);
 
  783      polyline.push_back(LibBoard::Point(xp,yp));
 
  788      Point p = (*fp.polygon().begin());
 
  789      double xp = (double)NumberTraits<TInteger>::castToInt64_t(p[0]);
 
  790      double yp = (double)NumberTraits<TInteger>::castToInt64_t(p[1]);
 
  791      polyline.push_back(LibBoard::Point(xp,yp));
 
  793  aBoard.drawPolyline(polyline);
 
  796template <typename TIterator, typename TInteger, int connectivity>
 
  798void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
 
  799           const DGtal::FP<TIterator,TInteger,connectivity> & fp )
 
  801  std::string mode = board.getMode( fp.className() );
 
  802  if ( mode == "Polygon" )
 
  803    drawAsPolygon( board, fp );
 
  804  else if ( ( mode == "Both" ) || ( mode == "" ) )
 
  806      drawAsPolygon( board, fp );
 
  810      FATAL_ERROR_MSG(false, "draw( DGtal::Board2D & board, const DGtal::FP<TIterator,TInteger,connectivity> & fp ): Unknown mode "+mode);
 
  817template <typename TInteger>
 
  819void DGtal::Display2DFactory::drawAsGrid( DGtal::Board2D & aBoard,
 
  820           const DGtal::FreemanChain<TInteger> & f )
 
  822  typedef TInteger Integer;
 
  823  typedef PointVector<2, Integer> Point;
 
  825  std::vector<Point> aVContour;
 
  826  FreemanChain<TInteger>::getContourPoints(f, aVContour);
 
  827  TInteger minX, minY, maxX, maxY;
 
  828  f.computeBoundingBox(minX, minY, maxX, maxY);
 
  830  std::vector<LibBoard::Point> contour;
 
  831  for(unsigned int i=0; i< aVContour.size(); i++){
 
  832    contour.push_back(LibBoard::Point(NumberTraits<TInteger>::castToDouble(aVContour[i][0]),
 
  833              NumberTraits<TInteger>::castToDouble(aVContour[i][1])));
 
  835  aBoard.drawPolyline(contour);
 
  838template <typename TInteger>
 
  840void DGtal::Display2DFactory::drawAsInterGrid( DGtal::Board2D & aBoard,
 
  841           const DGtal::FreemanChain<TInteger> & f )
 
  843  typedef TInteger Integer;
 
  844  typedef PointVector<2, Integer> Point;
 
  846  std::vector<Point> aVContour;
 
  847  FreemanChain<TInteger>::getContourPoints(f, aVContour);
 
  848  TInteger minX, minY, maxX, maxY;
 
  849  f.computeBoundingBox(minX, minY, maxX, maxY);
 
  851  std::vector<LibBoard::Point> contour;
 
  852  for(unsigned int i=0; i< aVContour.size(); i++){
 
  853    contour.push_back(LibBoard::Point(NumberTraits<TInteger>::castToInt64_t(aVContour[i][0])-0.5,
 
  854              NumberTraits<TInteger>::castToInt64_t(aVContour[i][1])+0.5));
 
  856  aBoard.drawPolyline(contour);
 
  859template <typename TInteger>
 
  861void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
 
  862     const DGtal::FreemanChain<TInteger> & f )
 
  864  std::string mode = aBoard.getMode( f.className() );
 
  865  FATAL_ERROR_MSG( (mode=="Grid" || mode=="" || mode=="InterGrid"),
 
  866    "draw( DGtal::Board2D & board, const DGtal::FreemanChain<TInteger> & f ): Unknown mode "+mode);
 
  868  if ( mode == "Grid"  || ( mode == "" )  )
 
  869    drawAsGrid( aBoard, f );
 
  870  else if ( mode == "InterGrid" )
 
  871    drawAsInterGrid( aBoard, f );
 
  876// StabbingLineComputer
 
  877template <typename TConstIterator>
 
  879void DGtal::Display2DFactory::draw(DGtal::Board2D & aBoard,
 
  880          const DGtal::StabbingLineComputer<TConstIterator> & g)
 
  882  typedef TConstIterator ConstIterator;
 
  883  typedef typename IteratorCirculatorTraits<ConstIterator>::Value Pair;
 
  884  typedef typename Pair::first_type Point;
 
  886  double alpha, beta, gamma;
 
  887  g.getParameters(alpha, beta, gamma);
 
  889  typedef typename Point::Coordinate Coordinate;
 
  892  Pair firstPair( *g.begin() );
 
  893  double fx1 = NumberTraits<Coordinate>::castToDouble(firstPair.first[0]);
 
  894  double fx2 = NumberTraits<Coordinate>::castToDouble(firstPair.second[0]);
 
  895  double fy1 = NumberTraits<Coordinate>::castToDouble(firstPair.first[1]);
 
  896  double fy2 = NumberTraits<Coordinate>::castToDouble(firstPair.second[1]);
 
  897  double fx = (fx1+fx2)/2.0;
 
  898  double fy = (fy1+fy2)/2.0;
 
  899  g.projects(fx, fy, alpha, beta, gamma);
 
  902  ConstIterator it (g.end());
 
  904  Pair lastPair( *it );
 
  905  double lx1 = NumberTraits<Coordinate>::castToDouble(lastPair.first[0]);
 
  906  double lx2 = NumberTraits<Coordinate>::castToDouble(lastPair.second[0]);
 
  907  double ly1 = NumberTraits<Coordinate>::castToDouble(lastPair.first[1]);
 
  908  double ly2 = NumberTraits<Coordinate>::castToDouble(lastPair.second[1]);
 
  909  double lx = (lx1+lx2)/2.0;
 
  910  double ly = (ly1+ly2)/2.0;
 
  911  g.projects(lx, ly, alpha, beta, gamma);
 
  913  aBoard.drawLine(fx,fy,lx,ly);
 
  915// StabbingLineComputer
 
  917// StabbingCircleComputer
 
  918template <typename TConstIterator>
 
  920void DGtal::Display2DFactory::draw(DGtal::Board2D & aBoard,
 
  921          const DGtal::StabbingCircleComputer<TConstIterator> & g)
 
  924  typedef TConstIterator ConstIterator;
 
  925  typedef typename IteratorCirculatorTraits<ConstIterator>::Value Pair;
 
  926  typedef typename Pair::first_type Point;
 
  932    typedef typename Point::Coordinate Coordinate;
 
  935    Pair firstPair( *g.begin() );
 
  936    double fx1 = NumberTraits<Coordinate>::castToDouble(firstPair.first[0]);
 
  937    double fx2 = NumberTraits<Coordinate>::castToDouble(firstPair.second[0]);
 
  938    double fy1 = NumberTraits<Coordinate>::castToDouble(firstPair.first[1]);
 
  939    double fy2 = NumberTraits<Coordinate>::castToDouble(firstPair.second[1]);
 
  940    PointVector<2,double> p1( (fx1+fx2)/2.0, (fy1+fy2)/2.0 );
 
  942    ConstIterator it (g.end());
 
  944    Pair lastPair( *it );
 
  945    double lx1 = NumberTraits<Coordinate>::castToDouble(lastPair.first[0]);
 
  946    double lx2 = NumberTraits<Coordinate>::castToDouble(lastPair.second[0]);
 
  947    double ly1 = NumberTraits<Coordinate>::castToDouble(lastPair.first[1]);
 
  948    double ly2 = NumberTraits<Coordinate>::castToDouble(lastPair.second[1]);
 
  949    PointVector<2,double> p2( (lx1+lx2)/2.0, (ly1+ly2)/2.0 );
 
  952    CircleFrom3Points<Point> separatingCircle = g.getSeparatingCircle();
 
  953    double px = NumberTraits<Coordinate>::castToDouble(separatingCircle.p()[0]);
 
  954    double py = NumberTraits<Coordinate>::castToDouble(separatingCircle.p()[1]);
 
  955    double qx = NumberTraits<Coordinate>::castToDouble(separatingCircle.q()[0]);
 
  956    double qy = NumberTraits<Coordinate>::castToDouble(separatingCircle.q()[1]);
 
  957    double rx = NumberTraits<Coordinate>::castToDouble(separatingCircle.r()[0]);
 
  958    double ry = NumberTraits<Coordinate>::castToDouble(separatingCircle.r()[1]);
 
  959    CircleFrom3Points<PointVector<2,double> > circleToDraw;
 
  960    circleToDraw.init( PointVector<2,double>(px,py),
 
  961           PointVector<2,double>(qx,qy),
 
  962           PointVector<2,double>(rx,ry) );
 
  965    FATAL_ERROR( g.getStabbingLineComputerPtr().get() != 0 );
 
  966    bool orientation = g.getStabbingLineComputerPtr()->isClockwiseOriented();
 
  969    std::string mode = aBoard.getMode( g.className() );
 
  970    if ( mode == "Sector" )
 
  971      drawSector( aBoard, circleToDraw, p1, p2, orientation );
 
  972    else if ( mode == "Annulus" )
 
  973      drawAnnulus( aBoard, circleToDraw, p1, p2, orientation );
 
  975      drawArc( aBoard, circleToDraw, p1, p2, orientation );
 
  979    FATAL_ERROR( g.getStabbingLineComputerPtr().get() != 0 );
 
  980    aBoard << ( *(g.getStabbingLineComputerPtr()) );
 
  985// StabbingCircleComputer
 
  990template <typename TIterator,typename TInteger>
 
  992  void DGtal::Display2DFactory::draw(DGtal::Board2D & aBoard, const DGtal::FrechetShortcut<TIterator,TInteger> & f)
 
  994  typedef TIterator Iterator;
 
  995  typedef PointVector<2,TInteger> Point;
 
  996  typedef typename Point::Coordinate Coordinate;
 
  998  // get first point of the shortcut
 
  999  Point p1 = *(f.begin());
 
 1000  double px1 = NumberTraits<Coordinate>::castToDouble(p1[0]);
 
 1001  double py1 = NumberTraits<Coordinate>::castToDouble(p1[1]);
 
 1003  // get last point of the shortcut
 
 1004  Iterator it (f.end());
 
 1007  double px2 = NumberTraits<Coordinate>::castToDouble(p2[0]);
 
 1008  double py2 = NumberTraits<Coordinate>::castToDouble(p2[1]);
 
 1010  aBoard.drawLine(px1,py1,px2,py2);
 
 1017template <typename TKSpace>
 
 1018void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
 
 1019           const GridCurve<TKSpace> & object )
 
 1022  std::string mode = aBoard.getMode( object.className() );
 
 1024    DGtal::Display2DFactory::drawFill(aBoard, object);
 
 1026    typedef typename GridCurve<TKSpace>::ConstIterator ConstIterator;
 
 1027    ConstIterator it ( object.begin() );
 
 1028    ConstIterator itEnd ( object.end() );
 
 1029    for( ; it != itEnd; ++it)
 
 1036template <typename TKSpace>
 
 1037void DGtal::Display2DFactory::drawFill( DGtal::Board2D & aBoard,
 
 1038            const GridCurve<TKSpace> & object )
 
 1042  typedef typename GridCurve<TKSpace>::PointsRange::ConstIterator Iterator;
 
 1043  typedef typename GridCurve<TKSpace>::PointsRange Range; //range
 
 1045  Range r = object.getPointsRange();
 
 1046  Iterator it (r.begin());
 
 1047  Iterator itEnd (r.end());
 
 1049  std::vector< LibBoard::Point > aPolygon;
 
 1050  for( ; it != itEnd; ++it)
 
 1052      LibBoard::Point pt((*it)[0], (*it)[1]);
 
 1053      aPolygon.push_back(pt);
 
 1055  aBoard.fillPolyline(aPolygon);
 
 1064template <typename TIterator, typename TSCell>
 
 1065void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
 
 1066           const ConstRangeAdapter<TIterator, functors::Identity, TSCell> & object )
 
 1068    typedef ConstRangeAdapter<TIterator, functors::Identity, TSCell> Range;
 
 1069    typedef typename Range::ConstIterator ConstIterator;
 
 1071    ConstIterator it ( object.begin() );
 
 1072    ConstIterator itEnd ( object.end() );
 
 1073    for( ; it != itEnd; ++it)
 
 1081template <typename TIterator, typename TKSpace>
 
 1082void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
 
 1083           const ConstRangeAdapter<TIterator, functors::SCellToPoint<TKSpace>, typename TKSpace::Point> & object )
 
 1085    typedef ConstRangeAdapter<TIterator, functors::SCellToPoint<TKSpace>, typename TKSpace::Point> Range;
 
 1086    typedef typename Range::ConstIterator ConstIterator;
 
 1088    ConstIterator it ( object.begin() );
 
 1089    ConstIterator itEnd ( object.end() );
 
 1090    for( ; it != itEnd; ++it)
 
 1092  aBoard << SetMode(it->className(),"Grid");
 
 1099template <typename TIterator, typename TKSpace>
 
 1100void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
 
 1101           const ConstRangeAdapter<TIterator, CanonicSCellEmbedder<TKSpace>,
 
 1102           typename TKSpace::Space::RealPoint> & object )
 
 1104    typedef typename TKSpace::Space::RealPoint RPoint;
 
 1105    typedef ConstRangeAdapter<TIterator, CanonicSCellEmbedder<TKSpace>, RPoint > Range;
 
 1106    typedef typename Range::ConstIterator ConstIterator;
 
 1108    ConstIterator it ( object.begin() );
 
 1109    ConstIterator itEnd ( object.end() );
 
 1110    for( ; it != itEnd; ++it)
 
 1114  aBoard.drawLine( p[0]-s, p[1]-s, p[0]+s, p[1]+s );
 
 1115  aBoard.drawLine( p[0]-s, p[1]+s, p[0]+s, p[1]-s );
 
 1121template <typename TIterator, typename TKSpace>
 
 1122void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
 
 1123           const ConstRangeAdapter<TIterator, functors::SCellToArrow<TKSpace>,
 
 1124           std::pair<typename TKSpace::Point, typename TKSpace::Vector> > & object )
 
 1126    typedef typename TKSpace::Point Point;
 
 1127    typedef typename TKSpace::Vector Vector;
 
 1128    typedef std::pair<Point, Vector> Arrow;
 
 1129    typedef ConstRangeAdapter<TIterator, functors::SCellToArrow<TKSpace>, Arrow > Range;
 
 1130    typedef typename Range::ConstIterator ConstIterator;
 
 1132    ConstIterator it ( object.begin() );
 
 1133    ConstIterator itEnd ( object.end() );
 
 1134    for( ; it != itEnd; ++it)
 
 1137  Vector shift( a.second );
 
 1138  aBoard << CustomStyle( shift.className(),
 
 1139             new CustomPen( Color::Black, Color::Black, 1.0,
 
 1140                Board2D::Shape::SolidStyle,
 
 1141                Board2D::Shape::RoundCap,
 
 1142                Board2D::Shape::RoundJoin ) );
 
 1143  draw(aBoard, shift, a.first);
 
 1149template <typename TIterator, typename TKSpace>
 
 1150void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
 
 1151           const ConstRangeAdapter<TIterator, functors::SCellToInnerPoint<TKSpace>,
 
 1152           typename TKSpace::Point > & object )
 
 1154    typedef typename TKSpace::Point Point;
 
 1155    typedef ConstRangeAdapter<TIterator, functors::SCellToInnerPoint<TKSpace>, Point > Range;
 
 1156    typedef typename Range::ConstIterator ConstIterator;
 
 1158    ConstIterator it ( object.begin() );
 
 1159    ConstIterator itEnd ( object.end() );
 
 1160    for( ; it != itEnd; ++it)
 
 1162  aBoard << SetMode( it->className(), "Both" )
 
 1163         << CustomStyle( it->className(),
 
 1164             new CustomFillColor( Color::Blue ) )
 
 1171template <typename TIterator, typename TKSpace>
 
 1172void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
 
 1173           const ConstRangeAdapter<TIterator, functors::SCellToOuterPoint<TKSpace>,
 
 1174           typename TKSpace::Point > & object )
 
 1176    typedef typename TKSpace::Point Point;
 
 1177    typedef ConstRangeAdapter<TIterator, functors::SCellToOuterPoint<TKSpace>, Point > Range;
 
 1178    typedef typename Range::ConstIterator ConstIterator;
 
 1180    ConstIterator it ( object.begin() );
 
 1181    ConstIterator itEnd ( object.end() );
 
 1182    for( ; it != itEnd; ++it)
 
 1184  aBoard << SetMode( it->className(), "Both" )
 
 1185         << CustomStyle( it->className(),
 
 1186             new CustomFillColor( Color::Green ) )
 
 1192// IncidentPointsRange
 
 1193template <typename TIterator, typename TKSpace>
 
 1194void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
 
 1195           const ConstRangeAdapter<TIterator, functors::SCellToIncidentPoints<TKSpace>,
 
 1196           std::pair<typename TKSpace::Point, typename TKSpace::Point> > & object )
 
 1198    typedef typename TKSpace::Point Point;
 
 1199    typedef std::pair<Point, Point> Pair;
 
 1200    typedef ConstRangeAdapter<TIterator, functors::SCellToIncidentPoints<TKSpace>, Pair > Range;
 
 1201    typedef typename Range::ConstIterator ConstIterator;
 
 1203    ConstIterator it ( object.begin() );
 
 1204    ConstIterator itEnd ( object.end() );
 
 1205    for( ; it != itEnd; ++it)
 
 1208  aBoard << SetMode( pair.first.className(), "Both" )
 
 1209         << CustomStyle( pair.first.className(),
 
 1210             new CustomFillColor( Color::Blue ) )
 
 1212         << CustomStyle( pair.second.className(),
 
 1213             new CustomFillColor( Color::Green ) )
 
 1217// IncidentPointsRange
 
 1220template<typename TSpace>
 
 1222void DGtal::Display2DFactory::drawAsGrid( DGtal::Board2D & aboard,
 
 1223           const DGtal::HyperRectDomain<TSpace> & h )
 
 1225  typedef typename TSpace::Integer Integer;
 
 1227  FATAL_ERROR(TSpace::dimension == 2 || "drawAsGrid-NOT-YET-IMPLEMENTED-in-ND");
 
 1229  if (TSpace::dimension == 2)
 
 1231    for (double x = NumberTraits<Integer>::castToDouble(h.myLowerBound[0]);
 
 1232   x <=  NumberTraits<Integer>::castToDouble(h.myUpperBound[0]); x++)
 
 1234          NumberTraits<Integer>::castToDouble(h.myLowerBound[1]) -
 
 1237          NumberTraits<Integer>::castToDouble(h.myUpperBound[1]) +
 
 1240    for (double y =  NumberTraits<Integer>::castToDouble(h.myLowerBound[1]);
 
 1241   y <=  NumberTraits<Integer>::castToDouble(h.myUpperBound[1]); y++)
 
 1242      aboard.drawLine(NumberTraits<Integer>::castToDouble(h.myLowerBound[0]) -
 
 1245          NumberTraits<Integer>::castToDouble(h.myUpperBound[0]) +
 
 1249    for (double x =  NumberTraits<Integer>::castToDouble(h.myLowerBound[0]);
 
 1250   x <=  NumberTraits<Integer>::castToDouble(h.myUpperBound[0]); x++)
 
 1251      for (double y =  NumberTraits<Integer>::castToDouble(h.myLowerBound[1]);
 
 1252     y <=  NumberTraits<Integer>::castToDouble(h.myUpperBound[1]); y++)
 
 1253        aboard.fillCircle(x, y, 0.1);
 
 1257template<typename TSpace>
 
 1259void DGtal::Display2DFactory::drawAsPaving( DGtal::Board2D & aboard,
 
 1260           const DGtal::HyperRectDomain<TSpace> & h )
 
 1262  typedef typename TSpace::Integer Integer;
 
 1264  FATAL_ERROR(TSpace::dimension==2 || "drawAsPaving-NOT-YET-IMPLEMENTED-in-ND" );
 
 1266  if (TSpace::dimension == 2)
 
 1268    for (DGtal::int64_t x = NumberTraits<Integer>::castToInt64_t(h.myLowerBound[0]);
 
 1269   x <= NumberTraits<Integer>::castToInt64_t(h.myUpperBound[0]); x++)
 
 1270      for (DGtal::int64_t y = NumberTraits<Integer>::castToInt64_t(h.myLowerBound[1]);
 
 1271     y <= NumberTraits<Integer>::castToInt64_t(h.myUpperBound[1]); y++)
 
 1272        aboard.drawRectangle(x - 0.5, y + 0.5, 1, 1);
 
 1276template<typename TSpace>
 
 1278void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
 
 1279           const DGtal::HyperRectDomain<TSpace> & h )
 
 1281  std::string mode = board.getMode( h.className() );
 
 1282  FATAL_ERROR((mode=="" || mode=="Grid" || mode=="Paving") ||
 
 1283   ("draw( DGtal::Board2D & board, const DGtal::HyperRectDomain<TSpace> & h ): Unknown mode "+mode)=="");
 
 1285  if ( ( mode == "" ) || ( mode == "Grid" ) )
 
 1286    drawAsGrid( board, h );
 
 1287  else if ( mode == "Paving" )
 
 1288    drawAsPaving( board, h );
 
 1293// ImageContainerByHashTree
 
 1294template <typename C, typename Domain, typename Value, typename HashKey>
 
 1296void DGtal::Display2DFactory::drawImageRecursive( DGtal::Board2D & aBoard,
 
 1297                                                  const DGtal::experimental::ImageContainerByHashTree<Domain, Value, HashKey> & i,
 
 1301                                                  LibBoard::Board & board,
 
 1305  FATAL_ERROR ( Domain::dimension == 2 );
 
 1309  //Node* n = i.getNode ( key );
 
 1310  if ( i.getNode ( key ) )
 
 1313    c = cmap ( i.getNode ( key )->getObject() );
 
 1314    board.setFillColorRGBi ( c.red(), c.green(), c.blue() );
 
 1316    board.drawRectangle ( p[0], p[1], len, len );
 
 1320    HashKey children[4];
 
 1321    i.myMorton.childrenKeys ( key, children );
 
 1326    np[1] = p[1] - nlen;
 
 1327    drawImageRecursive<C>( aBoard, i, children[0], np, nlen, board, cmap );
 
 1329    np[0] = p[0] + nlen;
 
 1330    np[1] = p[1] - nlen;
 
 1331    drawImageRecursive<C>( aBoard, i, children[1], np, nlen, board, cmap );
 
 1335    drawImageRecursive<C>( aBoard, i, children[2], np, nlen, board, cmap );
 
 1337    np[0] = p[0] + nlen;
 
 1339    drawImageRecursive<C>( aBoard, i, children[3], np, nlen, board, cmap );
 
 1343template <typename C, typename Domain, typename Value, typename HashKey>
 
 1345void DGtal::Display2DFactory::drawImageHashTree( Board2D & board,
 
 1346                const DGtal::experimental::ImageContainerByHashTree<Domain, Value, HashKey> & i,
 
 1347                const Value &minV, const Value &maxV )
 
 1349   static const HashKey ROOT_KEY = static_cast<HashKey>(1);
 
 1351  FATAL_ERROR ( Domain::dimension == 2 );
 
 1353  C colormap ( minV, maxV );
 
 1358  p[0] = i.myOrigin[0];
 
 1359  p[1] = i.myOrigin[1] + i.getSpanSize();
 
 1361  len = i.getSpanSize();
 
 1363  drawImageRecursive<C>( board, i, ROOT_KEY, p, len, board, colormap );
 
 1365// ImageContainerByHashTree
 
 1367// Draw image generic
 
 1368// ImageContainerBySTLVector, ImageContainerByHashTree, Image and ImageAdapter...
 
 1369template <typename Colormap, typename Image>
 
 1371void DGtal::Display2DFactory::drawImage( DGtal::Board2D & board,
 
 1373                                         const typename Image::Value & minV,
 
 1374                                         const typename Image::Value & maxV )
 
 1376  typedef typename Image::Domain D;
 
 1378  FATAL_ERROR(D::Space::dimension == 2);
 
 1380  Colormap colormap(minV, maxV);
 
 1382  typename Image::Value val;
 
 1383  for (typename Image::Domain::ConstIterator it =  i.domain().begin();
 
 1384       it != i.domain().end(); ++it)
 
 1386    val = i.operator()( (*it) );
 
 1387    c = colormap( val );
 
 1388    board.setFillColorRGBi( c.red(), c.green(), c.blue());
 
 1389    board.drawRectangle( NumberTraits<typename Image::Domain::Space::Integer>::
 
 1390                         castToDouble((*it)[0]) - 0.5,
 
 1391                         NumberTraits<typename Image::Domain::Space::Integer>::
 
 1392                         castToDouble((*it)[1]) + 0.5, 1, 1);
 
 1397template < DGtal::Dimension dim, typename TInteger >
 
 1399void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
 
 1400           const DGtal::KhalimskyCell<dim, TInteger> & k )
 
 1402  draw( board, k.preCell() );
 
 1406template < DGtal::Dimension dim, typename TInteger >
 
 1408void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
 
 1409           const DGtal::KhalimskyPreCell<dim, TInteger> & k )
 
 1411  FATAL_ERROR( dim == 2 );
 
 1414    ( NumberTraits<TInteger>::castToInt64_t( k.coordinates[0] ) >> 1 );
 
 1416    ( NumberTraits<TInteger>::castToInt64_t( k.coordinates[1] ) >> 1 );
 
 1417  float retract = 0.05f;
 
 1418  bool xodd = ( k.coordinates[ 0 ] & 1 );
 
 1419  bool yodd = ( k.coordinates[ 1 ] & 1 );
 
 1420  float dx = xodd ? 1.0f - 2.0f*retract : 2.0f*retract;
 
 1421  float dy = yodd ? 1.0f - 2.0f*retract : 2.0f*retract;
 
 1422  board.drawRectangle( !xodd ? x - retract - 0.5 : x + retract - 0.5,
 
 1423           !yodd ? y + retract - 0.5 : y - retract + 0.5,
 
 1430template <typename TDigitalTopology, typename TDigitalSet>
 
 1432void DGtal::Display2DFactory::drawWithAdjacencies( DGtal::Board2D & aBoard,
 
 1433           const DGtal::Object<TDigitalTopology, TDigitalSet> & o )
 
 1435  typedef TDigitalSet DigitalSet;
 
 1436  typedef typename DigitalSet::Point Point;
 
 1438  typedef TDigitalTopology DigitalTopology;
 
 1439  typedef typename DigitalSet::Domain Domain;
 
 1441      typename DigitalSetSelector < Domain,
 
 1442      SMALL_DS + HIGH_ITER_DS >::Type SmallSet;
 
 1443  typedef Object<DigitalTopology, SmallSet> SmallObject;
 
 1447  for (typename TDigitalSet::ConstIterator it = o.pointSet().begin();
 
 1448      it != o.pointSet().end();
 
 1451    //Brute-force scan of the neighborhood.
 
 1452    SmallObject neig = o.properNeighborhood(*it);
 
 1453    for (typename SmallObject::DigitalSet::ConstIterator it2 = neig.pointSet().begin();
 
 1454        it2 != neig.pointSet().end();
 
 1458      draw(aBoard, p, (*it));
 
 1463template <typename TDigitalTopology, typename TDigitalSet>
 
 1465void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
 
 1466           const DGtal::Object<TDigitalTopology, TDigitalSet> & o )
 
 1468  std::string mode = board.getMode( o.className() );
 
 1470    draw( board, o.pointSet() );
 
 1472    if ( mode == "DrawAdjacencies" )
 
 1474      draw( board, o.pointSet() );
 
 1475      drawWithAdjacencies( board, o );
 
 1478      FATAL_ERROR(false && (("draw( DGtal::Board2D & board, const DGtal::Object<TDigitalTopology, TDigitalSet> & o ): Unknown mode " + mode) == ""));
 
 1483template < typename TKSpace, typename TCellContainer >
 
 1486DGtal::Display2DFactory::draw( DGtal::Board2D & board,
 
 1487             const DGtal::CubicalComplex<TKSpace, TCellContainer> & cc )
 
 1489  FATAL_ERROR( cc.dimension == 2);
 
 1490  typedef DGtal::CubicalComplex<TKSpace, TCellContainer> CC;
 
 1491  typedef typename CC::KSpace               KSpace;
 
 1492  typedef typename CC::Point                Point;
 
 1493  typedef typename CC::ConstIterator        ConstIterator;
 
 1494  typedef typename KSpace::Integer          Integer;
 
 1495  for ( ConstIterator it = cc.begin(), itE = cc.end(); it != itE; ++it )
 
 1496    { // We are not using operator << for cells in order to use the
 
 1497      // style specified for the cubical complex.
 
 1498      Point kx = cc.space().uKCoords( *it );
 
 1499      float x = (float) ( NumberTraits<Integer>::castToInt64_t( kx[0] ) >> 1 );
 
 1500      float y = (float) ( NumberTraits<Integer>::castToInt64_t( kx[1] ) >> 1 );
 
 1501      float retract = 0.05f;
 
 1502      bool xodd = ( kx[ 0 ] & 1 );
 
 1503      bool yodd = ( kx[ 1 ] & 1 );
 
 1504      float dx = xodd ? 1.0f - 2.0f*retract : 2.0f*retract;
 
 1505      float dy = yodd ? 1.0f - 2.0f*retract : 2.0f*retract;
 
 1506      board.drawRectangle( !xodd ? x - retract - 0.5 : x + retract - 0.5,
 
 1507                           !yodd ? y + retract - 0.5 : y - retract + 0.5,
 
 1515template<DGtal::Dimension dim, typename TComponent, typename TContainer>
 
 1517void DGtal::Display2DFactory::drawAsPaving( DGtal::Board2D & board,
 
 1518           const DGtal::PointVector<dim, TComponent, TContainer> & p )
 
 1520  FATAL_ERROR(dim == 2);
 
 1521  board.drawRectangle( (float) NumberTraits<TComponent>::castToDouble(p[0]) - 0.5f,
 
 1522                       (float) NumberTraits<TComponent>::castToDouble(p[1]) + 0.5f, 1, 1 );
 
 1525template<DGtal::Dimension dim, typename TComponent, typename TContainer>
 
 1527void DGtal::Display2DFactory::drawAsGrid( DGtal::Board2D & board,
 
 1528           const DGtal::PointVector<dim, TComponent, TContainer> & p )
 
 1530  FATAL_ERROR(dim == 2);
 
 1531  board.fillCircle((float) NumberTraits<TComponent>::castToDouble(p[0]),
 
 1532                   (float) NumberTraits<TComponent>::castToDouble(p[1]),0.1);
 
 1535template<DGtal::Dimension dim, typename TComponent, typename TContainer>
 
 1537void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
 
 1538           const DGtal::PointVector<dim,TComponent, TContainer> & p )
 
 1540  std::string mode = board.getMode( p.className() );
 
 1541  FATAL_ERROR( (mode=="Paving" || mode=="Grid" || mode=="Both" || mode=="") ||
 
 1542    ("draw( DGtal::Board2D & board, const DGtal::PointVector<dim, TComponent, TContainer> & p ): Unknown mode "+mode)==""  );
 
 1544  if ( mode == "Paving"  || ( mode == "" )  )
 
 1545    drawAsPaving( board, p );
 
 1546  else if ( mode == "Grid" )
 
 1547    drawAsGrid( board, p );
 
 1548  else if ( ( mode == "Both" ))
 
 1550      drawAsPaving( board, p );
 
 1551      drawAsGrid( board, p );
 
 1555template<DGtal::Dimension dim, typename TComponent1, typename TComponent2, typename TContainer1, typename TContainer2>
 
 1557void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
 
 1558          const DGtal::PointVector<dim, TComponent1, TContainer1> & shift,
 
 1559          const DGtal::PointVector<dim, TComponent2, TContainer2> & basepoint )
 
 1561  FATAL_ERROR(dim == 2);
 
 1563  board.drawArrow((float)basepoint[0], (float) basepoint[1],
 
 1564      (float) basepoint[0] + shift[0], (float)basepoint[1] + shift[1],
 
 1571template <typename Shape>
 
 1573void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
 
 1574     const DGtal::Preimage2D<Shape> & p )
 
 1576  typedef typename Shape::Point Point;
 
 1577  typedef typename std::list<Point>::const_iterator ConstForwardIterator;
 
 1579  // now with accessor
 
 1580  Shape s( p.shape() );
 
 1581  ConstForwardIterator i = p.pHull().begin();
 
 1584  while ( i != p.pHull().end() ) {
 
 1586    draw(aBoard, s); //s.setStyle(aBoard);
 
 1591  i = p.qHull().begin();
 
 1594  while ( i != p.qHull().end() ) {
 
 1596    draw(aBoard, s); //s.setStyle(aBoard);
 
 1601  Point Pf(*p.pHull().begin());
 
 1602  Point Pl(*p.pHull().rbegin());
 
 1603  Point Qf(*p.qHull().begin());
 
 1604  Point Ql(*p.qHull().rbegin());
 
 1607  draw(aBoard, s); //s.setStyle(aBoard);
 
 1609  draw(aBoard, s); //s.setStyle(aBoard);
 
 1613// SignedKhalimskyCell
 
 1614template < DGtal::Dimension dim, typename TInteger >
 
 1616void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
 
 1617     const DGtal::SignedKhalimskyCell<dim, TInteger> & sk )
 
 1619  draw( board, static_cast< DGtal::SignedKhalimskyPreCell<dim, TInteger> const& >(sk) );
 
 1622// SignedKhalimskyPreCell
 
 1623template < DGtal::Dimension dim, typename TInteger >
 
 1625void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
 
 1626     const DGtal::SignedKhalimskyPreCell<dim, TInteger> & sk )
 
 1628  FATAL_ERROR( dim == 2 );
 
 1630    ( NumberTraits<TInteger>::castToInt64_t( sk.coordinates[0] ) >> 1 );
 
 1632    ( NumberTraits<TInteger>::castToInt64_t( sk.coordinates[1] ) >> 1 );
 
 1633  float retract = 0.05f;
 
 1634  bool xodd = ( sk.coordinates[ 0 ] & 1 );
 
 1635  bool yodd = ( sk.coordinates[ 1 ] & 1 );
 
 1636  float dx = xodd ? 1.0f - 2.0f*retract : 2.0f*retract;
 
 1637  float dy = yodd ? 1.0f - 2.0f*retract : 2.0f*retract;
 
 1638  board.drawRectangle( !xodd ? x - retract - 0.5 : x + retract - 0.5,
 
 1639           !yodd ? y + retract - 0.5 : y - retract + 0.5,
 
 1642// SignedKhalimskyPreCell
 
 1645// StraightLineFrom2Points
 
 1646template <typename TPoint>
 
 1648void DGtal::Display2DFactory::draw(Board2D & aBoard, const DGtal::StraightLineFrom2Points<TPoint> & slf2p)
 
 1650  // now with accessor
 
 1651  aBoard.drawLine(slf2p.p()[0],slf2p.p()[1],slf2p.q()[0],slf2p.q()[1]);
 
 1653// StraightLineFrom2Points
 
 1660void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
 
 1661           const DGtal::CustomStyle & cs )
 
 1663  board.myStyles[ cs.myClassname ] = cs.myStyle;
 
 1667void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
 
 1668     const DGtal::SetMode & sm )
 
 1670  board.myModes[ sm.myClassname ] = sm.myMode;
 
 1673template <typename TSpace, typename TSequence>
 
 1676DGtal::Display2DFactory::draw
 
 1677( DGtal::Board2D & aBoard,
 
 1678  const DGtal::LatticePolytope2D<TSpace, TSequence> & cip )
 
 1680  typedef typename LibBoard::Point BoardPoint;
 
 1681  typedef typename DGtal::LatticePolytope2D<TSpace>::Point CIPPoint;
 
 1682  typedef typename DGtal::LatticePolytope2D<TSpace>::ConstIterator ConstIterator;
 
 1683  typedef typename DGtal::LatticePolytope2D<TSpace>::Integer Integer;
 
 1684  std::string mode = aBoard.getMode( cip.className() );
 
 1685  FATAL_ERROR( mode=="Filled" || mode=="" || mode=="Transparent" ||
 
 1686          ("draw(Board2D & aBoard, const DGtal::LatticePolytope2D<Space,Sequence> & cip): Unknown mode "+mode)==""  );
 
 1688  std::vector<BoardPoint> pts;
 
 1690  for ( ConstIterator it = cip.begin(), it_end = cip.end(); it != it_end; ++it )
 
 1693      pts.push_back( BoardPoint( NumberTraits<Integer>::castToDouble( p[ 0 ] ),
 
 1694                                 NumberTraits<Integer>::castToDouble( p[ 1 ] ) ) );
 
 1696  aBoard.drawClosedPolyline( pts );
 
 1701///////////////////////////////////////////////////////////////////////////////