百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Python数学编程 第六章 绘制几何图形和分形 第一节

toyiye 2024-09-06 00:09 5 浏览 0 评论

在这一章,我们首先学习matplotlib中的patches,用它可以绘制各种几何图形,如圆、三角形和多边形。然后,我们将学习matplotlib的动画支持,并比那些一个程序动态演示抛物轨迹。在最后一节中,我们将需学习如何绘制分形图(一种重复应用简单的几何变换得到复杂的几何图形)。开始吧!

6.1 使用matplotlib的patches绘制几何图形

在matplotlib中,patches可以用来绘制几何图形,图形的每一部分都可视为一个块(patches).。例如,为了把一个圆添加到绘图中,你可以指定圆的半径和圆心。这与我们之前使用matplotlib的方式非常不同,之前我们只需要提供点的x坐标和y坐标即可,在使用patches的特点编写程序之前,我们需要先了解一下matplotlib是如何绘图的。考虑以下程序,其使用matplotlib绘制了三个点(1,1),(2,2),(3,3):


 >>> import matplotlib.pyplot as plt
 >>> x = [1,2,3]
 >>> y = [1,2,3]
 >>> plt.plot(x,y)
 [<matplotlib.lines.Line2D object at 0x000001605C4B7A58>]
 >>> plt.show()

这个程序创建一个matplotlib窗口,显示一条穿过给定的三个点的直线。在程序中,调用plt.plot()函数会创建一个Figure对象,在该对象中创建了坐标系,最后在坐标系中绘制数据点(见图6-1)。

下面的程序重新绘制了这个图,只是这次我们明确创建了Figure对象并添加了坐标轴,而不只是调用plot()函数并依赖它创建上述对象:


 >>> import matplotlib.pyplot as plt
 >>> x = [1,2,3]
 >>> y = [1,2,3]
 >>> fig = plt.figure()          # ①
 >>> ax = plt.axes()             # ②
 >>> plt.plot(x,y)
 [<matplotlib.lines.Line2D object at 0x000001605CF712E8>]
 >>> plt.show()

这里,我们在①处使用figure()函数创建Figure对象(fig),然后在②处使用axes()函数创建坐标轴。axes()函数同时将坐标轴添加到Figure对象中。最后两行代码与之前的程序相同。这一次,当我们调用plot()函数时,它会看到一个带有坐标系的Figure对象已经存在,因此直接根据提供的数据绘制图形。

除了手动创建Figure和Axes对象之外,还可以使用pyplot模块中的两个不同函数(gcf()函数和gca()函数)来获取对当前对象Figure和Axes对象的引用。当调用gcf()函数时,它返回当前Figure对象的引用;当调用gca()函数时,它返回当前Axes对象的引用。这两个该函数都有一个有趣的特性:如果对象不存在,它们将分别别创建相应的对象。我们在本章中使用这些函数时,它们的工作原理将变得更加清晰。

6.1.1 绘制一个圆

为了绘制一个圆,你可以添加一个Circle块到Axes对象中,如下例所示:


 '''
 Example of using matplotlib's Circle patch
 '''
 
 import matplotlib.pyplot as plt
 
 def create_circle():
     circle = plt.Circle((0, 0), radius = 0.5)       #  ①
     return circle
 def show_shape(patch):
     ax = plt.gca()                                  # ②
     ax.add_patch(patch)
     plt.axis('scaled')
     plt.show()
 
 if __name__ == '__main__':
     c= create_circle()                              # ③
     show_shape(c)

在这个程序中,我们将Circle块对象的创建和图中的块的添加分成两个函数:create_circle()和show_shape()。在create_circle()函数中,我们创建一个圆心在(0,0)且半径为0.5的圆,方法是在①处创建一Circle对象,将圆心坐标(0,0)作为一个元组传递,并将半径0.5使用同名的关键字(radius)进行传递。create_circle()函数将返回创建的Circle对象。

为了使show_shape()函数可以作用于任何matplotlib块,首先在②处用gca()函数获取当前Axes对象的引用,接着使用add_patch()函数添加传递给它的块,最后调用show()函数显示图形。我们这里使用scaled函数调用axis()函数,这个参数能够告诉matplotlib自动调节数轴的取值范围,我们需要在所有用块自动调节数轴范围的程序中使用这个语句。当然,你也可以指定固定的取值界限,正如第二章看到的那样。比如,axis(xmin=x,xmax=y,ymin=m,ymax=n)。

在③处,我们调用create_circle()函数,并使用标签c指代其返回的Circle对象。然后,调用show_shape()函数,将c作为参数输入。当运行程序时,你将看到一个matplotlib窗口显示的圆。

正如你看到的,这个圆看上去并不圆。这是由于自动宽高比决定了x轴和y轴的长度比例。如果在②后插入语句ax.set_aspect('equal'),你会发现这个圆将变得更加符合实际。set_aspect()函数用来设置图形的宽高比。使用equals参数可以使matplotlib将x轴和y轴的长度比设置为1:1。

可以使用ec和fc关键字参数修改块中的边缘颜色和表面颜色(填充颜色)。例如fc='g'和ec = 'r'将创建一个边缘颜色为红色和内部填充为绿色的圆。

