用pyCairo填充多边形的多边形
问题描述:
我不想用pyCairo
填充多边形,但我希望某些区域可以不填充。例如,我想产生这样的事情:用pyCairo填充多边形的多边形
灰色背景是SVG观看者的背景,所以表示图像的透明部分。
我试着用这个代码:
import cairo
cairo.FILL_RULE_EVEN_ODD
svg_file_pointer = open('CairoPoly.svg', 'wb')
shape_container = cairo.SVGSurface(svg_file_pointer, 500, 500)
shape_description = cairo.Context(shape_container)
shape_description.rectangle(0, 0, 500, 500)
shape_description.clip_preserve()
shape_description.stroke()
shape_description.set_line_width(1)
shape_description.set_source_rgb(20/51, 0, 0)
for r in ((100, 100, 400, 400), (200, 200, 350, 300), (150, 110, 190, 390)):
shape_description.move_to(r[0], r[1])
shape_description.line_to(r[0], r[3])
shape_description.line_to(r[2], r[3])
shape_description.line_to(r[2], r[1])
shape_description.line_to(r[0], r[1])
shape_description.close_path()
shape_description.fill()
shape_container.finish()
svg_file_pointer.close()
del shape_container
但它不工作。这可以用pyCairo完成,如果是的话,怎么样?
答
我不熟悉pyCairo,但从SVG的角度来看,您所做的基本概念是正确的。你很接近,但不太对。
你想要做的是为每个矩形创建一个包含子路径的路径。
<svg width="500" height="500">
<path d="M 100,100 L 100,400 L 400,400 L 400,100 L 100,100
M 200,200 L 200,300 L 350,300 L 350,200 L 200,200
M 150,110 L 150,390 L 190,390 L 190,110 L 150,110 Z"
fill-rule="evenodd" />
</svg>
它看起来像这样或多或少是你在做什么,但你也需要改变填充规则“EVENODD”。 “非零”的默认值将导致您的“洞”被填充,而不是留下空洞。
set_fill_rule(cairo.FILL_RULE_EVEN_ODD)
答
要获得带孔的多边形,您需要定义轮廓。纲要必须是单个中风。部分重叠的边缘会导致问题。我的建议:太难了。
我看到两个解决方案:
- 切割形状为矩形,其可以被填充和简单地省略“透明”的部件。
- 将外部矩形渲染为新的(屏幕外)图像。用透明颜色绘制孔。然后覆盖这个图像与其余的。
注意:有2D矩阵可以为您交叉矩形。如果你有一个(在开罗甚至可能有一个),那么你可以让图书馆通过对外部矩形应用布尔操作来计算必要的矩形列表(从中添加和删除矩形以获得矩形列表)。
非常感谢。原来问题是我不知道如何处理'cairo.FILL_RULE_EVEN_ODD'。在我的例子中,我简单地用'shape_description.set_fill_rule(cairo.FILL_RULE_EVEN_ODD)'替换它,现在它就像一个魅力。 –