[OpendTect_Developers] How to use the uiAxisHandler

Bruno Chaintreuil bruno.chaintreuil at dgbes.com
Wed Feb 23 15:35:30 CET 2011


Dear All,

In OpendTect 4.2. the uiAxisHandler class has been slightly reworked to 
fit the needs of our constantly improving 2D graphics displays. Since 
the uiAxisHandler is quite a powerful object when it comes to 
positioning data on a scene, I think this class really deserves a small 
post here. Although there are some facilities for function drawing in 
OpendTect that use internally the uiAxisHandler, you might want to draw 
some specific data and/or have full control on its position on the 
scene. Therefore you will have to use yourself the uiAxisHandler. Here 
is a brief reminder on how this class works and what are its benefits.

The uiAxisHandler (uiTools/uiaxishandler.h and uiaxishandler.cc) is an 
object that generates an axis to guide the positioning of a drawing 
(graphics, function, pattern... ) on the scene canvas. It is 
instantiated by giving a uiGraphicsScene (the equivalent of a 
QGraphicsScene) and a Setup where you can specify its properties. It is 
composed of an axis line, some grid lines and some annotations that can 
be drawn on the scene with a specific LineStyle (width and color). Each 
component can be turned on or off according to the setup wishes. The 
setup requires a rectangle side (left, top, right or bottom)  to 
determine the placement in the scene and the axis orientation (vertical 
for left and right, horizontal for top and bottom ). The other settings 
are optional and will be set to default if not specified (see the Setup 
class of the uiaxishandler.h for details). On the inner side of the 
axis, the drawing will be positioned and drawn on the scene. Grid lines 
perpendicular to the axis will optionally overlay this drawing. On the 
outer side, annotations will be drawn. This annotations are the tick 
(regular value marker orthogonal to the axis), axis values, and name. At 
last a uiBorder will add an extra border between the axis and the scene 
border. See attached picture number 1 for a schematic view of the 
uiAxisHandler.

Once created, you can easily position your drawing relatively to the 
axis by giving the uiAxisHandler a value range and using the getPix 
function. For each value of your range, getPix will give you the 
corresponding pixel on the scene. Every time the scene is resized (most 
of the time by a user interaction), you will have to resize the 
uiAxisHandler accordingly. This is done by calling the updateDevSize 
function.

Let us now depict this with a very simple example : the drawing of 
stratigraphic rectangle unit along a vertical Z axis. Let us suppose we 
only want to display one single stratigraphic unit, say "Jurassic", in a 
period ranging from 145 to 200 million years. We first create a class 
myClass that holds a uiGraphicsScene scene_ and a uiAxisHandler* zaxis_. 
Then the implementation of this drawing could be composed of two 
functions initAxis and drawJurassicUnit. In initAxis we declare the 
zaxis_ that will position the Jurassic unit on the scene. We give it a 
Setup that will put the axis on the left side of the scene, with a 
border of 20.  Then we give the axis a name and a total Z range from 100 
to 250 my.

void myClass::initAxis()
{
   uiAxisHandler::Setup su( uiRect::Left );
   uiBorder border( 20 );
   su.border( border ).nogridline( true );
   zaxis_ = new uiAxisHandler( &scene_, su );
   zaxis_->setName( "Age (my)" );
   zaxis_->setRange( 250, 100 ) );
}

The drawJurassicUnit will create and place the stratigraphic unit 
rectangle on the scene using the zaxis_. To build the unit rectangle we 
need a polygon of 4 points : x1, y1, x2, and y2. The vertical point y1 
and y2 are the pixels of the range limits of the unit (145 and 200), 
computed using the getPix function of the zaxis_. The x1 pixel is 
nothing else than the axis line itself, given by the function pixToEdge. 
The x2 position is the width of the scene (the unit will cover the whole 
scene area towards the right). Now we can use the function addPolygon to 
build the polygon on the scene given the 4 rectangle points. At last we 
give the unit a title (translated on the scene by a uiTextItem) that we 
place in the center of the unit display. Please see attached picture 
number 2 to view the resulting display.

