我已经制作了3个函数来绘制希尔伯特曲线。这更像是一个数学问题,但为了以防万一,我将包括编码。我使用turtle python模块绘制。
第一个,这个让我得到一个清单。
def derive(c1,c2,l,l1,l2):
"""
derive list l by list l1 for every c1 element and by list2 for every
c2 element. designed for hilbert fractal and dragon fractal
:param c1: element by which l2 will derive l1
:type c1: str
:param c2: element by which l2 will derive l1
:type c2: str
:param l: list to be derived
:type l: list
:param l1: list to derive with
:type l1: list
:param l2: list to derive with
:type l2: list
:return: list
:CU: l1 and l2 must only contain these elements : 'R','L','F','+','-'
:Example:
>>>derive('-','A',['F','-','F'],['+','+','F'])
['F', '+', '+', 'F', 'F']
"""
assert type(l) in {list} and type(l1) in {list} and type(l2) in {list},'parameter l1 or l2 must be a list'
assert type(c1) in {str} and type(c2) in {str},'parameter c1 and c2 must be a string'
lret = []
for e in l:
if e != c1 and e!= c2:
# assert type(e) in {str},'parameter l must only contain str'
# assert e == 'R' or e == 'L' or e == 'F' or e == '+' or e == '-','parameter l1 elements must be \'R\' or \'L\' or \'F\' or \'-\' or \'+\''
lret.append(e)
elif e == c1:
for e1 in l1:
# assert type(e1) in {str},'parameter l1 must only contain str'
# assert e1 == 'R' or e1 == 'L' or e1 == 'F' or e1 == '+' or e1 == '-','parameter l1 elements must be \'R\' or \'L\' or \'F\' or \'-\' or \'+\''
lret.append(e1)
elif e == c2:
for e2 in l2:
# assert type(e2) in {str},'parameter l2 must only contain str'
# assert e2 == 'R' or e2 == 'L' or e2 == 'F' or e2 == '+' or e2 == '-','parameter l1 elements must be \'R\' or \'L\' or \'F\' or \'-\' or \'+\''
lret.append(e2)
return lret
第二个,这个来自第n次
def derive_n(n,c1,c2,l,l1,l2):
"""
derive list l1 by list l2 for every c element n-th times
:param c1: element by which l1 will derive l
:type c1: str
:param c2: element by which l2 will derive l
:type c2: str
:param l: list to be derived
:type l: list
:param l1: list to derived with
:type l1: list
:param l2: list to derive with
:type l2: list
:param n: number of time l1 will be derived
:type n: int
:return: list
:CU: n >= 0
:Example:
>>>derive_n(0,'F','L',['F','-','F'],['F','+','F'],['L','R'])
['F', '-', 'F']
>>>derive_n(1,'F','L',['F','-','F'],['F','+','F'],['L','R'])
['F', '+', 'F', '-', 'F', '+', 'F']
>>>derive_n(2,'F','L',['F','-','F'],['F','+','F'],['L','R'])
['F', '+', 'F', '+', 'F', '+', 'F', '-', 'F', '+', 'F', '+', 'F', '+', 'F']
"""
if n == 0:
return l
else:
return derive(c1,c2,derive_n(n-1,c1,c2,l,l1,l2),l1,l2)
第3个函数绘制曲线:
def draw(il,l,a):
"""
draw a fractal by following parameter il
:param il: instruction list
:type il: list
:param l: length for forward() function
:type l: float or int
:param a: angle for left and right function in degree
:type a: float or int
:CU: l > 0
"""
assert type(a) in {int,float},'parameter a must be an int or float'
assert type(l) in {int,float},'parameter l must be an int or float'
assert type(il) in {list},'parameter il must be a list'
assert l > 0,'parameter l must be strictly superior to 0'
board_reset()
pendown()
for e in il:
if e == 'F':
forward(l)
elif e == '+':
left(a)
elif e == '−':
right(a)
penup()
boardrese()是一个重新初始化绘图板的功能。
这是我必须为课堂做的一个项目。我几乎完成了它,但根据我的教授的说法,无论你有多少时间得到这个列表,绘图必须总是填充一个大小不变的正方形。
基本上,我需要对draw函数的length参数进行一些数学运算。我只是不知道是什么。我已经尝试了l / n,l /(时间和#39; F'出现在最终列表中),l /(最终列表的长度)......感谢
答案 0 :(得分:0)
我已经单独使用turtle绘制Hilbert曲线的代码,因为我在Processing l-systems项目中有一堆可重复使用的代码(如果你真的想参考it为了灵感)。它使用递归生成器而不是列表 - 这意味着它在内存中非常有效,并且只需要跟踪几个堆栈帧,并且只需要跟踪单个"动作"它会回归。为了我自己的测试目的,它也有一个hacky小的argparser。
import turtle
import sys
from enum import Enum
screen = turtle.Screen()
t = turtle.Turtle()
t.speed(0)
t.pu()
t.setpos(-screen.window_width() * 0.5 + 50,
-screen.window_height() * 0.5 + 50)
t.pd()
class HilA(Enum):
F = 0
L = 1
R = 2
A = 3
B = 4
RULES = {HilA.A: [HilA.L, HilA.B, HilA.F, HilA.R, HilA.A, HilA.F, HilA.A, HilA.R, HilA.F, HilA.B, HilA.L],
HilA.B: [HilA.R, HilA.A, HilA.F, HilA.L, HilA.B, HilA.F, HilA.B, HilA.L, HilA.F, HilA.A, HilA.R]}
def gen_l(depth, pattern=RULES[HilA.A], rules=RULES):
if depth > 1:
for i in pattern:
if i in rules:
yield from gen_l(depth - 1, pattern=rules[i], rules=rules)
else:
yield i
else:
yield from pattern
def draw_hil(depth):
line_length = (min(screen.window_width(), screen.window_height()) - 100) * 2 ** -depth
for action in gen_l(depth):
if action == HilA.F:
t.forward(line_length)
elif action == HilA.L:
t.left(90)
elif action == HilA.R:
t.right(90)
try:
draw_hil(int(sys.argv[1]))
except (TypeError, IndexError):
draw_hil(5)
print("done")
input()
然而,你几乎可以忽略所有这些 - 重要的部分是
line_length = (min(screen.window_width(), screen.window_height()) - 100) * 2 ** -depth
归结为
line_length = width / (2 ** depth)
这对于任何超过深度的东西都非常有限〜= 2.对于深度= 1,由于“连接”中的非常快速的缩小因子,它有点偏离。线与结构线。
请注意,这并不能解释90以外的任何角度,但就我而言,这并不是很有意义,因为只有角度90会产生一个方形的边界如果你确实需要其他角度,你可能需要一些触发器。
答案 1 :(得分:0)
一种方法不是围绕问题进行编码,而是更改您的坐标系以适应。例如,Python龟:
id