• 4.8.谢尔宾斯基三角形

    4.8.谢尔宾斯基三角形

    另一个展现自相似性的分形是谢尔宾斯基三角形。 Figure 3 是一个示例。谢尔宾斯基三角形阐明了三路递归算法。用手绘制谢尔宾斯基三角形的过程很简单。 从一个大三角形开始。通过连接每一边的中点,将这个大三角形分成四个新的三角形。忽略刚刚创建的中间三角形,对三个小三角形中的每一个应用相同的过程。 每次创建一组新的三角形时,都会将此过程递归应用于三个较小的角三角形。 如果你有足够的铅笔,你可以无限重复这个过程。在继续阅读之前,你可以尝试运用所描述的方法自己绘制谢尔宾斯基三角形。

    4.8.谢尔宾斯基三角形.figure3

    Figure 3

    因为我们可以无限地应用算法,什么是基本情况? 我们将看到,基本情况被任意设置为我们想要将三角形划分成块的次数。有时我们把这个数字称为分形的“度”。 每次我们进行递归调用时,我们从度中减去 1,直到 0。当我们达到 0 度时,我们停止递归。在 Figure 3 中生成谢尔宾斯基三角形的代码见 ActiveCode 1。

    1. import turtle
    2. def drawTriangle(points,color,myTurtle):
    3. myTurtle.fillcolor(color)
    4. myTurtle.up()
    5. myTurtle.goto(points[0][0],points[0][1])
    6. myTurtle.down()
    7. myTurtle.begin_fill()
    8. myTurtle.goto(points[1][0],points[1][1])
    9. myTurtle.goto(points[2][0],points[2][1])
    10. myTurtle.goto(points[0][0],points[0][1])
    11. myTurtle.end_fill()
    12. def getMid(p1,p2):
    13. return ( (p1[0]+p2[0]) / 2, (p1[1] + p2[1]) / 2)
    14. def sierpinski(points,degree,myTurtle):
    15. colormap = ['blue','red','green','white','yellow',
    16. 'violet','orange']
    17. drawTriangle(points,colormap[degree],myTurtle)
    18. if degree > 0:
    19. sierpinski([points[0],
    20. getMid(points[0], points[1]),
    21. getMid(points[0], points[2])],
    22. degree-1, myTurtle)
    23. sierpinski([points[1],
    24. getMid(points[0], points[1]),
    25. getMid(points[1], points[2])],
    26. degree-1, myTurtle)
    27. sierpinski([points[2],
    28. getMid(points[2], points[1]),
    29. getMid(points[0], points[2])],
    30. degree-1, myTurtle)
    31. def main():
    32. myTurtle = turtle.Turtle()
    33. myWin = turtle.Screen()
    34. myPoints = [[-100,-50],[0,100],[100,-50]]
    35. sierpinski(myPoints,3,myTurtle)
    36. myWin.exitonclick()
    37. main()

    Activecode 1

    ActiveCode 1 中的程序遵循上述概念。谢尔宾斯基的第一件事是绘制外三角形。接下来,有三个递归调用,每个使我们在连接中点获得新的三角形。我们再次使用 Python 附带的 turtle 模块。你可以通过使用 help('turtle') 了解 turtle 可用方法的详细信息。

    看下代码,想想绘制三角形的顺序。虽然三角的确切顺序取决于如何指定初始集,我们假设三角按左下,上,右下顺序。由于谢尔宾斯基函数调用自身,谢尔宾斯基以它的方式递归到左下角最小的三角形,然后开始填充其余的三角形。填充左下角顶角中的小三角形。最后,它填充在左下角中右下角的最小三角形。

    有时,根据函数调用图来考虑递归算法是有帮助的。Figure 4 展示了递归调用总是向左移动。活动函数以黑色显示,非活动函数显示为灰色。向 Figure 4 底部越近,三角形越小。该功能一次完成一次绘制; 一旦它完成了绘制,它移动到左下方底部中间位置,然后继续这个过程。

    4.8.谢尔宾斯基三角形.figure4

    Figure 4

    谢尔宾斯基函数在很大程度上依赖于 getMid 函数。 getMid 接受两个端点作为参数,并返回它们之间的中点。 此外,ActiveCode 1 还有一个函数,使用 begin_fillend_fill 方法绘制填充一个三角形。