PDA

View Full Version : QPainter, setWindow, setViewport question



Micawber
2nd September 2007, 21:24
Hello,

I am confused trying to understand the relationship and effects of using the setWindow and setViewport calls in the QPainter class.

I think I understand the setWindow part. From what I can gather, setWindow allows me to define a coordinate system that will be device independent and I can draw things using that coordinate system and it gets mapped to the device that I'm painting on.

The setViewport call is what is tripping me up. In the examples that use setViewport, they all define a viewport that is smaller than the device that I'm painting on.

Is it possible (or better yet advisable?) to define a viewport that is larger than the device I'm painting on?

Is it possible (or better yet advisable?) to define a viewport that is positioned outside of the device I'm painting on?

What I'm trying to do is graph some data. I define the window as using...

mypainter.setWindow( -30000, -30000, 60000, 60000);

I then set the scale so that the data is reasonably large but what I need is a way to ensure that a certain data point is drawn on (or as close to) a particular point in the device such as 3/4 of the way across and 1/3 of the way down.

Perhaps I am using setViewport incorrectly? I'm sure its just that I can't see the forest for the trees and the solution will be trivial but for the life of me I can't figure it out. :confused:

Any help would be appreciated.

marcel
2nd September 2007, 21:35
All conversions between logical and device spaces are done with the painters matrix.
Usually you don't need to alter the device space. You want to make drawing easier for you so you alter the user space in a way that is more convenient to your purpose.


Is it possible (or better yet advisable?) to define a viewport that is larger than the device I'm painting on?
Yes, it is possible to do that. The mapping to device space will be done with a scale matrix.
I don't know about advisable. What's wrong with an 1:1 scale? Is the output device too big?



Is it possible (or better yet advisable?) to define a viewport that is positioned outside of the device I'm painting on?
Well, what would that solve?

Have you read this:http://doc.trolltech.com/4.3/coordsys.html? Especially the Window-Viewport conversion section.

Regards

Micawber
2nd September 2007, 22:26
Yes, it is possible to do that. The mapping to device space will be done with a scale matrix.
I don't know about advisable. What's wrong with an 1:1 scale? Is the output device too big?


The data range I'm plotting is too large for a 1:1 scale map to a widget 350 pixels wide.



Have you read this:http://doc.trolltech.com/4.3/coordsys.html? Especially the Window-Viewport conversion section.


Yes, but as you can see, I need to go back and re-read it.

I have been reading in another book and it said to use setViewport to carve up a device so that you can restrict the painting to the area within the viewport. So I'll assume that the values used in the setViewport call are in device coordinates. If these are true, then you are right, I probably don't need to dork around with setViewport.

I want to nail a (calculated from my data) point in my curve data to a specific spot on the device I'm painting on. This can be done by using translation and scaling. I see now that I need the ability to map a point in device coordinates, to a point in user coordinates to use in a painter.translate call. Any way to do that with a painter like in a QGraphicsView?

Thanks for the reply.

marcel
2nd September 2007, 22:45
The data range I'm plotting is too large for a 1:1 scale map to a widget 350 pixels wide.
...
I want to nail a (calculated from my data) point in my curve data to a specific spot on the device I'm painting on. This can be done by using translation and scaling. I see now that I need the ability to map a point in device coordinates, to a point in user coordinates to use in a painter.translate call. Any way to do that with a painter like in a QGraphicsView?
Then you need to scale the user space to an order of magnitude appropriate to the requirements of your data set.
So t6he device space should be the reference here. All you need is scaling. The translations should remain linear.
Theoretically user space corner (0,0) should map to device space (0,0) but device space (350, 350) should map to user space (350*scaleFactorX, 350*scaleFactorY).

For this you need to use setWindow() appropriately and compute the correct world matrix so that user->device transformations are done correctly.
As I see it you only need to scale an identity matrix with (1.0/scaleFactorX, 1.0/scaleFactorY).

Usually, the best way is to have the user space as wide as your data set, to make a coordinate in the data set map to the same coordinate in user space. So point (7,100) should be painted at (7,100) in user space. So, given a data set(2-dimensional), take the point that has both x and y minimal. That will be the top-left corner in the user space.
Similarly, the point with the maximum x and y coords should be the bottom right corner in user space. This means a 1:1 relation between the data set and user space.

If xmin, ymin are not (0,0) you could further translate user space top make drawing relative top (0,0), but that's easy.

Regards

Micawber
3rd September 2007, 19:33
Thanks Marcel for all your help. I finally got this working by obtaining the QMatrix from the painter, inverting it and then using the map() method to convert the device coordinates to my user coordinates. I then used these user coordinates to translate my curve data to that location. Now my fixed point in the curve data always appears in the same spot on the screen. Works well even when I change the scale (zoom in and out). :D