使用matplotlib.path.cleaned清理路径出现重复点的问题解决问询
解决matplotlib Path.cleaned()生成重复点的问题
我碰到过这个问题,在matplotlib 2.1.x版本里,Path.cleaned()处理闭合路径时确实会出现这种重复点的bug——它能正确移除对形状无贡献的点(比如你例子里的[0, 0.5]),但在收尾时错误地复制了倒数第二个顶点,导致路径出现冗余的[1, 0]点。
问题根源
这个问题和matplotlib旧版本中路径清理的闭合逻辑有关:当处理闭合路径的最后一段时,代码错误地重复添加了前一个顶点,而没有直接连接回起点。
可行的解决办法
1. 直接升级matplotlib(最推荐)
这个bug在matplotlib 3.0及以上版本已经被修复了。如果你能升级依赖,直接运行:
pip install --upgrade matplotlib
升级后再执行你的原始代码,cleaned()会输出正确的无重复点路径:[[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]。
2. 手动清理重复点(无法升级时用)
如果暂时不能升级版本,可以在调用cleaned()后手动移除重复的顶点,注意要保留路径的闭合状态:
import matplotlib.pyplot as plt from matplotlib.path import Path import matplotlib.patches as mpatches import numpy as np fig = plt.figure() ax = fig.add_subplot(111) verts = [[0, 0], [0, 0.5], [0, 1], [1, 1], [1, 0], [0, 0]] codes = [1, 2, 2, 2, 2, 0] path = Path(verts, codes) cleaned_path = path.cleaned(simplify=True) # 手动去重逻辑:跳过重复的非闭合点 fixed_verts = [] fixed_codes = [] seen = set() for v, c in zip(cleaned_path.vertices, cleaned_path.codes): v_tuple = tuple(np.round(v, 9)) # 浮点精度容错 if c == Path.CLOSEPOLY: # 闭合点必须保留 fixed_verts.append(v) fixed_codes.append(c) continue if v_tuple not in seen: seen.add(v_tuple) fixed_verts.append(v) fixed_codes.append(c) # 确保路径最终是闭合的 if fixed_codes[-1] != Path.CLOSEPOLY: fixed_verts.append(fixed_verts[0]) fixed_codes.append(Path.CLOSEPOLY) fixed_path = Path(np.array(fixed_verts), np.array(fixed_codes)) patch = mpatches.PathPatch(fixed_path) plt.plot(np.asarray(verts)[:, 0], np.asarray(verts)[:, 1], "rx") ax.add_patch(patch) plt.show()
3. 自定义路径简化函数
如果你想完全替代cleaned(),可以自己实现一个简单的共线点移除逻辑,针对你的场景更可控:
def simplify_collinear_points(verts, codes): simplified = [verts[0]] simplified_codes = [codes[0]] for i in range(1, len(verts)-1): prev = np.array(verts[i-1]) curr = np.array(verts[i]) next_v = np.array(verts[i+1]) # 计算叉积判断三点是否共线 cross_product = np.cross(next_v - prev, curr - prev) if not np.isclose(cross_product, 0, atol=1e-9): simplified.append(curr) simplified_codes.append(codes[i]) # 添加最后一个点和闭合代码 simplified.append(verts[-1]) simplified_codes.append(codes[-1]) return np.array(simplified), np.array(simplified_codes) # 使用自定义函数处理 simplified_verts, simplified_codes = simplify_collinear_points(verts, codes) fixed_path = Path(simplified_verts, simplified_codes)
总结
优先推荐升级matplotlib到3.0+版本,这样能从根源上解决这个bug;如果受限于环境,手动去重或者自定义简化逻辑也能完美解决你的问题。
内容的提问来源于stack exchange,提问作者Ian
相关产品推荐
相关产品推荐

