xxxxxxxxxx
194
let img;
const ldir = [-0.57735, -0.57735, 0.57735];
const dirs = { N: [0, -1], E: [1, 0], S: [0, 1], W: [-1, 0] };
const odirs = { N: "S", E: "W", S: "N", W: "E" };
let bends;
let subpath;
let t;
function setup() {
createCanvas(512, 512);
img = createGraphics(width, height);
for (let y = 0; y < height; ++y) {
for (let x = 0; x < width; ++x) {
let g = random(-10, 10);
img.set(x, y, color(246 + g, 215 + g, 176 + g));
}
}
img.updatePixels();
bends = {
NE: [-PI, -1.5*PI],
EN: [-1.5 * PI, -PI],
NW: [0, HALF_PI],
WN: [HALF_PI, 0],
SW: [0, -HALF_PI],
WS: [-HALF_PI, 0],
SE: [PI, 1.5*PI],
ES: [1.5*PI, PI],
};
t = 0;
const ds = ["N", "E", "W", "S"];
const i = int(random(4));
const d = ds[i];
ds.splice(i, 1);
//subpath = [[3, 3], 'E', 'S'];
subpath = [[int(random(1,7)), int(random(1,7))], d, ds[int(random(3))]];
}
function nextSubPath(cur) {
function nextCell(c, d) {
const vd = dirs[d];
return [c[0] + vd[0], c[1] + vd[1]];
}
const new_c = nextCell(cur[0], cur[2]);
const from_dir = odirs[cur[2]];
const next_dirs = ["N", "S", "E", "W"];
next_dirs.splice(next_dirs.indexOf(from_dir), 1);
while (next_dirs.length > 0) {
const i = int(random(next_dirs.length));
const d = next_dirs[i];
next_dirs.splice(i, 1);
if (d == from_dir) {
continue;
}
const next_c = nextCell(new_c, d);
if (next_c[0] < 0 || next_c[0] >= 8 || next_c[1] < 0 || next_c[1] >= 8) {
continue;
}
return [new_c, from_dir, d];
}
}
function block(x, y, xn, yn, xc, yc) {
let w = mag(xn, yn);
let th = mag(xc, yc);
for (let iy = -1.5 * th; iy < 1.5 * th; ++iy) {
const phase = iy / 5.0 + HALF_PI;
const h = sin(phase);
const der = cos(phase); // derivative
const sden = sqrt(1 + der * der);
const sx = -der / sden;
const sy = 1 / sden;
const pdir = [(xc / th) * sx, (yc / th) * sx, sy];
const pdot = pdir[0] * ldir[0] + pdir[1] * ldir[1] + pdir[2] * ldir[2];
let g = lerp(-10, 10, pdot) + random(-10, 10);
for (let ix = 0; ix < 3 * w; ++ix) {
let xx = x + (ix / (3 * w)) * xn + (iy / (3 * th)) * xc;
let yy = y + (ix / (3 * w)) * yn + (iy / (3 * th)) * yc;
// console.log( xx, yy );
img.set(xx, yy, color(246 + g, 215 + g, 176 + g));
}
}
img.updatePixels();
}
function wedge(x, y, ai, ao, ri, ro) {
const w = 2 * ro * sin((ao - ai) / 2);
const th = ro - ri;
const mid = th*1.5;
for (let ix = 0; ix < w * 3; ++ix) {
const a = lerp(ai, ao, ix / (w * 3));
for (let iy = 0; iy < (ro - ri) * 3; ++iy) {
const r = lerp(ri, ro, iy / ((ro - ri) * 3));
const phase = (iy-mid)/5.0 + HALF_PI;
const h = sin(phase);
const der = cos(phase); // derivative
const sden = sqrt(1 + der * der);
const sx = -der / sden;
const sy = 1 / sden;
const xc = cos(a);
const yc = sin(a);
const pdir = [xc * sx, yc * sx, sy];
const pdot = pdir[0] * ldir[0] + pdir[1] * ldir[1] + pdir[2] * ldir[2];
let g = lerp(-10, 10, pdot) + random(-10, 10);
let xx = x + r * cos(a);
let yy = y + r * sin(a);
img.set(xx, yy, color(246 + g, 215 + g, 176 + g));
}
}
img.updatePixels();
}
function draw() {
background(220);
image(img, 0, 0);
const dx = width / 16;
const dy = height / 16;
const period = 100.0;
if (t < 1) {
const c = subpath[0];
const cx = (c[0] + 0.5) * (width / 8);
const cy = (c[1] + 0.5) * (height / 8);
const ds1 = dirs[subpath[1]];
const ds2 = dirs[subpath[2]];
if (odirs[subpath[1]] == subpath[2]) {
// Straight line
const ddx = ds2[0] - ds1[0];
const ddy = ds2[1] - ds1[1];
const x1 = lerp(cx, cx + dx, ds1[0]);
const y1 = lerp(cy, cy + dy, ds1[1]);
const x2 = lerp(cx, cx + dx, ds2[0]);
const y2 = lerp(cy, cy + dy, ds2[1]);
// console.log( x1, y1, x2, y2 );
// console.log( dx, dy );
// console.log( ddx, ddy );
block(
lerp(x1, x2, t),
lerp(y1, y2, t),
(ddx * dx) / period,
(ddy * dy) / period,
-ddy * dy,
-ddx * dx
);
} else {
// Arc
const cax = cx + (ds1[0] + ds2[0]) * dx;
const cay = cy + (ds1[1] + ds2[1]) * dy;
const angs = bends[subpath[1] + subpath[2]];
let dt = 0.01;
if( angs[1] < angs[0] ) {
dt = -0.01;
}
wedge(
cax,
cay,
lerp(angs[0], angs[1], t),
lerp(angs[0], angs[1], t + dt),
0,
width / 8
);
}
t += 0.01;
} else {
subpath = nextSubPath(subpath);
// console.log( '' + subpath );
t = 0;
}
// noFill();
// rect( 3*width/8, 3*height/8, width/8, height/8 );
}