[vtkusers] Positioning titles within vtkAxis

Frese Daniel Dr. frese at heidenhain.de
Tue Dec 7 10:46:30 EST 2010


Hi Eric,

here it is, or at least the relevant part.
I'm sorry it's a bit lengthy, even though I omitted some stuff around. I did this
in the Visual Studio and created a WinForms control (which by the way worked nicely),
so "this" points to an instance of the form in order to get the dimensions of the output window.
The double locdata array and the dimensions of the image etc. are stored in private elements of the
WinForm control.

This is basically my first effort with these routines in order to try out things,
so I wouldn't be surprised if things can be done in a better way. I put the axes
in a different scene in order to work around some strange things when using vtk 5.6.1,
but now I am using the latest git stuff (or nearly, I downloaded yesterday afternoon)
and there is no need any more for any workarounds (vtk & life has become better :)).
Placing the axes into the view's scene does not change their behavior however (I tested).

Thank you very much for your interest in this !
Daniel


      void vtk2dDataControl::VTKRender() {
            double *minmax;                          // min and max within the data
            int nColors = 1000;                      // number of colors
            double colorposition[2];           // holds the position of the colorbar
            int windowsizeX;                   // X window size - to be supplied externally
            int windowsizeY;                   // Y window size - to be supplied externally
            int imageextent[6];                      // extent of the imgage
            int barwidth = 120;                      // FIXME, X space for colorbar
            int labelnum;                            // number of labels - a helper var
            int upperborder = 20;              // border space between upper image edge and window edge
            int rightborder = 40;              // space between image and colorbar
            int i;


            // calculate the effective width of the window, that can be used for the display
            windowsizeX = this->Width;
            windowsizeY = this->Height;
            effectiveSizeX = windowsizeX  - imageposition[0] - barwidth - rightborder;
            effectiveSizeY = windowsizeY  - imageposition[1] - upperborder;

            // import the data into the vtkimagedata structure
            VTK_CREATE(vtkImageImport, import);
            import->SetImportVoidPointer(localdata);
            import->SetDataScalarTypeToDouble();
            import->SetWholeExtent(0,locdimX-1,0,locdimY-1,0,0);
            import->SetDataExtent(0,locdimX-1,0,locdimY-1,0,0);
            import->Update(); // call update for getting the right minmax values below...
            minmax = import->GetOutput()->GetScalarRange();

            // resample the image in order to fit into the given window geometry
            VTK_CREATE(vtkImageResample, resample);
            resample->SetInputConnection(import->GetOutputPort());
            resample->SetDimensionality(2);
            resample->SetAxisMagnificationFactor(0, ((double) effectiveSizeX) / locdimX);
            resample->SetAxisMagnificationFactor(1, ((double) effectiveSizeY) / locdimY);

            // add a colorbar
            VTK_CREATE(vtkLookupTable, lookupTable);
            VTK_CREATE(vtkScalarBarActor, colorbar);
            lookupTable->SetNumberOfColors(nColors);
            lookupTable->SetTableRange(minmax);
            //lookupTable->SetSaturationRange(0, 1);
            //lookupTable->SetHueRange(0, 1);
            lookupTable->SetRampToLinear();
            lookupTable->Build();

            // Filter to convert the grey image into an RGB output
            VTK_CREATE(vtkImageMapToColors, rgb);
            rgb->SetInputConnection(resample->GetOutputPort());
            rgb->SetLookupTable(lookupTable);
            rgb->SetOutputFormatToRGBA();
            rgb->Update();

            // Set up a 2D context view - this is the basic 2D API structure
            if (view != NULL) view->Delete();
            view = vtkContextView::New();
            view->GetRenderWindow()->SetSize(windowsizeX, windowsizeY);

            // register the image into the view and position it
            VTK_CREATE(vtkImageItem, item);
            view->GetScene()->AddItem(item);
            item->SetImage(vtkImageData::SafeDownCast(rgb->GetOutput()));
            item->GetImage()->GetExtent(imageextent);
            item->SetPosition(imageposition[0], imageposition[1]);

            // create a new scene for axes and colorbar; also create actor for axes
            VTK_CREATE(vtkContextScene, axesscene);
            VTK_CREATE(vtkContextActor, axesactor);

            // Starting from here there is mainly stuff for the axes...
            // X Axis
            VTK_CREATE(vtkAxis, Xaxis);
            Xaxis->SetBehavior(1); // rescalable
            // now define location of axis by giving two points
            Xaxis->SetPoint1(imageposition[0], imageposition[1]);
            Xaxis->SetPoint2((int) imageextent[1]-imageextent[0] + imageposition[0], imageposition[1]);
            Xaxis->SetPosition(vtkAxis::BOTTOM);     // this is an axis at the bottom
            Xaxis->SetTitle(XAxisName->c_str());     // title of axis
            Xaxis->GetPen()->SetWidth(2);            // lines are 2 pixel wide
            Xaxis->SetMinimum(locXmin);                    // set Xmin and ...
            Xaxis->SetMaximum(locXmax);                    // ... Xmax for later autoscale()
            Xaxis->SetPrecision(2);                        // two figures after period
            Xaxis->SetNotation(2);                         // "mixed" (i.e. standard or scientific)
            Xaxis->AutoScale();                                  // perform autoscale for ticks
            Xaxis->Update();                               // do it !
            Xaxis->SetMinimum(locXmin);                    // got to reste min/max values afetr autoscale
            Xaxis->SetMaximum(locXmax);
            Xaxis->GetGridPen()->SetColor(0,0,0,1); // write in black
            Xaxis->SetLabelsVisible(true);                 // show it all...
            Xaxis->SetVisible(true);
            //Xaxis->GetTitleProperties()->SetLineOffset(10);
            Xaxis->Update();                               // do it !
            axesscene->AddItem(Xaxis);                     // add to scene

            // Y Axis
            // everything completely analogous to X Axis - so no need for comments here
            VTK_CREATE(vtkAxis, Yaxis);
            Yaxis->SetBehavior(1);
            Yaxis->SetPoint1(imageposition[0], imageposition[1]);
            Yaxis->SetPoint2(imageposition[0], (int) imageextent[3]-imageextent[2] + imageposition[1]);
            Yaxis->SetPosition(vtkAxis::LEFT);
            Yaxis->SetTitle(YAxisName->c_str());
            Yaxis->GetPen()->SetWidth(2);
            Yaxis->SetMinimum(locYmin);
            Yaxis->SetMaximum(locYmax);
            Yaxis->AutoScale();
            Yaxis->Update();
            Yaxis->SetMinimum(locYmin);
            Yaxis->SetMaximum(locYmax);
            Yaxis->GetGridPen()->SetColor(0,0,0,1);
            Yaxis->GetTitleProperties()->SetOrientation(90.0);
            Yaxis->SetLabelsVisible(true);
            Yaxis->SetVisible(true);
            Yaxis->Update();
            axesscene->AddItem(Yaxis);

            // prepare axes on top and on right w/o labels (just ticks)
            labelnum = Xaxis->GetTickPositions()->GetDataSize();
            VTK_CREATE(vtkStringArray, Xemptylabels);
            Xemptylabels->SetNumberOfValues(labelnum);
            for (i=0; i<labelnum; i++) {
                  Xemptylabels->SetValue(i, "");
            }
            labelnum = Yaxis->GetTickPositions()->GetDataSize();
            VTK_CREATE(vtkStringArray, Yemptylabels);
            Yemptylabels->SetNumberOfValues(labelnum);
            for (i=0; i<labelnum; i++) {
                  Yemptylabels->SetValue(i, "");
            }

            // create axis on top of image
            VTK_CREATE(vtkAxis, XaxisUpper);
            XaxisUpper->SetBehavior(1);
            XaxisUpper->SetPoint1(imageposition[0], imageposition[1] + (int) (imageextent[3]-imageextent[2]));
            XaxisUpper->SetPoint2((int) imageextent[1]-imageextent[0] + imageposition[0], imageposition[1] + (int) (imageextent[3]-imageextent[2]));
            XaxisUpper->SetPosition(vtkAxis::TOP);
            XaxisUpper->GetPen()->SetWidth(2);
            XaxisUpper->SetMinimum(locXmin);
            XaxisUpper->SetMaximum(locXmax);
            // want to have same number of ticks as X axis ...
            XaxisUpper->SetNumberOfTicks(Xaxis->GetTickPositions()->GetDataSize());
            XaxisUpper->GetGridPen()->SetColor(0,0,0,1);
            // ... and same positions of ticks as X axis ...
            XaxisUpper->SetTickPositions(Xaxis->GetTickPositions());
            // .. but no labels this time.
            XaxisUpper->SetTickLabels(Xemptylabels);
            XaxisUpper->SetVisible(true);
            XaxisUpper->Update();
            axesscene->AddItem(XaxisUpper);

            // create axis on the right of top image - analogous to XaxisUpper above
            VTK_CREATE(vtkAxis, YaxisRight);
            YaxisRight->SetBehavior(1);
            YaxisRight->SetPoint1(imageposition[0] + (int) imageextent[1]-imageextent[0], imageposition[1]);
            YaxisRight->SetPoint2(imageposition[0] + (int) imageextent[1]-imageextent[0], (int) imageextent[3]-imageextent[2] + imageposition[1]);
            YaxisRight->SetPosition(vtkAxis::RIGHT);
            YaxisRight->GetPen()->SetWidth(2);
            YaxisRight->SetMinimum(locYmin);
            YaxisRight->SetMaximum(locYmax);
            YaxisRight->SetNumberOfTicks(Yaxis->GetTickPositions()->GetDataSize());
            YaxisRight->GetGridPen()->SetColor(0,0,0,1);
            YaxisRight->SetTickPositions(Yaxis->GetTickPositions());
            YaxisRight->SetTickLabels(Yemptylabels);
            YaxisRight->SetVisible(true);
            YaxisRight->Update();
            axesscene->AddItem(YaxisRight);

            // now format and position colorbar
            colorbar->SetLookupTable(lookupTable);
            colorposition[0] = 1.0 - (1.0* barwidth)/windowsizeX;
            colorposition[1] = (1.0* imageposition[1])/windowsizeY;
            colorbar->SetWidth(0.5);
            colorbar->SetHeight(1.0 - 2* colorposition[1]);
            colorbar->SetPosition(colorposition);
            colorbar->SetLabelFormat("%1.2E");
            colorbar->PickableOff();
            colorbar->SetMaximumWidthInPixels(barwidth);
            colorbar->VisibilityOn();
            colorbar->GetLabelTextProperty()->SetShadow(0);
            colorbar->GetLabelTextProperty()->SetColor(0,0,0);

            // register the axescene to the axesactor, which and point to the renderer
            axesactor->SetScene(axesscene);
            view->GetRenderer()->AddActor(axesactor);

            // register the colorbar as an actor
            view->GetRenderer()->AddActor(colorbar);

            RenderWindow = view->GetRenderWindow();
            RenderWindow->SetWindowId((HWND)Handle.ToInt64());

            // set Interactor Style to RubberBand
            VTK_CREATE(vtkInteractorStyleRubberBand2D, RubberBandStyle);
            RubberBandStyle->SetRenderOnMouseMove(false);
            VTK_CREATE(vtkCallbackCommand, SelectionChangedCallback);
            SelectionChangedCallback->SetCallback(SelectionChangedCallbackFunction);
            RubberBandStyle->AddObserver(vtkCommand::SelectionChangedEvent,SelectionChangedCallback);
            RenderWindow->SetInteractor(WinInteractor);
            RenderWindow->SetDoubleBuffer(1);
            WinInteractor->SetInteractorStyle(RubberBandStyle);
            WinInteractor->Initialize();
      }

