Skip to content

Instantly share code, notes, and snippets.

@Garciat
Last active April 10, 2021 08:17
Show Gist options
  • Save Garciat/4e586d81abd67a7e39f820020487b139 to your computer and use it in GitHub Desktop.
Save Garciat/4e586d81abd67a7e39f820020487b139 to your computer and use it in GitHub Desktop.
<body style="margin:0"></body>
<script src="https://gbrlgrct.com/gists/07d74ba686ce04eccb11faa44f2ae229/functional.js"></script>
<script>
'use strict';
/* Init */
const SPACEW = document.body.clientWidth;
const SPACEH = document.body.clientHeight;
const SPACE_QUAD = [[0, 0], [SPACEW, 0], [SPACEW, SPACEH], [0, SPACEH]];
const canvas = document.createElement('canvas');
canvas.width = SPACEW;
canvas.height = SPACEH;
document.body.appendChild(canvas);
const ctx = canvas.getContext('2d');
/* Maths */
function interp(seg, p) {
const x0 = seg[0][0];
const y0 = seg[0][1];
const dx = seg[1][0] - x0;
const dy = seg[1][1] - y0;
return [x0 + p * dx, y0 + p * dy];
}
function uniform(a, b) {
return a + (b - a) * Math.random();
}
function segmentLength(seg) {
const dx = seg[1][0] - seg[0][0];
const dy = seg[1][1] - seg[0][1];
return Math.sqrt(dx * dx + dy * dy);
}
/* Transforms */
const fst = x => x[0];
const snd = x => x[1];
function quadSegments(q) {
return chain(q).cycle().pairwise().take(4);
}
/* Drawing */
function drawSegment(s) {
ctx.beginPath();
ctx.moveTo(s[0][0], s[0][1]);
ctx.lineTo(s[1][0], s[1][1]);
ctx.lineWidth = 1;
ctx.stroke();
}
function drawQuad(q) {
quadSegments(q).forEach(drawSegment);
}
/* Vortexing */
function* split(quad, depth) {
if (depth === 0) {
yield quad;
return;
}
const line0 = quad.slice(0, 2);
const line1 = quad.slice(2, 4);
const r0 = uniform(0.1, 0.9);
const r1 = uniform(0.1, 0.9);
const p0 = interp(line0, r0);
const p1 = interp(line1, r1);
const q0 = [p0, p1, quad[3], quad[0]];
const q1 = [quad[1], quad[2], p1, p0];
yield* split(q0, depth - 1);
yield* split(q1, depth - 1);
}
function vortexInfinite(quad) {
const points = memoized(function* () {
yield quad[0];
yield* steps.map(snd);
});
const steps = memoized(function* () {
yield* zip(points, segments.tail().map(s => interp(s, 0.1)));
});
const segments = memoized(function* () {
yield* quadSegments(quad);
yield* steps;
});
return segments;
}
function vortex(quad) {
return vortexInfinite(quad).takeWhile(seg => segmentLength(seg) > 1);
}
/* GO ! */
chain(split(SPACE_QUAD, 4))
.flatMap(vortex)
.forEach(drawSegment);
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment