python与分形0011 - 【教程】带辐条的多边形

上一篇的教程中说到了如何画一条旋转的带色的直线,其中已经把如何用turtle绘图所需的全部元素讲的比较细致了,也就是:配置,基本图形,色彩和动画

今天这篇,我们再延伸下直线,给一个教程,讲一下如何用turtle画一个带辐条的多边形,它的基本形状是这样的:

87bb2148d6f58ae5c070fdbe5d63e87a.png
五边形
4d0aa1485b77e7b35d7f626303213a63.png
六边形
dc29351d1b3b31998c4ad3739313dcad.png
360边形

看起来是不是还蛮酷。

注意多边形的顶点都同中心点相连接,也就是有辐条。

下面请开始表演,以画五边形为例。

首先,我们从数学和编程的角度把复杂的问题进行分解。

五边形是由五个同心的三角形组成的,中心角是72°。

N边形是由N个同心的三角形组成的,中心角是360/N°。

这是数学规律,小学的奥数应该讲过这个,手动狗头。

到这里,我们的问题就变成了如何画这个三角形,并且我们希望它的角度可变。

画三角形有2种画法:

5913b6c64196a66584a1c89dd3a8840c.png
三角形画法

鼠标指示的位置是中心点,从中心点出去的两条边是等边。

A方法的顺序是:1等边 - 2底边 - 3另一条等边

B方法的顺序是:1等边 - 2另一条等边 - 3底边

毫无疑问,从编程的角度来讲,B方法更简单,A方法至少需要3-4次数学计算才能算出来,而且还要处理误差,太南了。

对于B方法,编程的思路就比较简单:

  1. 从(0,0)出发,走length长度,结束点记为(x,y)

  2. 从(0,0)出发,在1基础上转动72°(五边形),走length长度

  3. 走到(x,y)点,结束

我们可以看到这个流程中,几乎没有数学计算。

a94f553aa39bf95e26c348d3e2974b1b.gif
三角形画法

我们把代码弄出来:

length = 400

turtle.goto(0, 0)
turtle.pendown()
turtle.seth(0)
turtle.fd(length)
(x,y)=turtle.pos()
turtle.penup()
turtle.goto(0, 0)
turtle.pendown()
turtle.seth(72)
turtle.fd(length)
turtle.goto(x,y)
turtle.penup()

实际上,如果到了这一步,画一个多边形所需要的的基础知识80%已经具备了。

画完第一个,我们再来画第二个。

同样上代码:

turtle.goto(0, 0)
turtle.pendown()
turtle.seth(72)
turtle.fd(length)
(x,y)=turtle.pos()
turtle.penup()
turtle.goto(0, 0)
turtle.pendown()
turtle.seth(72+72)
turtle.fd(length)
turtle.goto(x,y)
turtle.penup()
497a21fc82329df8488e48530d13c977.gif
三角形画法2

搞到这里,眼尖的同学一定发现了什么?

画第一个图和第二个图除了角度不一样,其他都是一样的,那还不赶紧重构一把,等着过年吗??

length = 400
for index in range(5):
    turtle.goto(0, 0)
    turtle.pendown()
    turtle.seth(72*index)
    turtle.fd(length)
    (x,y)=turtle.pos()
    turtle.penup()
    turtle.goto(0, 0)
    turtle.pendown()
    turtle.seth(72*(index+1))
    turtle.fd(length)
    turtle.goto(x,y)
    turtle.penup()
9529e41be4a4d191171a3876080ab475.gif
五边形

漂亮,一个完美的五边形。

我们再来把代码重构一把,让它支持N边形。

def draw_gon(length, line):
    angle = 360//line
    for index in range(line):
        turtle.goto(0, 0)
        turtle.pendown()
        turtle.seth(angle*index)
        turtle.fd(length)
        (x,y)=turtle.pos()
        turtle.penup()
        turtle.goto(0, 0)
        turtle.pendown()
        turtle.seth(angle*(index+1))
        turtle.fd(length)
        turtle.goto(x,y)
        turtle.penup()

到这里,基本功能就完工了。

