xxxxxxxxxx
181
const sidelen = 14;
const gap = 14;
const sw = 5;
const v1 = [0, -sidelen];
const v2 = [sidelen, 0];
let sz;
let pat;
let nextpat;
let ty;
function same(P, Q) {
return P[0] === Q[0] && P[1] === Q[1];
}
function slope(S) {
const Q = S[1];
const P = S[0];
return [Q[0] - P[0], Q[1] - P[1]];
}
function coincident(S, T) {
return same(S[0], T[1]) || same(S[1], T[0]);
}
function makeSegs(steps, prev) {
const ret = [prev.reverse()];
function maybeAdd(S) {
for (let s of ret) {
if (same(s[0], S[0]) && same(s[1], S[1])) {
return;
}
}
ret.push(S);
}
for (let row = 0; row < steps; ++row) {
for (let col = 0; col <= row; ++col) {
maybeAdd([
[col, row],
[col, row + 1],
]);
maybeAdd([
[col, row + 1],
[col + 1, row + 1],
]);
maybeAdd([
[col, row],
[col + 1, row + 1],
]);
}
}
return ret.reverse();
}
// Inspired by maze construction
function makePattern(steps, prev, straighten, shuffle) {
const segs = makeSegs(steps, prev);
const pat = [];
shuffle = shuffle || 1000;
function count(pt) {
let total = 0;
for (let s of pat) {
if (same(s[0], pt)) {
++total;
} else if (same(s[1], pt)) {
++total;
}
if (total >= 2) {
return total;
}
}
return total;
}
for (let idx = 0; idx < shuffle; ++idx) {
const i = int(random(segs.length));
const j = int(random(segs.length));
const tmp = segs[i];
segs[i] = segs[j];
segs[j] = tmp;
}
while (segs.length > 0) {
const s = segs.pop();
if (count(s[0]) < 2 && count(s[1]) < 2) {
pat.push(s);
if (straighten) {
// Promote adjacent collinear segs
for (let idx = 0; idx < segs.length; ++idx) {
if (coincident(segs[idx], s) && same(slope(segs[idx]), slope(s))) {
const nidx = segs.length - 1 - int(random(idx * 0.1));
const tmp = segs[nidx];
segs[nidx] = segs[idx];
segs[idx] = tmp;
}
}
}
}
}
return pat;
}
function drawPat(pat, x, y, ref) {
function samp(x, y) {
return [x * v1[0] + y * v2[0], x * v1[1] + y * v2[1]];
}
push();
translate(x, y);
if (ref) {
scale(-1, 1);
}
rotate(-QUARTER_PI);
for (let s of pat) {
const P = samp(s[0][0], s[0][1]);
const Q = samp(s[1][0], s[1][1]);
line(P[0], P[1], Q[0], Q[1]);
}
pop();
}
function setup() {
createCanvas(600,600);
sz = int(random(7, 13));
pat = makePattern(sz, [], true, 100);
nextpat = makePattern( sz, pat, true, 10 );
ty = 0;
}
function draw() {
background(30, 30, 40);
noFill();
stroke(200, 200, 220);
strokeWeight(sw);
strokeCap(ROUND);
let unit_width = (sidelen / 2) * sqrt(2) * sz;
let trans = 2 * unit_width + (1 + sqrt(2)) * gap;
let cycle = int((ceil(height/trans)+1)*trans);
let row = 0;
let y = ty;
while (y < height + 2 * unit_width) {
let the_pat = pat;
if( (y-ty) > cycle ) {
the_pat = nextpat;
}
let x = 0;
if (row % 2 == 1) {
x += trans / 2;
}
while (x < width + unit_width) {
drawPat(the_pat, x - gap / 2, y, true);
drawPat(the_pat, x + gap / 2, y, false);
x += trans;
}
y += trans / 2;
++row;
}
// pat = makePattern(sz, pat, true, 10);
ty -= 1;
if( ty == -cycle ) {
ty = 0;
pat = nextpat;
nextpat = makePattern( sz, pat, true, 2 );
}
}