2013-05-13 10 views
10

Inspired by this example Kullanıcının veri akışlarını dinamik olarak bir dağılım grafiğinde sürükleyip bırakmasını sağlayan küçük bir matplotlib programı yazmaya çalışıyorum. Bir çubuk çizimi kullanan örneğe (ve böylece dikdörtgenlerin sürüklenmesine izin verir) tersine, amacım, örneğin bir daire gibi diğer yamalarla aynı şeyi elde etmekti (bir dikdörtgenden daha fazla dağılım-arsa uyumlu olan herhangi bir yama). Ancak, yamalarımın konumunu güncelleme noktasında sıkışıp kaldım. Rectangle, set_xy işlevini sağlarken Cirlce veya Ellipse için doğrudan bir analog bulamıyorum. Bir dairenin pozisyonunun elde edilmesi, bir dikdörtgenin, ancak sınırlama kutusunun elde edilmesiyle mümkün olduğu için daha basittir. Kayıp parça şimdi, yamamın konumunu güncellemenin bir yolunu bulmak. Bunun nasıl başarılacağına dair herhangi bir ipucu harika olurdu! Geçerli asgari çalışma örneği şu şekilde görünecektir:matplotlib: yamalar konumunu güncelle (veya: daireler için set_xy)

import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib.patches as patches 

class DraggablePatch: 

    def __init__(self, patch): 
    self.patch = patch 
    self.storedPosition = None 
    self.connect() 

    def getPosOfPatch(self, marker): 
    ext = marker.get_extents().get_points() 
    x0 = ext[0,0] 
    y0 = ext[0,1] 
    x1 = ext[1,0] 
    y1 = ext[1,1] 
    return 0.5*(x0+x1), 0.5*(y0+y1) 

    def connect(self): 
    'connect to all the events we need' 
    self.cidpress = self.patch.figure.canvas.mpl_connect('button_press_event', self.onPress) 
    self.cidmotion = self.patch.figure.canvas.mpl_connect('motion_notify_event', self.onMove) 

    def onPress(self, event): 
    'on button press we will see if the mouse is over us and store some data' 
    contains, attrd = self.patch.contains(event) 
    if contains: 
     self.storedPosition = self.getPosOfPatch(self.patch), event.xdata, event.ydata 

    def onMove(self, event): 
    'how to update an circle?!' 
    contains, attrd = self.patch.contains(event) 
    if contains and self.storedPosition is not None: 
     oldPos, oldEventXData, oldEventYData = self.storedPosition 
     dx = event.xdata - oldEventXData 
     dy = event.ydata - oldEventYData 
     newX = oldPos[0] + dx 
     newY = oldPos[1] + dy 
     print "now I would like to move my patch to", newX, newY 


def myPatch(x,y): 
    return patches.Circle((x,y), radius=.05, alpha=0.5) 

N = 10 
x = np.random.random(N) 
y = np.random.random(N) 
patches = [myPatch(x[i], y[i]) for i in range(N)] 

fig = plt.figure() 
ax = fig.add_subplot(111) 
drs = [] 
for patch in patches: 
    ax.add_patch(patch) 
    dr = DraggablePatch(patch) 
    drs.append(dr) 

plt.show() 

cevap

11

O tutarsız, ama bir dairenin konumunu güncellemek için bu biraz sinir bozucu, circ.center = new_x, new_y ayarlayın. Basit (non-sürüklenebilir) örnek olarak

:

import matplotlib.pyplot as plt 
from matplotlib.patches import Circle 

class InteractiveCircle(object): 
    def __init__(self): 
     self.fig, self.ax = plt.subplots() 
     self.ax.axis('equal') 

     self.circ = Circle((0.5, 0.5), 0.1) 
     self.ax.add_artist(self.circ) 
     self.ax.set_title('Click to move the circle') 

     self.fig.canvas.mpl_connect('button_press_event', self.on_click) 

    def on_click(self, event): 
     if event.inaxes is None: 
      return 
     self.circ.center = event.xdata, event.ydata 
     self.fig.canvas.draw() 

    def show(self): 
     plt.show() 


InteractiveCircle().show() 
+0

hile yaptığını, çok teşekkür ederiz! Her zaman RTFM konseptini savunduğumdan, bu bilgiyi nereden bulabileceğimi merak ediyorum. [Patches.Circle] içinde göremiyorum (http://matplotlib.org/api/artist_api.html?highlight=patches.circle#matplotlib.patches.Circle), [yaches.Ellipse] (http: // matplotlib.org/api/artist_api.html?highlight=patches.circle#matplotlib.patches.Ellipse), [patches.Patch] (http://matplotlib.org/api/artist_api.html?highlight=patches.circle#matplotlib .patches.Patch) veya [artist.Artist] (http://matplotlib.org/api/artist_api.html?highlight=patches.circle#matplotlib.artist.Artist). – bluenote10

+2

Ne yazık ki, belgelenmemiş. Onu bulmak için kodu kazmak zorunda kaldım ('ipython 'da büyük bir yardımdır). Matplotlib'in bu tür "köşeleri" kesinlikle daha iyi belgelere ihtiyaç duyar ... –

+0

@JoeKington Peki bunu bir yay için nasıl yapabilirim? Merkezini hareket ettirmek istemiyorum, onun başlangıcını ve bitişini değiştirmek istiyorum, yani yayının yayılmasını istiyorum. –