matplotlib支持其他各种块,如椭圆(Ellipse)、多边形(POlygon)和矩形(Rectangle)。

6.1.2 创建动画图形

有时我们可能想要创建具有动态形状的图形,matplotlib的动画支持可以帮我们做到这一点。后面我们将创建一个电话版本的抛物轨迹绘制程序。

首先来看一个简单的例子,我们将绘制一个matplotlib图形,该图形从一个小的圆开始,无限的增长到某个半径(除非matplotlib窗口关闭)。


 '''
 A growing circle
 '''
 
 from matplotlib import pyplot as plt
 from matplotlib import animation
 
 def create_circle():
     circle = plt.Circle((0,0), radius=0.05)
     return circle
 
 def update_radius(i, circle):
     circle.radius = i*0.5
     return circle
 
 def create_animation():
     fig = plt.gcf()                             # ①
     ax = plt.axes(xlim=(-10,10),ylim=(-10,10))
     ax.set_aspect('equal')
     circle = create_circle()
     ax.add_patch(circle)                        # ②
     anim = animation.FuncAnimation(             # ③
         fig, update_radius, fargs = (circle,), frames=30, interval=50)
     plt.title('Simple Circle Animation')
     plt.show()
 
 if __name__ == '__main__':
     create_animation()

首先我们从matplotlib包中导入animation模块。create_animation()函数在这里执行了核心功能,在①处它使用gcf()函数获得当前Figure对象的引用,然后创建一个坐标系(x轴和y轴的区间均为-10到10)。在这之后,创建一个半径为0.05、圆心在(0,0)处的Circle对象,并在②处将这个对象添加到坐标系中。然后,在③处我们创建了FuncAnimation对象,它传递了将要创建的动画的数据。

(1)fig。它是当前Figure对象。

(2)update_radius。这个函数负责绘制每一帧。它需要两个参数——一个在调用时传递给它的帧编号,以及更新每一帧时的块对象。这个函数也返回一个块对象。

(3)fargs。这个元组包含了所有(除了帧编号)要传递给update_radius()函数的参数。如果没有要传递的此类参数,则不需要指定该关键字。

(4)frames。frames指动画中的帧数,也是update_radius()函数被调用的次数。这里我们任意取了30帧。

(5)interval。interval值两帧之间的时间间隔(毫秒)。如果共话显示速度太慢,则减小这个值,否则增大这个值。

接下来我们使用title()函数设置标题,最后用show()显示图形。

如前所述,update_radius()函数负责更新在每一帧都会发生变化的圆的属性。这里我们设置半径为i*0.5,其中i是帧编号。你将会看到每一帧逐渐增大的圆(共30帧),一次最大的圆的半径为15。因为坐标轴设置在-10到10之间,这就出现了圆形超出图形范围之外的效果。运行程序时,你将看到第一个动画图形。如下所示。

你会注意到动画会一直持续,直到关闭matplotlib窗口,这是默认情况,你可以在创建FuncAnimation对象时通过设置关键字参数repeat=False来改变此行为。

FunAnimation对象和持久化

你可能会注意到在圆的动画的程序中,我们用标签anim来指代创建的FuncAnimation对象,即使我们不再其他地方使用它。这是因为matplotlib当前的行为存在问题,他不存储任何对FuncAnimation对象额的引用,使该对象容易受到Python中垃圾回收机制的影响,这意味着动画将不会被创建。我们可以通过创建一个标签指代这个对象来阻止这一问题的发生。

6.1.3 抛物运动动画演示

在第二章中,我们绘制了一个球在抛物运动中的轨迹。这里,基于这个图象,使用matplotlib动画来支持制作动画轨迹,从而使得这一演示更接近于实际生活中看到的球的运动情况。


 '''
 Animation thr trajectory of an object in projectile mmotion
 '''
 
 from matplotlib import pyplot as plt
 from matplotlib import animation
 import math
 g = 9.8
 
 def get_intervals(u, theta):
     t_flight = 2*u*math.sin(theta)/g
     intervals = []
     starts = 0
     interval = 0.005
     while starts < t_flight:
         intervals.append(starts)
         starts += interval
     return intervals
 
 def update_position(i, circle, intervals, u, theta):
     t = intervals[i]
     x = u*math.cos(theta)*t
     y = u*math.sin(theta)*t - 0.5*g*t**2
     circle.center = x, y
     return circle
 def create_animation(u, theta):
     intervals = get_intervals(u, theta)
 
     xmin = 0
     xmax = u*math.cos(theta)*intervals[-1]
     ymin = 0
     tmax = u*math.sin(theta)/g
     ymax = u*math.sin(theta)*tmax - 0.5*g*tmax**2       # ①
 
     fig = plt.gcf()
     ax = plt.axes(xlim=(xmin,xmax), ylim=(ymin,ymax))
 
     circle = plt.Circle((xmin, ymin), 1.0)
     ax.add_patch(circle)
     anim = animation.FuncAnimation(
         fig, update_position, fargs=(circle, intervals, u, theta),
         frames=len(intervals), interval=1, repeat=False)
     plt.title('Projectile Motion')
     plt.xlabel('X')
     plt.ylabel('Y')
     plt.show()
 
 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:
         thete =math.radians(theta)
         create_animation(u, theta)

