gpt4 book ai didi

python - matplotlib 艺术家中的多边形包含测试

转载 作者:太空宇宙 更新时间:2023-11-04 03:46:45 26 4
gpt4 key购买 nike

我有以下代码,最初是从 here. 收集的,它使用 matplotlib、shapely、cartopy 绘制世界地图。

进行点击时,我需要确定点击是在哪个国家/地区进行的。我可以向 Canvas 添加一个 pick_event 回调,但是,每个艺术家都会调用它。(cartopy.mpl.feature_artist.FeatureArtist,对应于一个国家)。

给定一个艺术家和一个具有 x、y 坐标的鼠标事件,我如何确定包含?

我试过 artist.get_clip_box().contains,但它并不是真正的多边形,而是一个普通的矩形。

FeatureArist 的默认包含测试是None,因此我必须添加自己的包含测试。

如何正确检查鼠标事件点是否包含在 FeatureArtist 中?

import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import cartopy.io.shapereader as shpreader
import itertools, pdb, subprocess, time, traceback
from itertools import *
import numpy as np
from pydoc import help as h

shapename = 'admin_0_countries'
countries_shp = shpreader.natural_earth(resolution='110m',
category='cultural', name=shapename)

earth_colors = np.array([(199, 233, 192),
(161, 217, 155),
(116, 196, 118),
(65, 171, 93),
(35, 139, 69),
]) / 255.
earth_colors = itertools.cycle(earth_colors)

ax = plt.axes(projection=ccrs.PlateCarree())


def contains_test ( artist, ev ):
print "contain test called"
#this containmeint test is always true, because it is a large rectangle, not a polygon
#how to define correct containment test
print "click contained in %s?: %s" % (artist.countryname, artist.get_clip_box().contains(ev.x, ev.y))
return True, {}

for country in shpreader.Reader(countries_shp).records():
# print country.attributes['name_long'], earth_colors.next()
art = ax.add_geometries(country.geometry, ccrs.PlateCarree(),
facecolor=earth_colors.next(),
label=country.attributes['name_long'])

art.countryname = country.attributes["name_long"]
art.set_picker(True)
art.set_contains(contains_test)
def pickit ( ev ):
print "pickit called"
print ev.artist.countryname



def onpick ( event ):
print "pick event fired"

ax.figure.canvas.mpl_connect("pick_event", onpick)


def onclick(event):
print 'button=%s, x=%s, y=%s, xdata=%s, ydata=%s'%(event.button, event.x, event.y, event.xdata, event.ydata)

ax.figure.canvas.mpl_connect('button_press_event', onclick)
plt.show()

最佳答案

好问题。遗憾的是,FeatureArtist 似乎不是 PathCollection 的子类,从技术上讲它应该是,但它只是继承自 Artist。这意味着,正如您已经发现的那样,收容测试并未针对艺术家定义,事实上,在其当前状态下解决起来并不是特别容易。

也就是说,我可能不会使用 matplotlib 包含功能来解决这个问题;鉴于我们有 Shapely 几何形状,并且这种包容性是这种工具的面包和黄油,我会跟踪创造艺术家的形状几何形状,并询问它。然后我会简单地使用如下函数连接到 matplotlib 的通用事件处理:

def onclick(event):
if event.inaxes and isinstance(event.inaxes, cartopy.mpl.geoaxes.GeoAxes):
ax = event.inaxes
target = ccrs.PlateCarree()
lon, lat = target.transform_point(event.xdata, event.ydata,
ax.projection)
point = sgeom.Point(lon, lat)
for country, (geom, artist) in country_to_geom_and_artist.items():
if geom.contains(point):
print 'Clicked on {}'.format(country)
break

此函数的难点在于根据纬度和经度获取 x 和 y 坐标,但在那之后,创建一个形状匀称的点并检查每个国家/地区的几何形状的包含度是一个简单的例子。

完整的代码看起来像这样:

import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import cartopy.io.shapereader as shpreader
import cartopy.mpl.geoaxes
import itertools
import numpy as np
import shapely.geometry as sgeom


shapename = 'admin_0_countries'
countries_shp = shpreader.natural_earth(resolution='110m',
category='cultural', name=shapename)

earth_colors = np.array([(199, 233, 192), (161, 217, 155),
(116, 196, 118), (65, 171, 93),
(35, 139, 69)]) / 255.
earth_colors = itertools.cycle(earth_colors)

ax = plt.axes(projection=ccrs.Robinson())

# Store a mapping of {country name: (shapely_geom, cartopy_feature)}
country_to_geom_and_artist = {}

for country in shpreader.Reader(countries_shp).records():
artist = ax.add_geometries(country.geometry, ccrs.PlateCarree(),
facecolor=earth_colors.next(),
label=repr(country.attributes['name_long']))
country_to_geom_and_artist[country.attributes['name_long']] = (country.geometry, artist)


def onclick(event):
if event.inaxes and isinstance(event.inaxes, cartopy.mpl.geoaxes.GeoAxes):
ax = event.inaxes
target = ccrs.PlateCarree()
lon, lat = target.transform_point(event.xdata, event.ydata,
ax.projection)
point = sgeom.Point(lon, lat)
for country, (geom, artist) in country_to_geom_and_artist.items():
if geom.contains(point):
print 'Clicked on {}'.format(country)
break

ax.figure.canvas.mpl_connect('button_press_event', onclick)
plt.show()

如果遏制测试的数量比这个形状文件中的数量增加得多,我也会查看 "preparing"每个国家/地区的几何形状,以获得相当大的性能提升。

HTH

关于python - matplotlib 艺术家中的多边形包含测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23399704/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com