Visualize 2D DGtal objects with LibBoard

This part of the manual describes how to export 2D DGtal objects with LibBoard in order to construct SVG, EPS or XFIG drawings. This document is dedicated both to DGtal users and developers.

Table of contents:

  1. Short overview of the LibBoard library
  2. How to use LibBoard objects in DGtal ?
    1. Basic usage
    2. Advanced usage
  3. How to create your own export ?

Short overview of the LibBoard library

LibBoard is a C++ library for simple Postscript, SVG, and XFig drawings.

logo_Board.png

(Copyleft, LGPL) 2007 Sébastien Fourey - GREYC ENSICAEN

It allows simple drawings in:

The main class of the library is the LibBoard::Board class. It is intended to be as simple as possible so that it can be used quickly in programs to generate the kind of figure one would rather not draw by hand, but which can be easily drawn by a computer (C++) program.

A clone of the LibBoard source code (release: 0.8.8-3) has been included in DGtal. Its classes are grouped into the namespace Board.

How to use LibBoard objects in DGtal ?

Basic usage

Many DGtal objects implement a mechanism which aims at defining the way the objects export themselves with LibBoard commands into a DGtalBoard stream.

For instance, when a digital set (any model of CDigitalSet like DigitalSetBySTLSet or DigitalSetBySTLVector) is streamed to a DGtalBoard, a square primitives for each point of the set is appended to the current board.

For example, let us define a basic 2D set on Z^2:

 #include "DGtal/base/Common.h"
 #include "DGtal/kernel/SpaceND.h"
 #include "DGtal/kernel/domains/HyperRectDomain.h"
 #include "DGtal/kernel/sets/DigitalSetBySTLVector.h"
 #include "DGtal/kernel/sets/DigitalSetBySTLSet.h"
 #include "DGtal/kernel/sets/DigitalSetSelector.h"
 #include "DGtal/io/DGtalBoard.h"
 
 ...
 typedef SpaceND<2> Z2;
 typedef HyperRectDomain<Z2> DomainType;
 typedef Z2::Point Point;
 Point p1(  -10, -10  );
 Point p2(  10, 10  );
 DomainType domain( p1, p2 );
 typedef DigitalSetSelector
  < DomainType, BIG_DS + HIGH_ITER_DS + HIGH_BEL_DS >::Type SpecificSet; 
 SpecificSet mySet( domain );
 
 Point c(  0, 0  );
 mySet.insert( c );
 Point d(  5, 2  );
 mySet.insert( d );
 Point e(  1, -3  );
 mySet.insert( e );

The basic usage is :

 DGtalBoard board;
 board.setUnit(Board::UCentimeter);
 board << mySet;
 board.saveSVG( "simpleSet.svg" );

leading to the drawing (after a SVG->PNG conversion):

simpleSet.png

We can enhance the drawing displaying digital domain (any model of CDigitalDomain) containing the set. We have at least two ways to display the domain: either as a grid (mesh) or as a paving. Hence, digital domains introduces stream modifier that can be used as either

 DGtalBoard board;
 board.setUnit(Board::UCentimeter);

 board << DrawDomainGrid()
       << domain
       << mySet;

 board.saveSVG( "simpleSet-grid.svg" );

or

 LibBoard::Board board;
 board.setUnit(Board::UCentimeter);

 board << DrawDomainPaving()
       << domain
       << mySet;

 board.saveSVG( "simpleSet-Paving.svg" );
simpleSet-grid.png

DrawDomainGrid result.

simpleSet-paving.png

DrawDomainPaving result.

Similarly, an object of the class PointVector can be drawn either as a Point (dot), or as a Vector (arrow). In this case, instead of using the stream mecanism, the user can consider the methods:

Hence, the code will look like:

 myVector.selfDraw(board);

or

 myVector.selfDraw(board, aPoint);

NOTE: in such situation, if the user uses the stream mechanism

 board << myVector; 

the default selfDraw(DGtalBoard &board) is used.

As illustrated in the document Digital topology and digital objects, the following drawings represent an object with two different adjacency relationships. To obtain such figures, we have call selfDraw methods of the following objects:

DiskWithAdj4.png

Illustration of a Digital Object with the 4-adjacency

DiskWithAdj8.png

Illustration of a Digital Object with the 8-adjacency

Advanced usage

Todo:
finish rewritting

By default, each method selfDraw uses a specific style. For example, the default style or color associated to a digital domain is either a dashed grid with gray color, or a set of unfilled gray squares (see HyperRectDomain::SelfDrawStyleGrid and HyperRectDomain::SelfDrawStylePaving).

If the user wants to customize the output color for instance, he or she have to:

  1. Create a C++ class or struct with a constructor taking a LibBoard instance in parameter and such that the LibBoard commands to customize the colors belongs to this constructor.
  2. Use this class as a template parameter of the selfDraw methods.

For example, if you want the simple set considered above to be depicted in red with green edges, just create your own style "struct" as follows:

 struct SelfDrawStyleCustom
    {
      SelfDrawStyleCustom(LibBoard::Board & aboard)
      {
        aboard.setPenColorRGBi(0,255,0);
        aboard.setFillColorRGBi(255,0,0);
      }
    };

Then, we use this customized style in the selfDraw calls:

 LibBoard::Board board;
 board.setUnit(Board::UCentimeter);
 mySet.selfDraw<SelfDrawStyleCustom>(board);
 board.saveSVG( "simpleSet.svg" );

and we obtain:

simpleSet-color.png

How to create your own export ?

To create a LibBoard export on your object, you have to

  1. Create a SelfDrawStyle struct (e.g. DigitalSetBySTLVector::SelfDrawStyle)
  2. Implement a method selfDraw the will perform the drawing with a default template parameter set to SelfDrawDefaultStyle.

The second item can be done using the following declaration code for instance:

    /*
 Draw the object on a LibBoard board
 @param board the output board where the object is drawn.
 @tparam Functor a Functor to specialize the Board style
     */
    template<typename Functor>
    void selfDraw(LibBoard::Board & board ) const;

    /*
 Draw the object on a LibBoard board
 @param board the output board where the object is drawn.
     */
    void selfDraw(LibBoard::Board & board ) const
    {
      selfDraw<SelfDrawStyle>(board);
    }