2025年希尔伯特曲线的python递归实现

希尔伯特曲线的python递归实现希尔伯特曲线 也被称作希尔伯特空间填充曲线 是一个连续分形曲线 它由德国数学家大卫 希尔伯特在 1891 年提出 旨在证明可以通过连续运动完全填满一个平面区域 希尔伯特曲线是通过迭代过程构造的 在每一次迭代中 曲线变得更加复杂 并更紧密地逼近所包围的二维区域 这种曲线作为一种分形结构

大家好,我是讯享网,很高兴认识大家。

        希尔伯特曲线,也被称作希尔伯特空间填充曲线,是一个连续分形曲线。它由德国数学家大卫·希尔伯特在1891年提出,旨在证明可以通过连续运动完全填满一个平面区域。

        希尔伯特曲线是通过迭代过程构造的。在每一次迭代中,曲线变得更加复杂,并更紧密地逼近所包围的二维区域。这种曲线作为一种分形结构,其不仅呈现出重复性和自相似性,而且具有无限长的长度,却在有限的区域内。

认识希尔伯特曲线


讯享网

从左到右,从上到下分别为1-4阶希尔伯特曲线

希尔伯特曲线的构造

希尔伯特曲线的构造方法是一个递归过程,要构造n阶的希尔伯特曲线,先构造4个n-1阶的希尔伯

特曲线,这4个n-1阶的希尔伯特曲线通过特定的顺序连接起来。

以图像中央为原点,划分象限

观察发现:第一象限图形为前一阶数图形绕中心逆时针旋转90度并做轴对称所得

            第三、四象限图形为原图形

            第二象限图形为前一阶数图形绕中心顺时针旋转90度并做轴对称所得

            且每一象限之间通过单位长度的线段,将上一象限图形的终点与下一象限图形的起点连接

希尔伯特曲线的每一级迭代通常可以用以下步骤描述:

第0阶: 从一个点或者一个简单的线段开始,作为迭代的基础。

第1阶: 将现有的线段分为四份,然后按特定的顺序和方向通过这些点构建一个环形的路径。

更高阶: 对于每一阶迭代,都取前一阶曲线,按照规则复制四份,然后进行旋转和连接,形成新的一阶曲线。

经过资料查找与归纳总结,得到如下的规律

注:指令字符意义
# '-' 代表左转90度
# '+' 代表右转90度
# 'f' 代表向前画线(沿着当前方向)
 

