import { type MapGrid, type MapGridLevel } from "../door/grid.ts"; /** * One tile of the map pyramid: a level, a column counted east from longitude -180 and a row counted south from latitude 90. * * @example * ```ts * import type { TileId } from "@johnmorrisdotca/chikyu-earth/realistic"; * * const tile: TileId = { level: 4, col: 17, row: 5 }; * console.log(tile); * ``` */ export interface TileId { level: number; col: number; row: number; } /** * What a layer of a tile set holds, from its manifest: the pyramid's levels, each as wide as it is, and the tile size. * * @example * ```ts * import type { TileLayer } from "@johnmorrisdotca/chikyu-earth/realistic"; * * const day: TileLayer = { tileSize: 512, levels: [{ level: 3, width: 8192 }, { level: 4, width: 16384 }] }; * console.log(day.levels.length); * ``` */ export interface TileLayer { tileSize: number; levels: { level: number; width: number; }[]; } /** * Where the camera is, as the realistic Earth draws it: the place in the middle of the disc, the box in CSS pixels, the pan, and the disc's radius in CSS pixels. * * @example * ```ts * import type { TileCamera } from "@johnmorrisdotca/chikyu-earth/realistic"; * * const camera: TileCamera = { lon: 10, lat: 20, width: 800, height: 600, panX: 0, panY: 0, radius: 900 }; * console.log(camera.radius); * ``` */ export interface TileCamera { lon: number; lat: number; width: number; height: number; panX: number; panY: number; radius: number; /** A camera of the space view, which has a real place and a perspective, in place of the disc: when given, `lon`, `lat`, `panX`, `panY` are not read and `radius` is the disc's radius at the nearest ground. */ perspective?: TilePerspective; } /** * A camera that sees the Earth in perspective, from a place that can be a few kilometres above the ground, in the Earth's own axes (x toward longitude 90, y north, z toward longitude 0; the Earth's radius is 1). * * @example * ```ts * import type { TilePerspective } from "@johnmorrisdotca/chikyu-earth/realistic"; * * const look: TilePerspective = { eye: [0, 0, 1.0235], project: (p) => ({ x: 400 + p[0] * 5000, y: 300 - p[1] * 5000 }), ground: () => [0, 0, 1] }; * console.log(look.eye); * ``` */ export interface TilePerspective { /** Where the camera is. */ eye: readonly [number, number, number]; /** Where a point of the Earth's surface falls in the box (CSS pixels), or `null` where it is behind the camera. */ project(point: readonly [number, number, number]): { x: number; y: number; } | null; /** The point of the Earth's surface under a place in the box (a unit vector), or `null` where the box shows the sky. */ ground(x: number, y: number): readonly [number, number, number] | null; } /** * A tile that is in view: where, how far its middle is from the middle of the box (CSS pixels, for loading the middle first) and how dark its darkest sampled point is (`ndl`, the * cosine of the angle to the Sun, only when a Sun was given). * * @example * ```ts * import type { VisibleTile } from "@johnmorrisdotca/chikyu-earth/realistic"; * * const tile: VisibleTile = { level: 3, col: 0, row: 0, d: 120, ndl: -0.4 }; * console.log(tile.d); * ``` */ export interface VisibleTile extends TileId { d: number; ndl: number; } /** * How much larger than a device pixel a map texel may be before the next level is wanted: 1.25 is a quarter larger. * * @example * ```ts * import { TEXEL_SLACK } from "@johnmorrisdotca/chikyu-earth/realistic"; * * console.log(TEXEL_SLACK); * ``` */ export declare const TEXEL_SLACK = 1.25; /** * Columns in a level. * * @param level - A pyramid level. * @returns `2^(level + 1)`. * * @example * ```ts * import { tileColumns } from "@johnmorrisdotca/chikyu-earth/realistic"; * * console.log(tileColumns(4)); * ``` */ export declare const tileColumns: (level: number) => number; /** * Rows in a level. * * @param level - A pyramid level. * @returns `2^level`. * * @example * ```ts * import { tileRows } from "@johnmorrisdotca/chikyu-earth/realistic"; * * console.log(tileRows(4)); * ``` */ export declare const tileRows: (level: number) => number; /** * The first level to load for a disc: the smallest one whose texels are about a device pixel on the screen, else the finest there is, and none when the whole-Earth picture * (`baseWidth` across) is already that sharp. * * @param radiusPx - The disc's radius in device pixels. * @param layer - The levels the set has for this layer. * @param baseWidth - The width of the picture the tiles are laid over, 4096 for the day map. * @returns A level in `layer`, or `undefined` when no tile is worth loading. * * @example * ```ts * import { tileLevel, type TileLayer } from "@johnmorrisdotca/chikyu-earth/realistic"; * * const day: TileLayer = { tileSize: 512, levels: [{ level: 3, width: 8192 }, { level: 4, width: 16384 }] }; * console.log(tileLevel(600, day, 4096), tileLevel(1500, day, 4096), tileLevel(9000, day, 4096)); * ``` */ export declare function tileLevel(radiusPx: number, layer: TileLayer, baseWidth: number): number | undefined; /** * The tile of a coarser or the same level that holds a tile. * * @param tile - A tile. * @param level - A level no finer than the tile's. * @returns The tile at `level` that covers it. * * @example * ```ts * import { coveringTile } from "@johnmorrisdotca/chikyu-earth/realistic"; * * console.log(coveringTile({ level: 4, col: 17, row: 5 }, 3)); * ``` */ export declare function coveringTile(tile: TileId, level: number): TileId; /** * Where a tile's edges are, in longitude and latitude in radians: west, north, east and south. * * @param tile - A tile. * @returns `[west, north, east, south]`. * * @example * ```ts * import { tileRect } from "@johnmorrisdotca/chikyu-earth/realistic"; * * console.log(tileRect({ level: 3, col: 0, row: 0 })); * ``` */ export declare function tileRect(tile: TileId): [number, number, number, number]; /** * The longitude and latitude (degrees) under a point of the box, or `undefined` where the box shows the sky. * * @param camera - The camera. * @param x - Across the box, CSS pixels from its left. * @param y - Down the box, CSS pixels from its top. * @returns The longitude and latitude in degrees under that point, or `undefined` where the box shows the sky. * * @example * ```ts * import { pointOnEarth } from "@johnmorrisdotca/chikyu-earth/realistic"; * * console.log(pointOnEarth({ lon: 10, lat: 20, width: 800, height: 600, panX: 0, panY: 0, radius: 900 }, 400, 300)); * ``` */ export declare function pointOnEarth(camera: TileCamera, x: number, y: number): { lon: number; lat: number; } | undefined; /** * The tiles of a level that are in view: those with a sampled point inside the box (a little over, so a tile slides in before its edge does), and those under a grid of points * across the box. The antimeridian and the poles need nothing special: a tile is tested where it is on the sphere, and a longitude of 180 is the last column. * * @param level - A pyramid level. * @param camera - The camera. * @param sun - The Sun's direction as the camera sees it (+x right, +y up, +z toward the viewer), to read each tile's `ndl`; left out, `ndl` is 1. * @returns The tiles in view, the nearest to the middle of the box first. * * @example * ```ts * import { tilesInView } from "@johnmorrisdotca/chikyu-earth/realistic"; * * const tiles = tilesInView(4, { lon: 179.9, lat: 89, width: 800, height: 600, panX: 0, panY: 0, radius: 3000 }); * console.log(tiles.length, tiles[0]); * ``` */ export declare function tilesInView(level: number, camera: TileCamera, sun?: readonly [number, number, number]): VisibleTile[]; /** * Read a tile set's manifest (`manifest.json`): the tile size and, for each layer, its levels. A manifest with no usable layer gives `undefined`. * * @param json - The parsed JSON. * @returns A layer name to its levels, and the tile size; or `undefined`. * * @example * ```ts * import { parseManifest } from "@johnmorrisdotca/chikyu-earth/realistic"; * * const manifest = parseManifest({ tileSize: 512, layers: { day: { levels: [{ level: 3, width: 8192, height: 4096, columns: 16, rows: 8 }] } } }); * console.log(manifest?.layers["day"]?.levels); * ``` */ export declare function parseManifest(json: unknown): { tileSize: number; layers: Record; } | undefined; /** * The tiles of one level of a source's own grid that are in view. Only the columns and rows under the box are tested, so a fine matrix (hundreds of columns) is not walked. A tile that misses the Earth is left out. * * @param level - A level of the source's grid. * @param extent - The Earth's extent, from the same grid. * @param camera - The camera. * @param sun - The Sun's direction as the camera sees it, for each tile's `ndl`; left out, `ndl` is 1. * @returns The tiles in view, the nearest to the middle of the box first. * * @example * ```ts * import { gibsGrid } from "@johnmorrisdotca/chikyu-earth/door"; * import { gridTilesInView } from "@johnmorrisdotca/chikyu-earth/realistic"; * * const grid = gibsGrid("250m"); * console.log(gridTilesInView(grid.levels[6]!, grid.extent, { lon: 0, lat: 0, width: 800, height: 600, panX: 0, panY: 0, radius: 8000 }).length > 0); * ``` */ export declare function gridTilesInView(level: MapGridLevel, extent: MapGrid["extent"], camera: TileCamera, sun?: readonly [number, number, number]): VisibleTile[];