import type { TerrainField } from "./terrain.js"; /** A world-space point on the ground plane as an `[x, z]` pair. */ export type GroundPoint = readonly [number, number]; /** A height sampler over the ground: world elevation at any `x`/`z`. */ export type HeightSampler = (x: number, z: number) => number; /** An axis-aligned XZ rectangle to generate terrain-readability guides within. */ export interface GuideRegion { minX: number; minZ: number; maxX: number; maxZ: number; } /** * A sampled height grid over a region — the shared substrate contour extraction and elevation * summaries both read, so a caller can sample once and derive several guides from it. * @internal — an intermediate; games call {@link extractContours} / {@link summarizeElevation} directly. */ export interface HeightGrid { region: GuideRegion; /** Sample columns and rows (each is `resolution + 1` points across its axis). */ cols: number; rows: number; /** Row-major heights, length `cols * rows` (row `r`, column `c` at index `r * cols + c`). */ heights: Float64Array; min: number; max: number; } /** * Samples `sampleHeight` on a `(resolution + 1)²` grid across `region`, capturing the min/max seen — * the bounded, budget-capped scan every guide derives from. `resolution` is clamped to `[1, maxSamples]`. * @internal — building block behind the public guide generators. */ export declare function sampleHeightGrid(sampleHeight: HeightSampler, region: GuideRegion, resolution?: number, maxSamples?: number): HeightGrid; /** A single iso-elevation contour traced across a region as a flat list of XZ line segments. */ export interface ContourLine { /** The world elevation (`y`) this contour follows. */ level: number; /** Whether this is a major (emphasised) contour rather than a minor one. */ major: boolean; /** * Flat segment endpoints `[x0, z0, x1, z1, ...]` — every four numbers is one XZ segment. Draw each * at `y = level` to drape it on the surface; the contour is exact iso-height so it hugs terrain. */ segments: readonly number[]; } /** Shaping for {@link extractContours}: region, vertical spacing, emphasis cadence, and sample budget. */ export interface ContourOptions { region: GuideRegion; /** Vertical spacing between adjacent contour lines, in world units. Must be `> 0`. */ interval: number; /** Every Nth line (counting from `y = 0`) is a major contour. Default `5`; `<= 1` makes all major. */ majorEvery?: number; /** Samples per axis for the marching-squares grid. Default `128`, clamped to `[1, maxSamples]`. */ resolution?: number; /** Hard per-axis sample cap so extraction stays within an explicit budget. Default `256`. */ maxSamples?: number; } /** * Traces surface-following contour lines from a height field via marching squares: samples a bounded * grid over the region, then for every multiple of `interval` strictly inside the sampled height range * emits the iso-line as XZ segments (saddle cells disambiguated by the cell-center average). Because a * contour is exact constant elevation, drawing each segment at `y = level` makes it hug the terrain — * the readable, scale-bearing overlay a flat ground grid cannot give. Pure math, renderer-agnostic. * @capability terrain-contours iso-elevation contour lines that drape on sculpted terrain * @consumer editor terrain-readability overlay; any map/minimap wanting elevation contours */ export declare function extractContours(sampleHeight: HeightSampler, options: ContourOptions): ContourLine[]; /** * Picks a human-friendly contour interval — a `1/2/2.5/5 × 10ⁿ` step — so an elevation `range` splits * into roughly `targetLines` bands. Drives adaptive contour density: a tall terrain gets a coarse * interval, a shallow one a fine interval, without the author choosing a number. Returns `0` when the * range is non-positive (nothing to contour). * @capability contour-interval readable auto-spacing for elevation contours * @consumer editor terrain-readability overlay density control */ export declare function chooseContourInterval(range: number, targetLines?: number): number; /** Measurable elevation readout at a single world point — the cursor/hover feedback value. */ export interface ElevationReadout { x: number; z: number; /** Ground elevation at the point. */ height: number; /** `height - reference` — signed distance above (+) or below (−) the reference plane. */ delta: number; /** The reference-plane height the delta was measured against. */ reference: number; } /** * Reads the ground elevation under a world point and its signed delta from a reference plane — the * measurable cursor/hover feedback ("+3.4 above the pad") an author needs to judge sculpted height. * @capability elevation-readout cursor height and delta-from-reference feedback * @consumer editor terrain-readability HUD readout */ export declare function sampleElevation(sampleHeight: HeightSampler, x: number, z: number, reference?: number): ElevationReadout; /** Aggregate elevation statistics over a region — the selection min/max/mean and legend range. */ export interface ElevationSummary { min: number; max: number; mean: number; /** `max - min` — the vertical relief across the region. */ range: number; /** World point where the lowest sample was found. */ minAt: GroundPoint; /** World point where the highest sample was found. */ maxAt: GroundPoint; /** Number of grid samples taken. */ samples: number; } /** * Summarises elevation across a region on a bounded sample grid: min, max, mean, relief range, and the * world points of the extremes — the selection min/max and legend feedback the readability overlay * reports, and the input to {@link chooseContourInterval}. Pure math, renderer-agnostic. * @capability elevation-summary selection min/max/mean and relief over a region * @consumer editor terrain-readability legend and selection stats */ export declare function summarizeElevation(sampleHeight: HeightSampler, region: GuideRegion, resolution?: number, maxSamples?: number): ElevationSummary; /** Shaping for surface draping: subdivision spacing and a lift to keep the line off the ground. */ export interface DrapeOptions { /** Max world spacing between draped vertices; longer spans are subdivided so the line hugs the surface. Default `1`. */ spacing?: number; /** Lift each draped vertex this far above the sampled surface, to avoid z-fighting. Default `0`. */ offset?: number; } /** * Drapes an XZ polyline onto the surface: subdivides each span to at most `spacing` and lifts every * vertex to `sampleHeight + offset`, returning flat `[x, y, z, ...]` world triples. The reusable seam * behind surface-following placement guides and grid lines — a straight guide bends to follow terrain. * @capability surface-drape lift an XZ polyline onto sculpted terrain * @consumer editor placement guides and surface grid overlay */ export declare function drapePolyline(sampleHeight: HeightSampler, points: readonly GroundPoint[], options?: DrapeOptions): number[]; /** * A closed circle draped on the surface — the surface-following placement guide ring under a cursor or * a selected object. Returns flat `[x, y, z, ...]` world triples forming a loop (last vertex repeats * the first). `segments` sets the smoothness of the ring. * @capability surface-ring surface-following placement guide ring * @consumer editor cursor/placement guide */ export declare function surfaceRing(sampleHeight: HeightSampler, center: GroundPoint, radius: number, segments?: number, options?: DrapeOptions): number[]; /** One draped grid line from {@link surfaceGridLines}: its axis, emphasis, and draped vertices. */ export interface SurfaceGridLine { /** Which axis the line runs constant along: an `"x"` line holds `x` fixed and spans `z`, and vice versa. */ axis: "x" | "z"; /** The constant coordinate value the line holds. */ at: number; /** Whether this is a major (emphasised) grid line. */ major: boolean; /** Flat `[x, y, z, ...]` world triples draped on the surface. */ points: readonly number[]; } /** Shaping for {@link surfaceGridLines}: region, spacing, emphasis cadence, and draping. */ export interface SurfaceGridOptions { region: GuideRegion; /** World distance between adjacent grid lines. Must be `> 0`. */ spacing: number; /** Every Nth line (counting from origin) is a major line. Default `5`; `<= 1` makes all major. */ majorEvery?: number; /** Draping options for each line. */ drape?: DrapeOptions; } /** * Builds a surface-following major/minor grid over a region: constant-`x` and constant-`z` lines at * `spacing`, each draped onto the terrain so the reference grid climbs sculpted surfaces instead of * being occluded by them (the flat `y = 0` grid's core failure). Draping subdivides to * `drape.spacing`. Pure math, renderer-agnostic. * @capability surface-grid terrain-following reference grid that is not occluded by relief * @consumer editor terrain-readability grid overlay */ export declare function surfaceGridLines(sampleHeight: HeightSampler, options: SurfaceGridOptions): SurfaceGridLine[]; /** * Convenience over {@link extractContours} that auto-picks the interval from the field's own relief: * summarises the region, chooses a readable interval for `targetLines` bands, and traces the contours — * the one call the editor overlay makes to turn a `TerrainField` into ready-to-draw guides. Returns an * empty list for flat ground. * @capability terrain-guides one-call adaptive contours for a terrain field * @consumer editor terrain-readability overlay */ export declare function terrainContourGuides(field: Pick, region: GuideRegion, targetLines?: number, resolution?: number): { interval: number; summary: ElevationSummary; contours: ContourLine[]; };