• 【计算几何】大自然的艺术--分形


    一、前言

            分形几何是几何数学中的一个分支,也称大自然几何学,由著名数学家本华曼德勃罗( 法语:BenoitB.Mandelbrot)在 1975 年构思和发展出来的一种新的几何学。分形几何是对大自然中微观与宏观和谐统一之美的发现,并且揭示的部分只是冰山之一角,相信在人类认知的进步下,会开出一朵接一朵的美丽花朵。

            美国杰出的物理学家( 两弹元勋 、现代广义相对论之父)、物理学思想家、物理学教育家惠勒( Wheeler )断言: “ 可以相信,明天谁不熟悉分形,谁就不能被认为是科学上的文化人。”可以看出分形强大的影响力,当然个人也比较喜欢分形,因为利用分形可以画出很多美丽的图形,利用分形我们可以描绘出 树叶的纹路、画出完整的一棵树、形状酷似病毒的图形,混沌 ( chaos )、孤立子( solitons )和分形 ( fractals )是非线性科学 ( nonlinear  science ) 中三个最重要的概念。

    二、什么是分形

            分形(英语:fractal,源自拉丁语:frāctus,有“零碎”、“破裂”之意),又称碎形残形,通常被定义为:

            “一个零碎的几何形状,可以分成数个部分,且每一部分都(至少近似地)是整体缩小后的形状”[2],即具有自相似的性质。

            分形在数学中是一种抽象的物体,用于描述自然界中存在的事物。人工分形通常在放大后能展现出相似的形状[3]。 分形也被称为扩展对称展开对称。如果在每次放大后,形状的重复是完全相同的,这被称为自相似。自相似的一个例子是门格海绵[图1]。 分形在不同的缩放级别上可以是近似相似的。曼德博集合的【图2】放大图像中显示了这种模式[2][5][6][7]。 分形也包有图像的细节重复自身的意味。

    三、关于自相似

            如果一个物体自我相似(Self-similarity),表示它和它本身的一部分完全或是几乎相似。若说一个曲线自我相似,即每部分的曲线有一小块和它相似。自然界中有很多东西有自我相似性质,例如海岸线

    3.1 谢尔宾斯基地毯(Sierpinski carpet、波兰语:Dywan Sierpińskiego)

            由波兰数学家瓦茨瓦夫·谢尔宾斯基(Wacław Sierpiński)于1916年提出的一种分形,是自相似集的一种。它的豪斯多夫维是 log 8/log 3 ≈ 1.8928。门格海绵是它在三维空间中的推广。

            将一个实心正方形划分为3X3的9个小正方形,去掉中间的小正方形,再对余下的小正方形重复这一操作便能得到谢尔宾斯基地毯。

    3.2 门格海绵说明

            门格海绵(英语:Menger sponge、英语:Menger universal curve)是分形的一种。它是一个通用曲线,因为它的拓扑维数为一,且任何其它曲线都与门格海绵的某个子集同胚。它有时称为门格-谢尔宾斯基海绵谢尔宾斯基海绵。它是康托尔集谢尔宾斯基地毯在三维空间的推广。它首先由奥地利数学家卡尔·门格在1926年描述,当时他正在研究拓扑维数的概念。

    图1- 门格海绵的样子

    3.3  曼德博集合

            是基于复平面的分形典范。曼德博集合可以用复二次多项式来定义:

    f_c(z) = z^2+c     ,其中c 是一个复数参数。

    从z = 0开始迭代:

            不同的参数c可能使序列绝对值逐渐发散到无限大,也可能收敛在有限的区域内。曼德博集合M 就是使序列不延伸至无限大的所有复数c的集合

    图2- 曼德博集合

    3.4 科赫雪花

            科赫雪花是由瑞典数学家科赫在 1904 年提出的一种不规则几何图形,也称为雪花曲线。

            分形图形的特点是整体几何图形是由一个微图形结构自我复制、反复叠加形成,且最终形成的整体图案和微图形结构一样。在编写分形算法时,需要先理解微图案的生成过程。

    科赫雪花的微图案生成过程:

    •  先画一条直线。科赫雪花本质就由一条直线演化而成。
    • 三等分画好的直线。
    • 取中间线段,然后用夹角为 60° 的两条等长线段替代。
    • 可在每一条线段上都采用如上方式进行迭代操作,便会构造出多层次的科赫雪花。

    四、谢尔宾斯基地毯代码实现 

    4.1 算法代码:

    1. # importing necessary modules
    2. import numpy as np
    3. from PIL import Image
    4. # total number of times the process will be repeated
    5. total = 7
    6. # size of the image
    7. size = 3 ** total
    8. # creating an image
    9. square = np.empty([size, size, 3], dtype=np.uint8)
    10. color = np.array([255, 255, 255], dtype=np.uint8)
    11. # filling it black
    12. square.fill(0)
    13. for i in range(0, total + 1):
    14. stepdown = 3 ** (total - i)
    15. for x in range(0, 3 ** i):
    16. # checking for the centremost square
    17. if x % 3 == 1:
    18. for y in range(0, 3 ** i):
    19. if y % 3 == 1:
    20. # changing its color
    21. square[y * stepdown:(y + 1) * stepdown, x * stepdown:(x + 1) * stepdown] = color
    22. # saving the image produced
    23. save_file = "sierpinski.jpg"
    24. Image.fromarray(square).save(save_file)
    25. # displaying it in console
    26. i = Image.open("sierpinski.jpg")
    27. i.show()

    4.2 谢尔宾斯基地毯结果:

    五、分形树代码实现

    5.1 分形树代码

    1. import turtle
    2. def draw_tree(length):
    3. if length>=5:
    4. #设定颜色
    5. if length <=15:
    6. turtle.color('green')
    7. else:
    8. turtle.color('black')
    9. '''
    10. 先画右侧树枝
    11. '''
    12. #向前
    13. turtle.forward(length)
    14. #右转25度
    15. turtle.right(25)
    16. #递归draw_tree
    17. draw_tree(length - 15)
    18. '''
    19. 画左侧树枝
    20. '''
    21. #左转50度
    22. turtle.left(50)
    23. #递归draw_tree
    24. draw_tree(length - 15)
    25. '''
    26. 回退
    27. '''
    28. #设定颜色
    29. if length <=15:
    30. turtle.color('green')
    31. else:
    32. turtle.color('black')
    33. #右转25度
    34. turtle.right(25)
    35. #回退
    36. turtle.backward(length)
    37. def main():
    38. #起始点往下移100
    39. turtle.pensize(4)
    40. turtle.left(90)
    41. turtle.penup()
    42. turtle.backward(100)
    43. turtle.pendown()
    44. draw_tree(100)
    45. turtle.exitonclick()
    46. if __name__ == '__main__':
    47. main()

    5.2 分形树结果 

    六、曼德博集合代码

    6.1 代码

    1. from PIL import Image
    2. import colorsys
    3. import math
    4. import os
    5. #frame parameters
    6. width = 1000 #pixels
    7. x = -0.65
    8. y = 0
    9. xRange = 3.4
    10. aspectRatio = 4/3
    11. precision = 500
    12. height = round(width / aspectRatio)
    13. yRange = xRange / aspectRatio
    14. minX = x - xRange / 2
    15. maxX = x + xRange / 2
    16. minY = y - yRange / 2
    17. maxY = y + yRange / 2
    18. img = Image.new('RGB', (width, height), color = 'black')
    19. pixels = img.load()
    20. def logColor(distance, base, const, scale):
    21. color = -1 * math.log(distance, base)
    22. rgb = colorsys.hsv_to_rgb(const + scale * color,0.8,0.9)
    23. return tuple(round(i * 255) for i in rgb)
    24. def powerColor(distance, exp, const, scale):
    25. color = distance**exp
    26. rgb = colorsys.hsv_to_rgb(const + scale * color,1 - 0.6 * color,0.9)
    27. return tuple(round(i * 255) for i in rgb)
    28. for row in range(height):
    29. for col in range(width):
    30. x = minX + col * xRange / width
    31. y = maxY - row * yRange / height
    32. oldX = x
    33. oldY = y
    34. for i in range(precision + 1):
    35. a = x*x - y*y #real component of z^2
    36. b = 2 * x * y #imaginary component of z^2
    37. x = a + oldX #real component of new z
    38. y = b + oldY #imaginary component of new z
    39. if x*x + y*y > 4:
    40. break
    41. if i < precision:
    42. distance = (i + 1) / (precision + 1)
    43. rgb = powerColor(distance, 0.2, 0.27, 1.0)
    44. pixels[col,row] = rgb
    45. index = row * width + col + 1
    46. print("{} / {}, {}%".format(index, width * height, round(index / width / height * 100 * 10) / 10))
    47. img.save('output.png')
    48. os.system('open output.png')

    6.2 运算结果 

    七  科赫雪花代码

    7.1 科赫雪花代码

    1. import turtle
    2. turtle.speed(100)
    3. def ke_line(line_, n):
    4. if n == 0:
    5. turtle.fd(line_)
    6. else:
    7. line_len = line_ // 3
    8. for i in [0, 60, -120, 60]:
    9. turtle.left(i)
    10. ke_line(line_len, n - 1)
    11. # 原始线长度
    12. line = 300
    13. # 移动小海龟画布左下角
    14. turtle.penup()
    15. turtle.goto(-150, -150)
    16. turtle.pendown()
    17. # 几阶科赫雪花
    18. di_gui_deep = int(input("请输入科赫雪花的阶数:"))
    19. while True:
    20. # 当多少科赫雪花围绕成一个圆周时,就构成一个完整的雪花造型
    21. count = int(input("需要几个科赫雪花:"))
    22. if 360 % count != 0:
    23. print("请输入 360 的倍数")
    24. else:
    25. break
    26. for i in range(count):
    27. ke_line(line, di_gui_deep)
    28. turtle.left(360 // count)
    29. turtle.done()

    7.2 结果

    八、后记

            有专门的理论教学《分形几何》,其中的内容更加丰富, 我们将在以后的博客中继续介绍。

  • 相关阅读:
    go-channel
    QGC 参数设置中关于param_union的使用
    【Linux】yum && vim 基础工具的使用
    About Significance Tests
    python: window环境安装
    【OpenCV-Python】教程:3-9 轮廓(5)轮廓层级
    零基础学Python之循环语句的使用(手把手带你做牛客网python代码练习题)
    沃通SSL证书服务多省区一体化政务服务平台
    请问,wpf工程这种左下角有箭头的文件夹是如何创建的,它似乎是引用了共享项目
    微信小程序模板消息推送
  • 原文地址:https://blog.csdn.net/gongdiwudu/article/details/126597811