create_animation()函数有两个参数:u和theta,这两个参数对应于初始速度和抛射角度,他们是程序的初始输入。get_intervals()函数用来获取世纪那间隔,据此可以计算抛物运动的x和y坐标,这个函数是通过使用在第二章中用到的相同逻辑来实现的,那时我们单独定义了一个frange()函数。

为了给动画设置坐标界限,我们需要找到x和y的最大值和最小值。最小值都为0,及每一个坐标的初始值。x的最大值为球飞行结束时的坐标值,即列表intervals的最后一个时间间隔。y坐标的最大值为球飞行处于最高点的值,即在①处,我们可以使用如下公式进行计算:


得到这些值后,我们在②处创建坐标系,将合适的坐标界限作为参数输入。接下来的两个语句中,我们在(xmin,ymin)处创建一个半径为1.0的原来表示求(xmin, ymin分别表示x轴和y轴的最小坐标值),并将其添加到图形的Axes对象中。

接下来在③处创建FuncAnimation对象,以当前的图形对象和以下参数作为输入。

(1)update_position。这个函数将更改每一帧中圆的圆心。这里的想法是为每个时间间隔创建一个新的帧,因此我们将帧的数量设置为时间间隔的大小。我们在低i个时间间隔计算球在这一瞬间的x和y坐标,并将圆心设置为这些值。

(2)fargs。update_position()函数需要使用的时间间隔列表、间隔、初始速度和theta,他们都需要通过此关键字参数指定。

(3)frames。因为我们将在每一个时间间隔绘制一帧,所以将帧的数目设置为intervals列表的大小。

(4)repeat。如同我们在第一个动画例子中所讨论的,默认情况下动画将无限重复。这们并不希望看到这一点,所以将这个关键字设置为False。

运行程序,它会询问初始输入然后创建动画。

相关推荐

# Python 3 # Python 3字典Dictionary(1)

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中,格式如...

Python第八课:数据类型中的字典及其函数与方法

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值...

Python中字典详解(python 中字典)

字典是Python中使用键进行索引的重要数据结构。它们是无序的项序列(键值对),这意味着顺序不被保留。键是不可变的。与列表一样,字典的值可以保存异构数据,即整数、浮点、字符串、NaN、布尔值、列表、数...

Python3.9又更新了:dict内置新功能,正式版十月见面

机器之心报道参与:一鸣、JaminPython3.8的热乎劲还没过去,Python就又双叒叕要更新了。近日,3.9版本的第四个alpha版已经开源。从文档中,我们可以看到官方透露的对dic...

Python3 基本数据类型详解(python三种基本数据类型)

文章来源:加米谷大数据Python中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。在Python中,变量就是变量,它没有类型,我们所说的"类型"是变...

一文掌握Python的字典(python字典用法大全)

字典是Python中最强大、最灵活的内置数据结构之一。它们允许存储键值对,从而实现高效的数据检索、操作和组织。本文深入探讨了字典,涵盖了它们的创建、操作和高级用法,以帮助中级Python开发...

超级完整|Python字典详解(python字典的方法或操作)

一、字典概述01字典的格式Python字典是一种可变容器模型,且可存储任意类型对象,如字符串、数字、元组等其他容器模型。字典的每个键值key=>value对用冒号:分割,每个对之间用逗号,...

Python3.9版本新特性:字典合并操作的详细解读

处于测试阶段的Python3.9版本中有一个新特性:我们在使用Python字典时,将能够编写出更可读、更紧凑的代码啦!Python版本你现在使用哪种版本的Python?3.7分?3.5分?还是2.7...

python 自学,字典3(一些例子)(python字典有哪些基本操作)

例子11;如何批量复制字典里的内容2;如何批量修改字典的内容3;如何批量修改字典里某些指定的内容...

Python3.9中的字典合并和更新,几乎影响了所有Python程序员

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

Python3大字典:《Python3自学速查手册.pdf》限时下载中

最近有人会想了,2022了,想学Python晚不晚,学习python有前途吗?IT行业行业薪资高,发展前景好,是很多求职群里严重的香饽饽,而要进入这个高薪行业,也不是那么轻而易举的,拿信工专业的大学生...

python学习——字典(python字典基本操作)

字典Python的字典数据类型是基于hash散列算法实现的,采用键值对(key:value)的形式,根据key的值计算value的地址,具有非常快的查取和插入速度。但它是无序的,包含的元素个数不限,值...

324页清华教授撰写【Python 3 菜鸟查询手册】火了,小白入门字典

如何入门学习python...

Python3.9中的字典合并和更新,了解一下

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

python3基础之字典(python中字典的基本操作)

字典和列表一样,也是python内置的一种数据结构。字典的结构如下图:列表用中括号[]把元素包起来,而字典是用大括号{}把元素包起来,只不过字典的每一个元素都包含键和值两部分。键和值是一一对应的...

取消回复欢迎 发表评论:

请填写验证码