lsh-BlobFamily

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}`;