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

本文章重点表述QGraphicsItem中,对于旋转后的坐标变化。
我在实现QGraphicsRectItem的缩放和旋转时,遇到了这样一个问题。原本实现的缩放,在旋转后也是能用的。但是涉及到旋转中心的问题,让人有些难以理解,最终分析实践得到下述结论。
实例文章:https://blog.csdn.net/xiaonuo911teamo/article/details/106075647

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

进入正题

QGrahpicsItem 对于旋转仅仅是保存了旋转的角度与旋转中心,并不保存旋转之后的坐标。下面看一个例子。
在这里插入图片描述你看到这个例子中隐藏的病症了吗?
我给了他默认正方形中心为旋转中心(Qt里面不设置是默认为原点的)。原本是一个旋转了30度的正方形,然后从一个正方形拉伸到了一个长方形。到此看似还没有问题,但是如果考虑下一步,我们需要再次旋转呢?原本我们是以中心为旋转中心的,但是现在呢?仍然是那个点,但他不是中心了。至少在我使用时,这是一个需要解决的问题,我需要将中心再次设置为矩形中心。我简单执行了setTransformOriginPoint(this->rect().center());,然后我并没有如愿。

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

分析条件:O(x0,y0)点是之前的旋转中心,P1(x1,y1)是新的旋转中心,线段OP1=线段OP2,∠P2OP1为alpha(例子中是30度)。
思路:先求出P2坐标,然后平移P1到P2即可。求P2坐标可简化为,线OP1旋转30度后,点P1’(P2)的坐标。

插播一个小公式

在这里插入图片描述
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());
  • 13
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值