%% 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');
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:
R = [cos(theta) -1*sin(theta); sin(theta) cos(theta)];, where theta is the angle to rotate
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
Here are three patterns I drew using this script:
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.
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,
22.214.171.124.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.