Bagaimana cara memperbarui plot quiver setelah memindahkan objek di dalamnya?

Saya sedang menulis proyek visualisasi kecil yang seharusnya menunjukkan bidang vektor di sekitar beberapa benda bermuatan.

Masalah saya selanjutnya: Saya tidak tahu cara memperbarui bidang quiver setelah memindahkan lingkaran (partikel bermuatan) dari posisi utama.

Tautan ke gambar, karena reputasi saya terlalu rendah. Saya praktis baru dengan stackoverflow.

masukkan deskripsi gambar di sini

from pylab import *
from scipy import *
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import scipy.constants as const
skr = const.pi*const.epsilon_0*4

class DraggablePoint:
    def __init__(self, p, q0):
        self.q = q0
        self.point = p
        self.c_kruznice = p.center
        self.press = None

    def connect(self):
        self.cidpress = self.point.figure.canvas.mpl_connect('button_press_event', self.button_press_event) 
        self.cidrelease = self.point.figure.canvas.mpl_connect('button_release_event',self.button_release_event)   
        self.cidmotion = self.point.figure.canvas.mpl_connect('motion_notify_event', self.motion_notify_event)  

    def disconnect(self):
        self.point.figure.canvas.mpl_disconnect(self.cidpress)
        self.point.figure.canvas.mpl_disconnect(self.cidrelease)
        self.point.figure.canvas.mpl_disconnect(self.cidmotion)


    def button_press_event(self,event):
        if event.inaxes != self.point.axes:
            return
        contains = self.point.contains(event)[0]
        if not contains: return
        self.press = self.point.center, event.xdata, event.ydata


    def button_release_event(self,event):
        self.press = None
        self.point.figure.canvas.draw()

    def motion_notify_event(self, event):
        if self.press is None: return
        if event.inaxes != self.point.axes: return
        self.point.center, xpress, ypress = self.press
        dx = event.xdata - xpress
        dy = event.ydata - ypress
        self.point.center = (self.point.center[0]+dx, self.point.center[1]+dy)
        print(self.point.center)
        self.point.figure.canvas.draw()

if __name__ == '__main__':
    f_s=0.3
    def R(x,y):
        r=np.sqrt(x**2+y**2)+f_s
        return r

    def polje(tela, X, Y):
        Ex = 0
        Ey = 0
        for i in range(len(tela)):
            r=R(tela[i].c_kruznice[0] - X, tela[i].c_kruznice[1] - Y )
            ex = X - tela[i].c_kruznice[0]
            ey = Y - tela[i].c_kruznice[1]
            Ex += (tela[i].q/skr)*(1/(r+f_s)**3)*ex
            Ey += (tela[i].q/skr)*(1/(r+f_s)**3)*ey
        return Ex, Ey

    fig = plt.figure(figsize=(8,8))
    ax = fig.add_axes([0.05,0.05,0.92,0.92])
    ax.set_xlim(-6,6)
    ax.set_ylim(-6,6)
    scale = 0.2
    X,Y=np.mgrid[-5:5:scale, -5:5:scale]

    circles = []
    q=3*const.e
    s=abs(q)
    sx=sqrt(s/np.pi)*1e8*5
    circle2 = patches.Circle((3,0.3), 0.3, fc='r', alpha=0.5, picker=True)
    circle1 = patches.Circle((0.7,0.3), 0.3, fc='r', alpha=0.5, picker=True)
    circle = patches.Circle((-4,0.3), 0.3, fc='b', alpha=0.5, picker=True)
    circles.append(ax.add_patch(circle1))
    circles.append(ax.add_patch(circle))
    circles.append(ax.add_patch(circle2))
    drs = []

    for c in circles:
        print(c.center[0])
        dr = DraggablePoint(c,-1)
        dr.connect()
        drs.append(dr)

    racun=polje(drs, X, Y)
    ax.quiver(X,Y,racun[0],racun[1], color='r',  alpha=0.5)
    ax.quiver(X,Y,racun[0],racun[1], edgecolor='k', facecolor='None', linewidth =.5) 
    plt.show    ()  

