【问题标题】:Efficient code for draw a sierpinski triangle with matlab用matlab绘制谢尔宾斯基三角形的高效代码
【发布时间】:2013-09-10 09:42:19
【问题描述】:

以下是我的代码:

function sierpinski(A, B, C, n)
    if n == 0
        patch([A(1), B(1), C(1)], [A(2), B(2), C(2)], [0.0 0.0 0.0]);
    else
       sierpinski(A, (A + B)/2, (A + C)/2, n-1);
       sierpinski(B, (B + A)/2, (B + C)/2, n-1);
       sierpinski(C, (C + A)/2, (C + B)/2, n-1);
end

% sierpinski([0 0], [1 0], [.5 .8], 8)

这不是很有效。我想先生成所有数据然后打补丁,但我不知道如何正确使用。另外,我的代码可以写成用于循环吗?

【问题讨论】:

  • 做一些研究,搜索引擎应该会为您提供O(10) 解决方案。
  • @HighPerformanceMark 我认为这不公平 - OP 已经想出了如何绘制 sierpinski 三角形(他们的代码有效,但由于对 patch 的约 6000 次调用而速度很慢)和他们在问如何分别生成所有数据然后绘制它。

标签: matlab recursion fractals


【解决方案1】:

编写一个函数来生成数据并编写另一个函数来绘制数据的想法是一个不错的想法 - 将数据生成与处理以及处理与输出分开通常是个好主意。我会这样做:

function out = sierpinski(a, b, c, n)

    if n == 0
        out.xvals = [a(1), b(1), c(1)];
        out.yvals = [a(2), b(2), c(2)];
    else
        out1 = sierpinski(a, (a+b)/2, (a+c)/2, n-1);
        out2 = sierpinski(b, (a+b)/2, (b+c)/2, n-1);
        out3 = sierpinski(c, (a+c)/2, (b+c)/2, n-1);
        out = [out1, out2, out3];
    end

end

这将创建一个长度为3^n 的结构,其中的每个条目都包含谢尔宾斯基三角形中一个小三角形的坐标。您绘制它的代码可能看起来像

>> out = sierpinski([0,0], [1,0], [0.5, sqrt(3)/2], 8);
>> figure(); hold on;
>> for i = 1:length(out)
       patch(out(i).xvals, out(i).yvals, 'k');
   end

这在我的机器上崩溃了(似乎 Matlab 不能很好地处理同一个图上的数千个补丁)但是一个类似的循环在每个小三角形的角上绘制一个点。

>> x = [out.xvals];
>> y = [out.yvals];
>> plot(x, y, '.');

产生这个情节

【讨论】:

  • 感谢您的帮助。
  • 我能得到一些帮助吗?我想做同样的三角形,但我没有得到代码。甚至如何将其添加到文件中。我可以在电子邮件或这里获取代码。类似的东西?
  • 代码已经在我的答案中。如果你解释它是什么你不明白,那么也许我可以提供帮助,但只是说“我没有得到代码”不会让你走得太远。
【解决方案2】:

我没有准备好任何代码示例,但是:

您可以尝试在一个大块中绘制所有三角形,而不是将每个三角形绘制为单个补丁对象。 基本上,您只需要连接由 NaN 分隔的每个三角形的 x 和 y 坐标 - 这将防止补丁绘制连接各个三角形的线。 例如。以下行生成两个单独的三角形:

p = patch( [0 0.5 1 0 NaN 2 2.5 3 2 NaN ], [ 0 1 0 0 NaN 2 3 2 2 NaN], 'k')

请注意,要获得一个闭合三角形,这样每个三角形需要 4 个点,最后一个点与第一个点相同。

【讨论】:

    【解决方案3】:

    编辑: 对于每个递归级别,您可以“擦除”中心三角形,因此您必须修补更少的三角形。例如,在第一级,您有三个“向上”三角形和一个“向下”三角形。您可以路径这个,而不是其他三个。 一个更紧凑的例程是:

    function sierpinski(rec)
      [x, x0] = deal(cat(3, [1 0]', [-1 0]', [0 sqrt(3)]')); 
      for k = 1 : rec x = x(:,:) + x0 * 2 ^ k / 2; 
    end 
    patch('Faces', reshape(1 : 3 * 3 ^ k, 3, '')', 'Vertices', x(:,:)') 
    end
    

    所以你必须填充更少的三角形,如果...

    function sierpinski(rec)
    close all
    %Main Triangle
    hFig=figure;
    units=get(hFig,'units');
    set(hFig,'units','normalized','outerposition',[0 0 1 1], 'Color', 'white');
    set(hFig,'units',units); clear units
    hold on
    Vx=[0 0.5 1]; Vy=[0 realsqrt(3)/2 0];
    fill(Vx,Vy,'b')
    %the number of white triangles = sum(3.^(0:1:rec-1))
    whitex=NaN(3,sum(3.^(0:1:rec-1))); whitey=whitex; K=1;
    for S=1:rec
        [Vx,Vy]=sierpinskisect;
    end
    fill(whitex,whitey,'w')
    
    function [outX,outY]=sierpinskisect
        %the number of blue triangles = 3^S
        L=size(Vx,1);
        outX=NaN(3*L,3); outY=outX; J=1;
        for I=1:L
            %left blue triangle
            outX(J,:)=[Vx(I,1) mean(Vx(I,(1:2))) mean(Vx(I,([1 3])))];
            outY(J,:)=[Vy(I,1) mean(Vy(I,(1:2))) mean(Vy(I,([1 3])))];
            J=J+1;
            %right blue triangle
            outX(J,:)=[mean(Vx(I,([1 3]))) mean(Vx(I,(2:3))) Vx(I,3)];
            outY(J,:)=[mean(Vy(I,([1 3]))) mean(Vy(I,(2:3))) Vy(I,3)];
            J=J+1;
            %upper blue triangle
            outX(J,:)=[mean(Vx(I,(1:2))) Vx(I,2) mean(Vx(I,(2:3)))];
            outY(J,:)=[mean(Vy(I,(1:2))) Vy(I,2) mean(Vy(I,(2:3)))];
            J=J+1;
            %white triangle
            whitex(:,K)=[outX(J-3,2);outX(J-3,3);outX(J-2,2)];
            whitey(:,K)=[outY(J-3,2);outY(J-3,3);outY(J-2,2)];
            K=K+1;
        end
    end
    

    结束

    【讨论】:

    • 欢迎来到 Stack Overflow!答案除了显示代码外,还应该用文字说明他们是如何回答问题的。
    • 好的,抱歉,这是我的第一条评论。对于每个递归级别,您可以“擦除”中心三角形,因此您必须修补更多更少的三角形。例如,在第一级,您有三个“向上”三角形和一个“向下”三角形。你可以用这个来代替其他三个
    • 一个更紧凑的例程是:function sierpinski(rec) [x, x0] = deal(cat(3, [1 0]', [-1 0]', [0 sqrt(3) ]'));对于 k = 1 :rec x = x(:,:) + x0 * 2 ^ k / 2; end patch('Faces', reshape(1 : 3 * 3 ^ k, 3, '')', 'Vertices', x(:,:)') end
    • 我试图编辑你的 cmets,如果代码错误,请告诉我我可能没有做正确的行尾等。
    猜你喜欢
    • 2010-12-16
    • 1970-01-01
    • 2013-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多