Text position scaling - c++

I'm now using QGraphicsView and QGraphicsScene for showing some charts. Depending on values of that charts (they are histograms) I change the scale. I also draw some text (they are derived from QGraphicsItem) for showing their values like this
But I don't scale texts like charts, so it brings to a problem. If I don't scale texts, so I get it's bounding rect's real coordinates. I want to get scale of y axis for drawing texts in right positions.
So my question how may I get the scale in QGraphicsItem or in QGraphicsScene.
Thank you in advance.

If you implement your own function for scaling, then there is not a direct way for getting scale in QGraphicsItem. You can make a static variables in QGraphicsView (where you count scale) for scales and static functions for getting them.

Well, there is a solution for that. In QGraphicsScene you can get transformation matrix like this
QTransform matrix = views().at(0)->transform();
views() actually returns a QList of QGraphicsViews. After getting matrix for getting scale (for example vertical) you can do this
qreal verticalScale = matrix.m22();
Difference for getting scale in QGrapcsItem is just
QTransform matrix = scene()->views().at(0)->transform();
And the rest is same.

Related

Qt 3D scatter graph: how can I adjust the scale of an axis?

I'm currently developing a Qt desktop application using the Q3DScatter class. I'm inspecting Qt's 3D Scatter example project and I tried to modify the data item set to plot my own data. The data is plotted except that one axis is not well scaled and my 3D plot looks really messy. I'm looking for a way to adjust this axis. I've tried to change the range and the segment count of the axis, I even tried to set the "AutoAdjustRange" of the axis to true, but nothing seemed to solve the problem.
Would really appreciate some help.
PS: Here's a screen capture of what my 3D scatter graph looks like (the "messy" axis is shown with the red arrow)
I figured this out by creating a CustomFormatter class by subclassing QValue3DAxisFormatter and reimplementing some of its functions (I followed this tutorial). Then I set up my axis formatter to my custom formatter (m_graph->axisZ()->setFormatter(cf);).
Subclassing QValue3DAxisFormatter will not work: it determines where ticks and labels are placed, but not how large the axex actually are.
To do that, you can set the (horizontal) aspect ratio, that is a property of Q3DScatter. The following settings will make the data into a cube volume:
plot->setAspectRatio(1.0);
plot->setHorizontalAspectRatio(1.0);

Indicate angle in QTableView - possible approaches

I want to indicate an angle (0-359degrees) in a QTableView column as an arrow pointing in that very direction and wonder what would be the best approach:
Should I use a QPixmap and rotate the image accordingly?
Should I use the SVG approach and draw the image as SVG, then display it as QPixmap?
Should I draw that column directly with QPainter (docu)?
Anything completely different?
The approach has be reasonable fast, as the table view might contain 1-250 rows, and then I would have to draw as many angle icons. As 1 degree can hardly be distinguished I was thinking of creating 120 icons (as per 3 degrees) in memory and then just fetch the closest one.

Applying a transformation to a set in Raphael.js

Using Raphael 2.0, I am trying to apply a transform to a set of objects in a way that is relative to all of the objects in the set. However, the effect I am getting is that the transform is applied to each item individually, irrespective of the other objects in the set.
For example: http://jsfiddle.net/tim_iles/VCca9/8/ - if you now uncomment the last line and run the code, each circle is scaled to 0.5x. The actual effect I am trying to achieve would be to scale the whole set of circles, so their relative distances are also scaled, which should put all four of them inside the bounding box of the white square.
Is there a way to achieve this using Raphael's built in tools?
When you scale, the first parameter is the X-scale. If you provide no other parameters, it will use that as the Y-scale, and scale around the center of the object.
When you scaled the rectangle, it scaled around the center of the rectangle. If you want the circles to scale around that point as well, rather than their centers, you should provide that point.
So the last line could be set.transform("s0.5,0.5,100,100"); (100,100 being the center of the rectangle you scaled)
At least, I think this is what you're asking for.

Qt4: QGraphicsScene/View and custom transformation method?

I know that it is possible to use affine transformations with Qt. But is it also possible to set a complete custom global transformation method?
Use case: Drawing projected geographic points (lat, long) or retrieve mouse events etc. in geographic corrdinates (in the context of a QGraphicsScene/View).
At the moment I use it like that (little bit pseudo code):
MyPoint pt = myProjection(geographicPoint);
QPoint(pt.x, pt.y);
// or, to make it shorter, but essentially it's the same
QPoint p = myProjection(geoPoint);
geoPoint = myBackProjection(mouseEvent.getPoint());
And I'd like to do "register" my transformation methods somewhere so that the QGraphicsView (or whoever is responsible) internally uses these methods before it draws something on the screen.
Or does that neither make sense (because it would introduce problems where I don't expect them, e.g. in calculating distances) nor is it possible?
QGraphicsView uses a QTransform matrix, which is a 3x3 matrix. Therefore you can only do linear transformations. In Qt5/QtQuick or with QtQuick3d you may be able to achieve this with a QML ShaderProgram.
In "pure" Qt4 you would have to derive your own custom class from QGraphicsView, or QAbstractScrollArea or QGraphicsScene and override the paint methods.
A good approach would be to encapsulate this transform in your QGraphicsItem shape() method. Suppose you have a point defined as a pair of latitude and longitude, it would store pairs of lat lon, but its shape method would return projected values (usually in pixel equivalents).
If you feel like it, you could even subclass QPoint to make it geographically aware, thus creating it with latlon, but exposing projected values in its x, y properties.

Plotting a graph with given double coordinates

I receive an array of coordinates (double coordinates with -infinity < x < +infinity and 0 <= y <= 10) and want to draw a polyline using those points. I want the graph to always begin on the left border of my image, and end at the right. The bottom border of my image always represents a 0 y-value, and the top border always a 10 y-value. The width and height of the image that is created are decided by the user at runtime.
I want to realize this using Qt, and QImage in combination with QPainter seem to be my primary weapons of choice. The problem I am currently trying to solve is:
How to convert my coordinates to pixels in my image?
The y-values seem to be fairly simple, since I know the minimum and maximum of the graph beforehand, but I am struggling with the x-values. My approach so far is to find the min- and max-x-value and scale each point respectively.
Is there a more native approach?
Since one set of coordinates serves for several images with different widths and heights, I wondered whether a vector graphic (svg) may be a more suitable approach, but I couldn't find material on creating svg-files within Qt yet, just working with existing files. I would be looking for something comparable to the Windows metafiles.
Is there a close match to metafiles in Qt?
QGraphicsScene may help in this case. You plot the graph with either addPolygon() or addPath(). Then render the scene into a bitmap with QGraphicsScene::render()
The sceneRect will automatically grow as you add items to it. At the end of the "plotting" you will get the final size/bounds of the graph. Create a QImage and use it as the painter back store to render the scene.
QGraphicsScene also allows you to manipulate the transformation matrix to fit the orientation and scale to your need.
Another alternative to use QtOpenGL to render your 2d graph to a openGL context. No conversion/scaling of coordinates is required. Once you get past the opengl basics you can pick appropriate viewPort / eye parameters to achieve any zoom/pan level.