person penumbra    schedule 09.06.2015    source sumber
comment
Jika Anda ingin menganimasikan gambar, lihat perpustakaan matplotlib.animation. Lihat tautan.   -  person DarthSpeedious    schedule 09.06.2015
comment
Ini adalah ide yang bagus tetapi tidak yakin itu sederhana. Saat setiap titik diklik, hal itu memicu gambar ulangnya sendiri. Plot quiver bergantung pada posisi semua titik jadi mungkin tidak boleh digambar ulang di dalam peristiwa perpindahan titik. Anda dapat meretas sesuatu tetapi untuk melakukannya dengan benar Anda mungkin memerlukan kelas lapangan, yang berisi semua poin yang terikat pada peristiwa mouse. Kelas bidang kemudian dapat memanggil pembaruan titik yang sudah Anda miliki saat memperbarui bidang...   -  person Ed Smith    schedule 09.06.2015
comment
Saya, agaknya, telah memperbaiki masalah saya. link kode 'ini' berfungsi, tetapi setiap kali saya memindahkan beberapa lingkaran saya perlu mengklik lagi untuk menyegarkan bidang tempat anak panah. Selain itu, hanya satu tambalan yang dapat dipindahkan sepenuhnya, tambalan lainnya hilang begitu saja ketika saya mencoba memindahkannya, dan kemudian menggambar ulang lagi ketika saya 'mengklik-segarkan' bidang. Saya dapat mengatakan bahwa ini dapat digunakan, beli sangat bermasalah.   -  person penumbra    schedule 11.06.2015


Jawaban (1)


Saya juga baru di sini, jadi saya akan berusaha membantu semampu saya.

Solusi yang logis bagi saya adalah memberikan indeks untuk lingkaran Anda. Setiap kali Anda memindahkan lingkaran, panggilan kelas Anda berfungsi button_release_event sebanyak lingkaran yang Anda miliki. Jadi, ketika sampai pada lingkaran terakhir (dengan indeks spesifik yang Anda berikan) Anda hanya perlu menghapus plot Anda, dan mengulanginya lagi (Anda perlu menggambar lingkaran dan bidang).

Bagian yang menarik adalah ketika memeriksa lingkaran, ia akan selalu selesai pada lingkaran pertama, dengan indeks 0. Saya tidak yakin mengapa ini terjadi, tapi ini bagus karena tidak bergantung pada berapa banyak lingkaran yang Anda miliki pada grafik Anda.

Selain itu, Anda juga harus memiliki baris self.c_kruznice = self.point.center[0], self.point.center[1], karena ini akan memperbarui pusat titik yang Anda seret sehingga dapat menghitung bidang. Dan bagian yang penting: gunakan plt.draw() untuk bidang gambar karena hanya itu yang akan memperbarui bidang Anda setelah menyeret lingkaran. Karena plt.show() menunggu Anda menyelesaikan semuanya untuk menggambarnya (itulah sebabnya ia menggambar saat Anda memulai drag berikutnya), tetapi plt.draw() melakukannya pada saat rilis.

Sunting: Anda perlu menghapus daftar circles sebelum memplot ulang (saya mengedit kode).

Ini kode dengan ide ini.

from pylab import *
from scipy import *
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import scipy.constants as const

skr = const.pi*const.epsilon_0*4

