- /
-
Morphing Tiles
on 28 Oct 2024
- 23
- 144
- 0
- 2
- 1434
drawframe(1);
function drawframe(f)
if f <= 72
m=interp1([1 10 65 72],[0 0 1 1],f);
else
m=interp1([73 96],[1 0],f);
end
trhomboid(m);
set(gca,'pos',[-.2 -.2 1.4 1.4],'vis','off')
map=sky(28);
colormap(map(10:end,:))
set(gcf,'color',map(9,:));
end
% I wrote this function without worrying about character count, and it was short
% enough as-is. Huzzah!
function trhomboid(miter, opts)
% Create three rhomboids shape joined at center point.
% This is the same rhomboid shape you can tile together into a hexagon.
% When you adjust the miter, you can create a series of variations that
% eventually become hexagons.
arguments
miter = .3
opts.tileradius = 13
opts.maxtiles = 1000
end
% 6 vectors away from a central point to corners of a hexagon.
N = 6;
theta=linspace(0,2,N+1)';
theta=theta(1:end-1); % drop 1 pt
vec = [ cospi(theta), sinpi(theta) ];
center = [ 0 0 ];
% Compute vertices and end points for the 3 rhombuses
verts = [];
endpts = [];
% Compute miter points as ratio of length of sides.
% Easy since 'vec' is that distance.
mvec = vec * miter;
for i=1:2:N
vnext = mod(i,N)+1;
% This is the outward tip of the rhombus shape
newpt = [ cospi(theta(i)) sinpi(theta(i)) ] + vec(vnext,:);
if miter > 0
% Tip miters go in opposite direction of incominv direction
mtip = [ newpt-mvec(mod(i,N)+1,:)
newpt-mvec(mod(i-1,N)+1,:)
];
rvert = [ mvec(i,:)
vec(i,:)
mtip % newpt
vec(vnext,:)
mvec(vnext,:) ];
else
% No Miter - keeps it simple
rvert = [ center
vec(i,:)
newpt
vec(vnext,:) ];
end
verts = [ verts %#ok
rvert ];
% End points always ignores miter
endpts = [ endpts %#ok
newpt ];
end
%% Start tiling this shape.
%
% We can do this by chasing the 'endpts' of each star as a way to position
% the next shape in the tile.
tcount = 0;
centers = [ 0 0 ];
cidx = 0;
mverts = [];
mdist = [];
while tcount < opts.maxtiles && cidx < size(centers,1)
cidx = cidx+1;
% Generate the vertices for this tile
mverts = [mverts %#ok
verts + centers(cidx,:)];
mynorm = norm(centers(cidx,:));
mdist = [mdist %#ok
mynorm ];
% Compute next round of centers we could use off of thisi tile.
for k=1:size(endpts,1)
nextcenter = centers(cidx,:) - endpts(k,:);
% Don't create new tiles on top of old tiles.
% Compute distances, and any distance that is very close
% against all upcoming centers.
mask = vecnorm(centers((cidx+1):end,:)-nextcenter,2,2) < .01;
dist = norm(nextcenter);
% Rely on not going backward in radius to trim already used centers
if dist<opts.tileradius && dist>=mynorm && ~any(mask)
% This is a new center, add it to list
centers = [centers %#ok
nextcenter];
end
end
tcount = tcount+1;
end
mfaces = reshape(1:size(mverts,1),size(verts,1),[])';
newplot;
patch('Vertices',mverts,'Faces',mfaces,...
'facevertexcdata',mdist,...
'linewidth',1.5,...
'FaceColor','flat','EdgeColor','#222');
daspect([1 1 1]);
box on
axis tight
end
Movie
Audio
This submission does not have audio.