我很难理解这本书的作者为什么使用某些代码行:
import math
import turtle
bob = turtle.Turtle()
def polyline(t, n, length, angle):
"""Draws n line segments.
t: Turtle object
n: number of line segments
length: length of each segment
angle: degrees between segments
"""
for i in range(n):
t.fd(length)
t.lt(angle)
def polygon(t, n, length):
"""Draws a polygon with n sides.
t: Turtle
n: number of sides
length: length of each side.
"""
angle = 360.0/n
polyline(t, n, length, angle)
def arc(t, r, angle):
"""Draws an arc with the given radius and angle.
t: Turtle
r: radius
angle: angle subtended by the arc, in degrees
"""
arc_length = 2 * math.pi * r * abs(angle) / 360
n = int(arc_length / 4) + 3
step_length = arc_length / n
step_angle = float(angle) / n
# making a slight left turn before starting reduces
# the error caused by the linear approximation of the arc
t.lt(step_angle/2)
polyline(t, n, step_length, step_angle)
t.rt(step_angle/2)
def circle(t, r):
"""Draws a circle with the given radius.
t: Turtle
r: radius
"""
arc(t, r, 90)
circle(bob, 100)
我在评论中强调了我的困惑。说明是为了使一般功能能够在Python中使用乌龟绘制圆。我正在使用Python 3.7,但我并不认为这有所作为。为什么作者在第一条评论中使用n?他从哪里得到那个公式?另外,其余注释代码背后的逻辑是什么?我理解其余的练习,如果我知道他是怎么得到方程式的,我也会理解的。
答案 0 :(得分:1)
让我们逐行接弧功能:
arc_length = 2 * math.pi * r * abs(angle) / 360
2 * math.pi * r
是圆周长的公式。 abs(angle) / 360
告诉您您的路径将占圆周长的比例。将它们相乘,就可以得出乌龟描述该弧线所需的距离(假设它可以沿着弯曲的路径移动,而这只是我们的近似值)。
n = int(arc_length / 4) + 3
这是当我们近似由该圆的圆周描述的路径时,我们希望乌龟采取的步骤数。不一定是这个特定的值。其他实现使用int(arc_length / 3) + 1
和其他值。 step_length
和step_angle
都按比例缩放,因此增加它会使每个步骤更小,并使单个步骤更小旋转。忽略浮点数学问题和应计的舍入误差,行进的总距离和总的旋转将保持不变。
step_length = arc_length / n
step_angle = float(angle) / n
我们的折线将为我们迈出n
步。在每一步中,我们要移动1/n
的{{1}} th并旋转圆弧描述的总角度的arc_length
th。如果我们在这两行之前的行中将1/n
设为更大的值,则n
和step_length
将相应地缩小。
其余的:
step_angle
这里的半转弯对我们近似的弧度有很小的改善。想想我们在这里描述的路径,例如沿着单位圆的90度弧线,从(1,0)开始,以(3,3)结束于(0,1)。下表是单位圆本身的位置(理想x,理想y和理想航向,其中理想航向是该点处圆的切线),原始x,原始y和原始航向以及通过在开始路径前向左转t.lt(step_angle/2)
polyline(t, n, step_length, step_angle) # take a lot of little steps
t.rt(step_angle/2)
,然后向后弯曲step_angle/2
,将其取消,可以得到x,y和航向:
step_angle/2
请注意,调整后的值比原始值更接近理想值。在考虑折线的工作原理时,这具有直观的意义:折线朝着其面对的任何方向向前移动,然后左转。从未调整的航向开始时,您甚至在尝试转弯之前将 |ideal x|ideal y|ideal heading|raw x|raw y|raw heading|adj x|adj y|adj heading|
------------------------------------------------------------------------------------
Start|1 |0 |90 |1 |0 |90 |1 |0 |105 |
Step1|0.86 |0.5 |120 |1 |0.52 |120 |0.86 |0.51 |135 |
Step2|0.5 |0.86 |150 |0.74 |0.98 |150 |0.49 |0.88 |165 |
Step3|0 |1 |180 |0.28 |1.24 |180 |-0.01|1.01 |195 |
End |0 |1 |180 |0.28 |1.24 |180 |-0.01|1.01 |180 |
移至圆弧上方。您将始终位于圆弧的上方和右侧。首先向左转半个step_angle,您将在圆弧下花费每个step_length
,并在圆弧上花费每个step_length
。与严格位于弧外的弧相比,这将产生更好的弧近似值。
编辑:
关于更新的circle方法的问题,它需要两个参数(turtle和圆的半径),然后相应地调用arc,现在您的实现是:
step_length
def circle(t, r):
arc(t, r, 90)
的第三个参数是您要传播的弧的角度。要制作一个圆圈,您需要360度,而不是90度。