Matplotlib绘制小楔形相对轴尺寸精度不足问题求助
解决Matplotlib绘制Wedge半圆时PDF导出的精度丢失问题
问题背景
尝试绘制两个相邻半圆作为logo,当坐标轴范围(如-10到10)远大于半圆半径(0.1)时,导出PDF会出现半圆无法占满半个圆的精度丢失问题;但通过plt.show()放大查看时无此异常。曾尝试使用已废弃的resolution参数,导致报错。当前环境为Python 3.12.3 + Matplotlib 3.9.1.post1,需批量生成约350个该logo,优先解决PDF精度问题,SVG作为备选方案。
原因分析
Matplotlib的Wedge默认使用较少的顶点数近似曲线,当图形在坐标轴中占比极小时,这些顶点的坐标精度在PDF导出过程中被压缩,导致曲线变形。旧版的resolution参数已被移除,需使用新的参数控制曲线细分程度。
解决方案
方案1:增加Wedge的顶点数(优先推荐)
Matplotlib 3.3+版本可用num_points参数替代废弃的resolution,通过提升顶点数量来增强曲线平滑度与精度:
import matplotlib.pyplot as plt from matplotlib.patches import Wedge fig, ax = plt.subplots(figsize=(5, 5)) radius = 0.1 # 设置num_points提升曲线顶点数,数值越高精度越好 left_semicircle = Wedge((0, 0), radius, 0, 180, color="r", num_points=200) right_semicircle = Wedge((0, 0), radius, 180, 360, color="b", num_points=200) ax.add_patch(left_semicircle) ax.add_patch(right_semicircle) axis_limit = 10 ax.set_xlim((-axis_limit, axis_limit)) ax.set_ylim((-axis_limit, axis_limit)) ax.set_aspect('equal') # 保存时指定高DPI并tight裁剪,避免精度压缩 plt.savefig(f"TwoSemicircles_{axis_limit}.pdf", dpi=300, bbox_inches='tight')
方案2:先聚焦图形再导出
调整坐标轴范围至适配图形尺寸,导出后再通过PDF工具缩放至所需大小,避免小图形在大轴范围下的精度损失:
import matplotlib.pyplot as plt from matplotlib.patches import Wedge fig, ax = plt.subplots(figsize=(5, 5)) radius = 0.1 left_semicircle = Wedge((0, 0), radius, 0, 180, color="r") right_semicircle = Wedge((0, 0), radius, 180, 360, color="b") ax.add_patch(left_semicircle) ax.add_patch(right_semicircle) # 设置适配图形的轴范围,让图形占满画布 ax.set_xlim((-radius*1.1, radius*1.1)) ax.set_ylim((-radius*1.1, radius*1.1)) ax.set_aspect('equal') plt.savefig(f"TwoSemicircles_tight.pdf", dpi=300, bbox_inches='tight')
方案3:SVG导出后转PDF(备选)
SVG为矢量格式,放大无精度损失,可导出SVG后通过工具转换为PDF:
import matplotlib.pyplot as plt from matplotlib.patches import Wedge fig, ax = plt.subplots(figsize=(5, 5)) radius = 0.1 left_semicircle = Wedge((0, 0), radius, 0, 180, color="r") right_semicircle = Wedge((0, 0), radius, 180, 360, color="b") ax.add_patch(left_semicircle) ax.add_patch(right_semicircle) axis_limit = 10 ax.set_xlim((-axis_limit, axis_limit)) ax.set_ylim((-axis_limit, axis_limit)) ax.set_aspect('equal') # 导出SVG plt.savefig(f"TwoSemicircles_{axis_limit}.svg") # 可选:使用cairosvg批量转换为PDF # import cairosvg # cairosvg.svg2pdf(url=f"TwoSemicircles_{axis_limit}.svg", write_to=f"TwoSemicircles_{axis_limit}_from_svg.pdf")
内容的提问来源于stack exchange,提问作者Henry Ginn
相关产品推荐
相关产品推荐

