天天看點

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());
           

繼續閱讀