Stochastic tiling script

A bit over a year ago, I wrote a post about the mathematics of tiling. In this post, I explore some of those ideas further with an octave script I wrote to draw regular and semi-regular tilings.

The script

%% stochastictiling.m - this is a script to draw regular and semi-regular tilings. 
%
% A unit circle based on the vertex arrangement is drawn at a vertex of the tiling, then a new vertex is randomly selected and the reflected unit circle is drawn in the new location. This procedure is repeated out to a specified radius and then restarted from the origin along a new random path to ensure good coverage. 


%Input vertex arrangement (e.g. [4 4 4 4] for square tiling) and maximum radius
VArrange = input("Specify vertex arrangement: \n");
RadMax = input("Radius to tile: \n");

%check the vertex arrangement (needs to sum to 360 degrees)
AngleCk = (180 - (360./VArrange)); 
if sum(AngleCk) != 360
	error("Angles do not add up to 360 degrees");
end

%Create unit circle, using Rotation matrix = [ cos theta -sin theta; sin theta cos theta]
tav = length(VArrange); %tav = # tiles around vertex
unitcirc = zeros(2,tav);
unitcirc(:,1) = [1; 0]; %[x; y]
for item = 2:tav
	theta = (pi - (2*pi/VArrange(item-1)));
	R = [cos(theta) -1*sin(theta); sin(theta) cos(theta)];
	unitcirc(:,item) = R * unitcirc(:,(item-1));
end

%disp(unitcirc); %included for testing--comment out later

origunitcircle = unitcirc;


%Set up the axes
fid = figure();
XXYY = RadMax + 1; %axis size
axis([-XXYY XXYY -XXYY XXYY]);


%Draw the tiles stochastically
indexmax = (tav^RadMax)*2;

for index1=1:indexmax
	CurrPt = [0; 0]; %start at the origin
	CurrRad = 0; %radius will increase as tiles are laid
	unitcirc = origunitcircle; %reset the unit circle
	while CurrRad <= RadMax
		NewPts = zeros(2,tav);
		NewPtCounter = 1;
		for index2 = 1:tav
			%calculate the new coordinates at the end of each vector in the unit circle
			NewPts(:,NewPtCounter) = CurrPt + unitcirc(:,index2);
			%draw the vectors in the unit circle radiating from the current point
			line([CurrPt(1,1) NewPts(1,NewPtCounter)], [CurrPt(2,1) NewPts(2,NewPtCounter)]);
			NewPtCounter = NewPtCounter + 1;
		end
		%Replace current vertex with randomly-selected new one
		Stochastic = floor(rand(1)*tav)+1;
		PrevPt = CurrPt;
		CurrPt = NewPts(:,Stochastic);
		%Increase the current radius
		CurrRad = CurrRad + 1;
		%reflect the unit circle about a line orthogonal to the vector between prev and new vertex
		refline = [0 -1; 1 0]*(CurrPt - PrevPt); %reflection line is CurrPt - PrevPt, rotated 90 degrees
		rlx = refline(1,1);
		rly = refline(2,1);
		Rf = [(rlx^2 - rly^2) (2*rlx*rly); (2*rlx*rly) (rly^2 - rlx^2)]; %Reflection matrix
		unitcirc = Rf * unitcirc;
	end 
end


%Save the figure
print(fid,'tiles.png','-dpng'); 

Explanation

The script starts by asking for a vertex configuration number (explained here), given as a 1-row matrix (e.g. [4 8 8] for the first image below). The maximum radius to tile is also requested. After checking that the interior angles add up to 360°, a unit circle is created, consisting of vectors along each edge of the tiling pattern out to a distance of 1 from the origin. That unit circle is then drawn at a vertex that is in the tiling pattern, starting at the origin; the ends of the vectors are new vertices. After it is drawn, a new vertex is selected, and the unit circle is reflected and redrawn. This procedure is repeated out to the maximum radius selected, then repeated from the origin multiple times so that the random paths will eventually tile the entire space.

The script makes use of transformation matrices to rotate vectors and to reflect the unit circle:

Rotation:

R = [cos(theta) -1*sin(theta); sin(theta) cos(theta)];, where theta is the angle to rotate

Reflection:

Rf = [(rlx^2 - rly^2) (2*rlx*rly); (2*rlx*rly) (rly^2 - rlx^2)], where rlx and rly are the x and y components, respectively, of the reflection line

Results

Here are three patterns I drew using this script:

4.8.8 tiling

3.4.6.4 tiling

4.6.12 tiling

I used a image editing program to add the numbers in the vertex configuration around the origin; the vectors between the printed numbers comprise the unit circle used in the script.

Discussion

The script runs very slowly (because it goes through over 1000 iterations for a pattern with 5 tiles around each vertex and a radius of 4). It could probably be improved with further work (e.g. a more methodical approach to avoid traversing the same path multiple times like it does in this stochastic approach).

One of the tilings I tried, 3.3.3.4.4, did not draw the proper pattern. My assumption is that reflecting the unit circle between vertices is not the correct approach in that case—maybe a certain rotation would work instead, but I don't know for sure. This particular tiling has a different symmetry than the other ones I tried, so that is probably related to it not working from the same script.

Permalink