import type { Vec2 } from "@/lib/voronoi-mesh"; function mulberry32(seed: number) { let s = seed >>> 0; return () => { s = (s + 0x6d2b79f5) >>> 0; let t = Math.imul(s ^ (s >>> 15), 1 | s); t ^= t + Math.imul(t ^ (t >>> 7), 61 | t); return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }; } /** Gentle wave along the footer midline — peaks cross 50% so facet tops stay visible. */ export function buildFooterMidlineCurve( width: number, segments: number, seed: number, midY: number, amplitude: number ): Vec2[] { const rand = mulberry32(seed); const pts: Vec2[] = [[0, midY + (rand() - 0.5) * amplitude * 0.35]]; for (let i = 1; i <= segments; i++) { const x = (width * i) / segments; const t = i / segments; const wave = Math.sin(t * Math.PI * 3.8 + seed * 0.002) * amplitude * 0.5 + Math.sin(t * Math.PI * 7.4 + 0.8) * amplitude * 0.22; const jitter = (rand() - 0.5) * amplitude * 0.4; const y = midY + wave + jitter; pts.push([x, Math.max(midY - amplitude * 0.85, Math.min(midY + amplitude * 0.9, y))]); } return pts; } /** Closed SVG path: curved top, square bottom (clip region for facets). */ export function midlineCurveToClipPath(edge: Vec2[], width: number, height: number): string { if (edge.length < 2) return ""; const [x0, y0] = edge[0]; let d = `M ${x0},${y0}`; for (let i = 1; i < edge.length; i++) { const [x, y] = edge[i]; const [px, py] = edge[i - 1]; const cx = (px + x) / 2; d += ` Q ${cx},${py} ${x},${y}`; } d += ` L ${width},${height} L 0,${height} Z`; return d; } /** CSS clip-path (percent) — matches SVG curve for the HTML layer. */ export function midlineCurveToClipPathPercent( edge: Vec2[], width: number, height: number ): string { const pct = (x: number, y: number) => `${((x / width) * 100).toFixed(2)}% ${((y / height) * 100).toFixed(2)}%`; const top = edge.map(([x, y]) => pct(x, y)).join(", "); return `polygon(${top}, 100% 100%, 0% 100%)`; }