2014-04-30 1 views
1

다음 코드는 처음에는 here.에서 수집되었으며 matplotlib, 매끄럽게, cartopy를 사용하여 세계지도를 그립니다.matplotlib 아티스트의 폴리곤 격납 테스트

클릭이 이루어지면 해당 국가를 확인해야합니다. 캔버스에 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() 
+0

당신은 질문이 더 도움으로 간주하고 더 많은보기를 얻을 수있다, 그래서 더 일반적인 무언가로 제목을 변경 할 수 있습니다. – Seanny123

답변

1

좋은 질문입니다. 안타깝게도, FeatureArtist는 기술적으로는 PathCollection의 하위 클래스가 아니지만 아티스트에서 상속받은 것 같습니다. 즉, 이미 확인한 바와 같이, 봉쇄 테스트는 아티스트에 정의되어 있지 않으며 실제로는 현재 상태에서 해결하기가 쉽지 않습니다.

그렇긴해도 matplotlib 포함 기능을 사용하여 접근하지 못했을 것입니다. Shapely geometries를 가지고 있고 그러한 봉쇄가 그러한 도구의 빵과 버터라는 점을 감안할 때, 나는 아티스트를 만드는 데 사용 된 매끈한 기하학을 추적하고 심문 할 것입니다. 나는 단순히의 라인을 따라하는 기능을 처리하기 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 좌표의 보류를 얻고 있었다 매 모양의 Point를 만들고 각 국가의 지오메트리에 봉쇄를 검사하는 간단한 경우입니다.

무언가 같이 전체 코드는 같습니다, 나는 또한 꽤 들어, 각 국가의 구조 "preparing"보고 할 것

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() 

봉쇄 테스트의 수가이 모양 파일 내에서보다 훨씬 더 증가하는 경우 주요 성능 향상.

HTH