到目前为止,我们已经学会了在给定x、y轴数据的情况下进行绘图。在本节,主要来学习使用数学公式来创建图形。
根据牛顿万有引力定律,质量为的物体对另一个质量为的物体的吸引力F,有如下计算公式:
其中r是两个物体之间的距离,G是引力常数,我们想观察当两个物体之间的距离增加时,力会如何变化。
考虑两个物体:第一个物体的质量,第二个物体的质量。重力常数值为。现在我们准备计算两个物体之间19种不同距离的引力:100m、150m、200m、250m、300m以此类推,直到1000m。以下程序可以执行这些计算,并且绘制图形:
''' The relationship between gravitational force and distance between two bodies ''' import matplotlib.pyplot as plt # Draw the graph def draw_graph(x, y): plt.plot(x, y, marker='o') plt.xlabel('Distance in meters') plt.ylabel('Gravitational force in newtons') plt.title('Gravitational force and distance') plt.show() def caculate_F(): # Generate values of distance r = range(100, 1001, 50) F = [] # Constant G G = 6.674 * (10 ** (-11)) # Two bodies' masses m1 = 0.5 m2 = 1.5 # Caculate force and add it to the list,F for dist in r: F.append((G * m1 * m2) / (dist ** 2)) # call the draw_graph function draw_graph(r, F) if __name__ == '__main__': caculate_F()
caculate_F()函数完成了大部分的工作,首先在其中使用range()函数生成了一个距离列表r,列表步长为50,截至值为1001,这样子会包含1000在内;其次,创建了一个空列表F用来存储不同距离对应的万有引力,还创建了重力常量G和两个物体的质量m1、m2;最后,使用一个for循环计算不同的r对应的引力F,并将其加入到列表F中。然后距离为x周数据,F为y轴数据传入draw_graph()函数,进行绘图显示。
由图可知,随着距离r增加,引力减小,且图像非直线,即距离和引力非线性关系,且成反比。
现在,我们来绘制一些日常生活中熟悉的图形。如果你把一个球扔出,他将会遵循如下图所示轨迹:
图中,球从A点抛出并在B点落地,这种类型的运动被称为抛物运动。我们的目标是使用抛物运动的方程来绘制物体的运动轨迹。显示球从投掷点开始直到再次击中地面的位置。
当你扔球时,球具有一定的初始速度,该速度的方向与地面形成了一定的角度,我们称初始速度为u及其与地面的角度为θ (theta),如图4-1所示。球具有两个速度分量:一个沿x方向,由计算;另一个沿y方向,由计算。 当球移动时,其速度发生变化,我们将使用v表示变化的速度:水平分量为,垂直分量为。简单起见,假设水平分量在物体运动期间不改变,而垂直分量由于重力而不断减少,根据方程式计算。在该方程中,g是重力加速度,t是测量速度时的时间。因为我们可以替换得到:
由于速度的水平分量保持不变,因此物体的水平距离由给出。速度的垂直分量不断变化,运动的垂直距离由以下公式给出:
换句话说,和给出了球在飞行期间任意时间点的x和y坐标。我们使用程序会之轨迹时,将会使用这些方程式。在我们使用这些方程时,时间(t)单位为s,速度单位为m/s,投射角度(θ)单位为度,重力加速度(g)单位为。
然而,在我们编写程序之前,我们首先需要知道球在落地之前的飞行时间,以便知道程序何时停止,从而绘制球的轨迹。要做到这一点我们先来看看求到达最高点所需的时间。当速度的垂直分量时,球达到最高点,即时,我们求解t,可得:
我们记这个时间为,求在到达最高点后,将在空中飞行另一个后击中地面,所以球的总飞行时间为 为
我们投掷一个球,假设,计算总飞行时间,可将这些值代入上述公式:
求在这段时间内处于飞行状态,为了绘制轨迹,我们将计算这段时间内x与y坐标。我们应该多久计算一次呢?理想情况下计算越频繁越好,在本节中间,我们每隔0.0001s计算一次坐标。
(1)生成等间隔的浮点数
我们使用range()函 数来生成等间隔的整数,也就是说, 如果我们想要一一个1到10之间的整数列表,每个整数用1分隔,我们将使用range(1,10)。如果我们想要一个不同的步长值,我们可以给range()函数指定第三个参数。遗憾的是,对于浮点数来说没有这样的内置函数,即没有什么函数可以让我们创建一一个从0到0.72的数字列表,其中两个连续的数字用0.001分隔。我们可以使用while循环来创建我们自己的函数,如下所示:
''' Generate equally spaced floating point number between two given values ''' def frange(start, final, increment): numbers = [] while start < final: numbers.append(start) start += increment return numbers
我们定义了一个frange()函数,它接受三个参数,起始值start,截至值final,步长increment来模拟实现一个类似于整数range()的函数。创建以来列表numbers用来存储等间隔数字,for循环每次迭代都将start值存入到列表numbers中,然后start再加上increment,最终返回numbers列表。
我们将在绘制轨迹图形程序中使用这个函数。
(2)绘制轨迹
以下程序以一定的速度和角度绘制出跑去哦出的球的轨迹,速度和角度均作为程序的输入:
''' Generate equally spaced floating point number between two given values ''' def frange(start, final, increment): numbers = [] while start < final: numbers.append(start) start += increment return numbers ''' Draw the trajectory of a body in projectile motion ''' from matplotlib import pyplot as plt import math def draw_graph(x, y): plt.plot(x, y, marker='o') plt.xlabel('x-coordinate') plt.ylabel('x-coordinate') plt.title('Projectile motion of a ball') def draw_tarjectory(u, theta): theta = math.radians(theta) g = 9.8 # Time of flight t_flight = 2 * (u * math.sin(theta)) / g # Find time intervals intervals = frange(0, t_flight, 0.1) # List of a and y coordinate x, y = [], [] for t in intervals: x.append(u * math.cos(theta) * t) y.append((u * math.sin(theta) * t - 0.5 * g * (t ** 2))) draw_graph(x, y) if __name__ == '__main__': try: u = float(input('Enter the initial velocity (m/s) : ')) theta = float(input('Enter the angle of projection (degree) : ')) except ValueError: print('You entered an invalid input') else: draw_tarjectory(u, theta) plt.show()
在这个程序中,我们需要使用math模块中的radians()函数、cos()函数和sin()函数,我们我们在写程序一开始就导入math模块。draw_tarjectory()函数接受两个参数u和theta,分别对应于抛球时的速度和角度。math模块的正弦函数和余弦函数要求参数为弧度,因此使用math.radians()将角度转换为弧度。接下来创建一个g标签来指代重力加速度,赋值为。然后调用frange()函数对0~之间的数做等间隔划分,然后利用这个时间列表去计算该时刻下的x,y轴坐标,将x、y坐标单独存储在两个列表中。
最后用draw_graph()传入x,y作为参数来绘制轨迹。此时draw_graph()不调用show()函数(原因在下一段程序中讲)。然后在main函数中使用try...except程序块,控制用户输入为任意整数和浮点数,否则提示无效输入,运行程序:
Enter the initial velocity (m/s) : 25 Enter the angle of projection (degree) : 60
(3)比较以不同的初始速度投球时的轨迹
上面的程序以及绘图就是一个球的轨迹。但是假如我们要比较三个球以相同的角度,不同的初速度抛掷时的轨迹,该怎么办呢?很简单,只需要替换上述代码中的main代码块:
if __name__ == '__main__': # List of three different initial velocities u_list = [20, 40, 60] theta = 45 for u in u_list: draw_tarjectory(u, theta) # Add a legend and show the graph plt.legend(['20', '40', '60']) plt.show()
这里,我们不要求用户输入速度和抛射角度,而是创建了一个初速度列表u_list和抛射角度theta。然后对u_list中的每个值和theta都调用draw_tarjecrory()函数,分别计算不同初速度对应的x、有、坐标,然后绘制轨迹图形
留言与评论(共有 0 条评论) “” |