Von: Eric E. Monson [mailto:emonson at cs.duke.edu]
Gesendet: Dienstag, 7. Dezember 2010 16:13
An: Frese Daniel Dr.
Cc: Marcus D. Hanwell; vtkusers at vtk.org
Betreff: Re: AW: [vtkusers] Positioning titles within vtkAxis

Hey Daniel,

Yes, this shouldn't be happening. Would you be able to send the section of your code that generates this chart? I'm curious how you're implementing the combination of ImageItem and axes. Maybe there is another way of accomplishing the same thing that wouldn't cause the overlap, or it might at least help us diagnose why the label placement routine isn't dealing with your case correctly.

Also, just to be clear, was this generated with the current development (git) version, or with 5.6.1?

Thanks,
-Eric


On Dec 7, 2010, at 8:29 AM, Frese Daniel Dr. wrote:


Hello Eric, Marcus,

before I explain my problem once more I just want to add that I find the charts functionality already quite useful.
As I said I just updated my vtk stuff and I can imagine it must have been quite some work to get to this point.

I appended a screenshot illustrating the problem. Since I don't know how this appears on the mail list I just describe briefly.
I have a scene with a vtkImageItem to show some 2D matrix data. Around the image I have axes (vtkAxis objects) with
appropriate ticks, tick labels and axes titles. The problem is that the axes titles overlap with the tick labels. E.g. for the
case of the X axis , the title should be lower such that it does not touch the labels, but there does not seem to
be a way to do that as of now.

