python画卡通_python绘制参数方程的动画

webchat.jpg

© 2018 *All rights reserved by liudx .:smile:

​ Python的matplotlib是一个功能强大的绘图库,可以很方便的绘制数学图形。官方给出了很多简单的实例,结合中文翻译的示例Tutorial,可以满足日常工作的大部分需求了。但是实际工作中,一些有趣的东西很难使用常规方程(笛卡尔坐标和极坐标)方式绘制,事实上,大部分工程上都是使用参数方程来描述曲线。本文给出一些参数方程绘制的实例,之后会扩展为动画形式绘制,可以看到这些复杂的方程是如何简单优美的绘制出来。

1 参数方程绘制

​ 首先介绍下椭圆的参数方程:

$$

begin{cases}

x = a cdot cos(t)\

y = b cdot sin(t)

end{cases}

$$

​ 其中$a,b$分别是椭圆的长轴、短轴。绘制椭圆的python代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18import matplotlib.pyplot as plt

import numpy as np

fig = plt.figure()

ax = plt.gca()

r1 = 1.1

r2 = 1

t = np.linspace(0, np.pi*2, 1000) # 生成参数t的数组

x = r1 * np.cos(t)

y = r2 * np.sin(t)

plt.plot(x, y, color='blue', linewidth=2, label='ellipse')

plt.xlabel('x')

plt.ylabel('y')

plt.ylim(-2, 2)

plt.xlim(-1.5,1.5)

ax.grid()

plt.show()

​ 结果如下:

ellipse.png

​ 下面我们来个复杂点的例子,绘制炮弹的弹道曲线(当然是理想情况的),我们先根据公式推算一把,首先我们设炮弹出口速度$v_0(m/s)$,向上仰角为$theta$ °,时间为$t(s)$, 大炮的筒口初始坐标初始为(0,0),则有:

$$

begin{cases}

x=v_0cdotsin(theta)cdot t \

y=v_0cdotcos(theta)cdot t - v_0cdotcos(theta)cdot g cdot t^2

end{cases}

$$

​ 对应python代码為:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26def (v0, theta_x): # 模拟炮弹飞行曲线

g = 9.80665 # m/s^2

v0_x = v0*np.cos(theta_x)

v0_y = v0*np.sin(theta_x)

t_m = (v0_y / g) # 飞行时间

#h = g*t_m**2/2

t = np.linspace(0, v0_x * t_m * 2, v0*1000)

x = v0_x * t

y = v0_y *t - v0_y *g * t**2 / 2

return x,y

if __name__ == '__main__':

linestyles = ['-', '--', '-.', ':']

x1, y1 = Parabolic(100, np.deg2rad(45))

x2, y2 = Parabolic(100, np.deg2rad(30))

x3, y3 = Parabolic(100, np.deg2rad(60))

plt.plot(x1, y1, color='r', linewidth=1, linestyle="--",label='45deg')

plt.plot(x2, y2, color='y', linewidth=1, linestyle="-.", label='30deg')

plt.plot(x3, y3, color='c', linewidth=1, linestyle=":", label='60deg')

plt.xlabel('x')

plt.ylabel('h')

plt.xlim(0, 20)

plt.ylim(0, 8)

plt.legend(loc='upper center')

plt.show()

​ 为了方便示意,我分别绘制了初速为$100m/s$时,仰角为45°、30°、60°的炮弹落地曲线:

boom!.png

​ 验证了我们高中物理中的一个结论:这货不就是抛物线嘛。

​ 看完静态的参数方程,还是不过瘾,我们来做个动画玩玩。首先是绘制一个内旋轮,引用下这位老哥的例子:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30import numpy as np

import matplotlib

import matplotlib.pyplot as plt

import matplotlib.animation as animation

fig = plt.figure(figsize=(6, 6)) # 图像大小

ax = plt.gca()

ax.grid()

