Skip to content

Instantly share code, notes, and snippets.

@Perlkonig
Last active June 2, 2024 23:10
Show Gist options
  • Save Perlkonig/25a9ffd67bbf40faec649f5b174c94c5 to your computer and use it in GitHub Desktop.
Save Perlkonig/25a9ffd67bbf40faec649f5b174c94c5 to your computer and use it in GitHub Desktop.
A TypeScript implementation of Castux's code for generating conical projections of hexagonal rhombus boards (https://gist.github.com/Castux/ee792e2631716ec0041aa2732d142a4b)
type Vertex = [number,number];
type Hex = Vertex[];
const narrow = true; // Change this to toggle between the base and narrow versions
const size = 14; // board height; width = height - 1
const baseHex: Hex = [];
const s32 = Math.sqrt(3) / 2;
const rad = 1 / Math.sqrt(3);
for (let i = 0; i < 6; i++) {
const alpha = (i + 0.5) * 2 * Math.PI / 6;
baseHex.push([rad * Math.cos(alpha), rad * Math.sin(alpha)])
}
const hexes: Hex[] = [];
for (let x = 1; x < size; x++) {
for (let y = 0; y < size; y++) {
const yshift = narrow ? 0.5 : -0.5;
const dx = x + yshift * y;
const dy = s32 * y;
const hex: Hex = [];
for (let i = 0; i < 6; i++) {
hex.push([baseHex[i][0] + dx, baseHex[i][1] + dy]);
}
hexes.push(hex);
}
}
const toSegments = (hex: Hex): Vertex[] => {
const coords: Vertex[] = [];
for (let i = 0; i < 6; i++) {
const a = hex[i];
const b = hex[(i + 1) % 6];
const steps = 15;
for (let j = 0; j <= steps; j++) {
const s = j / steps;
coords.push([(1 - s) * a[0] + s * b[0], (1 - s) * a[1] + s * b[1]]);
}
}
return coords;
}
const fold = (p: Vertex, factor: number): Vertex => {
const d = Math.sqrt(p[0]**2 + p[1]**2);
let a = Math.atan2(p[1], p[0]);
a = a * factor;
const x = d * Math.cos(a);
const y = d * Math.sin(a);
return [x,y];
}
const truncate = (n: number): number => {
return Math.round(n * 100) / 100;
}
const svg: string[] = [];
const factor = narrow ? 6 : 3;
const scale = 20;
const allCoords: Vertex[] = [];
for (const hex of hexes) {
const coords: Vertex[] = [];
for (const pt of toSegments(hex)) {
const folded = fold(pt, factor);
coords.push([truncate(scale * folded[0]), truncate(scale * folded[1])]);
}
allCoords.push(...coords);
svg.push(`<polygon points="${coords.map(pt => pt.join(",")).join(" ")}" stroke="black" stroke-width="1" fill="none" />`)
}
svg.push(`</svg>`);
const minx = Math.min(...allCoords.map(pt => pt[0]));
const maxx = Math.max(...allCoords.map(pt => pt[0]));
const miny = Math.min(...allCoords.map(pt => pt[1]));
const maxy = Math.max(...allCoords.map(pt => pt[1]));
const width = maxx - minx;
const height = maxy - miny;
const buffer = 5;
svg.unshift(`<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="${minx - buffer} ${miny - buffer} ${width + (buffer * 2)} ${height + (buffer * 2)}">`);
console.log(svg.join("\n"));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment