PDA

View Full Version : Data Visualization GraphicsView/Scene/Item Design



vgrunert
8th April 2015, 10:35
Hi,

I am working on a custom data visualization program.

My question is how to display/map/transform the data from a model to the view/scene in order to:

1. Get correct results
2. Minimize computational effort

So far, in order to draw a scatterplot, I came up with two different approaches:

Here is a short pseudocode:



//initialize data
A[5], B[5]
i=0

//fill vectors with randon data
while (i < 5)
A[i] = rand(10);
B[i] = rand(10);
i++;
myGraphicsScene->addRect(A[i], -B[i], 5, 5);

//set scene
myGraphcisView->setScene(myGraphicsscene)


Since the data is not scaled to the scene coordinates there are two different ways to plot the data (from my current understanding):

1. Transform/multiply the data with some factor to expess the values in terms of scene coordinates
2. Fit the scene to the data (myScene->sceneRect(0,-max(B), max(A), max(B)) and then fit the scene to the graphicsview using myview -> fitInView(myscene)

Now from your experience, which approach would you recommend?
Are there another way to approach the problem?

Thank you many times,

Vincent

d_stranz
8th April 2015, 16:38
I have used the Graphics / View architecture to create a data graphics widget that plots scatter, line, and other scientific data plots. I used these design rules:

- all data (numerical values) are in their natural dimensions (for example, a temperature is in degrees C) in the model.
- the QGraphicsScene is dimensioned using these values (world coordinates). (So the scene might go from 0 - 1000 C on the x axis, and whatever on the y axis)
- each dot in a scatterplot, for example, has a *size* in pixels and a position in *world* coordinates, and is a separate QGraphicsItem instance. These instances are set to ignore transformations (because you generally don't want the dots to get bigger when you zoom in)
- the QGraphicsView sets a transformation to scale the scene (or the part of the scene, if zoomed in) to match its size in pixels.

In my case, my plot widget is a composite QWidget, made up of QLabel instances (for titles, etc.), some widgets borrowed from Qwt for the axes, and a central "canvas" which is the QGraphicsView. Using a grid layout with margins set to zero allows all of these sub-widgets to be positioned automatically inside of whatever widget contains the plot widget.

The data source is driven by a QAbstractItemModel. An adapter class allows selection of two columns from the model to be used as x and y data values, and signals and slots are used to connect changes in the model to updates in the plot. The adapter class is smart enough that it can tell the view the range of the datum points in each column so the view can set the transform appropriately. I also have a three-column adapter which allows use of the third column to control properties of the individual dots (eg. scaling by the third column value, or using the third column value to select a color from a heatmap gradient).

The reason you *don't* want dots to scale when zoomed is that if they do, you can never separate two or more overlapping dots by zooming. The dots will remain in the same world locations and would just grow, continuing to cover one another up. If the dots *don't* scale when zooming, then at some level of zoom, the dots will move apart from each other as their screen positions change but their sizes don't.

vgrunert
8th April 2015, 19:58
Thank you for the reply. Just one follow up question: is there a reason that you chose to add the label etc into the QWidget and not into to graphicsscene?

d_stranz
10th April 2015, 16:31
is there a reason that you chose to add the label etc into the QWidget and not into to graphicsscene?

The labels I add (using QLabel) are the plot title and other things that are outside of the canvas region. They have no relationship to the data being displayed - they are just decorations added by the user to give the plot a title or a footnote. ("My Beautiful and Informative Plot")

Labels for individual points in the canvas area are added as part of the scene. These have the same scaling issues as the dots - you generally don't want the point labels to grow as the plot is zoomed in. In addition, it is very awkward to dimension the point labels in world coordinates (when the data range is 0 - 1000 degrees C by 0 - 100 kPa, exactly what world coordinate size should you pick for a 10 pt label for a dot at 100 degrees C and 10 kPa anyway?), so I fake this by creating the dot labels with pixel coordinates and positioning them in world coordinates. When the plot is zoomed in, I scale the text so that it remains the same size. Eg. when the plot is zoomed in (a smaller data range per pixel) then text is zoomed inversely so that its pixel size remains constant.