微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何防止在文本和形状之间画一条额外的线?

如何解决如何防止在文本和形状之间画一条额外的线?

我正在为 Cairo 图形库尝试 PyCairo 绑定。我在混合文本和圆弧时遇到问题。在我的代码中,我绘制了一个圆圈,然后在它附近绘制了一个文本,在一个循环中绘制了 10 个圆圈及其相关文本。

enter image description here

使用 ctx.show_text() 绘制文本时,当前位置设置为前进点(应写入下一个字符的位置)。问题是在当前点和后续圆的第一个点之间画了一条线。

我看到的唯一可能是在绘制圆之前使用 ctx.move_to() 将当前点移动到圆弧起点。在这种情况下这不是一个大问题,因为第一个点可以很容易地计算出来,而且我已经有一个函数可以将极坐标(角度 0 和距离 = 半径)转换为 move_to() 所需的笛卡尔坐标。不过我还是不想这样做,因为其他情况可能不那么明显。

我想知道我是否遗漏了什么以及是否还有另一种可能性,例如在绘制圆之前删除当前点的命令。此外,问题似乎只与绘制文本有关,因为如果不绘制文本,则没有连接各个小圆圈的线,尽管它们也是使用多个命令绘制的:

enter image description here

为什么添加文本会产生不需要的线条?我该如何解决这个问题?

import math
import cairo

def polar_to_cart(cx,cy,angle,dist):
    x = cx + math.cos(angle) * dist
    y = cy - math.sin(angle) * dist
    return x,y

cx,cy = 150,150
two_pi = 2 * math.pi
radius = 100

# 300x300 px surface
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,2*cx,2*cy)
ctx = cairo.Context(surface)

# Draw large circle
ctx.set_source_rgb(0,0)
ctx.set_line_width(1)
ctx.arc(cx,radius,two_pi)
ctx.stroke()

# Draw small circles
n = 10
for i in range(n):
    # Center location
    x,y = polar_to_cart(cx,two_pi / n * i,radius)

    # Draw an empty circle at x,y
    ctx.arc(x,y,10,two_pi)    
    ctx.set_source_rgb(1,0)
    ctx.set_line_width(1)
    ctx.stroke()

    # Name location (bBox center)
    name = str(i)
    xbbc,ybbc = polar_to_cart(cx,radius + 25)

    # Equivalent reference point location
    x_bearing,y_bearing,width,height = ctx.text_extents(name)[:4]
    xrp = xbbc - width/2 - x_bearing
    yrp = ybbc - height/2 - y_bearing

    # Draw name
    ctx.set_source_rgb(0,1)
    ctx.select_font_face("Tahoma",cairo.FONT_SLANT_norMAL,cairo.FONT_WEIGHT_norMAL)
    ctx.set_font_size(16)
    ctx.move_to(xrp,yrp)
    ctx.show_text(name)

surface.write_to_png('_temp.png')

解决方法

正如 cairo_show_text 的文档所解释的那样,

在此调用之后,当前点将移动到下一个字形将在同一进程中放置的位置的原点。也就是说,当前点将位于最终字形的原点偏移其提前值。这允许通过多次调用 cairo_show_text() 轻松显示单个逻辑字符串。

这意味着在绘制文本后,当前路径由单个点组成。 ctx.arc 方法附加到当前路径,在这种情况下,这意味着通过一条直线将该点连接到圆的第一个点。这是不需要的红线。

要解决此问题,您可以将调用 ctx.show_text(name) 替换为

    ctx.text_path(name)
    ctx.fill()

其中 ctx.fill() 将在执行填充后隐式清除当前路径。 (ctx.stroke() 将改为绘制字体的轮廓。)

或者,您可以添加

   ctx.new_path()

在调用 ctx.show_text(name) 清除路径后,但这有点不太优雅。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。