PDA

View Full Version : QMatrix vs QWMatrix - porting Qt3 to Qt4



bitChanger
10th April 2006, 14:38
void test()
{
QRect selection(5,5,2,2);

#if QT3
QWMatrix m;
m.scale(2,5);
m.invert();
#else
QMatrix m;
m.scale(2,5);
m.inverted();
#endif

QRect r = m.mapRect(selection);
}


Qt 3.3.2
QRect r comes out as:
x1=10
y1=25
x2=12
y2=30

Qt 4.1.2
QRect r comes out as:
x1=10
y1=25
x2=13
y2=34


I'm converting an application from 3.3.2 to 4.1.2 and this seems to be where my problem is coming from.

Does anyone know why this is different and/or how i can fix it.
Thank you. :confused:

jacek
10th April 2006, 15:42
IMO the real anwer should be:
x1=10
y1=25
x2=14
y2=35

So Qt 4 is more accurate. The difference probably comes from some round offs.

PS. I hope you realize that QMatrix::inverted() and QWMatrix::invert() don't change the original matrix only return the inverted matrix.

bitChanger
10th April 2006, 18:42
void test()
{
QRect selection(10, 10, 20, 20);

#if QT3
QWMatrix m;
m.scale(128/350, 128/350);
m = m.invert();
#else
QMatrix m;
m.scale(128/350, 128/350);
m = m.inverted();
#endif

QRect r = m.mapRect(selection);
bool b = true;
}


Thanks, I did know that and forgot to use it in the example I posted.

Tell me if I'm wrong here:

If an image were 128 x 128 and displayed on the screen as 350 x 350 and a user selects a region from the 350 x 350 say QRect(10, 10, 20, 20) then the above QRect r would be the rectangle corresponding to the original 128 x 128 image. correct?

If this is the case, the Qt3 and Qt4 values for r are very different.

jacek
10th April 2006, 19:00
If an image were 128 x 128 and displayed on the screen as 350 x 350 and a user selects a region from the 350 x 350 say QRect(10, 10, 20, 20) then the above QRect r would be the rectangle corresponding to the original 128 x 128 image. correct?
IMO the above code will enlarge the rectangle, i.e. map region from 128x128 image to a region on 350x350 image.


If this is the case, the Qt3 and Qt4 values for r are very different.
As I wrote before, it might be caused by rounding errors. From the example in the first post, it looks like Qt4 is more accurate.

bitChanger
10th April 2006, 19:47
I'm not sure I'm explaining this enough.

Let's say I have a QPixmap that is 128 x 128 and I use the above code without the (invert) stuff to transform the image into a larger 350 x 350 QPixmap to display on screen.

Now I allow someone to select a region from the on screen image of QRect(10, 10, 20, 20).
This selection region corresponds to a region from the 350 x 350 enlarged image.

Now I would like to find out what the QRect region of the original 128 x 128 image would be.
So I perform the above with the (invert) stuff and the result QRect (r) should be just that.

The values of r, very more than rounding, they are REALLY different.

wysota
10th April 2006, 19:52
Just in case you forgotten...

Remember that

m.scale(128/350, 128/350);
is equal to

m.scale(0, 0);

jacek
10th April 2006, 19:59
So I perform the above with the (invert) stuff and the result QRect (r) should be just that.

QWMatrix m;
m.scale(128/350, 128/350); // scale is < 1, so it should make the rectangle smaller
m = m.invert(); // inverse matrix -> it should enlarge the rectangle now


The values of r very more than rounding they are REALLY different.
It depends when those errors were introduced. Could you provide some example dimensions?

bitChanger
10th April 2006, 20:04
void test()
{
QRect selection(10, 10, 20, 20);

#if QT3
QWMatrix m;
m.scale(128.0/350.0, 128.0/350.0);
m = m.invert();
#else
QMatrix m;
m.scale(128.0/350.0, 128.0/350.0);
m = m.inverted();
#endif

QRect r = m.mapRect(selection);
}


If you just run this function using 3.3.2 and then 4.1.2 you can see that the values for variable r differ greatly.
Is this not enough code to see the problem?

jacek
10th April 2006, 20:25
Is this not enough code to see the problem?
I wouldn't call it a minimal, compilable example, but I did run it under Qt 3.3.6 and Qt 4.1.2 and got this:

. x y w h
Qt3 27 27 53 53
Qt4 27 27 55 55
It's not a great difference. If you do the calculations by hand, you will see that Qt4's result is closer to the right answer.



QWMatrix m;
m.scale(128/350, 128/350); // scale is < 1, so it should make the rectangle smaller
m = m.invert(); // inverse matrix -> it should enlarge the rectangle now
On second thought, it just does what it should do. ;)

jacek
10th April 2006, 21:15
On second thought, it just does what it should do.
Or maybe not... If you have a bigger pixmap and some rectangle on it, than on a smaller pixmap that rectangle should be smaller. While your matrix will make it bigger.

bitChanger
11th April 2006, 15:20
I still think I have a QMatrix vs QWMatrix problem here, but I'm at a loss.
Here is a complete program that demonstrates my issue.

Compile using Qt 3 to see how the application is supposed to work.
This is simply an image with a rectangle in the middle for a reference point.
While holding down the mouse button, drag the image.
In Qt 3, the image point stays under the cursor and works as expected.

Then compile in Qt 4.
The image moves in the opposite direction and at an increased speed.

Thank you for any help on this issue.

jacek
11th April 2006, 16:02
It seems that matrices are correct. With both Qt3 and Qt4 I got the same values.

IMO the problem is here:
// determine direction of x move
int x = 0;
if (_rubberBandRect.width() <= 0)
x = _movedRect.x()+selectRect.width()-1;
else
x = _movedRect.x()-selectRect.width()+1;

// determine direction of y move
int y = 0;
if (_rubberBandRect.height() <= 0)
y = _movedRect.y()+selectRect.height()-1;
else
y = _movedRect.y()-selectRect.height()+1;

qDebug( "x=%d y=%d", x, y );I'm not sure what is wrong yet, but probably width() and height() are always positive. Edit: no, they aren't.

bitChanger
12th April 2006, 17:30
I need to find a solution to this problem and have yet to come up with even a workaround.

So, I've submitted a support request to Trolltech.

If someone has a solution for this, please post it.
I will post the response from support when I hear back from them.

:(

bitChanger
24th April 2006, 18:27
Here's the solution that I used for this problem.

The problem here was scaling the area instead of points
using QRect. In Qt 3 you could use set transformation on points and
then you could transform the points to your desired scaling factor,
whereas when you scale areas in Qt 4 it will be scaled twice as much as
thus the effect that pixmap moves faster then expected.

The best approach here is to use QPoint and then move the position of
the pixmap according to the movement of the position of the mouse.

Thanks to:
Amrit Pal Singh, Support Engineer
for this solution.