2016-09-23 58 views
0

我正在嘗試使用Matplotlib和matplotlib製作的動畫包做一個3d繪圖。另外,動畫應該是使用PyQt和Qt-Designer生成的Gui的一部分。目前我卡上使用「animation.Funcnimation()」正確的,至少我這麼認爲...... 因此,這裏是我的代碼:Python:使用mplot3d和動畫製作矢量動畫

import sys 
from PyQt4.uic import loadUiType 
from PyQt4 import QtGui 

from matplotlib import pyplot as plt 
from mpl_toolkits.mplot3d import Axes3D 
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas 
from matplotlib import animation 

import numpy as np 
import Quaternion as qt 

Ui_MainWindow, QMainWindow = loadUiType('Newsphere.ui') 

class Kinematic(Ui_MainWindow, QMainWindow): 
    def __init__(self): 
     super(Kinematic, self).__init__() 
     self.setupUi(self) 

     self.fig = plt.figure() 
     self.ax = self.fig.add_subplot(111,projection = '3d') 
     self.fig.tight_layout() 

     self.ani = animation.FuncAnimation(self.fig, self.update, 
             init_func=self.setup_plot, blit=True) 

     self.canvas = FigureCanvas(self.fig) 
     self.mplvl.addWidget(self.canvas) 
     self.canvas.draw() 

    def setup_plot(self): 
     self.ax.view_init(40, 45) 

     self.ax.set_xlabel('X') 
     self.ax.set_ylabel('Y') 
     self.ax.set_zlabel('Z') 

     self.ax.set_xlim3d(-1,1) 
     self.ax.set_ylim3d(-1,1) 
     self.ax.set_zlim3d(-1,1) 

     g_x = np.matrix([[1.0],[0.0],[0.0]]) 
     g_y = np.matrix([[0.0],[1.0],[0.0]]) 
     g_z = np.matrix([[0.0],[0.0],[1.0]]) 

     self.ax.plot([0,g_x[0]], [0,g_x[1]], [0,g_x[2]], label='$X_0$') 
     self.ax.plot([0,g_y[0]], [0,g_y[1]], [0,g_y[2]], label='$Y_0$') 
     self.ax.plot([0,g_z[0]], [0,g_z[1]], [0,g_z[2]], label='$Z_0$') 

     self.vek, = self.ax.plot([0,-1], [0,0], [0,0], label='$g \cdot R$', animated=True) 

     self.ax.legend(loc='best') 
     self.ax.scatter(0,0,0, color='k') 

     return self.vek, 

    def update(self, i): 
     b = self.bslider.value()/100 

     g = np.matrix([[1.0],[0.0],[0.0]]) 
     q = np.array([0,b,0.5,0]) 

     R = qt.QtoR(q) 
     x, y, z = R*g 

     self.vek, = self.ax.plot([0,x], [0,y], [0,z], label='$g \cdot R$', animated=True) #the rotated vector 
     return self.vek, 

if __name__ == '__main__': 

app = QtGui.QApplication(sys.argv) 

main = Kinematic() 
main.show() 

sys.exit(app.exec_()) 

您將無法通過只運行它複製粘貼,因爲你沒有文件「Newsphere.ui」(第13行)和Quaternion.py(第11行)。所以當我運行它時,我會得到以下(實際上就像我希望的那樣): Coordinate system

我的目標是使用我得到的數據繪製一個矢量(第50行)並使其動畫(第66行)桂滑塊(58行)。誰能幫我這個?我堅持了幾天!

+2

