在 Mathematica 中迭代生成谢尔宾斯基三角形?

Posted

技术标签:

【中文标题】在 Mathematica 中迭代生成谢尔宾斯基三角形?【英文标题】:Generating the Sierpinski triangle iteratively in Mathematica? 【发布时间】:2012-02-22 13:10:42 【问题描述】:

我编写了绘制谢尔宾斯基分形的代码。它真的很慢,因为它使用递归。你们有谁知道我如何在没有递归的情况下编写相同的代码以使其更快?这是我的代码:

 midpoint[p1_, p2_] := Mean[p1, p2]
 trianglesurface[A_, B_, C_] :=  Graphics[Polygon[A, B, C]]
 sierpinski[A_, B_, C_, 0] := trianglesurface[A, B, C]
 sierpinski[A_, B_, C_, n_Integer] :=
 Show[
 sierpinski[A, midpoint[A, B], midpoint[C, A], n - 1],
 sierpinski[B, midpoint[A, B], midpoint[B, C], n - 1],
 sierpinski[C, midpoint[C, A], midpoint[C, B], n - 1]
 ]

编辑:

我用混沌游戏的方法写了它,以防有人感兴趣。感谢您的精彩回答! 代码如下:

 random[A_, B_, C_] := Module[a, result,
 a = RandomInteger[2];
 Which[a == 0, result = A,
 a == 1, result = B,
 a == 2, result = C]]

 Chaos[A_List, B_List, C_List, S_List, n_Integer] :=
 Module[list,
 list = NestList[Mean[random[A, B, C], #] &, 
 Mean[random[A, B, C], S], n];
 ListPlot[list, Axes -> False, PlotStyle -> PointSize[0.001]]]

【问题讨论】:

看看***.com/questions/159590/… 当我画这些东西时,我发现渲染图形比计算三角形位置要花更长的时间。我还使用了递归方法(如果有一点不同)。 【参考方案1】:

这将ScaleTranslateNest 结合使用来创建三角形列表。

Manipulate[
  Graphics[Nest[
    Translate[Scale[#, 1/2, 0, 0], pts/2] &, Polygon[pts], depth], 
   PlotRange -> 0, 1, 0, 1, PlotRangePadding -> .2],
  pts, 0, 0, 1, 0, 1/2, 1, Locator,
  depth, 4, Range[7]]

【讨论】:

【参考方案2】:

如果您想要一个高质量的谢尔宾斯基三角形近似值,您可以使用一种称为chaos game 的方法。这个想法如下 - 选择您希望定义为谢尔宾斯基三角形顶点的三个点,然后随机选择其中一个点。然后,根据需要重复以下过程:

    随机选择三角形的顶点。 从当前点移动到其当前位置和三角形顶点之间的中点。 在该点绘制一个像素。

如您所见at this animation,此过程最终将绘制出三角形的高分辨率版本。如果你愿意,你可以多线程让它有多个进程同时绘制像素,这最终会更快地绘制三角形。

或者,如果您只想将递归代码转换为迭代代码,一种选择是使用工作列表方法。维护一个包含记录集合的堆栈(或队列),每个记录包含三角形的顶点和数字 n。最初将主三角形的顶点和分形深度放入此工作表中。那么:

当工作清单不为空时: 从工作清单中删除第一个元素。 如果其 n 值不为零: 画出连接三角形中点的三角形。 对于每个子三角形,将具有 n 值 n - 1 的三角形添加到工作列表中。

这实质上是迭代地模拟递归。

希望这会有所帮助!

【讨论】:

一开始我只是想翻译一下代码,但是混沌游戏的方法看起来真的很有趣!!我回家后试试看!非常感谢,这很有帮助! 再次感谢,我是用混沌游戏的方法写的!我已将其添加到我的帖子中,以防您有兴趣了解如何处理它。【参考方案3】:

你可以试试

l = 0, 1, 1, 0, 0, 0, 8;
g = ;
While [l != ,
 k = l[[1, 1]];
 n = l[[1, 2]];
 l = Rest[l];
 If[n != 0,
  AppendTo[g, k];
  (AppendTo[l, #1, Mean[#1, #2], Mean[#1, #3], n - 1] & @@ #) & /@
                                                 NestList[RotateLeft, k, 2]
  ]]
Show@Graphics[EdgeForm[Thin], Pink,Polygon@g]

然后将 AppendTo 替换为更有效的方法。参见例如https://mathematica.stackexchange.com/questions/845/internalbag-inside-compile

编辑

更快:

f[1] = 0, 1, 1, 0, 0, 0, 8;
i = 1;
g = ;
While[i != 0,
 k = f[i][[1]];
 n = f[i][[2]];
 i--;
 If[n != 0,
  g = Join[g, k];
  f[i + 1], f[i + 2], f[i + 3] =
    (#1, Mean[#1, #2], Mean[#1, #3], n - 1 & @@ #) & /@ 
                                                 NestList[RotateLeft, k, 2];
  i = i + 3
  ]]
Show@Graphics[EdgeForm[Thin], Pink, Polygon@g]

【讨论】:

【参考方案4】:

由于已经很好地介绍了基于三角形的函数,因此这里是基于栅格的方法。 这会迭代地构造帕斯卡三角形,然后取模 2 并绘制结果。

NestList[0, ## + ##, 0 & @@ # &, 1, 511] ~Mod~ 2 // ArrayPlot

【讨论】:

【参考方案5】:
Clear["`*"];
sierpinski[a_, b_, c_] := 
  With[ab = (a + b)/2, bc = (b + c)/2,  ca = (a + c)/2, 
   a, ab, ca, ab, b, bc, ca, bc, c];

pts = 0, 0, 1, 0, 1/2, Sqrt[3]/2 // N;
n = 5;
d = Nest[Join @@ sierpinski /@ # &, pts, n]; // AbsoluteTiming
Graphics[EdgeForm@Black, Polygon@d]

(*sierpinski=Map[Mean, Tuples[#,2]~Partition~3 ,2]&;*)

这里是3D版,https://mathematica.stackexchange.com/questions/22256/how-can-i-compile-this-function

ListPlot@NestList[(# + RandomChoice[0, 0, 2, 0, 1, 2])/2 &,
 N@0, 0, 10^4]

With[data = 
   NestList[(# + RandomChoice@0, 0, 1, 0, .5, .8)/2 &, 
    N@0, 0, 10^4], 
 Graphics[Point[data, 
   VertexColors -> (1, #[[1]], #[[2]] & /@ Rescale@data)]]
 ]

With[v = 0, 0, 0.6, -0.3, -0.5, -0.2, -0.3, 0.5, -0.2, 0.6, 
     0, -0.2, 
 ListPointPlot3D[
  NestList[(# + RandomChoice[v])/2 &, N@0, 0, 0, 10^4], 
  BoxRatios -> 1, ColorFunction -> "Pastel"]
 ]

【讨论】:

以上是关于在 Mathematica 中迭代生成谢尔宾斯基三角形?的主要内容,如果未能解决你的问题,请参考以下文章

瓦茨瓦夫·谢尔宾斯基的生平

谢尔宾斯基地毯三角形,周长,面积的变化规律

谢尔宾斯基三角 Pygame 递归

课时22:函数:递归是神马

sierpinski地毯几何画板怎么做

mathematica中RandomReal和Table函数随机生成点问题求助