/** * Classified symbology (issue #12 — "categorized/graduated styling, named * ramps + auto-generated legend"). The half `scale()` deliberately does NOT * cover: class breaks computed FROM THE DATA. An auto-domain expression was * rejected long ago as impure ("an auto-domain scale() broke the cache"), so * classification lives at the layer level instead, resolved where the rows * are already in hand (parse-manifest / descriptorToIR — the same "resolved * once data is present" seam `highlighted-id` and the CityJSON defaults * use). URL-backed layers classify on the reparse their data arrival * triggers; until then the layer renders unclassified, not blank. * * Authoring surface (universal layer attributes, like filter-*): * classify-by="magnitude" the numeric field * classify-scale="quantile" quantile (default) | equal-interval | jenks * classify-classes="5" 2–12, default 5 * classify-ramp="viridis" a named ramp below, default viridis * * An authored fill-color source (get-fill-color, a color shorthand, or a * script-block export) always wins — classification silently defers at * runtime and validation names the conflict at author time. The generated * accessor is a plain function with an updateTriggers key derived from the * actual computed breaks, so deck recomputes exactly when the classification * genuinely changes and never otherwise; results are memoized per data * reference (inline data is reference-stable since 0.6.11). */ import type { LayerData, LayerMeta } from "./ir"; import type { Shape } from "./expr"; /** * Named ramps — standard matplotlib / ColorBrewer stop sets, the same * vocabulary COGLayer's raster colormaps use where the names overlap. */ export declare const CLASSIFY_RAMPS: Record; export declare const CLASSIFY_SCALES: readonly ["quantile", "equal-interval", "jenks"]; export type ClassifyScale = (typeof CLASSIFY_SCALES)[number]; /** k colors sampled evenly along a ramp's stops (linear RGB interpolation). */ export declare function rampColors(name: string, k: number): string[]; /** k-1 ascending upper boundaries for k classes: value < b[0] → class 0, …, ≥ b[k-2] → class k-1. */ export declare function quantileBreaks(sorted: readonly number[], k: number): number[]; export declare function equalIntervalBreaks(sorted: readonly number[], k: number): number[]; /** * Jenks natural breaks via the classic Fisher–Jenks dynamic program. O(k·n²), * so inputs above 600 values are evenly strided down to 600 first — the * breaks of a stride-sampled sorted vector are statistically * indistinguishable for styling purposes, and this keeps a 25k-row layer's * reconcile pass flat. */ export declare function jenksBreaks(sortedInput: readonly number[], k: number): number[]; export interface ClassifySpec { classifyBy?: string; classifyScale?: string; classifyClasses?: number; classifyRamp?: string; } /** * Computes the classification for a layer and installs it as `getFillColor` * + updateTrigger + legend, shared verbatim by both front-ends. No-ops (and * leaves everything untouched) when: no `classifyBy`; a fill-color source is * already authored (it wins — validation names the conflict); the data * hasn't arrived yet or has under two distinct numeric values (the URL case * — the data-arrival reparse re-enters here with real rows). */ export declare function applyClassification(props: Record, meta: LayerMeta, updateTriggers: Record, spec: ClassifySpec, data: LayerData, shape: Shape, warnLabel: string): void;