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

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more