一个用于在Python的turtle模块中创建分形艺术的模块。
项目描述
fractalartmaker
一个用于在Python的turtle模块中创建分形艺术的模块。
分形是递归、自相似的形状。《code>fractalartmaker模块(简称为fam
)帮助您使用Python编程语言和Python的内置turtle
模块创建分形。此模块基于Al Sweigart的免费书籍《递归指南》(The Recursive Guide to Recursion)中的“分形艺术制作器”章节。已进行了一些修改,以便更容易使用和实验。
快速入门
运行pip install fractalartmaker
进行安装。在Windows上运行python -m fractalartmaker
,在macOS上运行python3 -m fractalartmaker
以运行演示并查看Al Sweigart制作的九件分形艺术作品。
首先,您需要了解一些Python编程知识和Python的turtle
模块。RealPython.com有一个turtle
模块教程。
您可以通过在交互式外壳(也称为REPL)中运行以下代码来查看演示分形:
>>> import fractalartmaker as fam
>>> fam.demo_four_corners()
这将在新的turtle窗口中绘制四角分形。一旦您了解了分形艺术制作器的工作原理,您就可以自己调用fam.draw_fractal()
函数
>>> import fractalartmaker as fam
>>> fam.draw_fractal(fam.square, 100, [{'size': 0.96, 'y': 0.5, 'angle': 11}], max_depth=100)
本例绘制了一个类似Horn演示分形的分形。`fam.square` 是一个函数,它接受两个参数 size
和 depth
,并使用 turtle
命令绘制一个正方形(每边应为 size
步长,depth
是当前递归层级深度,对于简单的分形通常忽略)。100
是第一个绘制的正方形的初始大小。`[{'size': 0.96, 'y': 0.5, 'angle': 11}]` 是一个 递归规范字典列表。此示例表示,对于每个绘制的正方形,递归地再绘制一个正方形,其大小为原始大小的 96%,位于旋转 11 度后的正方形的上方 50%。
如果您希望每个正方形递归绘制两个更多正方形,请向此列表添加第二个字典。检查模块中的 demo_*()
函数(以及以下“演示分形画廊”部分)以获取示例。
注意:调用 fam.draw_fractal()
会自动调用 turtle.reset()
来清除窗口并将海龟光标移回 0, 0。如果您不希望这种行为,请将 reset=False
传递给 fam.draw_fractal()
为了让您无需自己导入 turtle
模块,您可以从 fam
模块调用大多数 turtle
函数:例如 fam.reset()
、fam.update()
等。请参阅“Python Turtle 模块速查表”以获取函数列表。
演示分形画廊
def demo_four_corners(size=350, max_depth=5, **kwargs):
# Four Corners:
if 'colors' not in kwargs:
kwargs['colors'] = (('black', 'white'), ('black', 'gray'))
draw_fractal(square, size,
[{'size': 0.5, 'x': -0.5, 'y': 0.5},
{'size': 0.5, 'x': 0.5, 'y': 0.5},
{'size': 0.5, 'x': -0.5, 'y': -0.5},
{'size': 0.5, 'x': 0.5, 'y': -0.5}], max_depth=max_depth, **kwargs)
def demo_spiral_squares(size=600, max_depth=50, **kwargs):
# Spiral Squares:
if 'colors' not in kwargs:
kwargs['colors'] = (('black', 'white'), ('black', 'gray'))
draw_fractal(square, size, [{'size': 0.95,
'angle': 7}], max_depth=max_depth, **kwargs)
def demo_double_spiral_squares(size=600, **kwargs):
# Double Spiral Squares:
if 'colors' not in kwargs:
kwargs['colors'] = (('black', 'white'), ('black', 'gray'))
draw_fractal(square, 600,
[{'size': 0.8, 'y': 0.1, 'angle': -10},
{'size': 0.8, 'y': -0.1, 'angle': 10}], **kwargs)
def demo_triangle_spiral(size=20, max_depth=80, **kwargs):
# Triangle Spiral:
draw_fractal(triangle, size,
[{'size': 1.05, 'angle': 7}], max_depth=max_depth, **kwargs)
def demo_glider(size=600, **kwargs):
# Conway's Game of Life Glider:
if 'colors' not in kwargs:
kwargs['colors'] = (('black', 'white'), ('black', 'gray'))
third = 1 / 3
draw_fractal(square, 600,
[{'size': third, 'y': third},
{'size': third, 'x': third},
{'size': third, 'x': third, 'y': -third},
{'size': third, 'y': -third},
{'size': third, 'x': -third, 'y': -third}], **kwargs)
def demo_sierpinski_triangle(size=600, **kwargs):
# Sierpinski Triangle:
toMid = math.sqrt(3) / 6
draw_fractal(triangle, 600,
[{'size': 0.5, 'y': toMid, 'angle': 0},
{'size': 0.5, 'y': toMid, 'angle': 120},
{'size': 0.5, 'y': toMid, 'angle': 240}], **kwargs)
def demo_wave(size=280, **kwargs):
# Wave:
draw_fractal(triangle, size,
[{'size': 0.5, 'x': -0.5, 'y': 0.5},
{'size': 0.3, 'x': 0.5, 'y': 0.5},
{'size': 0.5, 'y': -0.7, 'angle': 15}], **kwargs)
def demo_horn(size=100, max_depth=100, **kwargs):
# Horn:
if 'colors' not in kwargs:
kwargs['colors'] = (('black', 'white'), ('black', 'gray'))
draw_fractal(square, size,
[{'size': 0.96, 'y': 0.5, 'angle': 11}], max_depth=max_depth, **kwargs)
def demo_snowflake(size=200, **kwargs):
# Snowflake:
if 'colors' not in kwargs:
kwargs['colors'] = (('black', 'white'), ('black', 'gray'))
draw_fractal(square, size,
[{'x': math.cos(0 * math.pi / 180),
'y': math.sin(0 * math.pi / 180), 'size': 0.4},
{'x': math.cos(72 * math.pi / 180),
'y': math.sin(72 * math.pi / 180), 'size': 0.4},
{'x': math.cos(144 * math.pi / 180),
'y': math.sin(144 * math.pi / 180), 'size': 0.4},
{'x': math.cos(216 * math.pi / 180),
'y': math.sin(216 * math.pi / 180), 'size': 0.4},
{'x': math.cos(288 * math.pi / 180),
'y': math.sin(288 * math.pi / 180), 'size': 0.4}], **kwargs)
创建您自己的分形
使用分形艺术制作器创建分形涉及两个部分。
首先,您需要编写我所说的 形状绘制函数。这是一个使用 turtle
函数绘制简单形状的函数,该形状将被绘制数十或数百次以创建您的分形。该函数必须接受至少两个参数:第一个参数名为 size
,第二个参数名为 depth
。
例如,此形状绘制函数绘制一个正方形(depth
参数被忽略)
def square(size, depth):
# Move to the top-right corner before drawing:
turtle.penup()
turtle.forward(size // 2)
turtle.left(90)
turtle.forward(size // 2)
turtle.left(180)
turtle.pendown()
# Draw a square:
for i in range(4): # Draw four lines.
turtle.forward(size)
turtle.right(90)
fam
库调用您的形状绘制函数,并提供适当的 size
参数。您的形状大小只需相对于传递给此参数的数字是相对的即可
您的形状绘制函数必须相对于 size
的尺寸和当前面向的方向绘制一个形状。使用相对的 turtle
函数,如 forward()
、back()
、left()
和 right()
,而不是绝对函数,如 goto()
或 setheading()
。传递给 forward()
和 back()
调用的参数应始终取决于 size
参数,而不是静态的、固定的数字。
depth
参数是形状绘制所在的递归级别。因此,对于第一级它是 0
,第二级它是 1
,依此类推。您可以使用它来执行一些更高级的效果(稍后讨论)。
您的形状绘制函数不会调用自己或进行任何递归。让它保持简单:它只是使用 turtle
函数绘制一个形状。
fam
库提供了一些形状绘制函数供您使用:`fam.square()` 和 `fam.triangle()`
其次,您必须调用 fam.draw_fractal()
函数,并传递三个东西:一个形状绘制函数、起始大小(通常 100
是一个好选择)和一个 递归规范字典列表。列表中的每个字典指定了形状在递归的每个级别上的变化:`'size'` 用于大小变化,`'x'` 用于左右移动,`'y'` 用于上下移动,`'angle'` 用于旋转。
请注意,对于 Fractal Art Maker 的递归规范字典,正的 `'y'` 向上移动,负的 `'y'` 向下移动。(这与学校数学课中的图表类似,而不是计算机图形。)
例如,让我们看看 Fractal Art Maker 中包含的 Horn 演示分形。您可以通过运行 import fractalartmaker as fam; fam.demo_horn()
来查看它
此分形是通过绘制一个正方形,然后递归地绘制一个更小的第二个正方形来制作的
- 略小。 (确切地说是前一个正方形大小的 96%。)
- 放置在上方。(确切地说,是前一个正方形大小的50%)
- 顺时针轻微旋转。(确切地说,11度。)
第二个正方形(由于这个分形在白色和灰色正方形之间交替,所以是灰色)依次递归地产生一个更小的第三个正方形,放置在上方,并轻微顺时针旋转。请注意,由于第二个正方形是向左/顺时针旋转的,因此它的“上方”也相应旋转。这就是为什么后续的正方形会向左倾斜。
我们可以用以下递归指定字典来绘制:{'size': 0.96, 'y': 0.5, 'angle': 11}
因此,要在Fractal Art Maker中绘制Horn分形,我们运行以下代码
>>> import fractalartmaker as fam
>>> fam.draw_fractal(fam.square, 100, [{'size': 0.96, 'y': 0.5, 'angle': 11}], max_depth=100)
max_depth
关键字参数表示您想要进行多少层递归。默认设置为8
。
如果我们传递一个'x'
或'y'
参数为0.0
,则下一个递归形状不会从父形状的位置移动。如果我们传递一个'size'
为1.0
,则下一个递归形状与父形状的大小相同。如果我们传递一个'angle'
为0
,则下一个递归形状不旋转。如果从字典中省略了键,这些也是默认值。
虽然'angle'
始终是旋转的绝对度数,但'x'
、'y'
和'size'
的值始终相对于形状绘制函数的当前形状大小。
让我们做一个与四边形演示类似的另一个示例。运行fam.reset()
以清除海龟窗口并将海龟光标放回0,0。此函数与turtle.reset()
相同。我想先画一个正方形,然后递归步骤在先前的正方形上方和左方画一个更小的正方形(不旋转)。运行以下代码
>>> import fractalartmaker as fam
>>> fam.draw_fractal(fam.square, 350, [{'size': 0.5, 'x': -0.5, 'y': 0.5}], max_depth=5)
此代码绘制以下内容
max_depth=5
关键字参数防止绘制过多的正方形。(默认最大递归深度为8。)
我们可以在所有这些正方形中添加一个第二个递归正方形,通过将第二个递归指定字典添加到列表中。这个第二个字典将绘制一个向上和向右的另一个递归步骤。通过以下代码继续交互式外壳示例。注意第二个字典有一个'x'
为0.5
而不是-0.5
>>> fam.reset() # Clears the screen.
>>> fam.draw_fractal(fam.square, 350, [{'size': 0.5, 'x': -0.5, 'y': 0.5}, {'size': 0.5, 'x': 0.5, 'y': 0.5}], max_depth=5)
此代码绘制以下内容
请注意,不仅仅是第一个正方形有两个递归正方形,每个得到两个递归正方形的正方形。
我们可以通过将第三个指定字典添加到列表中来添加一个第三个正方形,这个字典有一个'y'
为-0.5
>>> fam.reset() # Clears the screen.
>>> fam.draw_fractal(fam.square, 350, [{'size': 0.5, 'x': -0.5, 'y': 0.5}, {'size': 0.5, 'x': 0.5, 'y': 0.5}, {'size': 0.5, 'x': -0.5, 'y': -0.5}], max_depth=5)
此代码绘制以下内容
最后,我们可以添加一个第四个正方形
>>> fam.reset() # Clears the screen.
>>> fam.draw_fractal(fam.square, 350, [{'size': 0.5, 'x': -0.5, 'y': 0.5}, {'size': 0.5, 'x': 0.5, 'y': 0.5}, {'size': 0.5, 'x': -0.5, 'y': -0.5}, {'size': 0.5, 'x': 0.5, 'y': -0.5}], max_depth=5)
此代码绘制以下内容
您会注意到这个分形并不完全像fam.demo_four_corners()
中的一个。我们可以在形状绘制函数中交替使用白色和灰色填充颜色。让我们看看下一个。
FAM的形状绘制函数的高级功能
所有形状绘制函数都传递一个size
参数和一个depth
参数。我们可以通过检查depth
参数来创建白色和灰色的交替颜色。在以下形状绘制函数中,正方形的填充颜色设置为白色或灰色,取决于递归深度
def square_alternating_white_gray(size, depth):
# Move to the top-right corner before drawing:
turtle.penup()
turtle.forward(size // 2)
turtle.left(90)
turtle.forward(size // 2)
turtle.left(180)
turtle.pendown()
# Set fill color:
if depth % 2 == 0:
turtle.fillcolor('white')
else:
turtle.fillcolor('gray')
# Draw a square:
turtle.begin_fill()
for i in range(4): # Draw four lines.
turtle.forward(size)
turtle.right(90)
turtle.end_fill()
待办事项:本节的其余部分尚未完成。我将快速写下代码示例和基本描述,因为只是需要完成这个教程。
Fractal Art Maker 自带的 fam.square
和 fam.triangle
形状绘制函数具有特殊功能,您可以通过关键字参数传递给 fam.draw_fractal()
函数。(这些功能仅适用于这两个函数。您可以按照自己的意愿编写任何具有任何功能的形状绘制函数。关键字参数将转发到您的形状绘制函数。您的形状绘制函数应具有参数 size, depth, \*\*kwargsFor
,并且这些额外的参数将包含在 kwargs
字典中。《Kwargs》是 Python 的一个约定。[链接](https://realpython.com/python-kwargs-and-args/)
例如,下面是带有一些这些功能的 Horn 示例
蓝色笔色和红色填充色
>>> import fractalartmaker as fam
>>> fam.draw_fractal(fam.square, 100, [{'size': 0.96, 'y': 0.5, 'angle': 11}], max_depth=100, pen='blue', fill='red')
第一迭代为蓝色笔和红色填充色,第二迭代为绿色笔和黄色填充色,然后循环回到第一组颜色
>>> import fractalartmaker as fam
>>> fam.draw_fractal(fam.square, 100, [{'size': 0.96, 'y': 0.5, 'angle': 11}], max_depth=100, colors=[['blue', '#FF0000'], ['green', 'yellow']])
笔粗为 10
>>> import fractalartmaker as fam
>>> fam.draw_fractal(fam.square, 100, [{'size': 0.96, 'y': 0.5, 'angle': 11}], max_depth=100, pensize=10)
随机抖动,移动位置为大小的 25%
>>> import fractalartmaker as fam
>>> fam.draw_fractal(fam.square, 100, [{'size': 0.96, 'y': 0.5, 'angle': 11}], max_depth=100, jiggle=0.25)
Python Turtle 模块速查表
import turtle
turtle.forward(100) # Move forward 100 steps.
turtle.backward(100) # Move backwards 100 steps.
turtle.left(90) # Turn left/clockwise 90 degrees.
turtle.right(90) # Turn right/counterclockwise 90 degrees.
turtle.position() # Return (0, 0), the current XY position of the turtle.
turtle.heading() # Return 0.0, the current heading/direction of the turtle. (0 is right, 90 is up, 180 is left, 270 is down)
turtle.goto(30, 25) # Move turtle to X of 30 and Y of 25.
turtle.setx(30) # Move turtle left/right to X of 30 and current Y coordinate.
turtle.sety(25) # Move turtle up/down to Y of 25 and current X coordinate.
turtle.towards(30, 25) # Return degrees to turn left to face XY 30, 25 from current position/heading.
turtle.setheading(90) # Make the turtle face up (90 degrees).
turtle.penup() # "Raise the pen" and stop drawing as the turtle moves.
turtle.pendown() # "Lower the pen" and start drawing as the turtle moves.
turtle.pensize(4) # Set pen thickness size to 4. (Default is 1.)
turtle.width() # Return 4, the current pen thickness size.
turtle.pencolor('red') # Lines drawn will now be red. (Also use color formats '#FF0000' or (255, 0, 0))
turtle.fillcolor('white') # Set fill color of begin_fill() and end_fill() to white.
turtle.begin_fill() # Start drawing a filled-in shape.
turtle.end_fill() # End drawing a filled-in shape and draw the fill color.
turtle.home() # Move the turtle to 0, 0 and facing right (0 degrees).
turtle.clear() # Erase all drawings on the screen, but leave the turtle in its place.
turtle.reset() # Erase all drawings and move turtle to 0, 0 and facing right.
turtle.hideturtle() # Don't show the turtle cursor in the window.
turtle.showturtle() # Show the turtle cursor in the window.
turtle.bgcolor('blue') # Make the background color of the window blue. (Default is white.)
turtle.tracer(1000, 0) # Do 1000 turtle commands with 0 delay all at once. (Increase 1000 to make drawing speed faster.)
turtle.update() # Call this when done to update the screen with any remaining turtle commands' drawings.
turtle.exitonclick() # Close the window when the user clicks it.
简短函数名速查表
turtle.fd() # forward()
turtle.bk() # backward()
turtle.lt() # left()
turtle.rt() # right()
turtle.pos() # position()
turtle.pd() # pendown()
turtle.pu() # penup()
项目详情
fractalartmaker-0.2.0.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 2795a2ff62bf3dbc1c3ebd20ec4d67434766c92f8066465a0c09613ea02521fa |
|
MD5 | 2bb396296e7d041294dd4688ce371f7b |
|
BLAKE2b-256 | 69463263e22f5be383c5cd3c43d6c6d95c61c338053ab9d0d93c262b778f2631 |