根据罗塞塔码的说法:
混沌博弈是迭代函数系统(IFS)吸引子的一种生成方法。其中最著名和最简单的例子之一,创建分形,使用多边形和一个初始点随机选择。任务玩混沌游戏,以等边三角形的角为参照点。随机添加一个起始点(最好在三角形内)。然后在起点和一个参考点中间添加下一个点。这个参照点是随机选择的。经过足够的迭代后,Sierpinski三角形的图像就会出现。
下面是我用Python的解决方案:
"""This module performs the Chaos Game."""
from random import choice
from PIL import Image
def midpoint(p1, p2):
"""
Takes 2 points and calculates the midpoint.
Args:
p1 (real, real): A point in space.
p2 (real, real): Another point in space.
Returns:
(real, real): The midpoint between p1 and p2.
"""
return (p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2
def translate(point, screen_size):
"""
Takes a point and converts it to the appropriate coordinate system.
Note that PIL uses upper left as 0, we want the center.
Args:
point (real, real): A point in space.
screen_size (int): Size of an N x N screen.
Returns:
(real, real): Translated point for Pillow coordinate system.
"""
return point[0] + screen_size / 2, point[1] + screen_size / 2
def image_rep(point, img_size):
"""
Returns a representation of the point that can be used by Pillow.
Args:
point (real, real): A point in space.
img_size (int): The size of an N x N image
"""
# Convert the point to the correct coordinate system.
translated = translate((point[0], point[1]), img_size)
# Make it an integer so Pillow can use it.
return int(translated[0]), int(translated[1])
def play_chaos(guiders, seed, img, steps=1000):
"""
Play the Chaos Game:
1. Have a collection of n (ordered) "guider" points.
2. Start with a random seed some where on the screen.
3. Roll die that has n sides
4. Make a new point that is halfway between the appropriate gudier and the
previous point.
5. Repeat the game from the new point
Args:
guiders ([(real, real)]): List of guider points
seed (real, real): Initial seed, be sure to be within the screens range
img (Image): Image to write spiral to.
steps (int): The amount of times the process is repeated.
(default: 1000)
"""
prev_point = seed
for _ in range(steps):
# Select the next guider to move closer to
guider = choice(guiders)
new_point = midpoint(prev_point, guider)
img.putpixel(image_rep(new_point, img.size[0]), 1)
prev_point = new_point
def main():
"""
Main method, start of the program. Creates an image and populates it with
chaos.
"""
IMAGE_SIZE = 300, 300
img = Image.new('1', IMAGE_SIZE)
SEED = (0.0, 0.0)
GUIDERS = [(-100.0, -100.0),
(100.0, -100.0),
(0.0, 100.0)]
play_chaos(GUIDERS, SEED, img)
img.save('chaos.png')
if __name__ == '__main__':
main()发布于 2016-10-14 13:59:52
这个函数可以使用zip()编写得更优雅,而且它可以工作在任意数量的维度上。(不过,我怀疑速度可能会慢一些。)
def midpoint(p1, p2):
"""
Find the midpoint of two cartesian points.
"""
return tuple((c1 + c2) / 2 for c1, c2 in zip(p1, p2))因为translate()给出了一个枕头坐标的结果,所以我认为这个结果应该被量化为整数。您应该舍入最近的整数,而不是截断。
枕头坐标向右和向底部增加。按照惯例,笛卡尔坐标向右和向顶部方向增加。因此,我将在翻译中加入垂直轴的反映。
我不明白为什么图像必须是正方形的。
您可以只传递point,而不是将它打包成一个新的元组。
translated = translate(point, img_size)我建议将这两个助手函数隐藏在绘图例程中。(见下文)
我会把它分解成数学概念和它的可视化。
def chaos_points(attractors, start_point):
attractor_stream = (random.choice(attractors) for _ in itertools.count())
return itertools.accumulate(itertools.chain([start_point], attractor_stream), midpoint)
def plot(img, points):
half_width, half_height = img.size[0] / 2, img.size[1] / 2
to_pillow = lambda p: (int(round(half_width + p[0])), int(round(half_height - p[1])))
for point in points:
img.putpixel(to_pillow(point), 1)您的GUIDERS不像建议的那样形成等边三角形。
def main():
"""
Create an image and populate it with chaos.
"""
IMAGE_SIZE = 300, 300
SEED = (0.0, 0.0)
GUIDERS = [(-100.0, -50 * 3**.5),
(+100.0, -50 * 3**.5),
( 0.0, +50 * 3**.5)]
img = Image.new('1', IMAGE_SIZE)
plot(img, itertools.islice(chaos_points(GUIDERS, SEED), 1000))
img.save('chaos.png')
if __name__ == '__main__':
main()https://codereview.stackexchange.com/questions/144190
复制相似问题