import { Resvg } from "@resvg/resvg-js"; import { promises } from "fs"; import { JSDOM } from "jsdom"; import * as d3 from "d3"; import yargs from "yargs/yargs"; import { hideBin } from "yargs/helpers"; import random from "random"; const xmlns = "http://www.w3.org/2000/xmlns/"; const xlinkns = "http://www.w3.org/1999/xlink"; const svgns = "http://www.w3.org/2000/svg"; import {RADIUS_OPTS, DotMaker} from './src/components/dots.js'; import {PALETTES} from './src/components/palettes.js'; const CELL = 10; const MAG = 2; const WIDTH = 20; const HEIGHT = WIDTH; function poptimal_svg() { const window = new JSDOM().window; const document = window.document; const container = d3.select(document.body).append("div"); const dm = new DotMaker(WIDTH); const m1 = random.choice([1, 2, 3, 4, 5]); const n1 = random.choice([1, 2, 3, 4, 5]); const m2 = random.choice([1, 2, 3, 4, 5]); const n2 = random.choice([1, 2, 3, 4, 5]); const palette_fn = random.choice(Array.from(PALETTES.values())); const palette = palette_fn(); const bg = palette[0]; const fg1 = palette[1]; const fg2 = palette[2]; const f1 = random.choice(RADIUS_OPTS); const f2 = random.choice(RADIUS_OPTS); const r1 = random.float(0, 0.4); const r2 = random.float(0, 0.4); const dots1 = dm.dots(1 / m1, n1); const dots2 = dm.dots(1 / m2, n2); const svg = container.append("svg") .attr("width", WIDTH * CELL * MAG) .attr("height", HEIGHT * CELL * MAG) .attr("viewBox", [ 0, 0, WIDTH, HEIGHT ]); const background = svg.append("rect") .attr("x", 0) .attr("y", 0) .attr("width", WIDTH) .attr("height", WIDTH) .attr("fill", bg); const dots_g1 = svg.append("g") .attr("id", "dots1"); dots_g1.selectAll("circle") .data(dots1) .join("circle") .attr("r", (d) => dm.radius(d, f1, r1)) .attr("fill", fg1) .attr("cx", (d) => d.x) .attr("cy", (d) => d.y); const dots_g2 = svg.append("g") .attr("id", "dots2"); dots_g2.selectAll("circle") .data(dots2) .join("circle") .attr("r", (d) => dm.radius(d, f2, r2)) .attr("fill", fg2) .attr("cx", (d) => d.x) .attr("cy", (d) => d.y); const node = svg.node(); node.setAttributeNS(xmlns, "xmlns", svgns); node.setAttributeNS(xmlns, "xmlns:xlink", xlinkns); const serializer = new window.XMLSerializer; return serializer.serializeToString(node); } async function main() { const argv = yargs(hideBin(process.argv)) .usage("Usage: -w WIDTH -o OUTPUT_PNG") .default('w', 1200) .default('o', 'poptimal.png').argv; const svg = poptimal_svg(argv.w); const opts = { background: 'rgba(255, 255, 255, 1.0)', fitTo: { mode: 'width', value: argv.w, }, }; const resvg = new Resvg(svg, opts) const pngData = resvg.render() const pngBuffer = pngData.asPng() await promises.writeFile(argv.o, pngBuffer); } main();