在数学中,摆线(Cycloid)被定义为,一个圆在一条直线上滚动时,圆边界上一定点所形成的轨迹。它是一般旋轮线的一种。摆线亦称圆滚线。
摆线也是最速降线问题和等时降落问题的解。
应用matplotlib.animation.ArtistAnimation
可以画出摆线。
导入相关的包
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
配置绘图参数
包括jupyter notebook里的动画显示以及ffmpeg_path
的设置,我的代码运行在Windows环境,所以ffmpeg_path
指向了对应的软件路径。
# 在jupyter notebook配置动画显示
plt.rcParams['animation.html'] = 'html5'
# 配置ffmpeg路径
plt.rcParams['animation.ffmpeg_path'] = r'J:\software\ffmpeg-7.0.1-full_build\bin\ffmpeg.exe'
# 通过convert_path设置ImageMagick路径
plt.rcParams['animation.convert_path'] = r'J:\software\ImageMagick-7.1.1-33-portable-Q16-x64\convert.exe'
定义一个圆
包括设置圆心、半径等内容,我们可以通过如下代码进行定义。
# 圆半径
R = 1
- 通过一个方法定义圆及确定摆线
通过简单推导,我们知道摆线方程为:
{ x = r ( θ − s i n θ ) y = r ( 1 − c o s θ ) \begin{cases} x = r(\theta - sin\theta) \\ y = r(1 - cos\theta) \end{cases} {x=r(θ−sinθ)y=r(1−cosθ)
其中, r r r是圆半径, θ \theta θ是滚动角,即圆的半径所经过的弧度。
def circle(a, b, r, num=100):
# (a,b): 圆心坐标
# r: 圆半径
# num: 采样密度,默认100
x, y = [0]*num, [0]*num
for i,theta in enumerate(np.linspace(0,2*np.pi,num)):
x[i] = a + r*np.cos(theta)
y[i] = b + r*np.sin(theta)
return x, y
# 摆线计算
thetas = np.linspace(0,6*np.pi,200)
cycloid_x = R*(thetas-np.sin(thetas))
cycloid_y = R*(1-np.cos(thetas))
cycloid_c = R*thetas
绘制图像
根据上述定义的圆,画出图像,并为生成动画做准备。
fig = plt.figure()
lns = []
trans = plt.axes().transAxes
for i in range(len(thetas)):
x,y = circle(cycloid_c[i], R, R, len(thetas))
ln1, = plt.plot(x, y, 'g-', lw=2)
ln2, = plt.plot(cycloid_x[:i+1] ,cycloid_y[:i+1], 'r-', lw=2)
ln3, = plt.plot(cycloid_x[i], cycloid_y[i], 'bo', markersize=4)
ln4, = plt.plot([cycloid_c[i], cycloid_x[i]], [R,cycloid_y[i]], 'y-', lw=2)
tx1 = plt.text(0.05, 0.8, r'$\theta$ = %.2f $\pi$' % (thetas[i]/np.pi), transform=trans)
lns.append([ln1,ln2,ln3,ln4,tx1])
plt.xlim(0,20)
plt.ylim(0,3)
plt.xlabel('x')
plt.ylabel('y')
plt.grid()
# 设置x和y坐标轴,使它们具有相同的单位长度
plt.gca().set_aspect('equal')
创建并展示动画
将动画保存为.mp4
格式视频和.gif
格式图像,并展示出来。
ani = animation.ArtistAnimation(fig, lns, interval=50)
ani.save('cycloid_ArtistAnimation.mp4',writer='ffmpeg')
ani.save('cycloid_ArtistAnimation.gif',writer='imagemagick')
ani