使用 matplotlib 使图形随旋转矩阵旋转
Make a figure rotate with the rotation matrix using matplotlib
我想在 2D 中旋转图形(由线组成)space。我使用这种技术:
(1) 我翻译原处的图形。旋转点在 (0,0)
(2)我执行旋转
(3)我把图放回去
问题出在我的旋转函数上。不知道为什么它不起作用,因为我使用了旋转矩阵。您不必查看整个代码,只需查看 "rotation" 函数和 "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()
你的脚本有两个主要问题:
在旋转函数中,让j
循环,但根据i
设置x
和y
,这是一个常数第一个循环。
您设置旋转角度(以度为单位)。但是,三角函数需要以辐射点为单位设置角度。所以基本上你需要将角度乘以 2pi。
第三点虽然不是真正的问题但使脚本难以阅读是因为您 return None
在翻译功能中。我发现如果每个函数 return 都有一些值并且将这些值放回下一个函数,那么阅读起来会更容易。
这是一个完整的可运行脚本。
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()
我想在 2D 中旋转图形(由线组成)space。我使用这种技术: (1) 我翻译原处的图形。旋转点在 (0,0) (2)我执行旋转 (3)我把图放回去
问题出在我的旋转函数上。不知道为什么它不起作用,因为我使用了旋转矩阵。您不必查看整个代码,只需查看 "rotation" 函数和 "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()
你的脚本有两个主要问题:
在旋转函数中,让
j
循环,但根据i
设置x
和y
,这是一个常数第一个循环。您设置旋转角度(以度为单位)。但是,三角函数需要以辐射点为单位设置角度。所以基本上你需要将角度乘以 2pi。
第三点虽然不是真正的问题但使脚本难以阅读是因为您 return None
在翻译功能中。我发现如果每个函数 return 都有一些值并且将这些值放回下一个函数,那么阅读起来会更容易。
这是一个完整的可运行脚本。
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()