天天看点

QGraphicsItem旋转后,坐标变化机制解析

本文章重点表述QGraphicsItem中,对于旋转后的坐标变化。

我在实现QGraphicsRectItem的缩放和旋转时,遇到了这样一个问题。原本实现的缩放,在旋转后也是能用的。但是涉及到旋转中心的问题,让人有些难以理解,最终分析实践得到下述结论。

实例文章:https://blog.csdn.net/xiaonuo911teamo/article/details/106075647

如果你对QGraphicsItem的坐标机制,不甚了解,请先看此文章。https://blog.csdn.net/qq_25800311/article/details/81300923。

进入正题

QGrahpicsItem 对于旋转仅仅是保存了旋转的角度与旋转中心,并不保存旋转之后的坐标。下面看一个例子。

QGraphicsItem旋转后,坐标变化机制解析

你看到这个例子中隐藏的病症了吗?

我给了他默认正方形中心为旋转中心(Qt里面不设置是默认为原点的)。原本是一个旋转了30度的正方形,然后从一个正方形拉伸到了一个长方形。到此看似还没有问题,但是如果考虑下一步,我们需要再次旋转呢?原本我们是以中心为旋转中心的,但是现在呢?仍然是那个点,但他不是中心了。至少在我使用时,这是一个需要解决的问题,我需要将中心再次设置为矩形中心。我简单执行了setTransformOriginPoint(this->rect().center());,然后我并没有如愿。

我得到的是下图左侧黄色的矩形,而我想要的是右侧绿色的矩形。

QGraphicsItem旋转后,坐标变化机制解析

为什么会是这个结果呢?

经过一番研究,才得到开头说的结论,QGraphicsItem只是储存了旋转角度和旋转中心,当绘制的时候,再计算位置进行绘制。如此,当我们设置了新的中心点,如果已经有了旋转角度的话,那么则会出现平移的现象。所以为了解决这个问题,我们需要再拉伸之后,将以(P1为中心的矩形)平移到(以P2为中心的矩形)的位置。

分析条件:O(x0,y0)点是之前的旋转中心,P1(x1,y1)是新的旋转中心,线段OP1=线段OP2,∠P2OP1为alpha(例子中是30度)。

思路:先求出P2坐标,然后平移P1到P2即可。求P2坐标可简化为,线OP1旋转30度后,点P1’(P2)的坐标。

插播一个小公式
QGraphicsItem旋转后,坐标变化机制解析

x’ = x1 + r * cos(a + b);

x’ = x1 + r * cos(a) * cos(b) - r * sin(a) * sin(b);

又因为:

r * cos(b) = x2 - x1;

r * sin(b) = (y2 - y1);

最终可以求出:

x’ = x1 + cos(a) * (x2 - x1) - sin(a) * (y2 - y1);

同理求出:

y’ = y1 + sin(a) * (x2 - x1) + cos(a) * (y2 - y1);

回到正题

套用上述公式,就可以得到P2的坐标了。下面是代码示例。下面的代码取自母亲章节:https://blog.csdn.net/xiaonuo911teamo/article/details/106075647

auto rr = this->rect();
	auto angle = qDegreesToRadians(this->rotation());

	auto p1 = rr.center();
	auto origin = this->transformOriginPoint();
	QPointF p2 = QPointF(0, 0);

	p2.setX(origin.x() + qCos(angle)*(p1.x() - origin.x()) - qSin(angle)*(p1.y() - origin.y()));
	p2.setY(origin.y() + qSin(angle)*(p1.x() - origin.x()) + qCos(angle)*(p1.y() - origin.y()));

	auto diff = p1 - p2;
	this->setRect(rr.adjusted(-diff.x(), -diff.y(), -diff.x(), -diff.y()));
	setTransformOriginPoint(this->rect().center());
           

继续阅读