需求:根据脚本来绘制图形

 不是写代码而是写数据绘制轨迹(不是使用写代码的方式去实现,而是使用编制数据的方式来去绘制轨迹)

数据脚本是自动化最重要的第一步(能否写程序去读取数据并且根据数据来绘制轨迹)

在任何领域中,要希望我们的程序能够自动化或者模块化,设计相关的脚本或者数据接口是其中很重要的过程

读取一个文件,解析其中的数据,并且绘制图形,这是自动轨迹绘制的基本需求。

基本思路如下:

步骤1:定义数据文件格式(接口) (程序和数据之间的一种规范)

步骤2:编写程序,根据文件接口解析参数绘制图形。

步骤3:编制数据文件。

数据接口定义:

非常具有个性色彩

对于一列数据:300,0,144,1,0,0

对于其中第一个数据为300,为行进距离(表示当前位置开始向前行进的一个距离)

第二个数据为0,为转向判断,其中当数据为0时为当前画笔左转,当数据为1时为当前画笔右转

第三个数据为144,为转向角度,即向右转或向左转的绝对转向角度。

第四第五第六个数据为1,0,0,表示RGB三个通道颜色(画这段直线或曲线过程中所使用的RGB三个通道的颜色)

代码示例如下:


import turtle as t
t.title('自动轨迹绘制')
t.setup(800,600,0,0)
t.pencolor("red")
t.pensize(5)
datals=[]
f=open("data.txt")
for line in f:
    line=line.replace("\n"," ")
    if line !=" ":
      datals.append(list(map(eval,line.split(","))))
f.close()
for i in range(len(datals)):
  t.pencolor(datals[i][3],datals[i][4],datals[i][5])
  t.fd(datals[i][0])
  if datals[i][1]:
      t.right(datals[i][2])
  else:
      t.left(datals[i][2])


运行界面如图所示:

自动轨迹绘制实例Python 自动轨迹是什么_后端

 通过思考,我们设计出了需要的代码,我们对设计代码进行了如下解释:

因为我们要进行自动轨迹绘制,所以我们需要调用turtle库,在代码初始阶段,我们利用import进行对turtle库的调用,之后,我们对标题进行了设计,我们将标题命名为“自动轨迹绘制”,将画布大小设置为(800,600,0,0),将画笔颜色设置为red,将画笔宽度设置为5,我们完成这些之后,就初步完成了所展现出来的外部形象,之后继续进行对后续代码的设计:


import turtle
import turtle as t
t.title('自动轨迹绘制')
t.setup(800,600,0,0)
t.pencolor("red")
t.pensize(5)


之后,我们要打开数据文件,并且解析数据文件中每一行的信息,并且对这一行的信息做相关的处理。我们将所有信息的数据都读入之后,保存为列表。所以,首先,我们进行创建一个空列表,命名为datals,之后我们打开所要读取的文件,进行每一行的遍历,因为我们遍历的元素为字符串,所以我们需要将这些字符串分割为我们需要的列表类型,首先,我们利用replace方法将第一行的换行符去掉,转变为空字符串,即去掉换行的信息。这样子对于每一行字符串就不用换行,之后,由于遍历的为字符串,而在我们定义接口的时候我们希望每一个解析的元素都是真实的数字。由于字符串的每个数字之间以逗号进行分割,我们利用split将这些字符串以指定逗号的方式进行分割,将一个字符串分割为若干个字符串。之后,我们利用eval评估函数,将字符串两侧的引号去掉,所实现的效果即为不带任何引号的单个数字。之后利用list即可创建为一个列表,最后我们利用append方法将所创建的列表添加到我们所创建的空列表里面。

其中我们用到了map函数,map函数是python提供的内嵌函数,无需import,可以直接引用。map函数的功能是将第一个参数的功能作用于第二个参数的每一个元素,即eval评估函数作用于后面的每一行的字符串的每个元素,即将每一个字符串两侧的引号去掉,变成真实的数字。即对一个列表或者一个集合这样的组合数据类型的每一个元素都执行一次第一个参数所对应的函数。

在我们运行过程中,我们会由于忽略eval函数的用法而造成错误,我们解决错误的用法如下:

因为eval内参数为空时报错,需要加入if判断,使得eval函数在参数不为空时进行执行。根据map函数可知,eval的每个参数为line的每个字符串,所以我们判断line不为空时才进行执行。
eval()语法为:eval(expression[, globals[, locals]])。expression参数不为空,为空时则进行报错。

expression:表达式

globals:变量作用域,全局命名空间,如果被提供,则必须是一个字典对象

locals:变量作用域,局部命名空间,如果被提供,可以是任何映射对象。

代码如下所示:


datals=[]
f=open("data.txt")
for line in f:
    line=line.replace("\n"," ")
    if line !=" ":
      datals.append(list(map(eval,line.split(","))))
f.close()


数据读取之后,我们进行接口的设计,

我们利用循环进行遍历,我们需要遍历的次数为这个列表里面元素的个数,即datals这个列表里面的列表个数,我们对其中的每一个列表进行遍历的时候,我们利用列表索引进行接口的设计,通过开头的设计,我们知道第4,5,6个数字为RGB三个通道颜色,索引为从0开始,即遍历列表的每个列表的时候,第i列表的3,4,5数据为RGB三个通道颜色,即为画笔颜色。之后第i列表的第0个数据为前进方向。

对于第i列表的第1个数据和第2个数据的实现,我们使用if语句进行判断,当为0时,我们进行左转,当为1时,我们可以利用比较运算符==进行判断,即如果这个数据和1相等,即右转,否则左转。代码示例如下:


for i in range(len(datals)):
  t.pencolor(datals[i][3],datals[i][4],datals[i][5])
  t.fd(datals[i][0])
  if datals[i][1]==1:
      t.right(datals[i][2])
  else:
      t.left(datals[i][2])
turtle.done()


当然我们也可以这么设计代码,即利用python自定义的,if(真),大于等于1为真,0为假,这样子去确定当为1时,我们进行右转,当为0时,左转。设计代码时,将真的即右转写到if下面,而else写左转,得到的效果和上面一样。为了让所画出的画面在绘制完毕后不会关闭窗口,我们将turtle.done,防止窗口关闭。代码示例如下:


for i in range(len(datals)):
  t.pencolor(datals[i][3],datals[i][4],datals[i][5])
  t.fd(datals[i][0])
  if datals[i][1]:
      t.right(datals[i][2])
  else:
      t.left(datals[i][2])
turtle.done()
 
我们的data.txt文本示例如下:
 
300,0,144,1,0,0
300,0,144,0,1,0
300,0,144,0,0,1
300,0,144,1,1,0
300,0,108,0,1,1
184,0,72,1,0,1
184,0,72,0,0,0
184,0,72,0,0,0
184,0,72,0,0,0
184,1,72,1,0,1
184,1,72,0,0,0
184,1,72,0,0,0
184,1,72,0,0,0
184,1,72,0,0,0
184,1,720,0,0,0


举一反三:

理解方法思维:

自动化思维:数据和功能分离,数据驱动的自动运行

接口化设计:格式化设计接口,清晰明了

二维数据应用:应用维度组织数据,二维数据最常用

应用问题的扩展:

扩展接口设计,增加更多控制接口

扩展功能设计,增加弧形等更多功能

扩展应用需求,发展自动轨迹绘制到动画绘制。