Continuing my practice of trying new tools for this course, I decided to try out the thing umbrella for this project. The umbrella is a project by Karsten Schmidt in which he creates a giant package ecosystem full of every algorithm one could ever want. Thi.ng was originally written in Clojure, and the transform definitely feels like Clojure. For instance, I spent a long time fighting with the system until I realized certain functions fail unless passed empty lists as a final parameter. That being said, the library is wildly powerful! I was able to achieve amazing results with very little code. I would totally use the thingiverse again, though maybe when under a much longer deadline. I found myself thinking of Good Shape while I worked—how it’s particularly difficult to describe what makes a shape “better.”
import { quad, asSvg, withAttribs, path } from '@thi.ng/geom';
import { star } from '@thi.ng/geom/ctors/polygon';
import { vertices } from '@thi.ng/geom/ops/vertices';
import { scatter } from '@thi.ng/geom/ops/scatter';
import { fuzzyPoly, compFill } from '@thi.ng/geom-fuzz';
import { svg } from '@thi.ng/hiccup-svg';
import { serialize } from '@thi.ng/hiccup';
import { shuffle } from '@thi.ng/arrays';
const width = 648;
const height = 864;
const buffer = 20;
const rad = 45;
const s = scatter(
quad(
[buffer + rad, buffer + rad],
[width - buffer - rad, height - buffer - rad],
[width - buffer - rad, height - buffer - rad],
[0, height - buffer - rad],
),
17,
);
const blobShapes = s.flatMap(([x, y], i) =>
Array.from({ length: i % 2 ? 6 : 1 }, (_) =>
star(
rad + buffer * Math.random(),
~~(Math.random() * 5) + 3,
[1.0, 1.5],
{
fill: 'none',
stroke: 'black',
'stroke-width': '1px',
transform: `translate(${x},${y}) scale(${i / s.length})`,
},
),
),
);
const blobs = blobShapes
.map((s) =>
fuzzyPoly(vertices(s), s.attribs, { jitter: 5, curveScale: 0.5 }),
)
.map((b) => withAttribs(b.children.at(0), b.attribs));
const scene = asSvg(...blobs);
const output = serialize(svg({ width, height }, scene));
document.querySelector('#app').innerHTML = `${output}`;