[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