/** * Web Mercator projection helpers and XYZ tile-pyramid math. Pure * functions, no side effects, safe to call from any thread (including * the renderer worker). * * Mercator output is in *meters*, not the normalized [0, 1] form that * some libraries use. We feed the meter values straight into the * cartesian projection matrix in `plot-layout.ts`, so the upstream * domain stays in physical units and per-pixel ground resolution is a * straightforward division. */ /** * WGS84 equatorial radius in meters. Matches what every standard tile * provider (OSM, CartoDB, Mapbox, ...) uses for Web Mercator. */ export declare const EARTH_RADIUS_M = 6378137; /** * Half the world extent in Mercator meters: π · R ≈ 20037508.34. The * full Mercator square is `[-WORLD_HALF, +WORLD_HALF]` on both axes. */ export declare const WORLD_HALF: number; /** * Maximum absolute latitude representable in Web Mercator. Beyond this * the projection diverges to ±∞; tile providers don't ship tiles * outside [-MAX_LAT, +MAX_LAT]. Computed as * `atan(sinh(π)) · 180 / π ≈ 85.0511287798°`. */ export declare const MAX_LAT = 85.0511287798066; /** * Project (longitude, latitude) in degrees to Web Mercator meters. * * Latitudes outside ±MAX_LAT return `[NaN, NaN]` so callers in the * cartesian build path (which already has a post-`projectPoint` NaN * guard) discard those rows without special-casing. */ export declare function lonLatToMercator(lon: number, lat: number): [number, number]; /** * Inverse: Mercator meters → (lon, lat) in degrees. Used by tooltip * formatting and any UI that surfaces the cursor position to the user. */ export declare function mercatorToLonLat(x: number, y: number): [number, number]; /** * A single XYZ tile address. */ export interface TileId { z: number; x: number; y: number; } /** * Mercator extent in meters of one XYZ tile. Y is in the Mercator * convention (north positive), not the tile-pyramid convention (y=0 * at the top); the conversion is done inside the helper. */ export interface TileExtent { xMin: number; yMin: number; xMax: number; yMax: number; } /** * Return the Mercator-meter bounds of an XYZ tile. Tile (0, 0) at * zoom 0 covers `[-WORLD_HALF, +WORLD_HALF]` on both axes — the whole * world. Each zoom level subdivides into `2^z × 2^z` equal squares. */ export declare function tileExtent(z: number, x: number, y: number): TileExtent; /** * Pick the integer zoom level whose tile pixel resolution best matches * the requested Mercator-meters-per-pixel. Snaps to the next coarser * level so we never undersample (a finer level would fetch tiles only * to scale them down). * * `targetResolutionMpp` is meters per *device pixel*; the caller * computes it as `(domain.xMax - domain.xMin) / plotRect.width`. */ export declare function pickZoom(targetResolutionMpp: number, tileSizePx?: number, maxZoom?: number): number; /** * Enumerate every visible tile at a single zoom level that intersects * the given Mercator extent. Returned in left-to-right, top-to-bottom * order so the layer's render loop produces a deterministic draw * sequence (helps with debugging tile-load races). * * Tiles outside the world's `[0, 2^z)` X range are *not* wrapped — * antimeridian wraparound is a v2 feature. Callers see a gap when * panning past ±180° lon; tiles inside the valid range still render. */ export declare function tilesForExtent(extent: TileExtent, z: number): TileId[]; /** * Return the parent tile (one zoom level coarser) of the given tile, * along with the [0, 1] UV sub-rect that this tile occupies inside * its parent. Used by the layer's "draw what we have" fallback while * a missing target tile is in-flight — the parent texture is sampled * with the sub-rect so the visible region keeps tile-aligned content * instead of flashing blank. * * Returns `null` for zoom-0 tiles (no parent). */ export declare function parentTile(tile: TileId): { parent: TileId; uvMin: [number, number]; uvMax: [number, number]; } | null;