Skip to content

Instantly share code, notes, and snippets.

@bazzargh
Last active September 13, 2023 15:33
Show Gist options
  • Save bazzargh/961b6765042b17c0c25eadcc98b080e6 to your computer and use it in GitHub Desktop.
Save bazzargh/961b6765042b17c0c25eadcc98b080e6 to your computer and use it in GitHub Desktop.
recursively plot the h7/h8 substitution rule from the monotile paper p18
// this version lets the canvas take care of all the matrix operations.
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let A60 = Math.PI/3;
let A90 = Math.PI/2;
let S3 = Math.sqrt(3);
let ANGLES = [0, -2*A60, -A60, 0, 2*A60, A60, 0];
// Centres of patches in H8 at each substitution level.
let cache = [
[[0, 0], [0, 0]], [[3, 3*S3], [3, 5*S3]],
[[-3, 3*S3], [-6, 4*S3]], [[-6, 0], [-9, -S3]],
[[0, -4*S3], [-6, -6*S3]], [[-6, -4*S3], [-15, -7*S3]]]
function origin(part, z) {
if (part == 6) {
return origin(3, z + 1);
}
if (cache[part].length <= z) {
let r1 = origin(part, z - 1);
let r2 = origin(part, z - 2);
cache[part][z] = [3*r1[0]-r2[0], 3*r1[1]-r2[1]];
}
return cache[part][z];
}
function monotile(ctx) {
let u = 1;
let v = Math.sqrt(4-u*u);
ctx.save();
ctx.beginPath();
ctx.moveTo(0,0);
for(let [r, a] of [
[v, A90],
[u, A60],[u, -A90],
[v, A60],[v, A90],
[u,-A60],[u, A90],
[v,-A60],[v, A90],
[u, A60],[2*u, A60],
[u, A90]
]) {
ctx.lineTo(0, r);
ctx.translate(0, r);
ctx.rotate(-a);
}
ctx.closePath();
ctx.stroke();
ctx.restore();
}
// h(7,...) and h(8,...) supertiles.
function h(type, ctx, z, x, y, a) {
ctx.save();
ctx.translate(x, y);
ctx.rotate(a);
if (z == 0) {
monotile(ctx);
} else {
for(let part=0; part < type - 1; part++) {
h(part == 0 ? 7 : 8, ctx, z - 1, ...origin(part, z - 1), ANGLES[part]);
}
}
ctx.restore();
}
ctx.save();
ctx.translate(500, 400);
ctx.scale(14, 14);
ctx.lineWidth = 1/14;
h(8, ctx, 2, 0, 0, 0);
ctx.restore();
ctx.save();
ctx.translate(500, 400);
ctx.scale(2, 2);
ctx.lineWidth = 1/4;
ctx.strokeStyle = 'red'
h(8, ctx, 4, 0, 0, 0);
ctx.restore();
@bazzargh
Copy link
Author

bazzargh commented May 6, 2023

Since I wrote this I also came up with an L-system for drawing the tiling as a single line, which needs a lot less code (it's a lot slower and more repetitive tho) https://hachyderm.io/@bazzargh/110293551149890811

And in case that site disappears, the code inline:

import turtle
import math

def expand(order, a, s0, s1):
  for op in s0 if order <= 0 else s1:
    mono_op_map[op](order - 1, a)    

# an earlier version of this used a stack, but it's unnecessary since
# I can just complete the loop round a tile to return the turtle to the branch point
mono_op_map = {
  "a": lambda o, a: turtle.forward(a),
  "b": lambda o, a: turtle.forward(a*math.sqrt(3)),
  # U is drawn as "W--X--W", but I don't see how the rules would fit if I used that
  "U": lambda o, a: expand(o, a, "a+++b--b+++a--a+++b", "V++R++U++V++W++V++R--U++V++W++V++R++U--V"),
  "V": lambda o, a: expand(o, a, "b---a", "W++V++R++U++V++W++V++R--W"),  
  "W": lambda o, a: expand(o, a, "a+++b", "V++R++U++V++W++V++R--W++V++R++U++V++W--V"),
  "R": lambda o, a: expand(o, a, "aa", "V++R++U++V++W++V++R--W"),
  "+": lambda o, a: turtle.right(30),
  "-": lambda o, a: turtle.left(30),
}
start = "U++V++W++V++R"
size = 6
order = 3
turtle.speed("fastest")
expand(order, size, start, start)

it does share with the above js code the opinion that the flipped tile is a hole; but it's better in that the a/b lengths can be changed
and this will still just work. This code is small enough that a variation (using single-character symbols for the turns) fits the BBC Basic code of it into a single toot https://hachyderm.io/@bazzargh/110295590546847505

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment