Public
Edited
Dec 11, 2021
23 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
connections = constantConnections.length
? (n) => faceConnections[n]
: randomConnections;
Insert cell
w = width
Insert cell
h = Math.ceil((width / 16) * 9)
Insert cell
polys = coverRect(tiling, edgeSize, w, h)

Insert cell
polycon = polys.map(poly => [poly, connections(poly.length)]);

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
saesa = d3.json(
"https://gist.githubusercontent.com/esperanc/9b3651eb2fbff9bb04de23d594a0a361/raw/a46b20b967726a17d9c4b11edc909a92a57e6e41/SaeSa.json"
)
Insert cell
import {Vec, Ray} from "@esperanc/2d-geometry-utils"
Insert cell
import { coverRect } from "@esperanc/archimedean-tilings"
Insert cell
import {
colorleap as archimedeanPalettes,
colorpalettes as truchetPalettes
} from "@makio135/give-me-colors"
Insert cell
tiling = saesa[tilingName]
Insert cell
faceConnections = {
refresh;
return {
"3": randomConnections(3),
"4": randomConnections(4),
"6": randomConnections(6),
"12": randomConnections(12)
};
}
Insert cell
archPalette = archimedeanPalettes[archimedeanPaletteNumber] //d3.schemePastel2
Insert cell
truchetPalette = truchetPalettes[truchetPaletteNumber]
Insert cell
faceColors = {
let colors = archPalette;
return {
"3": colors[0],
"4": colors[1],
"6": colors[2],
"12": colors[3]
};
}
Insert cell
function genArcPath(ctx, a, b, c, d, ratio = 0.5) {
let ab = new Ray(a, b.sub(a));
let cd = new Ray(c, d.sub(c));
let inter = ab.intersectRay(cd);
if (inter && Math.abs(inter[0]) < 1e9) {
let center = ab.point(inter[0]);
let p = ab.point(ratio);
let radius = p.dist(center);
let q = cd.point(ratio);
let u = p.sub(center);
let v = q.sub(center);
let angAb = (Math.atan2(u.y, u.x) + Math.PI * 2) % (Math.PI * 2);
let angCd = (Math.atan2(v.y, v.x) + Math.PI * 2) % (Math.PI * 2);
let clock = Math.abs(angCd - angAb) > Math.PI == angCd > angAb;
ctx.arc(center.x, center.y, radius, angAb, angCd, clock);
} else {
let p = ab.point(ratio);
let u = c.sub(a);
let v = ab.v.normalize();
let d = u.dot(v);
let w = u.sub(v.scale(d));
let q = p.add(w);
ctx.lineTo(p.x, p.y);
ctx.lineTo(q.x, q.y);
}
}
Insert cell
function genPathEnd(ctx, a, b, ref, ratio = 0.5) {
let p = a.mix(b, 0.5);
let v = a.sub(p);
let radius = p.dist(a) * ratio;
let ang = Math.atan2(v.y, v.x);
let clock = a.orient(b, ref) > 0;
ctx.arc(p.x, p.y, radius, ang, ang + Math.PI, clock);
}
Insert cell
function genArcTile(ctx, poly, connections, thick) {
let tileCenter = Vec(0, 0);
for (let p of poly) tileCenter = tileCenter.add(p);
tileCenter = tileCenter.scale(1 / poly.length);
for (let con of connections) {
if (con.length == 2) {
let [i, j] = con;
let [a, b] = [poly[i], poly[(i + 1) % poly.length]];
let [c, d] = [poly[j], poly[(j + 1) % poly.length]];
ctx.beginPath();
genArcPath(ctx, a, b, c, d, 0.5 - thick / 2);
genArcPath(ctx, c, d, a, b, 0.5 - thick / 2);
ctx.fill();
ctx.beginPath();
genArcPath(ctx, a, b, c, d, 0.5 - thick / 2);
ctx.stroke();
ctx.beginPath();
genArcPath(ctx, c, d, a, b, 0.5 - thick / 2);
ctx.stroke();
} else {
let i = con[0];
let [a, b, ref] = [
poly[i],
poly[(i + 1) % poly.length],
poly[(i + 2) % poly.length]
];
ctx.beginPath();
genPathEnd(ctx, a, b, ref, thick);
ctx.fill();
ctx.stroke();
}
}
}
Insert cell
function randomConnections(n) {
let indices = d3.shuffle(d3.range(n));
if (n % 2 == 1 && pathCaps.length == 0) indices.push(indices[0]);
let pairs = [];
while (indices.length >= 2) {
pairs.push([indices.pop(), indices.pop()]);
}
if (indices.length == 1) pairs.push(indices);
return pairs;
}
Insert cell
{
let ctx = DOM.context2d(800, 600, 1);
ctx.strokeStyle = "black";
let a = Vec(400, 300);
const n = 7;

let pts = [];
for (let i = 0; i < n; i++) {
let ang = ((Math.PI * 2) / n) * i;
pts.push(a.add(Vec(Math.cos(ang), Math.sin(ang)).scale(200)));
}

let connections = randomConnections(n);

ctx.fillStyle = "lightgray";
ctx.strokeStyle = "black";
genArcTile(ctx, pts, connections, 0.1);
return ctx.canvas;
//
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more