PDA

View Full Version : Rotate QPixmap around an arbitrary point



Abion47
12th March 2014, 10:43
I'm trying to do a thing where I rotate an image around an arbitrary point (generally within the bounds of the image itself), but I want to retain the point that corresponds to the untransformed image's origin.

Thus far, I'm using the QTransform approach to rotate the image:


image.transformed(QTransform()
.translate(-point.x(), -point.y())
.rotateRadians(rot)
.translate(point.x(), point.y()));

This returns an image that is "rotated" around the point, but it is drawn into a new image object whose origin is respective to the transformed image, not the original, so painting the image makes it have the correct angle but is translated somewhere way out of position. Is there a way to either A] calculate the original origin's location in the transformed image, or B] rotate an image without altering its origin.

wysota
20th March 2014, 17:31
You should translate the resulting image along the vector obtained by mapping the new origin point to the old origin point. QTransform has a family of map() methods to help you with that.

Abion47
20th March 2014, 19:18
Using the Transform.map method on the origin point only applies the transformations to the image on the origin point as well, which tells me where the origin point is in the image's local space. It doesn't tell me where the origin point is with respect to the transformed image's new origin point.

Anyway, I've already solved this problem by calculating the distance between the original image's center and the transformed image's center, and adding that offset to the transformed origin point.

wysota
20th March 2014, 21:09
It doesn't tell me where the origin point is with respect to the transformed image's new origin point.

Sure it does.

Abion47
21st March 2014, 02:07
Sure it does.

Thanks for the detailed answer.

I'm not getting the map() method to give me anywhere near the right values. I'm using a QTransform to translate the origin by the inverse of the rotation point, rotating, translating back, then offsetting by the aforementioned difference in the image centers. I then compare the values to the ones from the ones coming out of my existing method that I know works, and its not even in the same ballpark.

Maybe its some error in my code, but like I said, I already have a method that works, so I don't really see the point in investigating further.


QPixmap getTransformedImage(QPixmap image, QPointF pos, QPointF anchor, qreal rot, QPointF &origin)
{
QPointF center = QPointF(image.width() / 2, image.height() / 2);
qreal dist = QLineF(anchor, center).length();
qreal a = qAtan2(anchor.y() - center.y(), anchor.x() - center.x());
QPointF rotAnchor(qCos(rot + a) * dist, qSin(rot + a) * dist);
rotAnchor += center;

QPixmap rotImage = image.transformed(QTransform().rotateRadians(rot)) ;

QPointF rotCenter = QPointF(rotImage.width() / 2, rotImage.height() / 2);
QPointF offset = rotCenter - center;

origin = pos - (rotAnchor + offset);

return rotImage;
}

wysota
21st March 2014, 07:19
The QTransform object you have can be used to transform points from the "old" coordinate system to the "new" coordinate system. If you want to do a mapping the other way, you have to invert the transform (QTransform::inverted()). If you map the new origin to a point in the old coordinate system and then calculate the difference vector, you'll know how much to move the new coordinate system so that the two points match.

Abion47
21st March 2014, 18:58
That seems overly complex though. What's wrong with just using raw math functions to rotate the origin around the same pivot point as the image then offset by the difference in centers?

wysota
21st March 2014, 23:14
I didn't say there was something wrong with your approach. You don't even have to use QTransform at all if you want to do all the math by yourself.