ln1, = ax.plot([], [], '-', color='b', lw=2) # 注意逗号,取出plot数据:plot return A list of Line2D objects representing the plotted data.

ln2, = ax.plot([], [], '-', color='r', lw=1)

theta = np.linspace(0, 2*np.pi, 100) # 参数t的数组

r_out = 1 # 静态圆的半径

r_in = 0.5 # 动态圆的半径

def init():

ax.set_xlim(-2, 2)

ax.set_ylim(-2, 2)

x_out = [r_out*np.cos(theta[i]) for i in range(len(theta))]

y_out = [r_out*np.sin(theta[i]) for i in range(len(theta))]

ln1.set_data(x_out, y_out) # 静圆

return ln1, # 此处返回tuple

def update(i): # 每次回调时,传入索引`0~range(len(theta))`,注意repeat时索引会归0

x_in = [(r_out-r_in)*np.cos(theta[i])+r_in*np.cos(theta[j]) for j in range(len(theta))]

y_in = [(r_out-r_in)*np.sin(theta[i])+r_in*np.sin(theta[j]) for j in range(len(theta))]

ln2.set_data(x_in, y_in) # 动圆

return ln2,

ani = animation.FuncAnimation(fig, update, range(len(theta)), init_func=init, interval=30)

#ani.save('roll.gif', writer='imagemagick', fps=100)

plt.show()

​ 看起来很不错,能动(这里发现了init函数可以绘制下静态的大圆ln1,update函数只对动圆ln2的plot对象数据进行更新):

roll2circle.gif

​ 最后研究下旋轮线, 看看能否绘制出wiki页面上那个动画效果。先列出参数方程:

$$

选轮线参数方程:

begin{cases}

x = rcdot(t-sin t) \

y = r cdot (1-cos t)

end{cases}

\

圆心的坐标为:(t,r)

$$

​ 经过观察摸索,发现需要绘制3部分,一个是滚动的圆,一个是摆线,还有个圆心到绘制曲线的支点。坐标都可直接从参数方程推算出来,不多说,直接上代码和注释吧:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43#def wheel_line():

fig = plt.figure(figsize=(8,2))

ax = plt.gca()

ax.grid()

ln, = ax.plot([], [], 'o-', color='g', lw=1) # 圆心连线 @center -> curve

circle, = ax.plot([], [], '-', color='b', lw=1) # 滚动的圆

curve, = ax.plot([], [], '-', color='r', lw=1) # 摆线

curve_x, curve_y = [], []

r = 1

t = np.linspace(0, math.pi*2, 1000)

L = 4*np.pi*r

theta = np.linspace(0, L, 250)

def init():

ax.set_xlim(-r, L + r)

ax.set_ylim(0, L/4 + r/2)

ln.set_data([0,0], [0,1])

x_out = r*np.cos(t)

y_out = r*np.sin(t) + r

circle.set_data(x_out, y_out)

return circle,ln

def update(frame):

tt = theta[frame] # 获取参数t

x=r*(tt-np.sin(tt))

y=r*(1-np.cos(tt))

curve_x.append(x)

curve_y.append(y)

curve.set_data(curve_x, curve_y) # 更新摆线

if i == len(theta) - 1:

curve_x.clear()

curve_y.clear()

# update circle

x_out = r*np.cos(t) + tt

y_out = r*np.sin(t) + r

circle.set_data(x_out, y_out)

# new circle center @(tt,r)

ln.set_data([tt,x],[r,y])

return curve,circle,ln

ani = animation.FuncAnimation(fig, update, frames=range(len(theta)), init_func=init, interval=1)

ani.save('roll.gif', writer='imagemagick', fps=60)

plt.show()

​ 大功告成:

roll.gif

3 后记

