import { curveBasisClosed, line, select } from "d3"; import type { PackedGraphFeature } from "../modules/features"; import { clipPoly, round } from "../utils"; declare global { var drawFeatures: () => void; var defs: d3.Selection; var coastline: d3.Selection; var lakes: d3.Selection; var simplify: ( points: [number, number][], tolerance: number, highestQuality?: boolean, ) => [number, number][]; } interface FeaturesHtml { paths: string[]; landMask: string[]; waterMask: string[]; coastline: { [key: string]: string[] }; lakes: { [key: string]: string[] }; } const featuresRenderer = (): void => { TIME && console.time("drawFeatures"); const html: FeaturesHtml = { paths: [], landMask: [], waterMask: [''], coastline: {}, lakes: {}, }; for (const feature of pack.features) { if (!feature || feature.type === "ocean") continue; html.paths.push( ``, ); if (feature.type === "lake") { html.landMask.push( ``, ); const lakeGroup = feature.group || "freshwater"; if (!html.lakes[lakeGroup]) html.lakes[lakeGroup] = []; html.lakes[lakeGroup].push( ``, ); } else { html.landMask.push( ``, ); html.waterMask.push( ``, ); const coastlineGroup = feature.group === "lake_island" ? "lake_island" : "sea_island"; if (!html.coastline[coastlineGroup]) html.coastline[coastlineGroup] = []; html.coastline[coastlineGroup].push( ``, ); } } defs.select("#featurePaths").html(html.paths.join("")); defs.select("#land").html(html.landMask.join("")); defs.select("#water").html(html.waterMask.join("")); coastline.selectAll("g").each(function () { const paths = html.coastline[this.id] || []; select(this).html(paths.join("")); }); lakes.selectAll("g").each(function () { const paths = html.lakes[this.id] || []; select(this).html(paths.join("")); }); TIME && console.timeEnd("drawFeatures"); }; function getFeaturePath(feature: PackedGraphFeature): string { const points: [number, number][] = feature.vertices.map( (vertex: number) => pack.vertices.p[vertex], ); if (points.some((point) => point === undefined)) { ERROR && console.error("Undefined point in getFeaturePath"); return ""; } const simplifiedPoints = simplify(points, 0.3); const clippedPoints = clipPoly(simplifiedPoints, graphWidth, graphHeight); const lineGen = line().curve(curveBasisClosed); const path = `${round(lineGen(clippedPoints) || "")}Z`; return path; } window.drawFeatures = featuresRenderer;