void myClass::drawJurassicUnit()
{
   BufferString unitname( "Jurassic" );
   Interval<float> unitzrange( 145, 200 );

   int x1 = zaxis_->pixToEdge();
   int x2 = (int)scene_.width();
   int y1 = zaxis_->getPix( unitzrange.start );
   int y2 = zaxis_->getPix( unitzrange.stop );

   TypeSet<uiPoint> rectpts;
   rectpts += uiPoint( x1, y1 );
   rectpts += uiPoint( x2, y1 );
   rectpts += uiPoint( x2, y2 );
   rectpts += uiPoint( x1, y2 );

   uiPolygonItem* pli = scene_.addPolygon( rectpts, true );
   pli->setFillColor( Color::stdDrawColor(1) );

   uiTextItem* ti = scene_.addItem( new uiTextItem( unitname ) );
   ti->setPos( x1 + abs(x2-x1)/2,  y1 + abs(y2-y1)/2 );

   zaxis_->plotAxis();
}

This was a simple unidirectional case with only one axis. Of course you 
might want to position the data along a X axis as well. Therefore you 
need to declare another uiAxisHandler. The graphic will then be 
positioned the same way with the getPix function in both the X and Z 
direction. But you have to make sure the two axis will share a common 
origin. This can be done by using the setBegin and setEnd functions of 
the uiAxisHandler. Both require as input the adjacent uiAxisHandler that 
will either share its end or its beginning, depending on the orientation 
of the axis. In our example of the stratigraphic function, the initAxis 
will just be added a xaxis_ and the zaxis_ and xaxis_ will be tied 
together.

void myClass::initAxis()
{
   ...

   uiAxisHandler::Setup xsu( uiRect::Top );                            
      
   xsu.border( border );
   xaxis_ = new uiAxisHandler( &scene_, xsu );
   xaxis_->setRange( Interval<float>( 0, 3 ) );
   xaxis_->setName( "Column number" );

   xaxis_->setBegin( zaxis_ );
   zaxis_->setEnd( xaxis_ );
}

In the drawJurassicUnit, only the computation of x1 and x2 will change. 
Result is given in picture 3.

void myClass::drawJurassicUnit()
{
   Interval<float> unitxrange( 1, 2 );
   ...

   int x1 = xaxis_->getPix( unitxrange.start );
   int x2 = xaxis_->getPix( unitxrange.stop );
   ...

   xaxis_->plotAxis();
}

In OpendTect 4.2, you have now an option to put your annotation inside 
the axis. This will report the ticks and values on the inner part of the 
drawing. This is useful when you want to display for instance juxtaposed 
views of different data in the same window without space separating the 
views but still with some annotations. Therefore you just have to turn 
on the annotinside_ boolean in the Setup before constructing the axis. 
Attached in picture 4 is an example of the stratigraphic unit with the 
the annotations inside.

I think you know all about the uiAxisHandler by now !

Happy coding and best Regards,
Bruno


-- 
 Bruno Chaintreuil, MSc.
 Software Engineer
 dGB Earth Sciences B.V.
 Nijverheidstraat 11-2, 7511 JM Enschede, The Netherlands
 bruno.chaintreuil at dgbes.com
 Tel: +31 534315155 , Fax: +31 534315104
 http://www.dgbes.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.opendtect.org/pipermail/developers/attachments/20110223/60596bc1/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Axis_schematic.png
Type: image/png
Size: 22115 bytes
Desc: not available
URL: <http://lists.opendtect.org/pipermail/developers/attachments/20110223/60596bc1/attachment.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Jurassic_1Axis.png
Type: image/png
Size: 8636 bytes
Desc: not available
URL: <http://lists.opendtect.org/pipermail/developers/attachments/20110223/60596bc1/attachment-0001.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Jurassic_2Axis.png
Type: image/png
Size: 9933 bytes
Desc: not available
URL: <http://lists.opendtect.org/pipermail/developers/attachments/20110223/60596bc1/attachment-0002.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Jurassic_2Axis_annotinside.png
Type: image/png
Size: 8904 bytes
Desc: not available
URL: <http://lists.opendtect.org/pipermail/developers/attachments/20110223/60596bc1/attachment-0003.png>


More information about the Developers mailing list