請創建一個[最小,完整,可驗證的示例](http://stackoverflow.com/help/mcve) –

+0

爲此,我必須轉換我的GUI .ui文件,這需要很長時間,對不起。但我明白了,看到我的答案在下面! – Michael

+0

如果解決了您的問題,請不要忘記接受答案。 –

回答

0

所以,如果有人對上述問題的解決方案感興趣,下面我們就去:(再次,它不是複製粘貼代碼,因爲缺少'Newsphere.ui',但我試圖解釋重要的代碼片段)

import sys 
from PyQt4.uic import loadUiType 
from PyQt4 import QtGui 

from matplotlib import pyplot as plt 
from mpl_toolkits.mplot3d import Axes3D 
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas 
from matplotlib import animation 

import numpy as np 

Ui_MainWindow, QMainWindow = loadUiType('Newsphere.ui') 

class Kinematic(Ui_MainWindow, QMainWindow): 

    def __init__(self): 
     super(Kinematic, self).__init__() 
     self.setupUi(self) 

     self.fig = plt.figure() 
     self.ax = self.fig.add_subplot(111,projection = '3d') 
     self.fig.tight_layout() 
     self.ax.view_init(40, -45) 

     # dashed coordinate system 
     self.ax.plot([0,1], [0,0], [0,0], label='$X_0$', linestyle="dashed") 
     self.ax.plot([0,0], [0,-1], [0,0], label='$Y_0$', linestyle="dashed") 
     self.ax.plot([0,0], [0,0], [0,1], label='$Z_0$', linestyle="dashed") 

     self.ax.set_xlim3d(-1,1) 
     self.ax.set_ylim3d(-1,1) 
     self.ax.set_zlim3d(-1,1) 

     self.ax.set_xlabel('X') 
     self.ax.set_ylabel('Y') 
     self.ax.set_zlabel('Z') 

     self.ax.scatter(0,0,0, color='k') # black origin dot 

     self.canvas = FigureCanvas(self.fig) 
     self.mplvl.addWidget(self.canvas) 

     self.ani = animation.FuncAnimation(self.fig, self.data_gen, init_func=self.setup_plot, blit=True) 

    def setup_plot(self): 

     self.ax.legend(loc='best') 

     self.vek = self.ax.quiver(0, 0, 0, 0, 0, 0, label='$g \cdot R$', pivot="tail", color="black") 

     return self.vek, 

    def data_gen(self, i): 

     b = self.bslider.value()/100 

     vx, vy, vz = np.cos(b), np.sin(b), 0 

     self.vek = self.ax.quiver(0, 0, 0, vx, vy, vz, label='$g \cdot R$', pivot="tail", color="black") 

     self.canvas.draw() 

     return self.vek, 

if __name__ == '__main__': 

    app = QtGui.QApplication(sys.argv) 

    main = Kinematic() 
    main.show() 

    sys.exit(app.exec_()) 

通過運行代碼我得到

enter image description here

(這是兩個圖片結合在一個示出的相同的處理)

我生成了一個名爲Newsphere.ui的GUI文件,下面是this tutorial。基本上它只包含一個Widget,一個QSlider和一個QSpinBox。 Widget的佈局名稱爲「mplvl」,它在第41行出現。這會將生成的圖形添加到窗口小部件(我認爲是這樣)。 QSlider與QSpinBox連接(在QtDesigner中完成),名稱爲「bslider」,第55行。因此,在這一行中,slider-value除以100,因爲我沒有找到一個生成浮點值的滑塊。對我來說,關鍵是第61行,繪製畫布的地方。現在當我更改滑塊值時,animation.FuncAnimation(第43行)繪製了一個新的矢量,比較了圖片。同樣重要的是將變化的矢量繪製爲ax.quiver而不是像我以前的嘗試中那樣繪製爲ax.plot

如果有任何問題或建議需要改進,請詢問/發佈。

2

由於您的問題與動畫部分有關,因此您可以在下面看到一個爲正在旋轉的箭頭設置動畫的片段。

import numpy as np 
from mpl_toolkits.mplot3d import Axes3D 
import matplotlib.pyplot as plt 
import matplotlib.animation as animation 


def data_gen(num): 
    """Data generation""" 
    angle = num * np.pi/36  
    vx, vy, vz = np.cos(angle), np.sin(angle), 1 
    ax.cla() 
    ax.quiver(0, 0, 0, vx, vy, vz, pivot="tail", color="black") 
    ax.quiver(0, 0, 0, vx, vy, 0, pivot="tail", color="black", 
       linestyle="dashed") 
    ax.set_xlim(-1, 1) 
    ax.set_ylim(-1, 1) 
    ax.set_zlim(-1, 1) 
    ax.view_init(elev=30, azim=60) 


fig = plt.figure() 
ax = fig.add_subplot(111, projection='3d') 
data_gen(0) 
ani = animation.FuncAnimation(fig, data_gen, range(72), blit=False) 
plt.show() 

有關動畫的文檔可能不是最好的。但有幾個例子,例如,這個動畫Lorenz attractor

+0

感謝您的回覆!在你的片段和Lorenz吸引子的鏈接的幫助下,我發現了它。我將在單獨的答案中發佈我的解決方案... – Michael