使用matplotlib使用旋转矩阵旋转图形

时间:2016-12-16 18:47:36

标签: python matplotlib rotational-matrices

我想在2D空间中旋转图形(由线条组成)。我使用这种技术: (1)我翻译原点的数字。旋转点位于(0,0) (2)我执行旋转 (3)我把数字放回去

问题来自我的旋转功能。不知道为什么它不起作用,因为我使用了旋转矩阵。您不需要查看整个代码,只需查看"旋转"功能和" animate"功能。你会看到我发表评论来帮助你。

如果你执行整个事情,你会看到一条线缓慢移动。我不知道它是什么,但它不是预期的结果。我应该看到我的身影旋转。

如果你不进行旋转并且只翻译两次(我的程序的步骤(1)和步骤(3)),你会看到整个图形没有移动(因为我将它移动到中心所以是预期的把它放回去的地方)你可以看到这个图的样子。所以唯一的问题来自旋转功能。

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
import pylab as pl
import math

#Deplacement de la base pour pouvoir utiliser la matrice de rotation
def center(x,y,c):
    for i in range(len(x)):
        x[i] = x[i] - c[0]
    for i in range(len(y)):
        y[i] = y[i] - c[1]
    return None

#Remettre la base à sa place
def recenter(x,y,c):
    for i in range(len(x)):
        x[i] = x[i] + c[0]
    for i in range(len(y)):
        y[i] = y[i] + c[1]
    return None

#Rotation
def rotation(x,y,angle):
    my_list = [[],[]]
    for i in range(len(x)):
        my_list[0].append(x[i]*math.cos(angle) + y[i]*math.sin(angle))
    for j in range(len(y)):
        my_list[1].append(x[i]*math.sin(angle)*(-1) + y[i]*math.cos(angle))
    return my_list

#Here is the rotation matrix
#cos sin
#-sin cos

# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(-125, 125), ylim=(-250, 250))
line, = ax.plot([], [], lw=2)

#Les lignes du tableau
plt.plot([0, 125], [50, 50], color='k', linestyle='-', linewidth=2)
plt.plot([0, 125], [200, 200], color='k', linestyle='-', linewidth=2)
plt.plot([17.5, 107.5], [80, 80], color='k', linestyle='-', linewidth=2)
plt.plot([17.5, 107.5], [110, 110], color='k', linestyle='-', linewidth=2)
plt.plot([17.5, 107.5], [140, 140], color='k', linestyle='-', linewidth=2)
plt.plot([17.5, 107.5], [170, 170], color='k', linestyle='-', linewidth=2)
plt.plot([17.5, 17.5], [80, 170], color='k', linestyle='-', linewidth=2)
plt.plot([17.5, 17.5], [80, 170], color='k', linestyle='-', linewidth=2)
plt.plot([47.5, 47.5], [80, 170], color='k', linestyle='-', linewidth=2)
plt.plot([77.5, 77.5], [80, 170], color='k', linestyle='-', linewidth=2)
plt.plot([107.5, 107.5], [80, 170], color='k', linestyle='-', linewidth=2)

# initialization function: plot the background of each frame
def init():
    line.set_data([], [])
    return line,

# animation function. This is called sequentially
def animate(i):
    c1 = 62.5
    c2 = 10
    pt_rot = (c1, c2) #Point from which I want to rotate
    x = [47.5, 47.5, 77.5, 77.5, 47.5, 62.5, c1, 57.5, 67.5]
    y = [15, 45, 45, 15, 15, 15, c2, 10, 10]

    center(x,y,pt_rot)
    #Uncomment these 3 following lines to test the double translation
    my_list = rotation(x,y,(i/180))
    x = my_list[0]
    y = my_list[1]
    recenter(x, y, pt_rot)

    line.set_data(x,y)

    return line,

# call the animator.  blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=200, interval=20, blit=True)

plt.show()

1 个答案:

答案 0 :(得分:2)

您的脚本中存在两个主要问题:

  1. 在轮换功能中,您允许j循环,但在x方面设置yi,这是第一个循环后的常量。

  2. 您可以用度数设置旋转角度。但是,三角函数需要在辐射中设置角度。所以基本上你需要将角度乘以2pi。

  3. 第三点不是真正的问题,但让脚本难以阅读的是你在翻译函数中返回None。如果每个函数返回一些值,我会发现它更容易阅读,并且会将这些值放回下一个函数。

    这是一个完整的可运行脚本。

    import numpy as np
    from matplotlib import pyplot as plt
    from matplotlib import animation
    import math
    
    
    def center(x,y,c):
        for i in range(len(x)):
            x[i] = x[i] - c[0]
        for i in range(len(y)):
            y[i] = y[i] - c[1]
        # return x,y  <--------------------- here 
        return x,y
    
    def recenter(x,y,c):
        for i in range(len(x)):
            x[i] = x[i] + c[0]
        for i in range(len(y)):
            y[i] = y[i] + c[1]
        # return x,y  <--------------------- here 
        return x,y
    
    def rotation(x,y,angle):
        my_list = [[],[]]
        for i in range(len(x)):
            my_list[0].append(x[i]*math.cos(angle) + y[i]*math.sin(angle))
        for j in range(len(y)):
            #Big mistake here, replace i by j <--------------------- here 
            my_list[1].append(x[j]*math.sin(angle)*(-1.) + y[j]*math.cos(angle))
        return my_list[0], my_list[1]
    
    
    
    fig = plt.figure()
    ax = plt.axes(xlim=(10, 110), ylim=(-40, 60))
    ax.set_aspect('equal')
    line, = ax.plot([],[], lw=2)
    
    def init():
        line.set_data([],[])
        return line,
    
    def animate(i):
        c1 = 62.5
        c2 = 10
        pt_rot = (c1, c2)
        x = [47.5, 47.5, 77.5, 77.5, 47.5, 62.5, c1, 57.5, 67.5]
        y = [15, 45, 45, 15, 15, 15, c2, 10, 10]
    
        x,y = center(x,y,pt_rot)  # <--------------------- here 
        x,y = rotation(x,y,(i/180.)*np.pi) # <------------ here 
        x,y = recenter(x, y, pt_rot) # <------------------ here 
    
        line.set_data(x,y)
        return line,
    
    
    anim = animation.FuncAnimation(fig, animate, init_func=init,
                                   frames=359, interval=20, blit=True)
    
    plt.show()