Python 在pycairo中围绕文本中心旋转文本
社区 我知道这里有很多答案、手册、教程和网上参考资料,还有关于这个问题的更多信息。我也知道线性代数的知识是必需的。 但是,当我考虑到时间去弄清楚所有的理论并在实践中解决问题时,我的脑袋都快晕过去了,我不能做最简单的事情:( 请告诉我,如果你知道一个快速的解决方案,在渲染之前如何使文本在其中心旋转,请告诉我 目前我有:Python 在pycairo中围绕文本中心旋转文本,python,graphics,rotation,cairo,pycairo,Python,Graphics,Rotation,Cairo,Pycairo,社区 我知道这里有很多答案、手册、教程和网上参考资料,还有关于这个问题的更多信息。我也知道线性代数的知识是必需的。 但是,当我考虑到时间去弄清楚所有的理论并在实践中解决问题时,我的脑袋都快晕过去了,我不能做最简单的事情:( 请告诉我,如果你知道一个快速的解决方案,在渲染之前如何使文本在其中心旋转,请告诉我 目前我有: #... cr.move_to(*text_center) myX, myY = text_center[0] - (width / 2), text_center[1] + (h
#...
cr.move_to(*text_center)
myX, myY = text_center[0] - (width / 2), text_center[1] + (height / 2)
cr.save()
cr.translate(myX, myY)
cr.rotate(radians(text_angle))
cr.show_text(letter)
cr.restore()
#...
但我的信并没有自转,就像掉到了右边:(
我知道我的代码不对。也许我错过了转换,但我不知道如何使它正确
更新:不幸的是,文本不受翻译的影响,因此
cr.translate(10000, 10000)
cr.rotate(radians(15))
cr.show_text("hello")
将与
cr.rotate(radians(15))
cr.show_text("hello")
我不知道如何在不创建新的曲面或其他东西(如图形处理器中的新层)的情况下使文本围绕其中心旋转:(应该
myX, myY = text_center[0] + (height / 2), text_center[1] - (width / 2)
是
?
这也许可以解释为什么它会落到右边。好的,cairo允许文本移动到和旋转。这意味着您需要计算出移动到(T)的(x,y),这样当您旋转(R)时,文本的中心点位于您想要的位置,c=(cx,cy): 因此,您必须求解方程Mv=c,其中v是相对于文本原点的文本中心:
M = T*R
T = (1 0 x)
(0 1 y)
(0 0 1)
R = (cos r -sin r 0)
(sin r cos r 0)
(0 0 1)
v = (w/2, h', 1)
c = (cx, cy, 1)
h' = h/2 - (h - y_bearing)
健全性检查:
- 当r为0(无旋转)时,得到x=cx-w/2,y=cy-h',你知道 答案正确吗
- 当r=-90(文本侧边,向右“向上”)时,您将得到您所期望的结果, ie x=cx-h'和y=cy+w/2
cr.move_to(x, y)
cr.rotate(r)
cr.show_text(yourtext)
请注意,cairo中的坐标系有+y下降,因此需要修正几个符号,可能y_方向不正确,但您知道了。至少在我的机器上可用的cairo版本(1.8.8)中,以下方法对我有效:
def text(ctx, string, pos, theta = 0.0, face = 'Georgia', font_size = 18):
ctx.save()
# build up an appropriate font
ctx.select_font_face(face , cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
ctx.set_font_size(font_size)
fascent, fdescent, fheight, fxadvance, fyadvance = ctx.font_extents()
x_off, y_off, tw, th = ctx.text_extents(string)[:4]
nx = -tw/2.0
ny = fheight/2
ctx.translate(pos[0], pos[1])
ctx.rotate(theta)
ctx.translate(nx, ny)
ctx.move_to(0,0)
ctx.show_text(string)
ctx.restore()
可按以下方式使用:
width = 500
height = 500
surface = cairo.ImageSurface(cairo.FORMAT_RGB24, width, height)
ctx = cairo.Context(surface)
ctx.set_source_rgb(1,1,1)
rect(ctx, (0,0), (width, height), stroke=False)
ctx.set_source_rgb(0,0,0)
for i in xrange(5):
for j in xrange(5):
x = 100 * i + 20
y = 100 * j + 20
theta = math.pi*0.25*(5*i+j)
text(ctx, 'hello world', (x, y), theta, font_size=15)
surface.write_to_png('text-demo.png')
基于以上输入,支持多行文本的类函数
def text(self, text, x, y, rotation=0, fontName="Arial", fontSize=10, verticalPadding=0):
rotation = rotation * math.pi / 180
self.ctx.select_font_face(fontName, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
self.ctx.set_font_size(fontSize)
fascent, fdescent, fheight, fxadvance, fyadvance = self.ctx.font_extents()
self.ctx.save()
self.ctx.translate(x, y)
self.ctx.rotate(rotation)
lines = text.split("\n")
for i in xrange(len(lines)):
line = lines[i]
xoff, yoff, textWidth, textHeight = self.ctx.text_extents(line)[:4]
offx = -textWidth / 2.0
offy = (fheight / 2.0) + (fheight + verticalPadding) * i
self.ctx.move_to(offx, offy)
self.ctx.show_text(line)
self.ctx.restore()
哦,拜托,这是我的错。我在手机上从头开始写了这个代码。在真实代码上,它和你的例子一样安静。但当我回家后,我会检查一下。你认为翻译-是我需要的唯一转换吗?这不是错误。结果是一样的。也许复杂的东西可以解决这个问题?也许新的转换矩阵或差异t代码顺序?“将文本放置在文本中心”-我如何才能做到这一点?我只有单独的函数cr.move_to(x,y)和单独的cr.show_text(text)。我必须何时将move_to()-在平移和旋转之前,或在放置文本前后?my
text\u center
表示原点的x,y坐标,用于将文本精确放置到与其(文本)中心(w/2,h/2)重叠的优先点。这些代码不起作用,也不会起作用,因为旋转总是围绕当前点进行。如果我写入:cr.move\u to(a,b);cr.rotate(rad);cr.show_text();
-它将仅围绕(a,b)旋转,平移不会影响旋转。但我知道有一些公式类似于[here][1]来计算移动到何处的新坐标。[1]:非常感谢您的详细回答。我无法理解其中的一些内容,但我会努力找出答案,因为在我自己的头脑中理解这一切对我来说非常重要=)非常感谢!@КСаааСа如果您能让每个人都知道这是答案(标记为答案),或者至少是有用的,那就太好了(投票赞成,并对你的发现发表评论).天才和完美!哦,自从我问了那个问题之后,我冻结了我的项目,打开了数学书。我知道你的解决方案就是我想要的,如果你不介意的话,我会把它粘贴到我的代码中,并在注释中写下你的名字。但是数学很棒,也很有趣,所以我会继续学习一些新的东西。你能告诉我在哪里可以找到你的答案吗数学书中的解决方案:它是如何命名的,它是什么?谢谢你的帮助。@Scholli是正确的,但事实证明Cairo API有一些复杂之处,这使它有点有趣。关键是旋转总是围绕原点发生。这意味着你需要将原点转换到你想要绘制文本的地方。然后您可以进行旋转。最后,为了确保渲染文本通过您的点,您需要进行最后一次平移(在旋转的坐标框中)。move_to(移动到)命令确保文本将从原点渲染。这种数学可能最好使用该术语来描述,它实际上只是表示坐标变换的一种方式。从广义上讲,这是一个线性代数问题。这项任务在力学中尤为重要(这反过来对从事物理、机器人和游戏开发的软件开发人员也很重要)。当然,Schollii是对的,但python中的三角函数会降低精度很多。乍一看,您的方法精度更高,可能更快。我将在web应用程序中使用此代码,它对动态图像渲染和浮点运算非常重要。再次感谢您。线性代数正在我的路上:)似乎对我不起作用。我的特例可能是我只使用单个字符。有什么想法吗?在过去的5年里有什么变化吗?这是我最喜欢的项目,我很久以前就放弃了,开始重新学习数学。从那以后我再也没有回到这个项目。但是,我很好奇,想再试一次。12改为17。我的意思是开罗/py开罗
def text(self, text, x, y, rotation=0, fontName="Arial", fontSize=10, verticalPadding=0):
rotation = rotation * math.pi / 180
self.ctx.select_font_face(fontName, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
self.ctx.set_font_size(fontSize)
fascent, fdescent, fheight, fxadvance, fyadvance = self.ctx.font_extents()
self.ctx.save()
self.ctx.translate(x, y)
self.ctx.rotate(rotation)
lines = text.split("\n")
for i in xrange(len(lines)):
line = lines[i]
xoff, yoff, textWidth, textHeight = self.ctx.text_extents(line)[:4]
offx = -textWidth / 2.0
offy = (fheight / 2.0) + (fheight + verticalPadding) * i
self.ctx.move_to(offx, offy)
self.ctx.show_text(line)
self.ctx.restore()