import { GeoJsonBbox, GeoJsonLinearRing, GeoJsonMultiPolygon, GeoJsonPoint, GeoJsonPolygon, GeoJsonPosition } from "./GeoJsonSchemas"; export declare const EARTH_RADIUS = 6378137; /** * @description Creates a polygon from a bounding box. * Handles antimeridian-crossing bboxes (where west > east) by splitting into * a MultiPolygon with one polygon per hemisphere. */ export declare const getPolygonFromBbox: (bbox: GeoJsonBbox) => GeoJsonPolygon | GeoJsonMultiPolygon; /** * @description Creates a bounding box from a GeoJSON Polygon or MultiPolygon. * Handles cases where the polygon crosses the 180/-180 meridian. */ export declare const getBboxFromGeoJsonPolygon: (polygon: GeoJsonPolygon | GeoJsonMultiPolygon) => GeoJsonBbox | null; /** * @description Creates a round polygon from a point and a radius. * * - Handles **antimeridian crossing** per RFC 7946 Section 3.1.9 by splitting * into a MultiPolygon. Clamps polar latitudes to [-90, 90]. * * - **Center longitude:** Map inputs may be outside [-180, 180] (e.g. 540°). The center is folded once by * whole 360° turns into that range—same meridian on the ground; only the number used for math changes. * - **Sampling the ring:** Each vertex is `lonCenter + offset` along the loop. Vertices use **continuous** * longitude (no per-point normalization to [-180, 180]) so the planar ring does not self-intersect at the * dateline; each hemisphere is clipped separately. We do not normalize every vertex to [-180, 180] by * itself; that would turn a short step across the dateline into a long wrong chord. The western overflow * piece is repaired so the ±180° seam is a short edge, which allows consumers such as * `mergeAntimeridianFeatures` to merge halves for rendering. * * Returns **null** when the polygon crosses the antimeridian but both hemisphere * intersections yield zero polygons (e.g. very small polygons near the * dateline). In that case, returning the original coordinates would produce * invalid geometry per RFC 7946 Section 3.1.9. */ export declare const getPolygonFromPointAndRadius: (point: GeoJsonPoint, radius: number) => GeoJsonPolygon | GeoJsonMultiPolygon | null; /** * @description Splits a polygon (exterior + holes) at the antimeridian (±180°) * into a two-member MultiPolygon per RFC 7946 Section 3.1.9, preserving * interior rings and pairing east/west hole fragments by stable original order. * If the exterior does not cross the antimeridian, the input is returned unchanged * (including any hole coordinates). * * Interior rings that lie entirely in [-180, 180] are assigned to exactly one * shell using longitude midpoint (see `oneSidedHoleGoesToFirstMultiPolygonMember`). * If splitting the exterior or any crossing hole would produce a fragment with * fewer than four positions (not a valid closed ring), the original polygon is * returned unchanged. */ export declare const splitPolygonWithHolesAtAntimeridian: (polygon: GeoJsonPolygon) => GeoJsonPolygon | GeoJsonMultiPolygon; /** * @description Splits a polygon at the antimeridian (±180° longitude) into a * MultiPolygon per RFC 7946 Section 3.1.9. If the polygon does not cross the * antimeridian, it is returned unchanged. * * Accepts unwrapped longitudes (outside [-180, 180]) as input — for example, * coordinates from a map SDK where the user panned past the antimeridian. * The output is always RFC 7946 compliant (all longitudes in [-180, 180]). * * For use in a future polygon draw mode: the user draws a polygon on the map * with coordinates that may wrap past ±180, and this function produces the * RFC 7946-compliant split representation. * * Delegates to {@link splitPolygonWithHolesAtAntimeridian} (holes are preserved). */ export declare const splitPolygonAtAntimeridian: (polygon: GeoJsonPolygon) => GeoJsonPolygon | GeoJsonMultiPolygon; /** * @description Gets the extreme point of a polygon in a given direction. * @param {object} params - The parameters object * @param {GeoJsonPolygon} params.polygon - The polygon to get the extreme point from * @param {("top" | "right" | "bottom" | "left")} params.direction - The direction to get the extreme point in * @returns {GeoJsonPoint} The extreme point in the given direction */ export declare const getExtremeGeoJsonPointFromPolygon: ({ polygon, direction, }: { polygon: GeoJsonPolygon; direction: "top" | "right" | "bottom" | "left"; }) => GeoJsonPoint | null; /** * Checks if a position is inside a linear ring. On edge is considered inside. */ export declare const isGeoJsonPositionInLinearRing: ({ position, linearRing, }: { position: GeoJsonPosition; linearRing: GeoJsonLinearRing; }) => boolean | null; /** * @description Checks if a point is inside a polygon. * Correctly handles holes per RFC 7946 Section 3.1.6: the first ring is the * exterior boundary, subsequent rings are holes. A point inside a hole is * considered outside the polygon. Validates, then delegates to the pure * `isPointInPolygon`. */ export declare const isGeoJsonPointInPolygon: ({ point, polygon, }: { point: GeoJsonPoint; polygon: GeoJsonPolygon; }) => boolean | null; /** * Checks if polygon1 is fully contained within polygon2. * Correctly handles holes per RFC 7946 Section 3.1.6: a polygon inside * a hole of polygon2 is NOT considered contained. */ export declare const isFullyContainedInGeoJsonPolygon: (polygon1: GeoJsonPolygon, polygon2: GeoJsonPolygon) => boolean | null; /** * @description Gets the intersection between two GeoJSON polygons/multi-polygons. * Returns a MultiPolygon representing the intersection, or null if there is no intersection. * * Delegates to `polygon-clipping`, which can **throw** `"Unable to complete output ring"` * for degenerate or near-self-intersecting geometry that is still schema-valid. Callers must * decide how to handle that: `null` here is reserved for a *provably empty* intersection, so * a thrown failure must not be silently folded into `null` (see SAGA-743). Callers for which * "no overlap" is a safe degradation (e.g. overlap grouping in `@trackunit/react-map`) should * catch and treat the throw as no intersection; callers that turn `null` into "no spatial * filter" (e.g. `mapUtils` viewport/area merges) must instead fall back to a conservative * geometry rather than assume disjointness. */ export declare const getGeoJsonPolygonIntersection: (polygon1: GeoJsonPolygon | GeoJsonMultiPolygon, polygon2: GeoJsonPolygon | GeoJsonMultiPolygon) => GeoJsonMultiPolygon | GeoJsonPolygon | null; /** * Scales a GeoJSON bounding box around its centre by a multiplier. * * `scale=1.0` → unchanged; `scale=2.0` → each dimension doubles; `scale=0.5` → half size. * Latitudes are clamped to `[-90, 90]`, longitudes to `[-180, 180]`. * Handles antimeridian-crossing bboxes (west > east). */ export declare const scaleGeoJsonBbox: (bbox: GeoJsonBbox, scale: number) => GeoJsonBbox; /** * Padding argument for {@link padGeoJsonBbox}. * * - `number` — the same padding (in degrees) applied to all four edges. * - `{ kind: 'axes' }` — separate values for horizontal (east/west) and vertical (north/south). * - `{ kind: 'sides' }` — per-edge values; any omitted edge defaults to `0`. * * Positive values expand the bbox; negative values shrink it. */ export type BboxPadding = number | { readonly kind: "axes"; readonly horizontal: number; readonly vertical: number; } | { readonly kind: "sides"; readonly north?: number; readonly south?: number; readonly east?: number; readonly west?: number; }; /** * Pads a GeoJSON bounding box by absolute degree amounts. * * See {@link BboxPadding} for the three supported forms: uniform, axis-grouped, or per-side. * Latitudes are clamped to `[-90, 90]`, longitudes to `[-180, 180]`. */ export declare const padGeoJsonBbox: (bbox: GeoJsonBbox, padding: BboxPadding) => GeoJsonBbox; /** * Computes the difference of subject minus the union of all clips. * Returns null when the subject is fully covered (zero remaining area). * Returns Polygon for a single-ring result, MultiPolygon otherwise. * When clips is empty the subject is returned unchanged. */ export declare const geoJsonPolygonDifference: (subject: GeoJsonPolygon | GeoJsonMultiPolygon, clips: ReadonlyArray) => GeoJsonPolygon | GeoJsonMultiPolygon | null; /** * Project a `[lng, lat]` position to Web Mercator metres (EPSG:3857). * * Web map renderers (Google Maps, Mapbox, …) draw straight polygon edges in this * projected space, not in planar lng/lat. Boolean geometry operations whose result * must visually align with rendered edges therefore have to run in Web Mercator — * see `unprojectWebMercatorToLngLat` for the inverse. */ export declare const projectLngLatToWebMercator: (position: GeoJsonPosition) => GeoJsonPosition; /** Inverse of `projectLngLatToWebMercator`: Web Mercator metres back to `[lng, lat]`. */ export declare const unprojectWebMercatorToLngLat: (position: GeoJsonPosition) => GeoJsonPosition; /** * Project a polygonal geometry's coordinates to Web Mercator metres, preserving its * ring/part structure. The output is no longer valid lng/lat — feed it to operations * such as `geoJsonPolygonDifference` and unproject the result with * `unprojectPolygonalFromWebMercator`. */ export declare const projectPolygonalToWebMercator: (geometry: GeoJsonPolygon | GeoJsonMultiPolygon) => GeoJsonPolygon | GeoJsonMultiPolygon; /** Inverse of `projectPolygonalToWebMercator`. */ export declare const unprojectPolygonalFromWebMercator: (geometry: GeoJsonPolygon | GeoJsonMultiPolygon) => GeoJsonPolygon | GeoJsonMultiPolygon; /** * Generalisation of isFullyContainedInGeoJsonPolygon to Polygon|MultiPolygon arguments. * Returns true when every outer-ring vertex of geom1 lies inside geom2 (holes respected). * For a MultiPolygon geom2, "inside" means inside any one of its polygon members. * Returns null if either geometry fails validation. Once validated, delegates to * the pure `isFullyContainedInGeometry`. */ export declare const isFullyContainedInGeoJsonGeometry: (geom1: GeoJsonPolygon | GeoJsonMultiPolygon, geom2: GeoJsonPolygon | GeoJsonMultiPolygon) => boolean | null; /** * Returns the minimum distance (in coordinate units) from the given position to the * nearest edge segment of any ring of the polygon/multipolygon, including hole rings. * Returns null if the geometry fails validation. * * Distance is in geographic-coordinate units (degrees), appropriate for relative * Penetration Depth comparisons where only ordering matters, not absolute metric values. */ export declare const distanceToGeoJsonPolygonBoundary: (position: GeoJsonPosition, geometry: GeoJsonPolygon | GeoJsonMultiPolygon) => number | null;