跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Python算法

Python 科赫雪花绘制:数学原理与 turtle 实现

介绍科赫雪花的分形数学原理及递归概念。利用 Python turtle 库,通过递归函数将线段三等分并构建等边三角形凸起来绘制雪花。包含垂直向量计算、坐标公式推导及代码实现步骤,展示从基础三角形到完整雪花的生成过程。

剑仙发布于 2026/3/25更新于 2026/10/1717K 浏览
Python 科赫雪花绘制:数学原理与 turtle 实现

科赫雪花

科赫雪花于 1904 年由瑞士数学家黑格尔 - 冯 - 科赫提出,是一种分形,即一种不断放大时会重复自己的图形。分形源自递归,递归操作本身就是在重复使用自己定义自己。其图片如下:

文章配图

递归的基础知识

递归操作的基本步骤

Step 1: 定义一个基线条件,达到条件时,自动结束递归。

Step 2: 写一个算法可能用到多次递归。

阶层的表达式就是一个经典的递归:

f(N)=f(N-1)*N

def factorial(N):
    if N == 1:
        return 1
    else:
        return N * factorial(N - 1)

循环与递归的选择方面:各有千秋,递归优雅紧凑,循环高效快捷,本节我们将用递归绘制分形。

数学内容补充

垂直向量计算技巧:已知点 A(a,b),当点 B 为 B (-b,a) 时:

A * B = 0

从空间中的一点 A 沿着向量 n 出发,到达点 B 的坐标运算公式:

B = A + d \cdot \underset{n}{\rightarrow}

已知线段的两个端点 A 和 B,求其上面任意一点 C 的坐标公式,其中 a 为点 A 到点 C 的距离,b 为点 B 到点 C 的距离:

aB+bA/a+b

科赫雪花的相关参数计算

文章配图

这是科赫雪花的第一个片段,我们一共需要 3 个相连接的片段。

文章配图

文章配图

文章配图

文章配图

文章配图

海龟 turtle 绘图

绘制三角形--热身

  • t.up() / t.down():海龟绘图的核心操作,抬笔移动不画线,落笔移动才画线,这里用来'跳'到指定坐标,避免画多余的线;
  • setpos(x,y):等价于 goto(x,y),让画笔移动到指定坐标,落笔时会画直线;
triangle.py
import turtle

def draw_triangle(x1, y1, x2, y2, x3, y3, t):
    t.up()
    t.setpos(x1, y1)
    t.down()
    t.setpos(x2, y2)
    t.setpos(x3, y3)
    t.setpos(x1, y1)
    t.up()

def main():
    print('testing turtle graphics...')
    # 创建海龟对象
    t = turtle.Turtle()
    # 隐藏海龟图标
    t.hideturtle()
    # 调用函数,传入海龟对象和坐标,确保绘制完成后不会关闭 tkinter 窗口
    draw_triangle(t, -100, 0, 0, 173.2, 100, 0)
    turtle.mainloop()

if __name__ == "__main__":
    main()

文章配图

绘制科赫雪花--实践

第一步:把原始大线段 (x1,y1)→(x2,y2) 拆成 4 段更小的线段(科赫雪花的规则):

  • 第 1 段:(x1,y1) → p1(三等分第一个点)
  • 第 2 段:p1 → p2(等边三角形的第一条边)
  • 第 3 段:p2 → p3(等边三角形的第二条边)
  • 第 4 段:p3 → (x2,y2)(三等分第二个点)

第二步:对这 4 条小线段,重复调用同一个函数(递归),让每条小线段也执行'拆分成 4 段 / 直接画'的逻辑 —— 所以形参变成了每条小线段的'起点 + 终点'。

koch.py
import turtle
import math

