2013-05-13 10 views
10

Zainspirowany przez this example Próbuję napisać mały program matplotlib, który pozwala użytkownikowi na dynamiczne przeciąganie i upuszczanie punktów danych na wykresie punktowym. W przeciwieństwie do przykładu, który używa wykresu słupkowego (i tym samym pozwala na przeciąganie prostokątów) moim celem było osiągnięcie tego samego z innymi łatami, jak na przykład kółko (każda łatka, która jest bardziej kompatybilna z działaniem rozproszonym niż prostokąt zrobiłby to). Jednak utknąłem w punkcie aktualizacji pozycji mojego patcha. Chociaż Rectangle zapewnia funkcję set_xy, nie mogę znaleźć bezpośredniego analogu dla Cirlce lub Ellipse. Uzyskanie pozycji koła jest również mniej proste niż w przypadku prostokąta, ale jest możliwe poprzez uzyskanie obwiedni. Brakujący element polega teraz na znalezieniu sposobu na aktualizację położenia mojej poprawki. Każda wskazówka, jak to osiągnąć, byłaby świetna! Obecna minimalna przykład praca będzie wyglądać następująco:matplotlib: zaktualizuj położenie łatek (lub: set_xy dla okręgów)

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

Odpowiedz

11

To trochę irytujące, że jest to sprzeczne, ale do aktualizowania położenia okręgu ustaw circ.center = new_x, new_y.

Jako prosty (nie przeciągać) Przykład:

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

Dziękuję bardzo, że załatwiło sprawę! Ponieważ zawsze opowiadam się za koncepcją RTFM, zastanawiam się, gdzie mogę znaleźć te informacje? Nie widzę tego w [patchs.Kircle] (http://matplotlib.org/api/artist_api.html?highlight=patches.circle#matplotlib.patches.Circle), [patches.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) lub [artist.Artist] (http://matplotlib.org/api/artist_api.html?highlight=patches.circle#matplotlib.artist.Artist). – bluenote10

+2

Niestety, jest to nieudokumentowane. Musiałem przekopać kod, aby go znaleźć ("ipython" jest również dużą pomocą). Tego rodzaju "narożniki" matplotlib zdecydowanie wymagają lepszej dokumentacji ... –

+0

@JoeKington Więc jak mam to zrobić dla łuku? Nie chcę przesuwać jego środka, a raczej chcę zmienić początek i koniec theta, czyli rozprzestrzenienie się łuku. –

Powiązane problemy