matplotlib.patches.Polygon的contains_point()方法add_patch后失效问题
嘿,我刚好踩过这个坑!你遇到的问题核心是坐标系统不匹配——matplotlib.patches.Polygon的contains_point()默认是基于屏幕显示坐标(像素)判断的,但你大概率是传入了数据坐标,而且调用add_patch()后,补丁和坐标轴的变换系统绑定,这就直接导致判断逻辑失效了。
下面给你两种靠谱的解决方法,全程只用matplotlib,完全不用依赖shapely:
第一步:理解问题根源
当你把Polygon通过add_patch()添加到轴(Axes)后,补丁的顶点存储的是数据坐标,但contains_point()默认接收的是经过轴变换后的屏幕像素坐标。直接传数据点进去,相当于用数据坐标系的数值去匹配像素位置,结果肯定不对。
第二步:两种正确的判断方式
方式1:手动转换数据点到显示坐标
利用轴的transData变换,把你的数据点转换成屏幕坐标后再传入判断:
import matplotlib.pyplot as plt from matplotlib.patches import Polygon # 初始化图表和轴 fig, ax = plt.subplots() # 创建多边形补丁(用数据坐标定义顶点) poly_verts = [(0, 0), (2, 0), (2, 2), (0, 2)] poly = Polygon(poly_verts, facecolor="#a8e6cf") ax.add_patch(poly) # 设置轴范围确保多边形可见 ax.set_xlim(-0.5, 2.5) ax.set_ylim(-0.5, 2.5) # 要判断的目标数据点 test_point = (1, 1) # 把数据点转换为屏幕显示坐标 display_point = ax.transData.transform(test_point) # 执行判断 is_inside = poly.contains_point(display_point) print(f"点{test_point}是否在多边形内:{is_inside}") # 会返回True
方式2:直接给contains_point()传入变换参数
contains_point()本身支持传入transform参数,指定你的点使用的坐标系统,它会自动帮你完成转换:
# 沿用上面的初始化代码... # 直接传入数据点,同时指定坐标变换为轴的transData is_inside = poly.contains_point(test_point, transform=ax.transData) print(f"点{test_point}是否在多边形内:{is_inside}") # 同样返回True
迭代更新补丁后的注意事项
如果你是逐迭代更新补丁的顶点(比如动态修改多边形形状),要记住:
- 不要直接修改补丁的
verts属性,一定要用poly.set_verts(new_verts)方法,这样matplotlib会同步更新内部的变换缓存。 - 更新后的判断逻辑和上面完全一致,不需要额外调整——因为补丁始终绑定着轴的
transData变换,只要用对坐标系统就没问题。
内容的提问来源于stack exchange,提问作者dinatrina
相关产品推荐
相关产品推荐

