@jarenjs/core 0.9.2 → 0.34.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +229 -26
- package/README.md +64 -10
- package/dist/types/array.d.ts +13 -0
- package/dist/types/cache.d.ts +166 -0
- package/dist/types/chunk.d.ts +102 -0
- package/dist/types/color.d.ts +64 -0
- package/dist/types/convert/convert.d.ts +33 -0
- package/dist/types/convert/currency.d.ts +47 -0
- package/dist/types/convert/index.d.ts +9 -0
- package/dist/types/convert/registry.d.ts +55 -0
- package/dist/types/dates/civil.d.ts +146 -0
- package/dist/types/dates/duration.d.ts +83 -0
- package/dist/types/dates/format.d.ts +59 -0
- package/dist/types/dates/index.d.ts +4 -0
- package/dist/types/{dates.d.ts → dates/rfc3339.d.ts} +57 -3
- package/dist/types/errors.d.ts +77 -0
- package/dist/types/finance/amortization.d.ts +51 -0
- package/dist/types/finance/bond.d.ts +45 -0
- package/dist/types/finance/cashflow.d.ts +44 -0
- package/dist/types/finance/depreciation.d.ts +26 -0
- package/dist/types/finance/index.d.ts +16 -0
- package/dist/types/finance/indicators.d.ts +76 -0
- package/dist/types/finance/interest.d.ts +44 -0
- package/dist/types/finance/returns.d.ts +43 -0
- package/dist/types/finance/tvm.d.ts +50 -0
- package/dist/types/geo/angle.d.ts +4 -0
- package/dist/types/geo/bbox.d.ts +32 -0
- package/dist/types/geo/distance.d.ts +67 -0
- package/dist/types/geo/geohash.d.ts +63 -0
- package/dist/types/geo/geojson.d.ts +108 -0
- package/dist/types/geo/index-tree.d.ts +52 -0
- package/dist/types/geo/index.d.ts +11 -0
- package/dist/types/geo/mercator.d.ts +57 -0
- package/dist/types/geo/predicates.d.ts +44 -0
- package/dist/types/geo/ring.d.ts +80 -0
- package/dist/types/geo/simplify.d.ts +31 -0
- package/dist/types/geo/valid.d.ts +24 -0
- package/dist/types/geo/wkt.d.ts +16 -0
- package/dist/types/math/float64.d.ts +126 -3
- package/dist/types/math/format.d.ts +58 -0
- package/dist/types/math/index.d.ts +5 -0
- package/dist/types/math/mat4.d.ts +60 -0
- package/dist/types/math/project.d.ts +54 -0
- package/dist/types/math/solve.d.ts +67 -0
- package/dist/types/math/word.d.ts +82 -0
- package/dist/types/message.d.ts +52 -0
- package/dist/types/object.d.ts +151 -0
- package/dist/types/scan.d.ts +30 -0
- package/dist/types/schema.d.ts +24 -0
- package/dist/types/string.d.ts +96 -0
- package/dist/types/text/base64.d.ts +6 -4
- package/dist/types/text/email.d.ts +0 -1
- package/dist/types/text/host.d.ts +39 -8
- package/dist/types/text/i18n.d.ts +13 -1
- package/dist/types/text/index.d.ts +1 -0
- package/dist/types/text/misc.d.ts +15 -1
- package/dist/types/text/punycode.d.ts +45 -85
- package/docs/CONVERT.md +45 -0
- package/docs/DATES.md +78 -0
- package/docs/FINANCE.md +59 -0
- package/docs/GEO.md +114 -0
- package/docs/MATH.md +75 -0
- package/package.json +57 -4
- package/src/array.js +16 -0
- package/src/cache.js +206 -0
- package/src/chunk.js +159 -0
- package/src/color.js +125 -0
- package/src/convert/convert.js +59 -0
- package/src/convert/currency.js +74 -0
- package/src/convert/index.js +11 -0
- package/src/convert/registry.js +213 -0
- package/src/dates/civil.js +360 -0
- package/src/dates/duration.js +225 -0
- package/src/dates/format.js +238 -0
- package/src/dates/index.js +30 -0
- package/src/dates/rfc3339.js +621 -0
- package/src/errors.js +102 -0
- package/src/finance/amortization.js +50 -0
- package/src/finance/bond.js +100 -0
- package/src/finance/cashflow.js +122 -0
- package/src/finance/depreciation.js +54 -0
- package/src/finance/index.js +27 -0
- package/src/finance/indicators.js +207 -0
- package/src/finance/interest.js +63 -0
- package/src/finance/returns.js +90 -0
- package/src/finance/tvm.js +94 -0
- package/src/function.js +0 -2
- package/src/geo/angle.js +12 -0
- package/src/geo/bbox.js +80 -0
- package/src/geo/distance.js +155 -0
- package/src/geo/geohash.js +224 -0
- package/src/geo/geojson.js +361 -0
- package/src/geo/index-tree.js +294 -0
- package/src/geo/index.js +52 -0
- package/src/geo/mercator.js +124 -0
- package/src/geo/predicates.js +313 -0
- package/src/geo/ring.js +182 -0
- package/src/geo/simplify.js +130 -0
- package/src/geo/valid.js +142 -0
- package/src/geo/wkt.js +262 -0
- package/src/math/float64.js +228 -11
- package/src/math/format.js +157 -0
- package/src/math/index.js +5 -0
- package/src/math/mat4.js +131 -0
- package/src/math/project.js +49 -0
- package/src/math/solve.js +112 -0
- package/src/math/word.js +177 -0
- package/src/message.js +119 -0
- package/src/object.js +329 -0
- package/src/scan.js +42 -0
- package/src/schema.js +37 -0
- package/src/string.js +189 -0
- package/src/text/base64.js +15 -52
- package/src/text/email.js +0 -5
- package/src/text/host.js +515 -140
- package/src/text/i18n.js +13 -6
- package/src/text/identifiers.js +1 -1
- package/src/text/index.js +1 -0
- package/src/text/misc.js +81 -5
- package/src/text/punycode.js +235 -323
- package/src/dates.js +0 -371
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Time Value of Money. The five TVM quantities — N,
|
|
3
|
+
* I/Y, PV, PMT, FV — obey one identity; each function here solves for its
|
|
4
|
+
* own variable. Sign convention follows the standard cash-flow model
|
|
5
|
+
* (money in is positive, money out negative), matching Excel/HP-12C:
|
|
6
|
+
*
|
|
7
|
+
* PV·(1+i)^n + PMT·(1 + i·type)·((1+i)^n − 1)/i + FV = 0
|
|
8
|
+
*
|
|
9
|
+
* `type` is 0 for an ordinary annuity (payment at period end) or 1 for an
|
|
10
|
+
* annuity-due (payment at period begin). Rates are per period; a caller
|
|
11
|
+
* with an annual rate and monthly periods passes `rate/12`.
|
|
12
|
+
*
|
|
13
|
+
* Pure and zero-dep except `math/solve` for the iterative `rate`.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Future value.
|
|
17
|
+
* @param {number} rate @param {number} nper @param {number} pmt
|
|
18
|
+
* @param {number} [pv] @param {number} [type]
|
|
19
|
+
* @returns {number}
|
|
20
|
+
*/
|
|
21
|
+
export declare function fv(rate: number, nper: number, pmt: number, pv?: number, type?: number): number;
|
|
22
|
+
/**
|
|
23
|
+
* Present value.
|
|
24
|
+
* @param {number} rate @param {number} nper @param {number} pmt
|
|
25
|
+
* @param {number} [fval] @param {number} [type]
|
|
26
|
+
* @returns {number}
|
|
27
|
+
*/
|
|
28
|
+
export declare function pv(rate: number, nper: number, pmt: number, fval?: number, type?: number): number;
|
|
29
|
+
/**
|
|
30
|
+
* Payment per period.
|
|
31
|
+
* @param {number} rate @param {number} nper @param {number} pval
|
|
32
|
+
* @param {number} [fval] @param {number} [type]
|
|
33
|
+
* @returns {number}
|
|
34
|
+
*/
|
|
35
|
+
export declare function pmt(rate: number, nper: number, pval: number, fval?: number, type?: number): number;
|
|
36
|
+
/**
|
|
37
|
+
* Number of periods.
|
|
38
|
+
* @param {number} rate @param {number} pmtv @param {number} pval
|
|
39
|
+
* @param {number} [fval] @param {number} [type]
|
|
40
|
+
* @returns {number}
|
|
41
|
+
*/
|
|
42
|
+
export declare function nper(rate: number, pmtv: number, pval: number, fval?: number, type?: number): number;
|
|
43
|
+
/**
|
|
44
|
+
* Periodic interest rate, solved iteratively (Newton, bisection
|
|
45
|
+
* fallback). Returns `NaN` if no rate is found.
|
|
46
|
+
* @param {number} nperv @param {number} pmtv @param {number} pval
|
|
47
|
+
* @param {number} [fval] @param {number} [type] @param {number} [guess]
|
|
48
|
+
* @returns {number}
|
|
49
|
+
*/
|
|
50
|
+
export declare function rate(nperv: number, pmtv: number, pval: number, fval?: number, type?: number, guess?: number): number;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The bounding box of a list of positions, as `[west, south, east, north]`.
|
|
3
|
+
* Returns null for an empty list — there is no box that bounds nothing,
|
|
4
|
+
* and an all-Infinity placeholder would silently intersect everything.
|
|
5
|
+
* @param {Array<number[]>} positions
|
|
6
|
+
* @returns {number[] | null}
|
|
7
|
+
*/
|
|
8
|
+
export declare function bboxOfPositions(positions: Array<number[]>): number[] | null;
|
|
9
|
+
/**
|
|
10
|
+
* Whether two bounding boxes share any area. Boxes that merely touch
|
|
11
|
+
* along an edge count as intersecting, matching `pointInRing`'s
|
|
12
|
+
* treatment of a boundary as inside.
|
|
13
|
+
* @param {number[]} a - [west, south, east, north]
|
|
14
|
+
* @param {number[]} b
|
|
15
|
+
* @returns {boolean}
|
|
16
|
+
*/
|
|
17
|
+
export declare function bboxIntersects(a: number[], b: number[]): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Whether a bounding box contains a position (edges included).
|
|
20
|
+
* @param {number[]} box - [west, south, east, north]
|
|
21
|
+
* @param {number} x - longitude
|
|
22
|
+
* @param {number} y - latitude
|
|
23
|
+
* @returns {boolean}
|
|
24
|
+
*/
|
|
25
|
+
export declare function bboxContains(box: number[], x: number, y: number): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* The smallest box containing both inputs.
|
|
28
|
+
* @param {number[]} a
|
|
29
|
+
* @param {number[]} b
|
|
30
|
+
* @returns {number[]}
|
|
31
|
+
*/
|
|
32
|
+
export declare function bboxUnion(a: number[], b: number[]): number[];
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/** IUGG mean Earth radius in metres — the sphere GeoJSON distances use. */
|
|
2
|
+
export declare const EARTH_RADIUS = 6371008.8;
|
|
3
|
+
/**
|
|
4
|
+
* Great-circle distance between two positions, in metres.
|
|
5
|
+
*
|
|
6
|
+
* @param {number} lon1 - longitude of the first position, degrees
|
|
7
|
+
* @param {number} lat1 - latitude of the first position, degrees
|
|
8
|
+
* @param {number} lon2 - longitude of the second position, degrees
|
|
9
|
+
* @param {number} lat2 - latitude of the second position, degrees
|
|
10
|
+
* @param {number} [radius] - sphere radius, to answer in other units
|
|
11
|
+
* @returns {number} distance in metres (or in `radius`'s unit)
|
|
12
|
+
* @example
|
|
13
|
+
* haversineDistance(4.9041, 52.3676, 2.3522, 48.8566); // 429_862 (Amsterdam-Paris)
|
|
14
|
+
*/
|
|
15
|
+
export declare function haversineDistance(lon1: number, lat1: number, lon2: number, lat2: number, radius?: number): number;
|
|
16
|
+
/**
|
|
17
|
+
* Equirectangular approximation of the distance between two positions,
|
|
18
|
+
* in metres — the **screening** form.
|
|
19
|
+
*
|
|
20
|
+
* Accurate to about 0.02% over a few hundred kilometres and roughly 12%
|
|
21
|
+
* across a hemisphere, for about a seventh of the cost. Use it to reject
|
|
22
|
+
* candidates that cannot be within a radius, then confirm the survivors
|
|
23
|
+
* with `haversineDistance`; do not report it as a measurement.
|
|
24
|
+
*
|
|
25
|
+
* @param {number} lon1
|
|
26
|
+
* @param {number} lat1
|
|
27
|
+
* @param {number} lon2
|
|
28
|
+
* @param {number} lat2
|
|
29
|
+
* @param {number} [radius]
|
|
30
|
+
* @returns {number} approximate distance
|
|
31
|
+
*/
|
|
32
|
+
export declare function equirectDistance(lon1: number, lat1: number, lon2: number, lat2: number, radius?: number): number;
|
|
33
|
+
/**
|
|
34
|
+
* Initial bearing from one position to another: degrees clockwise from
|
|
35
|
+
* true north, in `[0, 360)`.
|
|
36
|
+
*
|
|
37
|
+
* This is the bearing at the *start* of the great circle, and it changes
|
|
38
|
+
* along the path — a course of constant bearing is a rhumb line, which
|
|
39
|
+
* is a different curve.
|
|
40
|
+
*
|
|
41
|
+
* @param {number} lon1
|
|
42
|
+
* @param {number} lat1
|
|
43
|
+
* @param {number} lon2
|
|
44
|
+
* @param {number} lat2
|
|
45
|
+
* @returns {number} degrees in [0, 360)
|
|
46
|
+
*/
|
|
47
|
+
export declare function initialBearing(lon1: number, lat1: number, lon2: number, lat2: number): number;
|
|
48
|
+
/**
|
|
49
|
+
* The position reached by travelling `distance` metres from a position
|
|
50
|
+
* along a constant initial bearing (a great-circle course).
|
|
51
|
+
*
|
|
52
|
+
* @param {number} lon - starting longitude, degrees
|
|
53
|
+
* @param {number} lat - starting latitude, degrees
|
|
54
|
+
* @param {number} bearing - degrees clockwise from true north
|
|
55
|
+
* @param {number} distance - metres
|
|
56
|
+
* @param {number} [radius]
|
|
57
|
+
* @returns {[number, number]} the destination as a GeoJSON position
|
|
58
|
+
*/
|
|
59
|
+
export declare function destinationPoint(lon: number, lat: number, bearing: number, distance: number, radius?: number): [number, number];
|
|
60
|
+
/**
|
|
61
|
+
* Total great-circle length of a line of positions, in metres. An empty
|
|
62
|
+
* or single-position line has length 0.
|
|
63
|
+
* @param {Array<number[]>} positions - GeoJSON positions
|
|
64
|
+
* @param {number} [radius]
|
|
65
|
+
* @returns {number}
|
|
66
|
+
*/
|
|
67
|
+
export declare function lineLength(positions: Array<number[]>, radius?: number): number;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encode a position as a geohash string.
|
|
3
|
+
*
|
|
4
|
+
* @param {number} lon - longitude, degrees
|
|
5
|
+
* @param {number} lat - latitude, degrees
|
|
6
|
+
* @param {number} [precision] - characters, 1-12 (default 9, about 5 m)
|
|
7
|
+
* @returns {string}
|
|
8
|
+
* @example
|
|
9
|
+
* geohashEncode(4.9041, 52.3676, 5); // 'u173z' (Amsterdam)
|
|
10
|
+
*/
|
|
11
|
+
export declare function geohashEncode(lon: number, lat: number, precision?: number): string;
|
|
12
|
+
/**
|
|
13
|
+
* Whether a string is a well-formed geohash: non-empty and every
|
|
14
|
+
* character in the base-32 alphabet (lowercase; `a`, `i`, `l` and `o`
|
|
15
|
+
* are deliberately absent from it). Any length is valid — each
|
|
16
|
+
* character only names a finer cell.
|
|
17
|
+
* @param {string} hash
|
|
18
|
+
* @returns {boolean}
|
|
19
|
+
* @example
|
|
20
|
+
* isValidGeohash('u173z'); // true (Amsterdam)
|
|
21
|
+
* isValidGeohash('u17a'); // false ('a' is not in the alphabet)
|
|
22
|
+
*/
|
|
23
|
+
export declare function isValidGeohash(hash: string): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* The bounding box of a geohash cell, as `[west, south, east, north]`.
|
|
26
|
+
* Returns null for a string containing a character outside the base-32
|
|
27
|
+
* alphabet (`a`, `i`, `l` and `o` are deliberately absent).
|
|
28
|
+
* @param {string} hash
|
|
29
|
+
* @returns {number[] | null}
|
|
30
|
+
*/
|
|
31
|
+
export declare function geohashBounds(hash: string): number[] | null;
|
|
32
|
+
/**
|
|
33
|
+
* The centre of a geohash cell, as a GeoJSON position. Null for an
|
|
34
|
+
* invalid hash.
|
|
35
|
+
*
|
|
36
|
+
* Decoding is lossy by construction — a hash names a cell, not a point —
|
|
37
|
+
* so this is the cell's centre and the error is bounded by
|
|
38
|
+
* {@link geohashCellSize}.
|
|
39
|
+
*
|
|
40
|
+
* @param {string} hash
|
|
41
|
+
* @returns {[number, number] | null}
|
|
42
|
+
*/
|
|
43
|
+
export declare function geohashDecode(hash: string): [number, number] | null;
|
|
44
|
+
/**
|
|
45
|
+
* Approximate cell size at a precision, as `[lonWidth, latHeight]` in
|
|
46
|
+
* degrees. Null outside 1-12.
|
|
47
|
+
* @param {number} precision
|
|
48
|
+
* @returns {number[] | null}
|
|
49
|
+
*/
|
|
50
|
+
export declare function geohashCellSize(precision: number): number[] | null;
|
|
51
|
+
/**
|
|
52
|
+
* The eight geohash cells surrounding one, plus the cell itself, as a
|
|
53
|
+
* nine-element array. Cells that would fall off the poles are omitted,
|
|
54
|
+
* so the result may be shorter.
|
|
55
|
+
*
|
|
56
|
+
* This is what makes a prefix search safe near a boundary: two points
|
|
57
|
+
* metres apart can sit in different cells, so a proximity query tests
|
|
58
|
+
* the neighbourhood rather than the single cell.
|
|
59
|
+
*
|
|
60
|
+
* @param {string} hash
|
|
61
|
+
* @returns {string[]}
|
|
62
|
+
*/
|
|
63
|
+
export declare function geohashNeighbours(hash: string): string[];
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a value looks like a bare position: an array of at least two
|
|
3
|
+
* finite numbers.
|
|
4
|
+
* @param {any} value
|
|
5
|
+
* @returns {boolean}
|
|
6
|
+
*/
|
|
7
|
+
export declare function isPosition(value: any): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* The geometry inside a value: the value itself when it is already one,
|
|
10
|
+
* a Feature's `geometry`, or null when there is none (including a
|
|
11
|
+
* Feature whose geometry is legitimately null).
|
|
12
|
+
*
|
|
13
|
+
* A FeatureCollection has no single geometry and yields null — use
|
|
14
|
+
* {@link eachPosition} or {@link bboxOf}, which handle collections.
|
|
15
|
+
*
|
|
16
|
+
* @param {any} value
|
|
17
|
+
* @returns {object | null}
|
|
18
|
+
*/
|
|
19
|
+
export declare function geometryOf(value: any): object | null;
|
|
20
|
+
/**
|
|
21
|
+
* Call `visit(position)` for every position in a GeoJSON value, in
|
|
22
|
+
* document order. Accepts a bare position, a geometry, a Feature, a
|
|
23
|
+
* FeatureCollection or a GeometryCollection.
|
|
24
|
+
* @param {any} value
|
|
25
|
+
* @param {(position: number[]) => void} visit
|
|
26
|
+
*/
|
|
27
|
+
export declare function eachPosition(value: any, visit: (position: number[]) => void): void;
|
|
28
|
+
/**
|
|
29
|
+
* The bounding box of any GeoJSON value, as `[west, south, east, north]`.
|
|
30
|
+
* Null when the value contains no positions.
|
|
31
|
+
*
|
|
32
|
+
* A `bbox` member already present on the value is ignored: it is an
|
|
33
|
+
* optimization the producer may have got wrong, and recomputing is the
|
|
34
|
+
* only way to be sure.
|
|
35
|
+
*
|
|
36
|
+
* @param {any} value
|
|
37
|
+
* @returns {number[] | null}
|
|
38
|
+
*/
|
|
39
|
+
export declare function bboxOf(value: any): number[] | null;
|
|
40
|
+
/**
|
|
41
|
+
* Every position of a GeoJSON value, flattened into one array.
|
|
42
|
+
* @param {any} value
|
|
43
|
+
* @returns {Array<number[]>}
|
|
44
|
+
*/
|
|
45
|
+
export declare function positionsOf(value: any): Array<number[]>;
|
|
46
|
+
/**
|
|
47
|
+
* Geodesic area of a value in square metres: the sum over its polygons
|
|
48
|
+
* of the exterior ring's area less its holes'. Anything with no surface
|
|
49
|
+
* — a point, a line — has area 0 rather than being an error.
|
|
50
|
+
* @param {any} value
|
|
51
|
+
* @param {number} [radius]
|
|
52
|
+
* @returns {number}
|
|
53
|
+
*/
|
|
54
|
+
export declare function geometryArea(value: any, radius?: number): number;
|
|
55
|
+
/**
|
|
56
|
+
* Great-circle length of a value in metres: the sum of its line
|
|
57
|
+
* lengths, and of its polygon ring perimeters. A point has length 0.
|
|
58
|
+
* @param {any} value
|
|
59
|
+
* @param {number} [radius]
|
|
60
|
+
* @returns {number}
|
|
61
|
+
*/
|
|
62
|
+
export declare function geometryLength(value: any, radius?: number): number;
|
|
63
|
+
/**
|
|
64
|
+
* The centroid of a value's positions, as a GeoJSON position. Null when
|
|
65
|
+
* there are none.
|
|
66
|
+
*
|
|
67
|
+
* This is the mean of the vertices, NOT the area-weighted centre of
|
|
68
|
+
* mass: it is the cheap answer, it always lies in the convex hull, and
|
|
69
|
+
* for a concave shape it can fall outside the polygon. Labelling and
|
|
70
|
+
* clustering want this; a physics centre of mass does not.
|
|
71
|
+
*
|
|
72
|
+
* @param {any} value
|
|
73
|
+
* @returns {[number, number] | null}
|
|
74
|
+
*/
|
|
75
|
+
export declare function centroidOf(value: any): [number, number] | null;
|
|
76
|
+
/**
|
|
77
|
+
* Whether a position lies inside a value's surface. Only polygons have
|
|
78
|
+
* an inside, so a point or a line always answers false.
|
|
79
|
+
* @param {any} value - a Polygon, MultiPolygon, Feature or collection
|
|
80
|
+
* @param {number} lon
|
|
81
|
+
* @param {number} lat
|
|
82
|
+
* @returns {boolean}
|
|
83
|
+
*/
|
|
84
|
+
export declare function containsPosition(value: any, lon: number, lat: number): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* The distance in metres between two GeoJSON values, measured between
|
|
87
|
+
* their **representative positions**: a bare position or Point is
|
|
88
|
+
* itself, anything else is its centroid. Null when either side has no
|
|
89
|
+
* positions.
|
|
90
|
+
*
|
|
91
|
+
* This is deliberately not the minimum distance between two shapes,
|
|
92
|
+
* which needs point-to-segment geodesics and is a different (and much
|
|
93
|
+
* larger) piece of work. Callers wanting "how far is this point from
|
|
94
|
+
* that region" should test containment first.
|
|
95
|
+
*
|
|
96
|
+
* @param {any} a
|
|
97
|
+
* @param {any} b
|
|
98
|
+
* @param {number} [radius]
|
|
99
|
+
* @returns {number | null}
|
|
100
|
+
*/
|
|
101
|
+
export declare function geoDistance(a: any, b: any, radius?: number): number | null;
|
|
102
|
+
/**
|
|
103
|
+
* Whether every linear ring of a value is closed — the invariant the
|
|
104
|
+
* portable GeoJSON schema cannot express. True for values with no rings.
|
|
105
|
+
* @param {any} value
|
|
106
|
+
* @returns {boolean}
|
|
107
|
+
*/
|
|
108
|
+
export declare function ringsClosed(value: any): boolean;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interleave the low 16 bits of x and y into a Hilbert distance.
|
|
3
|
+
* Boxes ordered by this stay spatially clustered, which is what makes
|
|
4
|
+
* the packed parents tight.
|
|
5
|
+
*
|
|
6
|
+
* Bit-parallel: all sixteen levels of the per-bit quadrant rotation run
|
|
7
|
+
* at once as mask arithmetic (the public-domain transform from
|
|
8
|
+
* rawrunprotected/hilbert_curves), which is what makes computing 100k of
|
|
9
|
+
* these a millisecond instead of the build's dominant cost. The values
|
|
10
|
+
* are identical to the classical per-bit walk of the curve.
|
|
11
|
+
*
|
|
12
|
+
* @param {number} x - 0..65535
|
|
13
|
+
* @param {number} y - 0..65535
|
|
14
|
+
* @returns {number}
|
|
15
|
+
*/
|
|
16
|
+
export declare function hilbertDistance(x: number, y: number): number;
|
|
17
|
+
export type BboxIndex = {
|
|
18
|
+
/**
|
|
19
|
+
* - how many boxes were indexed
|
|
20
|
+
*/
|
|
21
|
+
size: number;
|
|
22
|
+
/**
|
|
23
|
+
* the indexes of every box whose bounds overlap the query box
|
|
24
|
+
*/
|
|
25
|
+
search: (minX: number, minY: number, maxX: number, maxY: number) => number[];
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* A queryable static index over bounding boxes.
|
|
29
|
+
* @typedef {Object} BboxIndex
|
|
30
|
+
* @property {number} size - how many boxes were indexed
|
|
31
|
+
* @property {(minX: number, minY: number, maxX: number, maxY: number) => number[]} search
|
|
32
|
+
* the indexes of every box whose bounds overlap the query box
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* Build a static index over `[west, south, east, north]` boxes.
|
|
36
|
+
*
|
|
37
|
+
* The returned `search` yields **candidate** indexes into the original
|
|
38
|
+
* array: every box that truly overlaps is included, and boxes that merely
|
|
39
|
+
* share a tree node may be too. Confirm each with the exact test.
|
|
40
|
+
*
|
|
41
|
+
* A null entry (a value with no positions, so no box) is indexed as a
|
|
42
|
+
* degenerate box that overlaps nothing, so it can never be a candidate
|
|
43
|
+
* while the array indexes stay aligned with the caller's data.
|
|
44
|
+
*
|
|
45
|
+
* @param {Array<number[] | null>} boxes
|
|
46
|
+
* @param {number} [nodeSize] - children per node
|
|
47
|
+
* @returns {BboxIndex}
|
|
48
|
+
* @example
|
|
49
|
+
* const index = createBboxIndex(regions.map(bboxOf));
|
|
50
|
+
* for (const i of index.search(...bboxOf(point))) confirm(regions[i]);
|
|
51
|
+
*/
|
|
52
|
+
export declare function createBboxIndex(boxes: Array<number[] | null>, nodeSize?: number): BboxIndex;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './predicates.js';
|
|
2
|
+
export * from './distance.js';
|
|
3
|
+
export * from './ring.js';
|
|
4
|
+
export * from './bbox.js';
|
|
5
|
+
export * from './geohash.js';
|
|
6
|
+
export * from './geojson.js';
|
|
7
|
+
export * from './valid.js';
|
|
8
|
+
export * from './wkt.js';
|
|
9
|
+
export * from './index-tree.js';
|
|
10
|
+
export * from './mercator.js';
|
|
11
|
+
export * from './simplify.js';
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The latitude where Web Mercator's y reaches the edge of its square.
|
|
3
|
+
* Poleward of this the projection is unbounded.
|
|
4
|
+
*/
|
|
5
|
+
export declare const MERCATOR_MAX_LAT = 85.05112877980659;
|
|
6
|
+
/**
|
|
7
|
+
* Project a position into the Web Mercator unit square: x and y both in
|
|
8
|
+
* `[0, 1]`, with **y increasing southward** so the result is already in
|
|
9
|
+
* screen order and a renderer needs no flip.
|
|
10
|
+
*
|
|
11
|
+
* Latitude is clamped, longitude is not: a latitude past the Mercator
|
|
12
|
+
* limit has a defensible answer (the edge) while a longitude past ±180
|
|
13
|
+
* is simply invalid under RFC 7946, and folding it silently into range
|
|
14
|
+
* would move a shape to the wrong side of the world rather than let the
|
|
15
|
+
* defect show.
|
|
16
|
+
*
|
|
17
|
+
* @param {number} lon - longitude in degrees, `[-180, 180]`
|
|
18
|
+
* @param {number} lat - latitude in degrees, clamped to ±85.051129
|
|
19
|
+
* @returns {[number, number]} `[x, y]` in the unit square
|
|
20
|
+
* @example
|
|
21
|
+
* projectMercator(0, 0); // [0.5, 0.5] — null island is the centre
|
|
22
|
+
* projectMercator(-180, 85.05112877980659); // [0, 0] — the north-west corner
|
|
23
|
+
*/
|
|
24
|
+
export declare function projectMercator(lon: number, lat: number): [number, number];
|
|
25
|
+
/**
|
|
26
|
+
* The inverse of {@link projectMercator}: a unit-square point back to a
|
|
27
|
+
* position. Needed to turn a click or a viewport corner back into
|
|
28
|
+
* longitude and latitude.
|
|
29
|
+
*
|
|
30
|
+
* @param {number} x - 0..1
|
|
31
|
+
* @param {number} y - 0..1, increasing southward
|
|
32
|
+
* @returns {[number, number]} `[longitude, latitude]` in degrees
|
|
33
|
+
*/
|
|
34
|
+
export declare function unprojectMercator(x: number, y: number): [number, number];
|
|
35
|
+
/**
|
|
36
|
+
* A projection fitted to a geographic bounding box: the transform that
|
|
37
|
+
* maps positions inside `bbox` into `[0, 1]` on both axes, **without
|
|
38
|
+
* distorting the aspect ratio**, centring whichever axis has room left
|
|
39
|
+
* over.
|
|
40
|
+
*
|
|
41
|
+
* Stretching a map to fill its frame is the single most common way to
|
|
42
|
+
* make one look wrong, so the fit is uniform by construction and the
|
|
43
|
+
* spare room becomes margin rather than distortion. `aspect` is the
|
|
44
|
+
* width:height ratio of the frame the result will be drawn into: the fit
|
|
45
|
+
* happens in a box `aspect` wide and 1 tall, then x is divided back down
|
|
46
|
+
* so both outputs are in `[0, 1]` — the same unit-square convention the
|
|
47
|
+
* treemap uses, where the renderer maps height from width by the same
|
|
48
|
+
* ratio.
|
|
49
|
+
*
|
|
50
|
+
* @param {number[]} bbox - `[west, south, east, north]`
|
|
51
|
+
* @param {number} [aspect] - frame width:height (default 1, a square)
|
|
52
|
+
* @returns {(lon: number, lat: number) => [number, number]}
|
|
53
|
+
* @example
|
|
54
|
+
* const fit = fitMercator([4, 52, 5, 53], 1.6);
|
|
55
|
+
* fit(4.5, 52.5); // near [0.5, 0.5] whatever the box's shape
|
|
56
|
+
*/
|
|
57
|
+
export declare function fitMercator(bbox: number[], aspect?: number): (lon: number, lat: number) => [number, number];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The orientation of the triple (a, b, c): **positive** when c lies to
|
|
3
|
+
* the left of the directed line a->b (counter-clockwise), **negative**
|
|
4
|
+
* when it lies to the right, and **exactly zero** when the three points
|
|
5
|
+
* are collinear.
|
|
6
|
+
*
|
|
7
|
+
* The sign is always correct. The magnitude is twice the signed area of
|
|
8
|
+
* the triangle, but only approximately — callers must use this for its
|
|
9
|
+
* sign, and `ringArea` for a measurement.
|
|
10
|
+
*
|
|
11
|
+
* Coordinates are raw numbers rather than vector objects so a GeoJSON
|
|
12
|
+
* position (`[lon, lat]`) can be passed straight through.
|
|
13
|
+
*
|
|
14
|
+
* @param {number} ax
|
|
15
|
+
* @param {number} ay
|
|
16
|
+
* @param {number} bx
|
|
17
|
+
* @param {number} by
|
|
18
|
+
* @param {number} cx
|
|
19
|
+
* @param {number} cy
|
|
20
|
+
* @returns {number} positive, negative, or zero
|
|
21
|
+
* @example
|
|
22
|
+
* orient2d(0, 0, 1, 0, 0, 1); // > 0 — (0,1) is left of the x axis
|
|
23
|
+
* orient2d(0, 0, 1, 0, 0, -1); // < 0
|
|
24
|
+
* orient2d(0, 0, 2, 2, 1, 1); // 0 — exactly collinear
|
|
25
|
+
*/
|
|
26
|
+
export declare function orient2d(ax: number, ay: number, bx: number, by: number, cx: number, cy: number): number;
|
|
27
|
+
/**
|
|
28
|
+
* The same determinant without the exact fallback: fast, and **wrong on
|
|
29
|
+
* near-collinear input**.
|
|
30
|
+
*
|
|
31
|
+
* This exists for the one case where that is acceptable — a bounding
|
|
32
|
+
* pre-filter whose answer is checked by `orient2d` afterwards. Anything
|
|
33
|
+
* that decides containment, winding or intersection must use `orient2d`;
|
|
34
|
+
* a wrong sign there is a wrong answer, not a rounding error.
|
|
35
|
+
*
|
|
36
|
+
* @param {number} ax
|
|
37
|
+
* @param {number} ay
|
|
38
|
+
* @param {number} bx
|
|
39
|
+
* @param {number} by
|
|
40
|
+
* @param {number} cx
|
|
41
|
+
* @param {number} cy
|
|
42
|
+
* @returns {number}
|
|
43
|
+
*/
|
|
44
|
+
export declare function orient2dFast(ax: number, ay: number, bx: number, by: number, cx: number, cy: number): number;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a ring is closed: its last position repeats its first.
|
|
3
|
+
*
|
|
4
|
+
* Compares longitude and latitude only. A position may legally carry a
|
|
5
|
+
* third element (altitude), and RFC 7946 does not require it to match
|
|
6
|
+
* for the ring to close.
|
|
7
|
+
*
|
|
8
|
+
* @param {Array<number[]>} ring - positions
|
|
9
|
+
* @returns {boolean}
|
|
10
|
+
* @example
|
|
11
|
+
* isRingClosed([[0,0],[1,0],[1,1],[0,0]]); // true
|
|
12
|
+
* isRingClosed([[0,0],[1,0],[1,1]]); // false
|
|
13
|
+
*/
|
|
14
|
+
export declare function isRingClosed(ring: Array<number[]>): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Twice the signed planar area of a ring (the shoelace sum), in squared
|
|
17
|
+
* degrees. **Positive is counter-clockwise.**
|
|
18
|
+
*
|
|
19
|
+
* The sign is the useful part and is exact for the purpose: it is a sum
|
|
20
|
+
* of `orient2d` determinants about the ring's first vertex, so a ring
|
|
21
|
+
* whose vertices are near-collinear still winds the way this says. The
|
|
22
|
+
* magnitude is a planar quantity in degree-space and is NOT an area on
|
|
23
|
+
* the Earth — use `sphericalRingArea` for that.
|
|
24
|
+
*
|
|
25
|
+
* @param {Array<number[]>} ring - positions
|
|
26
|
+
* @returns {number} twice the signed area; positive = counter-clockwise
|
|
27
|
+
*/
|
|
28
|
+
export declare function ringSignedArea(ring: Array<number[]>): number;
|
|
29
|
+
/**
|
|
30
|
+
* The winding direction of a ring: `1` counter-clockwise, `-1`
|
|
31
|
+
* clockwise, `0` degenerate (zero area).
|
|
32
|
+
*
|
|
33
|
+
* RFC 7946 section 3.1.6 requires exterior rings to be counter-clockwise
|
|
34
|
+
* and holes clockwise — the right-hand rule. Parsers are told to accept
|
|
35
|
+
* non-conforming data, so this reports rather than rejects.
|
|
36
|
+
*
|
|
37
|
+
* @param {Array<number[]>} ring - positions
|
|
38
|
+
* @returns {number} 1, -1 or 0
|
|
39
|
+
*/
|
|
40
|
+
export declare function ringWinding(ring: Array<number[]>): number;
|
|
41
|
+
/**
|
|
42
|
+
* Geodesic area of a ring on the sphere, in square metres, always
|
|
43
|
+
* non-negative.
|
|
44
|
+
*
|
|
45
|
+
* Uses the spherical excess of the polygon (the standard formula for a
|
|
46
|
+
* ring of great-circle edges), so unlike `ringSignedArea` this is a real
|
|
47
|
+
* measurement. Accurate to the sphere approximation — under half a
|
|
48
|
+
* percent, the same bound as `haversineDistance`.
|
|
49
|
+
*
|
|
50
|
+
* @param {Array<number[]>} ring - positions
|
|
51
|
+
* @param {number} [radius]
|
|
52
|
+
* @returns {number} square metres
|
|
53
|
+
*/
|
|
54
|
+
export declare function sphericalRingArea(ring: Array<number[]>, radius?: number): number;
|
|
55
|
+
/**
|
|
56
|
+
* Whether a position lies inside a ring, by the even-odd (crossing)
|
|
57
|
+
* rule. A position exactly on an edge or vertex counts as **inside**,
|
|
58
|
+
* which is the convention that makes adjacent polygons tile without
|
|
59
|
+
* gaps.
|
|
60
|
+
*
|
|
61
|
+
* The ray cast runs in the ring's own coordinate space, so this is a
|
|
62
|
+
* planar test on longitude/latitude. That is what GeoJSON consumers
|
|
63
|
+
* mean by containment, and it is correct for any ring that does not
|
|
64
|
+
* cross the antimeridian — which RFC 7946 tells producers to cut.
|
|
65
|
+
*
|
|
66
|
+
* @param {number} x - longitude
|
|
67
|
+
* @param {number} y - latitude
|
|
68
|
+
* @param {Array<number[]>} ring - positions
|
|
69
|
+
* @returns {boolean}
|
|
70
|
+
*/
|
|
71
|
+
export declare function pointInRing(x: number, y: number, ring: Array<number[]>): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Whether a position lies inside a polygon: inside its exterior ring and
|
|
74
|
+
* outside every hole.
|
|
75
|
+
* @param {number} x - longitude
|
|
76
|
+
* @param {number} y - latitude
|
|
77
|
+
* @param {Array<Array<number[]>>} rings - a GeoJSON Polygon's coordinates
|
|
78
|
+
* @returns {boolean}
|
|
79
|
+
*/
|
|
80
|
+
export declare function pointInPolygon(x: number, y: number, rings: Array<Array<number[]>>): boolean;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simplify a line with the Douglas-Peucker algorithm, keeping every
|
|
3
|
+
* vertex further than `tolerance` from the line its neighbours describe.
|
|
4
|
+
*
|
|
5
|
+
* The first and last positions always survive, so a **ring stays closed**
|
|
6
|
+
* — simplification can never turn a valid polygon into an invalid one.
|
|
7
|
+
* Positions are returned by reference, not copied, so any third element
|
|
8
|
+
* (altitude) rides along untouched.
|
|
9
|
+
*
|
|
10
|
+
* @param {Array<number[]>} line - positions
|
|
11
|
+
* @param {number} tolerance - in the input's own coordinate units
|
|
12
|
+
* @returns {Array<number[]>} a new array; the input is not modified
|
|
13
|
+
* @example
|
|
14
|
+
* simplifyLine([[0,0],[1,0.001],[2,0]], 0.01); // [[0,0],[2,0]]
|
|
15
|
+
* simplifyLine([[0,0],[1,1],[2,0]], 0.01); // all three: the corner carries the shape
|
|
16
|
+
*/
|
|
17
|
+
export declare function simplifyLine(line: Array<number[]>, tolerance: number): Array<number[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Simplify a linear ring, refusing to destroy it.
|
|
20
|
+
*
|
|
21
|
+
* A ring needs four positions to bound a surface, so when the tolerance
|
|
22
|
+
* would leave fewer the ring is returned **unsimplified** rather than
|
|
23
|
+
* degenerate. Dropping a small island entirely is a defensible rendering
|
|
24
|
+
* choice, but silently emitting a two-vertex "polygon" is not — a caller
|
|
25
|
+
* wanting the island gone should filter by area first.
|
|
26
|
+
*
|
|
27
|
+
* @param {Array<number[]>} ring - positions, first === last
|
|
28
|
+
* @param {number} tolerance
|
|
29
|
+
* @returns {Array<number[]>}
|
|
30
|
+
*/
|
|
31
|
+
export declare function simplifyRing(ring: Array<number[]>, tolerance: number): Array<number[]>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a value is a structurally valid GeoJSON object: one of the
|
|
3
|
+
* seven geometry types, a Feature, or a FeatureCollection, with the
|
|
4
|
+
* coordinate nesting its `type` requires, positions of 2 or 3 numbers
|
|
5
|
+
* inside the WGS 84 bounds, and **every linear ring closed** — the
|
|
6
|
+
* invariant a JSON Schema cannot state.
|
|
7
|
+
*
|
|
8
|
+
* This is the shallow twin of the schema artifacts in `@jarenjs/json`:
|
|
9
|
+
* it answers yes or no in one call, where the meta-schema reports what
|
|
10
|
+
* failed and where, and the Jaren-extended variant also checks winding.
|
|
11
|
+
* Foreign members and a `bbox` are ignored rather than judged, exactly
|
|
12
|
+
* as the meta-schema leaves them open.
|
|
13
|
+
*
|
|
14
|
+
* @param {any} value
|
|
15
|
+
* @returns {boolean}
|
|
16
|
+
* @example
|
|
17
|
+
* isValidGeoJson({ type: 'Point', coordinates: [4.9, 52.4] }); // true
|
|
18
|
+
* isValidGeoJson({ type: 'Polygon',
|
|
19
|
+
* coordinates: [[[0,0],[1,0],[1,1],[0,0]]] }); // true
|
|
20
|
+
* isValidGeoJson({ type: 'Polygon',
|
|
21
|
+
* coordinates: [[[0,0],[1,0],[1,1],[2,2]]] }); // false (open ring)
|
|
22
|
+
* isValidGeoJson({ type: 'Point', coordinates: [52.4, 4.9, 0, 0] }); // false (4 axes)
|
|
23
|
+
*/
|
|
24
|
+
export declare function isValidGeoJson(value: any): boolean;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a string is a well-formed WKT geometry: one of the seven
|
|
3
|
+
* tagged types, `EMPTY` or a body whose nesting matches the tag, a
|
|
4
|
+
* coordinate count consistent with the `Z`/`M`/`ZM` modifier and with
|
|
5
|
+
* itself, closed polygon rings, and nothing before or after.
|
|
6
|
+
*
|
|
7
|
+
* @param {string} text
|
|
8
|
+
* @returns {boolean}
|
|
9
|
+
* @example
|
|
10
|
+
* isValidWkt('POINT (4.9041 52.3676)'); // true
|
|
11
|
+
* isValidWkt('POLYGON ((0 0, 4 0, 4 4, 0 0))'); // true (closed)
|
|
12
|
+
* isValidWkt('POLYGON ((0 0, 4 0, 4 4, 1 1))'); // false (open ring)
|
|
13
|
+
* isValidWkt('POINT Z (1 2)'); // false (Z wants 3)
|
|
14
|
+
* isValidWkt('LINESTRING (0 0, 1 1 1)'); // false (mixed dimension)
|
|
15
|
+
*/
|
|
16
|
+
export declare function isValidWkt(text: string): boolean;
|