对于 QGraphicsItem,绘制对象的总体转换是什么样的?
What is does the total transformation of painted objects look like for QGraphicsItem?
让
painter.transform()
= P,
self.transform()
= L,
self.sceneTransform()
= S
self.parent().transform()
= P1
self.parent().parent().transform()
= P2(依此类推...)
当我在不设置任何变换的情况下绘制一个点时(不在 painter
上,不在任何形状上 map
,在 self
上不(除了在其他中所做的控制移动、缩放和旋转的方法)。那么这个点 x 如何使用上述矩阵变量映射到它在屏幕上的最终位置?
我的目标是充分理解这一点,以便我可以做到这一点(起初,但我总是在做 QGraphicsItem 的东西);这意味着我不想 post 一个特定的问题代码(还),因为这不一定能解决我普遍缺乏理解的问题:
使用正确的笔外观和大小绘制选择矩形,但在调用 self.setTransform(self.transform().scale(Sx, Sy))
时,对象正确缩放,但选择矩形随之缩放!因此,如果在原始比例下有 10 个 1x1 像素点构成选择矩形的一侧,那么在缩放时有 10 个 Sx x Sy 像素点构成一侧并且它看起来不正确。
我的直觉解决方案是先缩放选择的形状QPainterPath
(在绘画之前),然后在同一尺度上绘制它。这似乎是一个简单的想法,但如果不了解所涉及的转换是如何应用的,几乎不可能实现。
所以请告诉我将绘制点映射到屏幕的矩阵乘法公式,在绘制过程中不考虑任何变换。
情况是这样开始的:
我=身份
到 = 画家原点(小部件左上角)到场景中心(屏幕上)的平移。
L=I
S=我
P = 到
对象移动
Tm = 物体在场景坐标中的平移矩阵。
(Tm 标准方向(+y = 向下,+x = 右)
翻译的处理方式似乎与以下操作不同,因为有一个 setPos(x,y)
函数没有相对转换,除非您反转旧的翻译并将其也乘以。
如果 T 是以下操作序列的总矩阵,则 S 将是:
S = T * Tm^-1
同样,
P = T * Tm
L=T
对象缩放
Ts = QTransform().fromScale(Sx, Sy)
找到的缩放矩阵
L *= Ts
S *= Ts
P *= Ts
结果由 self.setTransform(self.transform().scale(Sx, Sy))
.
应用
对象旋转
Tr =由QTransform().fromRotation(R)
找到的旋转矩阵,其中+R
表示顺时针。
L *= Tr
S *= Tr
P *= Tr
结果由 self.setTransform(self.transform().rotate(R))
.
应用
乘法以与传统线性代数相反的顺序完成,因此请确保所有 m12(), m21(), m13(), m31(), ...
调用都已转置。
因此在没有任何额外矩阵变化的情况下用 painter.drawPoint(*x)
绘制点 x = (x,y)
将导致 x' = x T Tm.
使用它作为模型,默认绘制的选择框 b 被绘制为 *b' = b TTm**,
所以我想在绘画之前删除缩放和旋转,然后先将它们应用到 QPainterPath
。根据我们的模型,这似乎应该可行:
p = self.shape()
T = self.transform() # Local transform doesn't include translation in scene
p = T.map(p)
# b = p + pen stroke applied
painter.save()
painter.setTransform(QTransform().fromTranslation(self.pos()))
painter.strokePath(p, pen)
painter.restore()
这不起作用,但问题似乎仍然只出在我们的翻译模型上。笔路径的缩放有效。
我们忘记了到。请注意,To 将随 QGraphicsView 调整大小而改变。
所以实际上 P = T ToTm = T TmTo。 TmTo 只触及矩阵的 dx = m31(), dy = m32()
所以,我们要做的是使用 .fromTranslate(m31, m32)
.
而不是 .fromTranslate(self.pos()))
有效吗?
是的,行得通!
让
painter.transform()
= P,
self.transform()
= L,
self.sceneTransform()
= S
self.parent().transform()
= P1
self.parent().parent().transform()
= P2(依此类推...)
当我在不设置任何变换的情况下绘制一个点时(不在 painter
上,不在任何形状上 map
,在 self
上不(除了在其他中所做的控制移动、缩放和旋转的方法)。那么这个点 x 如何使用上述矩阵变量映射到它在屏幕上的最终位置?
我的目标是充分理解这一点,以便我可以做到这一点(起初,但我总是在做 QGraphicsItem 的东西);这意味着我不想 post 一个特定的问题代码(还),因为这不一定能解决我普遍缺乏理解的问题:
使用正确的笔外观和大小绘制选择矩形,但在调用
self.setTransform(self.transform().scale(Sx, Sy))
时,对象正确缩放,但选择矩形随之缩放!因此,如果在原始比例下有 10 个 1x1 像素点构成选择矩形的一侧,那么在缩放时有 10 个 Sx x Sy 像素点构成一侧并且它看起来不正确。我的直觉解决方案是先缩放选择的形状
QPainterPath
(在绘画之前),然后在同一尺度上绘制它。这似乎是一个简单的想法,但如果不了解所涉及的转换是如何应用的,几乎不可能实现。
所以请告诉我将绘制点映射到屏幕的矩阵乘法公式,在绘制过程中不考虑任何变换。
情况是这样开始的:
我=身份
到 = 画家原点(小部件左上角)到场景中心(屏幕上)的平移。
L=I
S=我
P = 到
对象移动
Tm = 物体在场景坐标中的平移矩阵。
(Tm 标准方向(+y = 向下,+x = 右)
翻译的处理方式似乎与以下操作不同,因为有一个 setPos(x,y)
函数没有相对转换,除非您反转旧的翻译并将其也乘以。
如果 T 是以下操作序列的总矩阵,则 S 将是:
S = T * Tm^-1
同样,
P = T * Tm
L=T
对象缩放
Ts = QTransform().fromScale(Sx, Sy)
找到的缩放矩阵
L *= Ts
S *= Ts
P *= Ts
结果由 self.setTransform(self.transform().scale(Sx, Sy))
.
对象旋转
Tr =由QTransform().fromRotation(R)
找到的旋转矩阵,其中+R
表示顺时针。
L *= Tr
S *= Tr
P *= Tr
结果由 self.setTransform(self.transform().rotate(R))
.
乘法以与传统线性代数相反的顺序完成,因此请确保所有 m12(), m21(), m13(), m31(), ...
调用都已转置。
因此在没有任何额外矩阵变化的情况下用 painter.drawPoint(*x)
绘制点 x = (x,y)
将导致 x' = x T Tm.
使用它作为模型,默认绘制的选择框 b 被绘制为 *b' = b TTm**,
所以我想在绘画之前删除缩放和旋转,然后先将它们应用到 QPainterPath
。根据我们的模型,这似乎应该可行:
p = self.shape()
T = self.transform() # Local transform doesn't include translation in scene
p = T.map(p)
# b = p + pen stroke applied
painter.save()
painter.setTransform(QTransform().fromTranslation(self.pos()))
painter.strokePath(p, pen)
painter.restore()
这不起作用,但问题似乎仍然只出在我们的翻译模型上。笔路径的缩放有效。
我们忘记了到。请注意,To 将随 QGraphicsView 调整大小而改变。
所以实际上 P = T ToTm = T TmTo。 TmTo 只触及矩阵的 dx = m31(), dy = m32()
所以,我们要做的是使用 .fromTranslate(m31, m32)
.
.fromTranslate(self.pos()))
有效吗?