# drawKochSF() 计算点的坐标
def drawKochSF(x1, y1, x2, y2, t):
    d = math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))
    r = d/3.0
    h = r*math.sqrt(3)/2.0
    p3 = ((x1 + 2*x2)/3.0, (y1 + 2*y2)/3.0)
    p1 = ((2*x1 + x2)/3.0, (2*y1 + y2)/3.0)
    c = (0.5*(x1+x2), 0.5*(y1+y2))
    n = ((y1-y2)/d, (x2-x1)/d)
    p2 = (c[0]+h*n[0], c[1]+h*n[1])

    # 递归
    if d > 10:  # flake
        # flake #1/片段
        drawKochSF(x1, y1, p1[0], p1[1], t)
        # flake #2/片段
        drawKochSF(p1[0], p1[1], p2[0], p2[1], t)
        # flake #3/片段
        drawKochSF(p2[0], p2[1], p3[0], p3[1], t)
        # flake #4/片段
        drawKochSF(p3[0], p3[1], x2, y2, t)
    else:  # draw cone
        t.up()
        t.setpos(p1[0], p1[1])
        t.down()
        t.setpos(p2[0], p2[1])
        t.setpos(p3[0], p3[1])
        # draw sides
        t.up()
        t.setpos(x1, y1)
        t.down()
        t.setpos(p1[0], p1[1])
        t.up()
        t.setpos(p3[0], p3[1])
        t.down()
        t.setpos(x2, y2)

# main() function
def main():
    print('Drawing the Koch Snowflake...')
    t = turtle.Turtle()
    t.hideturtle()
    # draw
    try:
        drawKochSF(-100, 0, 100, 0, t)
        drawKochSF(0, -173.2, -100, 0, t)
        drawKochSF(100, 0, 0, -173.2, t)
    except:
        print("Exception, exiting.")
        exit(0)
    # wait for user to click on screen to exit
    turtle.Screen().exitonclick()

# call main
if __name__ == '__main__':
    main()

try-except 代码块,异常捕获机制,专门用来处理绘制过程中可能出现的错误,避免程序直接崩溃。

文章配图

  • 递归阈值:线段长度 d > 10 时递归拆分,d ≤ 10 时执行 else 里的绘制逻辑;
  • 雪花由 3 条线段组成:(-100,0)→(100,0)、(0,-173.2)→(-100,0)、(100,0)→(0,-173.2);
阶段 1:程序启动与初始化
if __name__ == '__main__':
    main()  # 调用主函数
  1. 执行 main() 函数,首先打印提示:Drawing the Koch Snowflake...;
  2. 创建海龟画笔对象:t = turtle.Turtle(),隐藏画笔箭头:t.hideturtle()(画笔默认速度,无加速);
  3. 进入 try 代码块,准备依次绘制 3 条科赫边。
阶段 2:绘制第一条边 drawKochSF(-100, 0, 100, 0, t)
步骤 1:计算几何参数(第一次调用)
  • 线段长度 d = √[(-100-100)² + (0-0)²] = 200(>10,触发递归);
  • 三等分长度 r = 200/3 ≈ 66.67,等边三角形高 h = 66.67×√3/2 ≈ 57.74;
  • 三等分点:p1 = (2×(-100)+100)/3, (2×0+0)/3 = (-33.33, 0);p3 = (-100+2×100)/3, (0+2×0)/3 = (33.33, 0);
  • 线段中点 c = (0, 0);
  • 法向量 n = (0-0)/200, (100-(-100))/200 = (0, 1);
  • 凸起顶点 p2 = (0 + 57.74×0, 0 + 57.74×1) = (0, 57.74)。
步骤 2:递归拆分(d=200>10)

函数不绘制,而是拆成 4 段,依次递归调用自身:

  • 调用 1:drawKochSF(-100, 0, -33.33, 0, t) → 处理第一段(起点→p1);
  • 调用 2:drawKochSF(-33.33, 0, 0, 57.74, t) → 处理第二段(p1→p2);
  • 调用 3:drawKochSF(0, 57.74, 33.33, 0, t) → 处理第三段(p2→p3);
  • 调用 4:drawKochSF(33.33, 0, 100, 0, t) → 处理第四段(p3→终点)。
步骤 3:递归深入(直到 d ≤ 10)

以「调用 1:drawKochSF(-100, 0, -33.33, 0, t)」为例,继续拆解:

  • 计算该线段长度 d = √[(-100+33.33)² + 0] ≈ 66.67(>10,继续拆);
  • 计算该段的 p1/p2/p3(比如新 p1≈-77.78,新 p3≈-55.56,新 p2≈-66.67, 19.25);
  • 再次拆成 4 段,递归调用……
  • 这个过程会持续,直到某次计算出的 d ≤ 10(比如拆到第 3 层,d≈7.41),触发 else 分支。
