实现高阶分形的算法
Algorithm to implement a higher order fractal
我正在尝试为 n 阶科赫分形编写代码,定义为:
为此,我正在 Matlab 中实现一个代码。我已经能够开发能够绘制二阶分形的代码(虽然零阶和一阶非常容易)。为此,我将代码基于 this post。到现在为止,我已经得到了这个,它可以工作,但显然只适用于二阶(或一阶和零,只需编辑一下代码)
clear all;
clc;
close all;
hold on;
% Counter-clockwise rotation matrix
R = [cosd(60) -sind(60);sind(60) cosd(60)];
angles = [0 60 -60 0 0]; % main angles
n = 2; % order
% Length of each straight segment
seglength = 3^-(n-1);
% Initialization of variables
a=0;
b=0;
c=1/3;
d=0;
for i=1:4^(n-2)
for j=1:4
p1 = [a;b];
p5 = [c;d];
p2 = (2.*p1+p5)/3;
p4 = (2.*p5+p1)/3;
p3 = p2 + R*(p4-p2);
x = [p1(1) p2(1) p3(1) p4(1) p5(1)];
y = [p1(2) p2(2) p3(2) p4(2) p5(2)];
line(x,y);
a=a+seglength*cosd(angles(j));
c=c+seglength*cosd(angles(j+1));
b=b+seglength*sind(angles(j));
d=d+seglength*sind(angles(j+1));
end
end
axis equal;
我知道这不是一个干净和优化的代码。我只是对任何可以帮助我开发 n 阶科赫分形的技巧感兴趣,只需更改 n 的值即可。
感谢任何帮助!
您当然可以改进您的算法,特别是利用矢量化将计算减少到单个 for 循环(并使其易于扩展到任何顺序)。您甚至不需要递归(尽管这是另一种选择)。这是一个矢量化函数 koch
:
function [x, y] = koch(N, x, y)
R = [cosd(60) -sind(60); sind(60) cosd(60)];
x = x(:).';
y = y(:).';
for iOrder = 1:N % Loop N times
x1 = x(1:(end-1));
x5 = x(2:end);
x2 = (2.*x1+x5)./3;
x4 = (x1+2.*x5)./3;
y1 = y(1:(end-1));
y5 = y(2:end);
y2 = (2.*y1+y5)./3;
y4 = (y1+2.*y5)./3;
temp = R*[x4-x2; y4-y2];
x = [x1; x2; x2+temp(1, :); x4];
y = [y1; y2; y2+temp(2, :); y4];
x = [x(:).' x5(end)];
y = [y(:).' y5(end)];
end
end
对于一组 M
个点(x
和 y
)在每次迭代中,每条线的起点由 x(1:(M-1))
和终点给出分数由 x(2:M)
给出。您可以通过构建一个 4-by-M-1
矩阵将您的 3 个新点插入其中,其中顶行是您的起点,每个连续的行都是您的 3 个新点之一(按照您的 link).使用 (:).'
重塑生成的矩阵(并添加最后一个端点)将为您提供 1×4*M-3
的直线点集,可用于下一次迭代。
下面是实际的代码:
[x, y] = koch(0, [0 1], [0 0]);
plot(x, y);
axis equal;
hold on;
[x, y] = koch(1, x, y); % or [x, y] = koch(1, [0 1], [0 0]);
plot(x, y);
[x, y] = koch(1, x, y); % or [x, y] = koch(2, [0 1], [0 0]);
plot(x, y);
[x, y] = koch(1, x, y); % or [x, y] = koch(3, [0 1], [0 0]);
plot(x, y);
legend({'0' '1' '2' '3'});
请注意,您可以通过传递 n
和起点或传递 1
和点来获得第 n
th 阶分形对于 n-1
th 分形。
我正在尝试为 n 阶科赫分形编写代码,定义为:
clear all;
clc;
close all;
hold on;
% Counter-clockwise rotation matrix
R = [cosd(60) -sind(60);sind(60) cosd(60)];
angles = [0 60 -60 0 0]; % main angles
n = 2; % order
% Length of each straight segment
seglength = 3^-(n-1);
% Initialization of variables
a=0;
b=0;
c=1/3;
d=0;
for i=1:4^(n-2)
for j=1:4
p1 = [a;b];
p5 = [c;d];
p2 = (2.*p1+p5)/3;
p4 = (2.*p5+p1)/3;
p3 = p2 + R*(p4-p2);
x = [p1(1) p2(1) p3(1) p4(1) p5(1)];
y = [p1(2) p2(2) p3(2) p4(2) p5(2)];
line(x,y);
a=a+seglength*cosd(angles(j));
c=c+seglength*cosd(angles(j+1));
b=b+seglength*sind(angles(j));
d=d+seglength*sind(angles(j+1));
end
end
axis equal;
我知道这不是一个干净和优化的代码。我只是对任何可以帮助我开发 n 阶科赫分形的技巧感兴趣,只需更改 n 的值即可。
感谢任何帮助!
您当然可以改进您的算法,特别是利用矢量化将计算减少到单个 for 循环(并使其易于扩展到任何顺序)。您甚至不需要递归(尽管这是另一种选择)。这是一个矢量化函数 koch
:
function [x, y] = koch(N, x, y)
R = [cosd(60) -sind(60); sind(60) cosd(60)];
x = x(:).';
y = y(:).';
for iOrder = 1:N % Loop N times
x1 = x(1:(end-1));
x5 = x(2:end);
x2 = (2.*x1+x5)./3;
x4 = (x1+2.*x5)./3;
y1 = y(1:(end-1));
y5 = y(2:end);
y2 = (2.*y1+y5)./3;
y4 = (y1+2.*y5)./3;
temp = R*[x4-x2; y4-y2];
x = [x1; x2; x2+temp(1, :); x4];
y = [y1; y2; y2+temp(2, :); y4];
x = [x(:).' x5(end)];
y = [y(:).' y5(end)];
end
end
对于一组 M
个点(x
和 y
)在每次迭代中,每条线的起点由 x(1:(M-1))
和终点给出分数由 x(2:M)
给出。您可以通过构建一个 4-by-M-1
矩阵将您的 3 个新点插入其中,其中顶行是您的起点,每个连续的行都是您的 3 个新点之一(按照您的 link).使用 (:).'
重塑生成的矩阵(并添加最后一个端点)将为您提供 1×4*M-3
的直线点集,可用于下一次迭代。
下面是实际的代码:
[x, y] = koch(0, [0 1], [0 0]);
plot(x, y);
axis equal;
hold on;
[x, y] = koch(1, x, y); % or [x, y] = koch(1, [0 1], [0 0]);
plot(x, y);
[x, y] = koch(1, x, y); % or [x, y] = koch(2, [0 1], [0 0]);
plot(x, y);
[x, y] = koch(1, x, y); % or [x, y] = koch(3, [0 1], [0 0]);
plot(x, y);
legend({'0' '1' '2' '3'});
请注意,您可以通过传递 n
和起点或传递 1
和点来获得第 n
th 阶分形对于 n-1
th 分形。