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

发布于 2024-12-29 21:12:34 字数 917 浏览 5 评论 0原文

我编写了绘制谢尔宾斯基分形的代码。由于它使用递归,所以速度非常慢。你们中有人知道我如何在不使用递归的情况下编写相同的代码以使其更快吗?这是我的代码:

 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]]]

I have written code which draws the Sierpinski fractal. It is really slow since it uses recursion. Do any of you know how I could write the same code without recursion in order for it to be quicker? Here is my code:

 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]
 ]

edit:

I have written it with the Chaos Game approach in case someone is interested. Thank you for your great answers!
Here is the code:

 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]]]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

天生の放荡 2025-01-05 21:12:34

这使用 ScaleTranslate 结合 Nest 来创建三角形列表。

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]}]

Mathematica 图形

This uses Scale and Translate in combination with Nest to create the list of triangles.

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]}]

Mathematica graphics

风追烟花雨 2025-01-05 21:12:34

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

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

正如您在此动画中所看到的,此过程最终将追踪出一个高-三角形的分辨率版本。如果您愿意,您可以对其进行多线程处理,以便让多个进程同时绘制像素,这最终会更快地绘制三角形。

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

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

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

希望这有帮助!

If you would like a high-quality approximation of the Sierpinski triangle, you can use an approach called the chaos game. The idea is as follows - pick three points that you wish to define as the vertices of the Sierpinski triangle and choose one of those points randomly. Then, repeat the following procedure as long as you'd like:

  1. Choose a random vertex of the trangle.
  2. Move from the current point to the halfway point between its current location and that vertex of the triangle.
  3. Plot a pixel at that point.

As you can see at this animation, this procedure will eventually trace out a high-resolution version of the triangle. If you'd like, you can multithread it to have multiple processes plotting pixels at once, which will end up drawing the triangle more quickly.

Alternatively, if you just want to translate your recursive code into iterative code, one option would be to use a worklist approach. Maintain a stack (or queue) that contains a collection of records, each of which holds the vertices of the triangle and the number n. Initially put into this worklist the vertices of the main triangle and the fractal depth. Then:

  • While the worklist is not empty:
    • Remove the first element from the worklist.
    • If its n value is not zero:
      • Draw the triangle connecting the midpoints of the triangle.
      • For each subtriangle, add that triangle with n-value n - 1 to the worklist.

This essentially simulates the recursion iteratively.

Hope this helps!

北城半夏 2025-01-05 21:12:34

您可以尝试

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}]

You may try

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}]

And then replace the AppendTo by something more efficient. See for example https://mathematica.stackexchange.com/questions/845/internalbag-inside-compile

enter image description here

Edit

Faster:

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}]
烛影斜 2025-01-05 21:12:34

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

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

Mathematica 图形

Since the triangle-based functions have already been well covered, here is a raster based approach.
This iteratively constructs pascal's triangle, then takes modulo 2 and plots the result.

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

Mathematica graphics

巴黎夜雨 2025-01-05 21:12:34
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"]
 ]

在此处输入图像描述
在此处输入图像描述

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}]&;*)

Here is a 3D version,https://mathematica.stackexchange.com/questions/22256/how-can-i-compile-this-function

enter image description here

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"]
 ]

enter image description here
enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文