import type { CityFrame } from "../cities/geometry.ts"; /** * One country outline the names are made from: a GeoJSON feature in longitude and latitude (a `Polygon` or `MultiPolygon`) with its code and its English and Japanese names, as chizu's * `world-geo` has them. A feature with no name is passed over. * * @example * ```ts * import type { NamedShape } from "@johnmorrisdotca/chikyu-earth/realistic"; * * const square: NamedShape = { properties: { code: "A", name: "Square", nameJa: "四角" }, geometry: { type: "Polygon", coordinates: [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]] } }; * console.log(square.properties?.name); * ``` */ export interface NamedShape { properties?: { code?: string | null; name?: string | null; nameJa?: string | null; } | null; geometry: { type: string; coordinates: unknown; } | null; } /** * The countries ready to be named: for each, its code and names, and points spread evenly over its land (longitude, latitude, the area each stands for in square degrees of the sphere, and which * of the country's polygons it is in), with the cap of the sphere they all lie in. * * @example * ```ts * import { countrySpots, type CountrySpots } from "@johnmorrisdotca/chikyu-earth/realistic"; * * const spots: CountrySpots = countrySpots({ features: [] }); * console.log(spots.countries.length); * ``` */ export interface CountrySpots { countries: { code: string; name: { en: string; ja?: string; }; /** lon, lat, area, polygon for each point. */ points: Float32Array; /** The middle of the points on the sphere, and how far from it (degrees) the farthest one is. */ cap: { lon: number; lat: number; reach: number; }; }[]; } /** * A country named at one draw: its code, the text, where the middle of the part in view falls, the box the text goes in (top left corner and size) and the text's size in pixels. * * @example * ```ts * import type { CountryName } from "@johnmorrisdotca/chikyu-earth/realistic"; * * const say = (one: CountryName): string => `${one.text} at ${one.left}, ${one.top}`; * console.log(typeof say); * ``` */ export interface CountryName { code: string; text: string; x: number; y: number; left: number; top: number; width: number; height: number; size: number; } /** * Where the Earth is on the screen at one draw: the frame the city names use, and the Earth's disc (its middle and radius in CSS pixels), which no name may leave. * * @example * ```ts * import type { CountryFrame } from "@johnmorrisdotca/chikyu-earth/realistic"; * * const frame: CountryFrame = { width: 400, height: 400, radius: 150, disc: { x: 200, y: 200, radius: 150 }, project: (lon, lat, out) => { out.x = 200 + lon; out.y = 200 - lat; return 1; } }; * console.log(frame.disc?.radius); * ``` */ export interface CountryFrame extends CityFrame { disc?: { x: number; y: number; radius: number; }; } /** * What the names are laid out with: the most names, the smallest and largest text in pixels, the boxes other names use, and the width and height of a text as the browser draws it. * * @example * ```ts * import type { CountryLayoutOptions } from "@johnmorrisdotca/chikyu-earth/realistic"; * * const options: CountryLayoutOptions = { max: 40, smallest: 10, largest: 16 }; * console.log(options.max); * ``` */ export interface CountryLayoutOptions { max: number; smallest: number; largest: number; /** Boxes other names already use (cities, places, the bodies' names): no country name is put over one. */ taken?: readonly { left: number; top: number; width: number; height: number; }[]; /** * The width and height of a text at a size, as the browser draws it in the names' own font (a canvas's `measureText`). The estimate from the length is a floor and the larger is used, so a * fallback font with wider letters or taller lines is measured as it is. Left out, the estimate alone is used, as in Node. */ measure?: (text: string, size: number) => { width: number; height: number; }; } /** * The space between the letters of a country's name, as a share of the text's size (the style sheet's `letter-spacing` in `em`). * * @example * ```ts * import { COUNTRY_LETTER_SPACING } from "@johnmorrisdotca/chikyu-earth/realistic"; * * console.log(COUNTRY_LETTER_SPACING * 12); * ``` */ export declare const COUNTRY_LETTER_SPACING = 0.06; /** * Spreads points over each named country's land, about 48 to a country on an even grid of longitude and latitude, so that a view can find the middle of the part of it in sight and how large * that part is. A polygon too small for the grid gets one point, at the middle of its outline. Made once, when the outlines arrive. * * @param shapes - The outlines, as chizu's `world-geo` has them. * @returns The countries and their points. * * @example * ```ts * import { countrySpots } from "@johnmorrisdotca/chikyu-earth/realistic"; * * const square = { properties: { code: "A", name: "Square" }, geometry: { type: "Polygon", coordinates: [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]] } }; * const spots = countrySpots({ features: [square] }); * console.log(spots.countries[0]?.points.length! / 4); * ``` */ export declare function countrySpots(shapes: { features: readonly NamedShape[]; }): CountrySpots; /** * The name to write for a country: its Japanese name on a page in Japanese where there is one, else its English name in capitals. * * @param country - The country's names. * @param lang - The page's language, `en` or `ja`. * @returns The text. * * @example * ```ts * import { countryNameText } from "@johnmorrisdotca/chikyu-earth/realistic"; * * const japan = { name: { en: "Japan", ja: "日本" } }; * console.log(countryNameText(japan, "en"), countryNameText(japan, "ja")); * ``` */ export declare function countryNameText(country: { name: { en: string; ja?: string; }; }, lang: "en" | "ja"): string; /** * About how wide and tall a country's name is, in pixels, without reading any layout: a Japanese character as wide as the text is tall, a capital about 0.7 of it, with the letters' spacing. * * @param text - The name. * @param size - The text size in pixels. * @returns The width and height. * * @example * ```ts * import { countryNameBox } from "@johnmorrisdotca/chikyu-earth/realistic"; * * console.log(countryNameBox("JAPAN", 12), countryNameBox("日本", 12)); * ``` */ export declare function countryNameBox(text: string, size: number): { width: number; height: number; }; /** * Lays the names out for one draw. Each country in sight is named at the middle of the largest part of it the view shows (snapped to a point of its own land, so a crescent's name is not out at * sea), the largest on the screen first, its text sized by that part, only where the text fits within it, inside the Earth's disc, and free of the names already placed and of `taken` * (tried at the middle, a line above and below, then at the next points of its land out from the middle). A country on the far side, or too small for its name, is left out: fewer names when the Earth is small, more as it grows. * * @param spots - The countries' points (see {@link countrySpots}). * @param frame - Where the Earth is on the screen. * @param lang - The page's language, `en` or `ja`. * @param options - The most names, the text sizes, the boxes taken and how to measure. * @returns The names to show, the largest first. * * @example * ```ts * import { countrySpots, layoutCountryNames } from "@johnmorrisdotca/chikyu-earth/realistic"; * * const square = { properties: { code: "A", name: "Square", nameJa: "四角" }, geometry: { type: "Polygon", coordinates: [[[-20, -20], [20, -20], [20, 20], [-20, 20], [-20, -20]]] } }; * const frame = { * width: 400, height: 400, radius: 180, disc: { x: 200, y: 200, radius: 180 }, * project: (lon: number, lat: number, out: { x: number; y: number }) => { out.x = 200 + lon * 3; out.y = 200 - lat * 3; return 1; }, * }; * console.log(layoutCountryNames(countrySpots({ features: [square] }), frame, "en", { max: 10, smallest: 10, largest: 16 }).map((one) => one.text)); * ``` */ export declare function layoutCountryNames(spots: CountrySpots, frame: CountryFrame, lang: "en" | "ja", options: CountryLayoutOptions): CountryName[]; /** * The most names `country-names` may ask for at once. * * @example * ```ts * import { COUNTRY_NAMES_MAX } from "@johnmorrisdotca/chikyu-earth/realistic"; * * console.log(COUNTRY_NAMES_MAX); * ``` */ export declare const COUNTRY_NAMES_MAX = 120; /** * How many names a bare `country-names` asks for. * * @example * ```ts * import { COUNTRY_NAMES_DEFAULT } from "@johnmorrisdotca/chikyu-earth/realistic"; * * console.log(COUNTRY_NAMES_DEFAULT); * ``` */ export declare const COUNTRY_NAMES_DEFAULT = 40; /** * Reads the `country-names` attribute: absent (or `off`) is none, bare is 40 names at most, a number is that many at most (1 to 120). * * @param value - The attribute's value, or `null` when it is absent. * @returns How many names at most, or `null` for none. * * @example * ```ts * import { readCountryNames } from "@johnmorrisdotca/chikyu-earth/realistic"; * * console.log(readCountryNames(null), readCountryNames(""), readCountryNames("12"), readCountryNames("500"), readCountryNames("off")); * ``` */ export declare function readCountryNames(value: string | null): number | null; /** * The attributes the country names read: `country-names`. * * @example * ```ts * import { COUNTRY_NAMES_ATTRIBUTES } from "@johnmorrisdotca/chikyu-earth/realistic"; * * console.log(COUNTRY_NAMES_ATTRIBUTES.join(" ")); * ``` */ export declare const COUNTRY_NAMES_ATTRIBUTES: readonly ["country-names"];