Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/30.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在pycairo中围绕文本中心旋转文本_Python_Graphics_Rotation_Cairo_Pycairo - Fatal编程技术网

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
对于python代码,您必须重写上面的等式,以得到A*t=b,其中t=(x,y),然后计算t=inv(A)*b。然后,您只需执行以下操作

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