class DraggablePoint:
    global Polje
    def __init__(self, p, q0, ind):
        self.q = q0
        self.point = p
        self.c_kruznice = p.center
        self.press = None
        self.indeks = ind

    def connect(self):
        self.cidpress = self.point.figure.canvas.mpl_connect('button_press_event', self.button_press_event)
        self.cidrelease = self.point.figure.canvas.mpl_connect('button_release_event',self.button_release_event)  
        self.cidmotion = self.point.figure.canvas.mpl_connect('motion_notify_event', self.motion_notify_event)  

    def disconnect(self):
        self.point.figure.canvas.mpl_disconnect(self.cidpress)
        self.point.figure.canvas.mpl_disconnect(self.cidrelease)
        self.point.figure.canvas.mpl_disconnect(self.cidmotion)

    def button_press_event(self,event):
        if event.inaxes != self.point.axes:
            return
        contains = self.point.contains(event)[0]
        if not contains: return
        self.press = self.point.center, event.xdata, event.ydata

    def button_release_event(self,event):
        self.press = None
        self.point.figure.canvas.draw()
        # This is the part which will erase field
        # and draw for us new one
        self.c_kruznice = self.point.center[0], self.point.center[1]
        if self.indeks == 0:
            racun = polje(drs, X, Y)
            ax.cla()
            circles = []
            circles.append(ax.add_patch(circle1))
            circles.append(ax.add_patch(circle))
            circles.append(ax.add_patch(circle2))
            circles.append(ax.add_patch(circle3))
            ax.quiver(X,Y,racun[0],racun[1], color='r',  alpha=0.5)
            ax.quiver(X,Y,racun[0],racun[1], edgecolor='k', facecolor='None', linewidth =.5)
            plt.draw()

    def motion_notify_event(self, event):
        if self.press is None: return
        if event.inaxes != self.point.axes: returnO
        self.point.center, xpress, ypress = self.press
        dx = event.xdata - xpress
        dy = event.ydata - ypress
        self.point.center = (self.point.center[0]+dx, self.point.center[1]+dy)
        self.point.figure.canvas.draw()


if __name__ == '__main__':
    f_s=0.3
    def R(x,y):
        r=np.sqrt(x**2+y**2)+f_s
        return r

    def polje(tela, X, Y):
        Ex = 0
        Ey = 0
        for i in range(len(tela)):
            r = R(tela[i].c_kruznice[0] - X, tela[i].c_kruznice[1] - Y )
            ex = X - tela[i].c_kruznice[0]
            ey = Y - tela[i].c_kruznice[1]
            Ex += (tela[i].q/skr)*(1/(r+f_s)**3)*ex
            Ey += (tela[i].q/skr)*(1/(r+f_s)**3)*ey
        return Ex, Ey


    fig = plt.figure(figsize=(8,8))
    ax = fig.add_axes([0.05,0.05,0.92,0.92])
    ax.set_xlim(-6,6)
    ax.set_ylim(-6,6)
    scale = 0.2
    X,Y=np.mgrid[-5:5:scale, -5:5:scale]

    circles = []
    q=3*const.e
    s=abs(q)
    sx=sqrt(s/np.pi)*1e8*5
    circle2 = patches.Circle((2,3), 0.3, fc='r', alpha=0.5, picker=True)
    circle1 = patches.Circle((2,-3), 0.3, fc='r', alpha=0.5, picker=True)
    circle = patches.Circle((-2,3), 0.3, fc='b', alpha=0.5, picker=True)
    circle3 = patches.Circle((-2,-3), 0.3, fc = 'b', alpha = 0.5, picker = True )
    circles.append(ax.add_patch(circle1))
    circles.append(ax.add_patch(circle))
    circles.append(ax.add_patch(circle2))
    circles.append(ax.add_patch(circle3))
    drs = []

    i = 0
    q = [-1, 1, -1, 1]
    for c in circles:
        dr = DraggablePoint(c, q[i], i)
        dr.connect()
        drs.append(dr)
        i += 1

    racun = polje(drs, X, Y)
    ax.quiver(X,Y,racun[0],racun[1], color='r',  alpha=0.5)
    ax.quiver(X,Y,racun[0],racun[1], edgecolor='k', facecolor='None', linewidth =.5)
    plt.show()
person Dusan V    schedule 11.06.2015
comment
Terima kasih!!! Ini sebenarnya yang saya inginkan. Setelah ini, saya memperbarui ke N visualisasi tubuh dalam beberapa detik. - person penumbra; 11.06.2015