I'm trying to make a code for a n-order Koch fractal, defined as:
For that, I'm implementing a code in Matlab. I've been able to develop a code that is able to plot a second order fractal (zero and first orders are pretty easy though). For that, I've based the code in this post. Up to now, I've got this, which works, but obviously just for order two (or one and zero, just editing a bit the code)
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;
I know it is not a clean and optimum code. I'm just interested in any kind of tip that could help me to develop a n-order Koch fractal, just changing the value of n.
Any help is appreciated!
You can certainly improve upon your algorithm, specifically taking advantage of vectorization to reduce the computation to a single for loop (and making it easy to extend it to any order). You don't even really need recursion (although that's another option). Here's a vectorized function 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
For a set of M
points (both x
and y
) at each iteration, the starting points for each line are given by x(1:(M-1))
and the ending points are given by x(2:M)
. You can interleave your 3 new points in between these by building a 4-by-M-1
matrix where the top row is your starting points and each successive row is one of your 3 new points (computed as in your link). Reshaping the resulting matrix with (:).'
(and adding the very last end point) will give you a 1-by-4*M-3
set of points for the line, which can be used by the next iteration.
And here's the code in action:
[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'});
Notice you can get an n
th order fractal by either passing n
and your starting points or passing 1
and the points for the n-1
th fractal.