function Spiral_of_black_and_white_squares()
% source code for drawing the animation
%
% 2017-04-26 Jahobr
fps = 50;
[pathstr,fname] = fileparts(which(mfilename)); % save files under the same name and at file location
figHandle = figure(15124455);
clf
axesHandle = axes;
hold(axesHandle,'on')
set(figHandle, 'Units','pixel');
set(figHandle, 'position',[1 1 1000 1000]); % set default
set(axesHandle,'position',[0 0 1 1]); % stetch axis bigger as figure, easy way to get rid of ticks [x y width hight]
set(figHandle,'GraphicsSmoothing','on') % requires at least version 2014b
L(1) = 1; % definition, length of first square
xyLim = [-L(1) L(1)]*0.99;
xlim(xyLim); ylim(xyLim); % set axis limits
axis equal; drawnow;
for nSquaresTillRep = [4 10] % ONLY EVEN NUMBERS! number of squares till the orientation repeats (90°)
alpha = pi/2/nSquaresTillRep;
% +--a1--+==----b1------+
% I / ----____ a1
% b1 / ----+
% I / 90° /I<-alpha
% I / / I
% I / / I
% I/ / b1
% +---___ / I
% a1 ----___ / I
% +----b1-------=+--a1--+
for index = 1:nSquaresTillRep+1
% L = a+b
% tan(alpha) = a/b; tan(alpha)*b = a
% 1 = tan(alpha)*b+b = b*(tan(alpha)+1)
b(index) = L(index)/(tan(alpha)+1);
a(index) = L(index)-b(index);
L(index+1) = sqrt(a(index)^2+b(index)^2); % side length of inner square
end
for currentCase = 1:2
switch currentCase
case 1 % zoom
nFrames = 200;
set(figHandle, 'position',[1 1 500 500]); %
method = 'zooming_in';
endVal = log( 1/L(nSquaresTillRep+1) );
scale = linspace(0,endVal,nFrames+1);
scale = exp(scale);
scale = scale(1:end-1); % cut of doubled frame
rotImage = linspace(0,-pi/2,nFrames+1);
rotImage = rotImage(1:end-1); % cut of doubled frame
case 2 % spiral
if nSquaresTillRep == 4
nFrames = 100;
set(figHandle, 'position',[1 1 700 700]); %
elseif nSquaresTillRep == 10
nFrames = 50;
set(figHandle, 'position',[1 1 1000 1000]); %
else
error('not defined')
end
method = 'spiraling_in';
endVal = log( 1/L(3) );
scale = linspace(0,endVal,nFrames+1);
scale = exp(scale);
scale = scale(1:end-1); % cut of doubled frame
rotImage = linspace(0,-2*alpha,nFrames+1);
rotImage = rotImage(1:end-1); % cut of doubled frame
end
sb = b(1); % scale square down one itteration (assuming a(1)+b(1)=1)
sa = a(1); % scale square down one itteration (assuming a(1)+b(1)=1)
for iFrame = 1:nFrames
cla(axesHandle) % fresh frame
col = [0 0 0]; % start black
curScale = scale(iFrame);
x = curScale*[-L(1) -L(1) L(1) L(1)]; % make base square bigger, to "zoom in"
y = curScale*[-L(1) L(1) L(1) -L(1)]; % make base square bigger, to "zoom in"
if currentCase == 2 % rotate base square
rotM = [cos(-rotImage(iFrame)) -sin(-rotImage(iFrame)); sin(-rotImage(iFrame)) cos(-rotImage(iFrame))];
vecTemp = rotM*[x; y];
x = vecTemp(1,:);
y = vecTemp(2,:);
end
while norm([x(1) y(1)]) > 0.5/900 % squares smaller than a pixel
patch([x x(1)],[y y(1)],col,'EdgeColor','none');
col = 1-col; % flip color
x = [sb*x(1)+sa*x(2) sb*x(2)+sa*x(3) sb*x(3)+sa*x(4) sb*x(4)+sa*x(1)]; % create next square
y = [sb*y(1)+sa*y(2) sb*y(2)+sa*y(3) sb*y(3)+sa*y(4) sb*y(4)+sa*y(1)]; % create next square
end
%% save animation
xlim(xyLim); ylim(xyLim); % set axis limits
drawnow % update figure window and execute pending callbacks
pause(0.01)
f = getframe(figHandle);
if iFrame== 1
map = gray(8); % 8 colors % create color map % or use : [im,map] = rgb2ind(f.cdata,4,'nodither'); %
im = rgb2ind(f.cdata,map,'nodither'); % create first image
im(1,1,1,nFrames) = 0; % allocate
if currentCase == 1
if ~isempty(which('plot2svg'))
plot2svg(fullfile(pathstr, [fname '_' num2str(nSquaresTillRep) '_till_repetition.svg']),figHandle) % by Juerg Schwizer, See http://www.zhinst.com/blogs/schwizer/
else
disp('plot2svg.m not available; see http://www.zhinst.com/blogs/schwizer/');
end
end
end
imtemp = rgb2ind(f.cdata,map,'nodither');
im(:,:,1,iFrame) = imtemp;
end
imwrite(im,map,fullfile(pathstr, [fname '_' num2str(nSquaresTillRep) '_till_repetition_' method '.gif']),'DelayTime',1/fps,'LoopCount',inf) % save gif
disp([fname '_' num2str(nSquaresTillRep) '_till_repetition_' method '.gif has ' num2str(numel(im)/10^6 ,4) ' Megapixels']) % Category:Animated GIF files exceeding the 50 MP limit
end
end