GRV-Summit-Site/components/brand/WavyTessellationMesh.tsx
“kirukib” 6bdb2204b3
Some checks failed
Deploy to Cloudflare Workers (OpenNext) / deploy (push) Has been cancelled
-
2026-05-22 11:14:01 +03:00

95 lines
2.7 KiB
TypeScript

/** GRV greens for wavy interlocking footer tessellation. */
export const WAVY_TESS_PALETTE = [
"#1a5c38",
"#1d5f3c",
"#216342",
"#246845",
"#286a48",
"#2b6e4b",
] as const;
export type WavyTessCell = { d: string; fill: string };
function hashCell(col: number, row: number, cols: number) {
return (col * 17 + row * 31 + ((col + row) % cols) * 11) % WAVY_TESS_PALETTE.length;
}
type MeshOptions = {
/** Tilts wave flow diagonally (higher = more angled, less vertical). */
diagonalSkew?: number;
amplitude?: number;
};
/**
* Diagonal wavy columns + horizontal ripples — interlocking mosaic (not flat vertical stripes).
*/
export function buildWavyTessellationMesh(
cols: number,
rows: number,
width = 100,
height = 100,
options: MeshOptions = {}
): WavyTessCell[] {
const skew = options.diagonalSkew ?? 0.72;
const amp = (width / cols) * (options.amplitude ?? 0.62);
const ampRow = amp * 0.48;
const loops = 3.6;
const boundaryX = (col: number, yNorm: number) => {
const base = (col / cols) * width;
const phase = col * 1.13 + 0.42;
const u = yNorm + (col / cols) * skew;
const v = yNorm - (col / cols) * skew * 0.45;
const wave =
Math.sin(u * Math.PI * 2 * loops + phase) +
0.52 * Math.sin(v * Math.PI * 2 * (loops + 0.85) - col * 0.4) +
0.28 * Math.cos((u + v) * Math.PI * loops * 0.55 + phase * 0.6);
return base + amp * wave * 0.42;
};
const boundaryY = (row: number, xNorm: number) => {
const base = (row / rows) * height;
const phase = row * 0.91 + 0.18;
const u = xNorm + (row / rows) * skew;
const wave =
Math.sin(u * Math.PI * 2 * (loops * 0.9) + phase) +
0.4 * Math.cos(u * Math.PI * 2 * (loops * 1.15) - row * 0.55);
return base + ampRow * wave * 0.38;
};
const cells: WavyTessCell[] = [];
const corner = (col: number, row: number) => {
const yn = row / rows;
const x = boundaryX(col, yn);
const y = boundaryY(row, x / width);
return { x, y };
};
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
const bl = corner(c, r);
const br = corner(c + 1, r);
const tl = corner(c, r + 1);
const tr = corner(c + 1, r + 1);
const ymL = (bl.y + tl.y) / 2;
const ymR = (br.y + tr.y) / 2;
const d = [
`M ${bl.x.toFixed(2)} ${bl.y.toFixed(2)}`,
`Q ${bl.x.toFixed(2)} ${ymL.toFixed(2)} ${tl.x.toFixed(2)} ${tl.y.toFixed(2)}`,
`L ${tr.x.toFixed(2)} ${tr.y.toFixed(2)}`,
`Q ${br.x.toFixed(2)} ${ymR.toFixed(2)} ${br.x.toFixed(2)} ${br.y.toFixed(2)}`,
"Z",
].join(" ");
const layer = (r + Math.floor(c / 2)) % 3;
const fill = WAVY_TESS_PALETTE[hashCell(c + layer, r, cols)];
cells.push({ d, fill });
}
}
return cells;
}