如何保存支持增量添加点的预计算Voronoi图至文件?
解决Scipy增量Voronoi图无法序列化的问题
Scipy的Voronoi对象无法通过pickle/dill序列化,核心原因是其底层依赖的_qh是Qhull的C语言结构,无法被转换为可序列化的Python对象。以下是几种可行的解决方案:
方案1:保存原始点集,重新构建增量Voronoi
这是最直接的方案,虽然会有重建开销,但1e6个二维点的Voronoi构建时间在多数硬件上处于可接受范围(几秒到十几秒):
- 保存原始点集:
import numpy as np np.save("voronoi_points.npy", points)
- 后续加载并重建:
import numpy as np from scipy.spatial import Voronoi points = np.load("voronoi_points.npy") vor = Voronoi(points, incremental=True)
方案2:手动序列化Voronoi核心状态(进阶)
手动保存增量Voronoi的关键属性,后续通过初始化空对象并恢复状态来实现复用:
- 保存核心数据:
import numpy as np save_data = { "points": vor.points, "vertices": vor.vertices, "regions": np.array(vor.regions, dtype=object), "ridge_points": vor.ridge_points, "ridge_vertices": vor.ridge_vertices, "npoints": np.array(vor.npoints), "incremental": np.array(vor.incremental) } np.savez("voronoi_state.npz", **save_data)
- 加载并恢复状态:
import numpy as np from scipy.spatial import Voronoi loaded_data = np.load("voronoi_state.npz", allow_pickle=True) # 初始化空的增量Voronoi对象 vor = Voronoi([[0,0]], incremental=True) # 覆盖初始状态 vor.points = loaded_data["points"] vor.vertices = loaded_data["vertices"] vor.regions = loaded_data["regions"].tolist() vor.ridge_points = loaded_data["ridge_points"] vor.ridge_vertices = loaded_data["ridge_vertices"] vor.npoints = loaded_data["npoints"].item() vor.incremental = loaded_data["incremental"].item() # 继续添加新点 new_point = np.array([[10.0, 10.0]]) vor.add_points(new_point)
注意:该方案依赖Scipy Voronoi的内部属性结构,不同版本可能存在兼容性问题,使用前需测试。
方案3:换用支持序列化的Voronoi实现
如果对重建开销敏感,可以考虑:
- 使用
pyhull等Qhull原生绑定库,直接操作并保存Qhull的内部状态 - 手动实现增量Voronoi算法,完全控制数据结构以支持自由序列化
内容的提问来源于stack exchange,提问作者yik_him
相关产品推荐
相关产品推荐