else:
    # 1. 绘制'凸起':p1→p2→p3
    t.up()
    t.setpos(p1[0], p1[1])  # 移动到当前短线段的 p1
    t.down()
    t.setpos(p2[0], p2[1])  # 画 p1→p2
    t.setpos(p3[0], p3[1])  # 画 p2→p3
    # 2. 绘制两端:起点→p1,p3→终点
    t.up()
    t.setpos(x1, y1)  # 移动到当前短线段的起点
    t.down()
    t.setpos(p1[0], p1[1])  # 画起点→p1
    t.up()
    t.setpos(p3[0], p3[1])  # 移动到当前短线段的 p3
    t.down()
    t.setpos(x2, y2)  # 画 p3→终点
步骤 5:递归回溯

完成当前短线段的绘制后,函数执行完毕,回到上一层递归调用,继续处理下一段,直到第一层递归的 4 段都处理完,第一条边绘制结束。

阶段 3:绘制第二、第三条边(重复阶段 2)
  1. 调用 drawKochSF(0, -173.2, -100, 0, t):
    • 计算该线段长度≈200(>10),递归拆分→直到 d≤10,执行你的 else 绘制逻辑;
    • 这条边是「(0,-173.2)→(-100,0)」,是倒置等边三角形的左斜边;
  2. 调用 drawKochSF(100, 0, 0, -173.2, t):
    • 同理,递归拆分→绘制,是倒置等边三角形的右斜边。
阶段 4:程序收尾
  1. 3 条边的递归绘制全部完成(无论图形是否正常);
  2. 执行 turtle.Screen().exitonclick():等待你点击画布,程序退出;

若绘制中出现任何错误(比如递归深度超限、坐标计算异常),触发 except 块:打印 Exception, exiting. 并退出程序。

文章配图

目录

  1. 科赫雪花
  2. 递归的基础知识
  3. 递归操作的基本步骤
  4. 数学内容补充
  5. 科赫雪花的相关参数计算
  6. 海龟 turtle 绘图
  7. 绘制三角形--热身
  8. triangle.py
  9. 绘制科赫雪花--实践
  10. koch.py
  11. drawKochSF() 计算点的坐标
  12. main() function
  13. call main
  14. 阶段 1:程序启动与初始化
  15. 阶段 2:绘制第一条边 drawKochSF(-100, 0, 100, 0, t)
  16. 步骤 1:计算几何参数(第一次调用)
  17. 步骤 2:递归拆分(d=200>10)
  18. 步骤 3:递归深入(直到 d ≤ 10)
  19. 步骤 5:递归回溯
  20. 阶段 3:绘制第二、第三条边(重复阶段 2)
  21. 阶段 4:程序收尾

更多推荐文章

查看全部
  • C++ 继承机制详解:从概念到多继承模型
  • Android 通过代码模拟媒体按键控制音乐播放器
  • RunningHub:基于开源生态的图形音视频 AIGC 平台解析
  • 前端调用 AI 接口全流程实战:从配置到流式响应
  • AI Agent 架构:基础组成模块深度解析
  • Win10 系统关闭 Microsoft Copilot 弹窗的 6 种有效方案
  • AI 产品经理必备的核心能力与知识体系
  • 架构演进实战:从单机到分布式,Redis 的核心价值
  • 论文笔记 DiT:基于 Transformer 的可扩展扩散模型
  • PyCharm 集成 GitHub Copilot 安装与配置指南
  • Mac mini 打造家庭数据中心:集成 OpenClaw 与私有云导航服务
  • Sam Altman:超级人工智能将在几年后诞生
  • 全排列与回溯算法详解:LeetCode 经典题目解析
  • FPGA 实现 HDMI 输出:接口原理、时序与实战案例
  • 前端微前端架构:大型项目是解药还是新坑?
  • 2025 AI Agent 技术栈全解析:从 LLM 到自主智能体
  • 前端岗位面试高频原题与参考答案
  • Java 依赖管理详解:Maven 与 Gradle 的下载、缓存及配置
  • 基于 Dify 与 LangBot 搭建飞书智能体对话机器人
  • 本地 Qwen 与 ComfyUI 制作 AI 漫剧教程

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online