要求:阅读螺线(spiral)的相关知识; 然后编写一个绘制阿基米德螺线(或者其他种类的螺线)的程序。
阿基米德螺线
import turtle
from math import sin, cos, pi
bob = turtle.Turtle() # create a Turtle object
bob.delay = 0.01 # 设置延迟值
def spiral(t, a, n, w=6):
''' 画阿基米德螺线
t: Turtle
a: 每转w度增加的内径长度
n: 圈数
w: 精度.默认为6(每次转过的角度)(角度值)
'''
theta = 0 # 转过角度初始化
m = int(360 / w) * n # 精度w下转n圈所需循环次数
#t.lt(w / 2) # 练习4-1第2问
for i in range(m):
dtheta = pi * w/ 180 # 精度变为弧度制
# 勾股定理得到要移动的小距离
length = pow((a*sin(dtheta)*(theta + dtheta))**2 +
(a*cos(dtheta)*(theta + dtheta) - a * theta)**2, 0.5)
#t.lt(w)
t.fd(length)
t.lt(w)
theta += dtheta # 为弧度制
#t.rt(w / 2) #练习4-1第2问
#t.lt(90)
#t.fd(200)
spiral(bob, 5, 3, 6)
turtle.mainloop()
这题参考了 九月初夏 的文章 https://blog.csdn.net/nineth9t/article/details/90322356 还有 4-1的练习 https://blog.csdn.net/nineth9t/article/details/90676590 写的很明了。
然后这里主要记录自己在搞这个螺线时的一些疑惑。
因为看了4-1练习的关于停止点偏离思考那篇文章,然后发现里面polyline函数跟螺线的实现函数很像。因为一开始很不明白这个走一小段然后转一小个角度这是怎么实现画阿基米德螺线的。但是看了文章后就明白了。
因为在那之前,我的函数是这样的:
import turtle
def draw_spiral(t, n, w, a=0.05):
'''画阿基米德螺线
t: Turtle
n: 循环次数(越大圈数越多)
w: 每条弧对应的角度
a: 每转1度增加的内径长 (默认值为0.05)
'''
r = 0
b = 0.1
c = 0 # 转过的角度
for i in range(n):
r = a * c + b
t.circle(r, 1)
c += w
bob = turtle.Turtle()
bob.delay = 0.001
draw_spiral(bob, 1000, 6, 0.05)
思路主要是看了阿基米德螺线的数学关系后得出的:
阿基米德螺线 r=aθ + b
然后在一个小角度内处理成为半径不变的弧,然后画出来。
结果就是画的速度乌龟一样慢,并且怎么调参数也不会得到作者大大写的函数的画的蚊香…只能是松松的蚊香 = =
顺便提醒一句要记得 turtle.mainloop() 不然在不是IDLE环境下运行会画完光速关系窗口了…
然后看了一遍作者的函数代码。发现没有用circle这种画弧的方法ORZ
然后拜读了 九月初夏 的文章(上面贴的)后才理解了。
ORZ数学不是很好,然后还是没有明白作者在这里的思路。
欢迎来交流~要是弄出来了,再回来更新。
附作者的代码:
from __future__ import print_function, division
import turtle
def draw_spiral(t, n, length=3, a=0.1, b=0.0002):
"""Draws an Archimedian spiral starting at the origin.
Args:
n: how many line segments to draw
length: how long each segment is
a: how loose the initial spiral starts out (larger is looser)
b: how loosly coiled the spiral is (larger is looser)
http://en.wikipedia.org/wiki/Spiral
"""
theta = 0.0
for i in range(n):
t.fd(length)
dtheta = 1 / (a + b * theta)
t.lt(dtheta)
theta += dtheta
# create the world and bob
bob = turtle.Turtle()
draw_spiral(bob, 300, 3, 0.1, 0.0002)
turtle.mainloop()
上了stackoverflow看了一下,虽然没有还是没有理解上面的。
用平面直角坐标系法画:
import turtle
from math import cos, sin, pi
def spiral(t, rotations=3, a=0.0, b=5):
theta = 0.0
while theta < rotations * 2 * pi:
radius = a + b * theta
x, y = radius * cos(theta), radius * sin(theta)
turtle.goto(x, y)
theta += 0.1
bob = turtle.Turtle()
spiral(bob)
turtle.mainloop()
然后有因为混着莫名其妙看了4-1的文章,然后就有了以下的莫名其妙关于停止点的偏离的思考。因为一开始我也感觉不出来 arc 函数修改前和修改后会有多大影响…然后看了文章后又对自己的螺线试了一番。
这是没有用 rt (angle / 2) 和 lt(angle / 2) 的,把之前的代码这两行解除注释来画条直线来看到停止点与起始点的距离
#t.lt(90)
#t.fd(200)
然后用了rt (angle / 2) 和 lt(angle / 2):
对上去了~大概跟画字母J的弧对上去是差不多的意思。
然后还有一个疑惑,就是为什么是先前进再转Δθ呢。
然后就画了先转Δθ然后再走的…(注释了转一半角的误差调整下)
emmmmmm跟第一张先走一段距离再转一个角度比起来竟然有这么多的差别,虽然只是终点偏离的有点远。螺线结构虽然人眼好像看不出有什么差别就是了ORZ
具体在误差上有什么差别还没有去深入探讨过。有的话再回来更新。
斐波那契螺线
def FibonacciSpiral(t, n):
'''画斐波那契螺线
t: Turtle
n: 循环次数
'''
r = a = b = 1
# draw the first half circle
arc(bob, r, 180)
# Draw the 1/4 circle
for i in range(n):
r = a + b # 斐波那契数列
b = a
a = r
arc(bob, r, 90)
阅读了斐波那契螺线后画的。
欢迎围观和有什么错误可以跟我一起交流~
原文链接:https://blog.csdn.net/YunoSawano/article/details/105238691