Sierpiński Triangle via Chaos
Short one today, as my new job is keeping me busy. Here’s something fun:
- Start with an equilateral triangle.
- Pick a random point inside that triangle.
- Pick one of the three vertices and move halfway towards it.
- Make a mark.
- Repeat 3 & 4.
You end up with the Sierpiński Triangle by way of the awesomely-named Chaos Game.
Demo
Borrowing how to calculate a random point inside a triangle from this reference (remember when people used StackOverflow instead of LLMs?), here’s a demo. Hit Start/Stop to, well, start or stop, then Reset to start over. It’ll probably slow down once there are a lot of points, so caveat emptor.
Code plz
My Javascript code is short enough to include here; even unminified, it’s only
43 lines after formatting with biome.[1]
const [S, A, B, C] = ["serpent_ski", "ss_a", "ss_b", "ss_c"].map((i) =>
document.getElementById(i),
);
const FILL = A.getAttribute("fill");
const XS = [A, B, C].map((c) => c.cx.baseVal.value);
const YS = [A, B, C].map((c) => c.cy.baseVal.value);
let [X, Y, ON] = [0, 0, null];
const new_xy = () => {
const [u, v] = [Math.sqrt(Math.random()), Math.random()];
X = (1 - u) * XS[0] + u * (1 - v) * XS[1] + u * v * XS[2];
Y = (1 - u) * YS[0] + u * (1 - v) * YS[1] + u * v * YS[2];
};
document.getElementById("reset").addEventListener("click", () => {
ON = clearInterval(ON);
S.replaceChildren(A, B, C);
new_xy();
});
document.getElementById("start_stop").addEventListener("click", () => {
if (!ON) {
new_xy();
ON = setInterval(() => {
const p = document.createElementNS(
"http://www.w3.org/2000/svg",
"circle",
);
const i = Math.floor(XS.length * Math.random());
X += 0.5 * (XS[i] - X);
Y += 0.5 * (YS[i] - Y);
[
["cx", X],
["cy", Y],
["r", 0.5],
["fill", FILL],
["opacity", 1],
].forEach(([k, v]) => {
p.setAttribute(k, v);
});
S.appendChild(p);
});
} else {
ON = clearInterval(ON);
}
});-
There are also some lines of HTML needed to set up the buttons and SVG to begin with. ↩