You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何平滑Python绘制的韦恩图(Venn diagram)所有边缘?

问题描述

使用Python结合matplotlib与matplotlib_venn库绘制韦恩图时,图中所有边缘(包括内部边缘)均呈现棱角,需解决:

  1. 棱角产生的原因
  2. 边缘平滑的实现方法

附原代码及效果图:

import matplotlib.pyplot as plt
from matplotlib_venn import venn3
from matplotlib.patches import PathPatch
from matplotlib.path import Path


set1 = {i for i in range(150)}
set2 = {i for i in range(150 - 75, 350 - 75)}
set3 = {i for i in range(150 - 75, 150 - 75 + 20)}

fig, ax = plt.subplots()
venn = venn3([set1, set2, set3], set_labels=('', '', ''))

circle1 = venn.get_patch_by_id('100')
circle2 = venn.get_patch_by_id('010')
circle3 = venn.get_patch_by_id('110')
circle4 = venn.get_patch_by_id('111')

circle1.set_edgecolor('none')
circle2.set_edgecolor('none')
circle3.set_edgecolor('none')
circle4.set_edgecolor('none')

path_data1 = circle1.get_path().vertices.tolist()
patch1 = PathPatch(Path(path_data1), facecolor='yellow', edgecolor='#d6d3d6', hatch='/', lw=0)
ax.add_patch(patch1)

path_data2 = circle2.get_path().vertices.tolist()
patch2 = PathPatch(Path(path_data2), facecolor='purple', edgecolor='#d6d3d6', hatch='\\', lw=0)
ax.add_patch(patch2)

path_data3 = circle3.get_path().vertices.tolist()
patch3 = PathPatch(Path(path_data3), facecolor='pink', edgecolor='#d6d3d6', hatch="\/", lw=0)
ax.add_patch(patch3)


path_data4 = circle4.get_path().vertices.tolist()
patch4 = PathPatch(Path(path_data4), facecolor='orange', edgecolor='#d6d3d6', hatch=".", lw=0)
ax.add_patch(patch4)

venn.get_label_by_id('100').set_text('')
venn.get_label_by_id('010').set_text('')
venn.get_label_by_id('110').set_text('')
venn.get_label_by_id('111').set_text('')

# Show the plot
plt.axis('off')
plt.show()

效果图:
棱角化的韦恩图

棱角产生的原因

matplotlib_venn生成的韦恩图区块,其路径(Path)是通过贝塞尔曲线实现平滑边缘的。每个Path对象包含两部分核心数据:

  • vertices:路径的顶点坐标
  • codes:每个顶点对应的路径指令(比如移动到起点、贝塞尔曲线控制点、绘制曲线等)

你在代码中仅提取了vertices来创建新Path,忽略了codes。此时matplotlib会默认用直线连接所有顶点,自然出现棱角。

边缘平滑的解决方案

有两种简单的修正方式:

方式一:直接复用原Patch的Path

无需重新创建Path,直接基于原区块的路径生成带样式的新PathPatch:

import matplotlib.pyplot as plt
from matplotlib_venn import venn3
from matplotlib.patches import PathPatch


set1 = {i for i in range(150)}
set2 = {i for i in range(150 - 75, 350 - 75)}
set3 = {i for i in range(150 - 75, 150 - 75 + 20)}

fig, ax = plt.subplots()
venn = venn3([set1, set2, set3], set_labels=('', '', ''))

# 获取原区块并隐藏
circle1 = venn.get_patch_by_id('100')
circle2 = venn.get_patch_by_id('010')
circle3 = venn.get_patch_by_id('110')
circle4 = venn.get_patch_by_id('111')

for patch in [circle1, circle2, circle3, circle4]:
    patch.set_visible(False)

# 基于原路径创建带填充和hatch的新Patch
patch1 = PathPatch(circle1.get_path(), facecolor='yellow', edgecolor='#d6d3d6', hatch='/', lw=0)
ax.add_patch(patch1)

patch2 = PathPatch(circle2.get_path(), facecolor='purple', edgecolor='#d6d3d6', hatch='\\', lw=0)
ax.add_patch(patch2)

patch3 = PathPatch(circle3.get_path(), facecolor='pink', edgecolor='#d6d3d6', hatch="\/", lw=0)
ax.add_patch(patch3)

patch4 = PathPatch(circle4.get_path(), facecolor='orange', edgecolor='#d6d3d6', hatch=".", lw=0)
ax.add_patch(patch4)

# 隐藏所有标签
for label_id in ['100', '010', '110', '111']:
    venn.get_label_by_id(label_id).set_text('')

plt.axis('off')
plt.show()

方式二:同时提取vertices和codes创建Path

如果需要手动构建Path,需同时传入顶点坐标和路径指令:

import matplotlib.pyplot as plt
from matplotlib_venn import venn3
from matplotlib.patches import PathPatch
from matplotlib.path import Path


set1 = {i for i in range(150)}
set2 = {i for i in range(150 - 75, 350 - 75)}
set3 = {i for i in range(150 - 75, 150 - 75 + 20)}

fig, ax = plt.subplots()
venn = venn3([set1, set2, set3], set_labels=('', '', ''))

circle1 = venn.get_patch_by_id('100')
circle2 = venn.get_patch_by_id('010')
circle3 = venn.get_patch_by_id('110')
circle4 = venn.get_patch_by_id('111')

for patch in [circle1, circle2, circle3, circle4]:
    patch.set_edgecolor('none')

# 同时提取vertices和codes
path1 = circle1.get_path()
patch1 = PathPatch(Path(path1.vertices, path1.codes), facecolor='yellow', edgecolor='#d6d3d6', hatch='/', lw=0)
ax.add_patch(patch1)

path2 = circle2.get_path()
patch2 = PathPatch(Path(path2.vertices, path2.codes), facecolor='purple', edgecolor='#d6d3d6', hatch='\\', lw=0)
ax.add_patch(patch2)

path3 = circle3.get_path()
patch3 = PathPatch(Path(path3.vertices, path3.codes), facecolor='pink', edgecolor='#d6d3d6', hatch="\/", lw=0)
ax.add_patch(patch3)

path4 = circle4.get_path()
patch4 = PathPatch(Path(path4.vertices, path4.codes), facecolor='orange', edgecolor='#d6d3d6', hatch=".", lw=0)
ax.add_patch(patch4)

for label_id in ['100', '010', '110', '111']:
    venn.get_label_by_id(label_id).set_text('')

plt.axis('off')
plt.show()

内容的提问来源于stack exchange,提问作者maciejwww

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 08:18:10