使用 pyCairo 填充具有多个孔的多边形
Filling a polygon with with multiple holes with 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 完成吗?如果可以,怎么做?
要获得带孔的多边形,您需要定义轮廓。轮廓必须是单笔画。部分重叠的边缘会导致问题。我的建议:太难了。
我看到两个解决方案:
- 将形状切成可以填充的矩形,只需省略 "transparent" 部分。
- 将外部矩形渲染为新的(屏幕外)图像。用透明颜色画出孔。然后将此图像与其余图像叠加。
注意:有可以为您相交矩形的二维库。如果你有一个(开罗甚至可能有一个),那么你可以让库通过对外部矩形应用布尔运算来计算必要的矩形列表(从中添加和删除矩形以获得矩形列表)。
我不熟悉 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"。 "nonzero" 的默认值将导致您的 "holes" 被填充而不是留下空洞。
set_fill_rule(cairo.FILL_RULE_EVEN_ODD)
我不想用 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 完成吗?如果可以,怎么做?
要获得带孔的多边形,您需要定义轮廓。轮廓必须是单笔画。部分重叠的边缘会导致问题。我的建议:太难了。
我看到两个解决方案:
- 将形状切成可以填充的矩形,只需省略 "transparent" 部分。
- 将外部矩形渲染为新的(屏幕外)图像。用透明颜色画出孔。然后将此图像与其余图像叠加。
注意:有可以为您相交矩形的二维库。如果你有一个(开罗甚至可能有一个),那么你可以让库通过对外部矩形应用布尔运算来计算必要的矩形列表(从中添加和删除矩形以获得矩形列表)。
我不熟悉 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"。 "nonzero" 的默认值将导致您的 "holes" 被填充而不是留下空洞。
set_fill_rule(cairo.FILL_RULE_EVEN_ODD)