A possible low level solution would be a way to specify some vertical (horizontal axis case) or some horizontal (vertical axis case) offset
for the position of the titles (in pixel or font size units).
In principle of course the vtkAxis object could calculate such an offset by itself, since it has access to both
the labels' and the titles' text properties.

What do you think ?
Daniel

Von: Eric E. Monson [mailto:emonson at cs.duke.edu]
Gesendet: Dienstag, 7. Dezember 2010 13:54
An: Frese Daniel Dr.
Cc: vtkusers at vtk.org<mailto:vtkusers at vtk.org>
Betreff: Re: [vtkusers] Positioning titles within vtkAxis

Hey Daniel,

It does seem like SetLineOffset should do something like what you want, but I think they way the label text is applied with VerticalJustification probably nullifies any line offset setting. Line spacing shouldn't matter for a single line of text.

So, the adjustments you want are just not implemented. Marcus, the developer, has worked hard to get the labels right, though, so if you have a use case where the labels are running into the axis ticks maybe you should describe the situation and send a screen shot - it may be something that needs fixing.

You're right that the charts are still under development, but some of the core functionality has settled down, and as you said, the current implementation is better than the 5.6.1 version.

-Eric

------------------------------------------------------
Eric E Monson
Duke Visualization Technology Group




On Dec 7, 2010, at 3:35 AM, Frese Daniel Dr. wrote:



Hi all,

I have a problem positioning an axis title relative to its vtkAxis object.
Basically, if I draw a horizontal  X-axis, the assigned title is written such that it overlapps with the
tick labels. Reading through the docs, I got the impression that I should be able to introduce a
vertical offset between the drawn axis and the titel by using either a call to
Xaxis->GetTitleProperties()->SetLineOffset(offset_in_pixel)
or by
Xaxis->GetTitleProperties()->SetLineSpacing(scale_factor).
But neither call seems to have any effect.
Moving from 5.6.1 to the latest vtk git source tree I noticed that the chart stuff seems to have
improved greatly (most functions a joy to use !), but it still seems to be a work in progress.
So am doing something stupid and do I miss something here or is this feature just not
implemented yet ?

Daniel

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.vtk.org/pipermail/vtkusers/attachments/20101207/04a56ecb/attachment.htm>
-------------- next part --------------
</PRE><p>
------------------------------------------------------------------------------------------------------ <br>
Registergericht: Traunstein / Registry Court: HRB 275 - Sitz / Head Office: Traunreut <br>
Aufsichtsratsvorsitzender / Chairman of Supervisory Board: Rainer Burkhard <br>
Gesch?ftsf?hrung / Management Board: Thomas Sesselmann (Vorsitzender / Chairman),<br>
Michael Grimm, Matthias Fauser, Sebastian Tondorf<br><br>
<a href="http://www.heidenhain.de/disclaimer" target="_blank">E-Mail Haftungsausschluss / E-Mail Disclaimer</a><br><pre>


More information about the vtkusers mailing list