2013-05-13 36 views
10

Lấy cảm hứng từ this example Tôi đang cố gắng viết một chương trình matplotlib nhỏ cho phép người dùng kéo và thả các điểm dữ liệu trong một ô phân tán động. Ngược lại với ví dụ sử dụng cốt truyện (và do đó cho phép kéo hình chữ nhật), mục tiêu của tôi là đạt được cùng với các bản vá khác, ví dụ như một vòng tròn (bất kỳ bản vá nào tương thích với âm mưu hơn so với hình chữ nhật)). Tuy nhiên tôi đang bị mắc kẹt tại thời điểm cập nhật vị trí của bản vá của tôi. Trong khi Rectangle cung cấp chức năng set_xy Tôi không thể tìm thấy trực tiếp tương tự cho Cirlce hoặc Ellipse. Việc lấy vị trí của một vòng tròn cũng ít đơn giản hơn đối với hình chữ nhật, nhưng có thể thông qua việc thu được hộp giới hạn. Phần còn thiếu bây giờ là tìm cách cập nhật vị trí của bản vá của tôi. Bất kỳ gợi ý về cách để đạt được điều này sẽ là tuyệt vời! Các tối thiểu dụ làm việc hiện tại sẽ trông như thế này:matplotlib: cập nhật vị trí của các bản vá lỗi (hoặc: set_xy cho các vòng tròn)

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

Trả lời

11

Đó là một chút phiền phức là nó không phù hợp, nhưng để cập nhật vị trí của một vòng tròn, thiết circ.center = new_x, new_y.

Là một đơn giản (không kéo) ví dụ:

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

Cảm ơn bạn rất nhiều, mà đã làm các trick! Vì tôi luôn ủng hộ khái niệm RTFM, tôi tự hỏi mình có thể tìm thấy thông tin này ở đâu? Tôi không thể nhìn thấy nó trong [patches.Circle] (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) hoặc [artist.Artist] (http://matplotlib.org/api/artist_api.html?highlight=patches.circle#matplotlib.artist.Artist). – bluenote10

+2

Thật không may, nó không có giấy tờ. Tôi phải đào sâu mã để tìm nó ('ipython' cũng là một trợ giúp lớn). Những loại "góc" của matplotlib chắc chắn cần tài liệu tốt hơn ... –

+0

@JoeKington Vì vậy, làm thế nào để tôi làm điều này cho một vòng cung? Tôi không muốn di chuyển trung tâm của nó thay vì tôi muốn thay đổi bắt đầu và kết thúc của nó theta tức là sự lây lan của vòng cung. –

Các vấn đề liên quan