0
votes

I have built a small custom qml item that is used as a selection area (something like the QRubberBand component provided in Qt Widgets). The item also give the ability to user to resize the content of the selection, so by grabbing the bottom corner of the selection rectangle it is possible to drag to enlarge the content. After the user has done resizing I would like to compute the QTransform matrix of the transformation. QTransform provides a convenient QTransform::scale method to get a scale transformation matrix (which I can use by comparing the width and height ratio with the previous size of the selection). The problem is that QTransform::scale assumes that the center point of the transformation is the center of the object, but I would like my transformation origin to be the top left of the selection (since the user is dragging from the bottom-right).

So for example, if I have the following code:

QRectF selectionRect = QRectF(QPointF(10,10), QPointF(200,100));

// let's resize the rectangle by changing its bottom-right corner
auto newSelectionRect = selectionRect;
newSelectionRect.setBottomRight(QPointF(250, 120));

QTransform t;
t.scale(newSelectionRect.width()/selectionRect.width(), newSelectionRect.height()/selectionRect.height());

The problem here is that if I apply the transformation t to my original selectionRect I don't get my new rectangle newSelectionRect back, but I get the following:

QRectF selectionRect = QRectF(QPointF(10,10)*sx, QPointF(200,100)*sy);

where sx and sy are the scale factors of the transform. I would like a way to compute the QTransform of my transformation that gives back newSelectionRect when applied to selectionRect.

1
Can you please provide minimal reproducible example?Robert.K
@Robert.K I have update my post with a small example that illustrates what I need.reckless
And what you got instead of newSelectionRect as a result?Robert.K
@Robert.K it's written in my question. I get QRectF selectionRect = QRectF(QPointF(10,10)*sx, QPointF(200,100)*sy); where sx and sy are the ration between the widths and heights of the two rectangles.reckless

1 Answers

1
votes

The problem lies in this assumption:

QTransform::scale assumes that the center point of the transformation is the center of the object

All transformations performed by QTransform are referred to the origin of the axis, is just an application of various tranformation matrixes (https://en.wikipedia.org/wiki/Transformation_matrix): enter image description here

Also, QTransform::translate (https://doc.qt.io/qt-5/qtransform.html#translate) states:

Moves the coordinate system dx along the x axis and dy along the y axis, and returns a reference to the matrix.

Thereby, what you are looking for is:

QTransform t;
t.translate(+10, +10); // Move the origin to the top left corner of the rectangle
t.scale(newSelectionRect.width()/selectionRect.width(),  newSelectionRect.height()/selectionRect.height()); // scale
t.translate(-10, -10); // move the origin back to where it was

QRectF resultRect = t.mapRect(selectionRect); // resultRect == newSelectionRect!