这里,我们每次起笔都是往东画,我们再重构一把,给它增加一个起始的角度值,为我们后面的旋转埋下伏笔。

def draw_gon(length, start_angle, line):
    angle = 360//line
    for index in range(line):
        turtle.goto(0, 0)
        turtle.pendown()
        turtle.seth(start_angle + angle*index)
        turtle.fd(length)
        (x,y)=turtle.pos()
        turtle.penup()
        turtle.goto(0, 0)
        turtle.pendown()
        turtle.seth(start_angle+angle*(index+1))
        turtle.fd(length)
        turtle.goto(x,y)
        turtle.penup()
0bb9d8a1d70c519970e7dde9e3bcd77f.png
五边形_角度10

最后,再把各个多边形的美图给一下:

ede3752887679bdbfa0f41b4235270be.png
八边形
c2621d53b074fe1b53a08f391758ab8f.png
九边形
3fb03edf640e9cca8e2a2c83c3e8d197.png
十边形
a78ef18b780d90c9125f13138097898d.png
十二边形
cba5630083b9df7a45d42a059e26d07a.png
十八边形
416c3b4528cc5a00a77899b97ac4e508.png
三十边形

--EOF--

例行求粉,谢谢!

ed47a5a5bd7d2ccbe7d461ff7005639a.png
702bff94c9da9e83dae08e065573ff98.gif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 绘制花草树木的分形图形可以使用L-system方法,L-system是一种基于字符串替换的方法,用于生成自相似的形状。以下是使用octave绘制分形花草树木的步骤: 1.定义L-system规则 首先,我们需要定义L-system规则。这里我们使用以下规则: - A → B[+A][-A],表示从A开始,向前移动1个单位,转向右侧,绘制B,然后向左转,绘制A的左子代,向右转,绘制A的右子代。 - B → BB,表示将B替换为两个B。 2.生成L-system字符串 接下来,我们使用octave生成指定迭代次数的L-system字符串。例如,我们可以使用以下代码生成迭代2次的字符串: ```octave n = 2; axiom = 'A'; rules = {'A', 'B[+A][-A]', 'B', 'BB'}; lsystem = axiom; for i = 1:n lsystem = strrep(lsystem, rules{1}, rules{2}); lsystem = strrep(lsystem, rules{3}, rules{4}); end disp(lsystem); ``` 输出结果为:`B[+B[+B][-B]][-B[+B][-B]]` 3.解析L-system字符串 接下来,我们需要解析L-system字符串,并根据规则绘制花草树木。我们可以使用以下代码实现: ```octave n = 2; axiom = 'A'; rules = {'A', 'B[+A][-A]', 'B', 'BB'}; lsystem = axiom; for i = 1:n lsystem = strrep(lsystem, rules{1}, rules{2}); lsystem = strrep(lsystem, rules{3}, rules{4}); end disp(lsystem); angle = 25; step = 10; stack = []; pos = [0, 0]; dir = [0, -1]; for i = 1:length(lsystem) switch lsystem(i) case 'F' pos = pos + step * dir; plot([pos(1) pos(1)-step*dir(1)], [pos(2) pos(2)-step*dir(2)], 'k'); case '+' dir = [dir(1)*cosd(angle) - dir(2)*sind(angle), dir(1)*sind(angle) + dir(2)*cosd(angle)]; case '-' dir = [dir(1)*cosd(-angle) - dir(2)*sind(-angle), dir(1)*sind(-angle) + dir(2)*cosd(-angle)]; case '[' stack = [stack; pos dir]; case ']' last = stack(end, :); pos = last(1:2); dir = last(3:4); stack = stack(1:end-1, :); end end ``` 这段代码将生成迭代2次的花草树木分形图形,使用plot函数绘制线条。其中,F表示向前移动一定距离,+表示向右转一定角度,-表示向左转一定角度,[表示保存当前位置和方向,]表示回到最近的[位置,并将方向恢复为之前的方向。 4.调整参数 最后,我们可以调整angle和step参数来改变分形图形的形状。例如,我们可以将angle设为30,step设为5,生成迭代3次的花草树木分形图形: ```octave n = 3; axiom = 'A'; rules = {'A', 'B[+A][-A]', 'B', 'BB'}; lsystem = axiom; for i = 1:n lsystem = strrep(lsystem, rules{1}, rules{2}); lsystem = strrep(lsystem, rules{3}, rules{4}); end disp(lsystem); angle = 30; step = 5; stack = []; pos = [0, 0]; dir = [0, -1]; for i = 1:length(lsystem) switch lsystem(i) case 'F' pos = pos + step * dir; plot([pos(1) pos(1)-step*dir(1)], [pos(2) pos(2)-step*dir(2)], 'k'); case '+' dir = [dir(1)*cosd(angle) - dir(2)*sind(angle), dir(1)*sind(angle) + dir(2)*cosd(angle)]; case '-' dir = [dir(1)*cosd(-angle) - dir(2)*sind(-angle), dir(1)*sind(-angle) + dir(2)*cosd(-angle)]; case '[' stack = [stack; pos dir]; case ']' last = stack(end, :); pos = last(1:2); dir = last(3:4); stack = stack(1:end-1, :); end end ``` 运行以上代码,将生成迭代3次的花草树木分形图形。 ### 回答2: 要利用Octave绘制花草树木的分形图形,可以使用L-系统(L-system)来生成这些形状。L-系统是一种形式语法系统,它可以通过迭代规则生成自相似的结构。 首先,我们需要定义一些规则来生成花草树木的形状。以下是一个例子: 1. 定义“F”为向前移动一定距离的指令 2. 定义“+”为顺时针旋转的指令 3. 定义“-”为逆时针旋转的指令 4. 定义“[”为保存当前状态的指令 5. 定义“]”为恢复到之前保存的状态的指令 6. 定义“X”为删除的指令(即不绘制线段) 接下来,我们可以创建一个递归函数,该函数将根据这些规则以及一些参数绘制出花草树木的形状。以下是一个例子: ```octave function drawTree(length, angle, generations, axiom) if generations == 0 return; endif nextGeneration = ''; for i = 1:length(axiom) currentChar = axiom(i); if currentChar == 'X' nextGeneration = [nextGeneration, currentChar]; elseif currentChar == 'F' line([0, 0], [0, length]); translate([0, length]); elseif currentChar == '+' rotate(angle); elseif currentChar == '-' rotate(-angle); elseif currentChar == '[' saveState(); elseif currentChar == ']' restoreState(); endif endfor drawTree(length * 0.6, angle, generations - 1, nextGeneration); endfunction ``` 通过调用这个函数,我们可以绘制出花草树木的分形图形。例如,以下是一个绘制二叉树的示例: ```octave clf; hold on; drawTree(100, pi/4, 9, 'X'); ``` 使用这些规则和参数,您可以根据自己的需要绘制出各种不同形状的花草树木分形图。调整绘制函数中的参数以及规则定义,您可以创建出独特的花草树木图形。 ### 回答3: 利用Octave绘制花草树木分形图形可以通过递归的方式实现。以下是一种常见的方法: 首先,我们需要确定绘制花草树木所需的参数,如树的高度、分支角度、分支长度和分支的减小比例等。 接下来,我们可以定义一个递归函数,用于在每个分支的末端绘制一个更小分支。该函数可能接受参数,如当前分支的起点坐标、当前分支的角度、当前分支的长度等。 在递归函数中,我们可以绘制当前分支,并计算出下一个分支的起点坐标、角度和长度。然后,我们可以调用递归函数,并将下一个分支的信息作为参数传入,以绘制更小的分支。 我们可以通过迭代调用递归函数,绘制出一个完整的花草树木形状。 在Octave中,我们可以使用plot函数进行绘图。我们可以定义一个函数来实现花草树木的绘制,然后在主程序中调用该函数。 最后,我们可以调整绘图窗口的大小、添加坐标轴和标题等元素,以美化我们的花草树木分形图形。 通过上述步骤,我们可以在Octave中使用递归函数和plot函数来绘制花草树木分形图形。这种方法允许我们根据定义的参数来创建不同形状的花草树木,并在绘图窗口中进行显示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值