​ 在摸索过程中,还是有很多坑需要注意的,最初那个摆线的例子,我没有计算好图形范围,画出来的圆是扁扁的,后来通过改figsize和ax.set_xlim/set_ylim为相同比例解决的;保存动画那个ani.save('roll.gif', writer='imagemagick', fps=60)总是报错,经过查找资料,解决方案是安装imagemagic,下载安装后第2节的例子都能顺利保存动图为gif。还有需要注意是的save函数里面的fps参数不能调太低,否则会出现动画卡顿的现象,太高又会出现动画速度很快的问题,这个参数需要配合frames即动画的总帧数,以及FuncAnimation里面的interval帧间隔时间参数(单位是ms),总动画时间(秒)公式为:$frames * interval/1000+frames/fps$。

​ 读完这篇文章,相信绘制参数方程和动画不是一件难事吧:smile:。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要用 Python 绘制三维参数方程的图像,可以使用 Matplotlib 库中的 mplot3d 模块。下面是一个简单的例子,展示了如何绘制参数方程 x = cos(t), y = sin(t), z = t 的图像: ```python import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # 定义参数 t 的取值范围和步长 t = np.arange(-10, 10, 0.1) # 定义参数方程 x = np.cos(t) y = np.sin(t) z = t # 创建 3D 图像并绘制参数方程 fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.plot(x, y, z) # 显示图像 plt.show() ``` 运行这段代码,将会得到一个三维的曲线图,显示了参数方程 x = cos(t), y = sin(t), z = t 的图像。你可以修改代码中的参数方程和取值范围,来绘制你想要的三维参数方程图像。 ### 回答2: 要使用Python绘制三维参数方程的图像,我们可以使用matplotlib模块中的mpl_toolkits.mplot3d子模块来实现。 首先,我们需要导入必要的模块: ```python import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D ``` 接下来,我们定义参数方程的变量范围。例如,如果我们要绘制一个球体,可以使用以下代码: ```python u = np.linspace(0, 2 * np.pi, 100) v = np.linspace(0, np.pi, 100) ``` 然后,我们可以使用参数方程计算每个点的x、y、z坐标。例如,对于球体的参数方程,可以使用以下代码计算: ```python x = r * np.outer(np.cos(u), np.sin(v)) y = r * np.outer(np.sin(u), np.sin(v)) z = r * np.outer(np.ones(np.size(u)), np.cos(v)) ``` 最后,我们可以使用matplotlib的3D子模块来绘制图像。例如,我们可以使用以下代码绘制球体的图像: ```python fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.plot_surface(x, y, z, cmap='viridis') plt.show() ``` 在这个例子中,我们使用plot_surface()函数来绘制球体的曲面,cmap参数用于指定颜色映射。 这样,我们就可以使用Python绘制三维参数方程的图像了。具体来说,我们需要定义参数范围、计算每个点的坐标,并利用matplotlib的3D子模块进行绘制。最后,我们可以使用plot_surface()函数来绘制参数方程的曲面图。 ### 回答3: 使用Python绘制三维参数方程的图形可以通过使用Matplotlib库中的mplot3d模块来实现。以下是一个简单的示例代码: ```python import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # 定义参数方程 def parametric_equation(u, v): x = np.sin(u) * np.cos(v) y = np.sin(u) * np.sin(v) z = np.cos(u) return x, y, z # 生成u和v的取值范围 u = np.linspace(0, 2 * np.pi, 100) v = np.linspace(0, np.pi, 50) # 创建网格点 U, V = np.meshgrid(u, v) # 计算参数方程对应的坐标值 X, Y, Z = parametric_equation(U, V) # 创建3D图形窗口 fig = plt.figure() ax = fig.add_subplot(111, projection='3d') # 绘制三维图形 ax.plot_surface(X, Y, Z, cmap='viridis') # 设置坐标轴标签 ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') # 显示图形 plt.show() ``` 这个示例代码绘制了一个球面的图像,球面的参数方程为x = sin(u) * cos(v),y = sin(u) * sin(v),z = cos(u)。通过调整参数方程,可以绘制出任意参数方程对应的三维图像。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值