จะอัพเดต quiver plot หลังจากย้ายวัตถุไปได้อย่างไร?

ฉันกำลังเขียนโปรเจ็กต์การสร้างภาพขนาดเล็กซึ่งควรจะแสดงสนามเวกเตอร์รอบๆ วัตถุที่มีประจุเพียงไม่กี่ตัว

ปัญหาของฉันคือต่อไป: ฉันไม่รู้วิธีอัปเดตฟิลด์สั่นหลังจากเคลื่อนที่วงกลม (อนุภาคที่มีประจุ) จากตำแหน่งหลัก

ลิงก์ไปยังรูปภาพ เนื่องจากชื่อเสียงของฉันต่ำเกินไป ฉันยังใหม่กับ stackoverflow

ป้อนคำอธิบายรูปภาพที่นี่

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 แหล่งที่มา
comment
หากคุณต้องการสร้างภาพเคลื่อนไหว ให้ดูที่ไลบรารี matplotlib.animation ดูลิงก์.   -  person DarthSpeedious    schedule 09.06.2015
comment
นี่เป็นความคิดที่ดี แต่ไม่แน่ใจว่ามันง่าย เมื่อคลิกแต่ละจุด มันจะทริกเกอร์การวาดใหม่ของตัวเอง แผนภาพสั่นขึ้นอยู่กับตำแหน่งของจุดทั้งหมด ดังนั้นจึงไม่ควรวาดใหม่ภายในเหตุการณ์การย้ายจุด คุณสามารถแฮ็กบางสิ่งบางอย่างได้ แต่เพื่อให้ทำอย่างถูกต้องคุณอาจต้องมีคลาสภาคสนามที่มีประเด็นทั้งหมดซึ่งเป็นสิ่งที่เชื่อมโยงกับเหตุการณ์ของเมาส์ คลาสฟิลด์สามารถเรียกการอัปเดตจุดที่คุณมีอยู่แล้วขณะอัปเดตฟิลด์...   -  person Ed Smith    schedule 09.06.2015
comment
ฉันแก้ไขปัญหาของฉันแล้ว link โค้ด 'นี้' ใช้งานได้ แต่ทุกครั้งที่ฉันย้ายวงกลม ฉันต้องคลิกอีกครั้งเพื่อรีเฟรชฟิลด์ตัวสั่น นอกจากนี้ มีเพียงแพตช์เดียวเท่านั้นที่สามารถเคลื่อนย้ายได้ทั้งหมด ส่วนแพตช์อื่นๆ ก็หายไปเมื่อฉันพยายามย้าย และวาดใหม่อีกครั้งเมื่อฉันฟิลด์ 'คลิกรีเฟรช' พูดได้เลยว่ามันใช้งานได้ ซื้อรถมาก   -  person penumbra    schedule 11.06.2015


คำตอบ (1)


ฉันยังใหม่ที่นี่ ดังนั้นฉันจะพยายามช่วยเหลือให้มากที่สุด

วิธีแก้ปัญหาซึ่งสมเหตุสมผลสำหรับฉันคือการจัดทำดัชนีให้กับแวดวงของคุณ ทุกครั้งที่คุณย้ายแวดวง การเรียกชั้นเรียนของคุณจะทำหน้าที่ button_release_event แวดวงให้มากที่สุดเท่าที่คุณมี ดังนั้น เมื่อถึงวงกลมสุดท้าย (ด้วยดัชนีเฉพาะที่คุณให้ไว้) คุณเพียงแค่ต้องลบโครงเรื่องของคุณออก และทำซ้ำทั้งหมดอีกครั้ง (คุณต้องวาดวงกลมและฟิลด์)

ส่วนที่น่าสนใจคือเมื่อตรวจสอบวงกลม มันจะจบที่วงกลมแรกเสมอ โดยมีดัชนี 0 ฉันไม่แน่ใจว่าทำไมมันถึงเกิดขึ้น แต่มันดีมากเพราะมันไม่ขึ้นอยู่กับจำนวนวงกลมที่คุณมีบนกราฟของคุณ

นอกจากนี้ คุณต้องมีบรรทัด self.c_kruznice = self.point.center[0], self.point.center[1] เนื่องจากมันจะอัปเดตจุดศูนย์กลางของจุดที่คุณลากเพื่อให้สามารถคำนวณฟิลด์ได้ และส่วนสำคัญ: ใช้ plt.draw() สำหรับการวาดฟิลด์ เพราะจะอัปเดตฟิลด์ของคุณหลังจากลากวงกลมเท่านั้น เนื่องจาก plt.show() รอให้คุณทำทุกอย่างให้เสร็จสิ้นเพื่อวาดมัน (นั่นคือสาเหตุที่มันวาดเมื่อคุณเริ่มลากครั้งถัดไป) แต่ plt.draw() ให้ทำในขณะที่ปล่อย

แก้ไข: คุณต้องล้างรายการ circles ก่อนที่จะพล็อตใหม่ (ฉันแก้ไขโค้ดแล้ว)

นี่คือรหัสที่มีแนวคิดนี้

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
ขอบคุณ!!! นี่คือสิ่งที่ฉันต้องการจริงๆ หลังจากนี้ ฉันอัปเดตเป็นการแสดงภาพ N Body ภายในไม่กี่วินาที - person penumbra; 11.06.2015