hilbert_map = { 'a': "-bf+afa+fb-", # 若当前部分曲线是‘a’类型,则按照这串字符进行操作和递归生成 'b': "+af-bfb-fa+", # 若当前部分曲线是‘b’类型,则按照这串字符进行操作和递归生成 } def hilbert(t, char, angle, length, depth): if depth > 0: # 当递归深度大于0时,进行递归绘制 instructions = hilbert_map[char] # 获取当前部分曲线类型的操作指令 for cmd in instructions: # 遍历指令字符,执行相应操作 if cmd == 'a' or cmd == 'b': # 如果遇到部分曲线类型,进行更深一层递归 hilbert(t, cmd, angle, length, depth - 1) elif cmd == '-': # 如果遇到'-'字符,乌龟左转90度 t.left(angle) elif cmd == '+': # 如果遇到'+'字符,乌龟右转90度 t.right(angle) elif cmd == 'f': # 如果遇到'f'字符,乌龟向前移动指定长度并画线 t.forward(length) 

讯享网

其中
# t:turtle对象,执行绘图的实体
# char:当前递归所处理的部分曲线类型(‘a’或者‘b’)
# angle:转动角度,希尔伯特曲线使用的是90度
# length:每向前移动画线时的长度
# depth:阶数 

解释一下:+ 和 - 是转向命令,f 表示画线命令。a和b为递归展开部分,在本级曲线不做实际画图操作。

举例解释:

首先定义规则:

hilbert_map = {
'a': "-bf+afa+fb-", 
'b': "+af-bfb-fa+",
}

第0阶希尔伯特曲线:

第0阶可以简单地表示为单个起始字符 b。

第1阶希尔伯特曲线:

以 b 作为起始字符,它按照 hilbert_map 中定义的替换规则 "+af-bfb-fa+" 被替换,生成第1阶曲线。

第2阶希尔伯特曲线:

为了进行到第2阶曲线的生成,我们将对上一阶曲线(即现在的第1阶)中每个字符按照替换规则进行扩展。这次我们需要对包含 a 和 b 的每一部分进行替换。每一个 a 和 b 将根据 hilbert_map 中的规则被展开,整个 b 的替换过程如下:

+:表示右转90度;

a:替换为第1阶中的 a 对应的操作序列 -bf+afa+fb-;

f:表示向前画线;

-:表示左转90度;

b:替换为第1阶中的 b 对应的操作序列 +af-bfb-fa+,同理,它将被进一步替换;

f:表示向前画线;

b:被扩展替换;

-:表示左转90度;

f:表示向前画线;

a:被扩展替换;

+:表示右转90度;

对于 a 和 b 的每个实例,你会按照相同的步骤继续递归替换,直到达到2阶曲线的完整结构。

可以理解成对于a,b进行对应扩展,扩展指定次数(根据曲线阶数而定)之后,按照表达式顺序再一起执行

主要步骤:扩展(递归替换)和执行(绘制)。

  1. 扩展(Replacement or Expansion) 这一步是递归的。它遵循提前定义好的规则(提供的 hilbert_map 字典),将当前阶段的每个字符替换为对应更复杂的序列,以生成下一阶段的曲线表达式。这一步不涉及实际的图形绘制,而只是按照规则生成更长的字符串序列。
  2. 执行(Execution) 扩展完成之后,获得的是一长串的字符序列,每个字符代表一个操作指令。这时再根据这个序列逐个执行字符对应的动作来进行实际的绘制,包括前进(f)、左转(-)和右转(+)的动作。这个步骤实际上构建和描绘了曲线的路径

模拟从’b‘开始的多次扩展过程:

 b

=>

+af-bfb-fa+

=>

=>

...

后面的画图基础操作不做详细说明,仅附上相应代码与注释

讯享网import turtle # 指令字符意义: # '-' 代表左转90度 # '+' 代表右转90度 # 'f' 代表向前画线(沿着当前方向) # 'b' 代表向后画线(沿着当前方向的反方向) # 注:在本示例中,'b' 实际上未被使用 # 希尔伯特曲线的迭代规则定义 # 字典中的键’a’和‘b’表示特定的部分曲线类型 # 字典中的值表示相应部分曲线类型的生成规则 hilbert_map = { 'a': "-bf+afa+fb-", # 若当前部分曲线是‘a’类型,则按照这串字符进行操作和递归生成 'b': "+af-bfb-fa+", # 若当前部分曲线是‘b’类型,则按照这串字符进行操作和递归生成 } # 递归函数定义:绘制希尔伯特曲线 # t:turtle对象,执行绘图的实体 # char:当前递归所处理的部分曲线类型(‘a’或者‘b’) # angle:转动角度,希尔伯特曲线使用的是90度 # length:每向前移动画线时的长度 # depth:阶数 def hilbert(t, char, angle, length, depth): if depth > 0: # 当递归深度大于0时,进行递归绘制 instructions = hilbert_map[char] # 获取当前部分曲线类型的操作指令 for cmd in instructions: # 遍历指令字符,执行相应操作 if cmd == 'a' or cmd == 'b': # 如果遇到部分曲线类型,进行更深一层递归 hilbert(t, cmd, angle, length, depth - 1) elif cmd == '-': # 如果遇到'-'字符,乌龟左转90度 t.left(angle) elif cmd == '+': # 如果遇到'+'字符,乌龟右转90度 t.right(angle) elif cmd == 'f': # 如果遇到'f'字符,乌龟向前移动指定长度并画线 t.forward(length) # 初始化turtle窗口 window = turtle.Screen() # 创建绘图窗口对象 window.bgcolor("white") # 设置窗口背景颜色为白色 # 创建一个turtle对象,也即"乌龟",用于执行绘制希尔伯特曲线的操作 tur = turtle.Turtle() # 创建一个turtle实例 tur.speed(0) # 设置绘图速度,0为最快 tur.hideturtle() # 绘图过程中隐藏乌龟图标 tur.penup() # 抬起画笔,移动到起始绘制位置时不留下痕迹 # 设置乌龟的起始位置,位于屏幕左上四分之一处 tur.setpos(-window.window_width()//4, window.window_height()//4) tur.pendown() # 放下画笔准备开始绘图 # 现在来设定绘制希尔伯特曲线的几个主要参数 # 希尔伯特曲线的阶数,这里是4阶曲线, # 即按照给定的'a'或'b'类型的基础规则进行一次曲线生成过程 depth = 4 # 绘图时乌龟每次移动画线的长度 length = 25 # 转弯的角度,对于希尔伯特曲线是90度 angle = 90 # 调用hilbert函数开始绘制,其开始的部分曲线类型为'b' # 因为希尔伯特曲线是递归定义的,选择'a'或'b'作为起始类型将产生不同的初始模式 hilbert(tur, 'b', angle, length, depth) # 绘图完成后隐藏乌龟图标,以便清晰地查看绘制结果 tur.hideturtle() # 保持绘图窗口开启,直到用户关闭,可在窗口中欣赏绘制出的希尔伯特曲线 window.exitonclick() 

本文为自己学习时所写,若有错误,敬请批评指正! 

小讯
上一篇 2025-03-24 08:39
下一篇 2025-03-15 23:07

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/126333.html