@konfirm/geojson 1.0.0 → 1.0.1-beta.0
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/README.md +7 -7
- package/dist/{geojson.d.ts → main.d.mts} +18 -79
- package/dist/main.d.ts +137 -15
- package/dist/main.global.js +853 -0
- package/dist/main.global.js.map +1 -0
- package/dist/main.js +824 -0
- package/dist/main.js.map +1 -0
- package/dist/main.mjs +772 -0
- package/dist/main.mjs.map +1 -0
- package/package.json +101 -63
- package/.editorconfig +0 -16
- package/.github/workflows/release.yml +0 -21
- package/.github/workflows/tests.yml +0 -56
- package/CHANGELOG.md +0 -21
- package/dist/Domain/Constants.d.ts +0 -5
- package/dist/Domain/GeoJSON/Concept/Altitude.d.ts +0 -3
- package/dist/Domain/GeoJSON/Concept/BoundingBox.d.ts +0 -6
- package/dist/Domain/GeoJSON/Concept/ExteriorRing.d.ts +0 -4
- package/dist/Domain/GeoJSON/Concept/GeoJSONObject.d.ts +0 -11
- package/dist/Domain/GeoJSON/Concept/InteriorRing.d.ts +0 -4
- package/dist/Domain/GeoJSON/Concept/Latitude.d.ts +0 -3
- package/dist/Domain/GeoJSON/Concept/LinearRing.d.ts +0 -4
- package/dist/Domain/GeoJSON/Concept/Longitude.d.ts +0 -3
- package/dist/Domain/GeoJSON/Concept/Position.d.ts +0 -7
- package/dist/Domain/GeoJSON/Feature.d.ts +0 -12
- package/dist/Domain/GeoJSON/FeatureCollection.d.ts +0 -8
- package/dist/Domain/GeoJSON/GeoJSON.d.ts +0 -7
- package/dist/Domain/GeoJSON/Geometry/LineString.d.ts +0 -11
- package/dist/Domain/GeoJSON/Geometry/MultiLineString.d.ts +0 -7
- package/dist/Domain/GeoJSON/Geometry/MultiPoint.d.ts +0 -8
- package/dist/Domain/GeoJSON/Geometry/MultiPolygon.d.ts +0 -7
- package/dist/Domain/GeoJSON/Geometry/Point.d.ts +0 -11
- package/dist/Domain/GeoJSON/Geometry/Polygon.d.ts +0 -11
- package/dist/Domain/GeoJSON/Geometry.d.ts +0 -9
- package/dist/Domain/GeoJSON/GeometryCollection.d.ts +0 -8
- package/dist/Domain/GeoJSON/GeometryObject.d.ts +0 -12
- package/dist/Domain/Guards/Number.d.ts +0 -3
- package/dist/Domain/Guards/Tuple.d.ts +0 -3
- package/dist/Domain/Iterator/IterablePair.d.ts +0 -32
- package/dist/Domain/Iterator/SimpleGeometry.d.ts +0 -90
- package/dist/Domain/Utility/Calculate.d.ts +0 -9
- package/dist/Domain/Utility/Distance.d.ts +0 -3
- package/dist/Domain/Utility/Intersect.d.ts +0 -2
- package/dist/Domain/Utility/Segments.d.ts +0 -2
- package/dist/Domain/Utility/Winding.d.ts +0 -3
- package/dist/geojson.cjs.js +0 -655
- package/dist/geojson.cjs.min.js +0 -1
- package/dist/geojson.es.js +0 -627
- package/dist/geojson.es.min.js +0 -1
- package/dist/geojson.js +0 -660
- package/dist/geojson.min.js +0 -1
- package/rollup.config.mjs +0 -43
- package/source/Domain/Constants.ts +0 -5
- package/source/Domain/GeoJSON/Concept/Altitude.ts +0 -9
- package/source/Domain/GeoJSON/Concept/BoundingBox.ts +0 -31
- package/source/Domain/GeoJSON/Concept/ExteriorRing.ts +0 -12
- package/source/Domain/GeoJSON/Concept/GeoJSONObject.ts +0 -23
- package/source/Domain/GeoJSON/Concept/InteriorRing.ts +0 -12
- package/source/Domain/GeoJSON/Concept/Latitude.ts +0 -7
- package/source/Domain/GeoJSON/Concept/LinearRing.ts +0 -14
- package/source/Domain/GeoJSON/Concept/Longitude.ts +0 -7
- package/source/Domain/GeoJSON/Concept/Position.ts +0 -18
- package/source/Domain/GeoJSON/Feature.ts +0 -24
- package/source/Domain/GeoJSON/FeatureCollection.ts +0 -16
- package/source/Domain/GeoJSON/GeoJSON.ts +0 -9
- package/source/Domain/GeoJSON/Geometry/LineString.ts +0 -12
- package/source/Domain/GeoJSON/Geometry/MultiLineString.ts +0 -9
- package/source/Domain/GeoJSON/Geometry/MultiPoint.ts +0 -10
- package/source/Domain/GeoJSON/Geometry/MultiPolygon.ts +0 -9
- package/source/Domain/GeoJSON/Geometry/Point.ts +0 -12
- package/source/Domain/GeoJSON/Geometry/Polygon.ts +0 -20
- package/source/Domain/GeoJSON/Geometry.ts +0 -11
- package/source/Domain/GeoJSON/GeometryCollection.ts +0 -23
- package/source/Domain/GeoJSON/GeometryObject.ts +0 -20
- package/source/Domain/Guards/Number.ts +0 -13
- package/source/Domain/Guards/Tuple.ts +0 -6
- package/source/Domain/Guards/Utility.ts +0 -1
- package/source/Domain/Iterator/IterablePair.ts +0 -47
- package/source/Domain/Iterator/SimpleGeometry.ts +0 -137
- package/source/Domain/Utility/Calculate.ts +0 -143
- package/source/Domain/Utility/Distance.ts +0 -56
- package/source/Domain/Utility/Intersect.ts +0 -42
- package/source/Domain/Utility/Numeric.ts +0 -8
- package/source/Domain/Utility/Segments.ts +0 -5
- package/source/Domain/Utility/Winding.ts +0 -19
- package/source/main.ts +0 -20
- package/test/Domain/GeoJSON/Concept/Altitude.ts +0 -58
- package/test/Domain/GeoJSON/Concept/BoundingBox.ts +0 -77
- package/test/Domain/GeoJSON/Concept/ExteriorRing.ts +0 -65
- package/test/Domain/GeoJSON/Concept/GeoJSONObject.ts +0 -56
- package/test/Domain/GeoJSON/Concept/InteriorRing.ts +0 -65
- package/test/Domain/GeoJSON/Concept/Latitude.ts +0 -56
- package/test/Domain/GeoJSON/Concept/LinearRing.ts +0 -63
- package/test/Domain/GeoJSON/Concept/Longitude.ts +0 -56
- package/test/Domain/GeoJSON/Concept/Position.ts +0 -56
- package/test/Domain/GeoJSON/Feature.ts +0 -9
- package/test/Domain/GeoJSON/FeatureCollection.ts +0 -9
- package/test/Domain/GeoJSON/GeoJSON.ts +0 -21
- package/test/Domain/GeoJSON/Geometry/LineString.ts +0 -11
- package/test/Domain/GeoJSON/Geometry/MultiLineString.ts +0 -11
- package/test/Domain/GeoJSON/Geometry/MultiPoint.ts +0 -11
- package/test/Domain/GeoJSON/Geometry/MultiPolygon.ts +0 -11
- package/test/Domain/GeoJSON/Geometry/Point.ts +0 -11
- package/test/Domain/GeoJSON/Geometry/Polygon.ts +0 -11
- package/test/Domain/GeoJSON/Geometry.ts +0 -9
- package/test/Domain/GeoJSON/GeometryCollection.ts +0 -9
- package/test/Domain/GeoJSON/GeometryObject.ts +0 -4
- package/test/Domain/Guards/Number.ts +0 -49
- package/test/Domain/Guards/Tuple.ts +0 -27
- package/test/Domain/Iterator/IterablePair.ts +0 -203
- package/test/Domain/Iterator/SimpleGeometry.ts +0 -195
- package/test/Domain/Utility/Calculate.ts +0 -178
- package/test/Domain/Utility/Distance.ts +0 -19
- package/test/Domain/Utility/Intersect.ts +0 -54
- package/test/Domain/Utility/Numeric.ts +0 -30
- package/test/Domain/Utility/Winding.ts +0 -52
- package/test/README.ts +0 -123
- package/test/data/Distance.ts +0 -51
- package/test/data/HolySee.ts +0 -74
- package/test/data/Intersect.ts +0 -300
- package/test/data/Italy.ts +0 -2883
- package/test/data/SanMarino.ts +0 -83
- package/test/data/Shapes.ts +0 -107
- package/test/helper/geometry.ts +0 -76
- package/test/helper/malform.ts +0 -82
- package/test/main.ts +0 -4
- package/tsconfig.json +0 -12
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import { Point } from "../GeoJSON/Geometry/Point";
|
|
2
|
-
import { EARTH_RADIUS, EARTH_RADIUS_MAJOR, EARTH_RADIUS_MINOR, EARTH_FLATTENING } from '../Constants';
|
|
3
|
-
|
|
4
|
-
const D2R = Math.PI / 180;
|
|
5
|
-
const π = Math.PI;
|
|
6
|
-
|
|
7
|
-
function constrain(value: number, min: number, max: number): number {
|
|
8
|
-
return Math.max(Math.min(value, max), min);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function squared(n: number): number {
|
|
12
|
-
return n * n;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function rad(n: number): number {
|
|
16
|
-
return n * D2R;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const EARTH_RADIUS_MAJOR_SQUARED = squared(EARTH_RADIUS_MAJOR);
|
|
20
|
-
const EARTH_RADIUS_MINOR_SQUARED = squared(EARTH_RADIUS_MINOR);
|
|
21
|
-
const EARTH_RADIUS_FACTOR = (EARTH_RADIUS_MAJOR_SQUARED - EARTH_RADIUS_MINOR_SQUARED) / EARTH_RADIUS_MINOR_SQUARED;
|
|
22
|
-
const EARTH_INVERSE_FLATTENING = 1 / EARTH_FLATTENING;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const PointToPoint: { [key: string]: (...positions: [Point['coordinates'], Point['coordinates']]) => number } = {
|
|
26
|
-
cartesian([λa, φa], [λb, φb]) {
|
|
27
|
-
return EARTH_RADIUS * rad(Math.sqrt(squared(λb - λa) + squared(φb - φa)));
|
|
28
|
-
},
|
|
29
|
-
haversine([λa, φa], [λb, φb]) {
|
|
30
|
-
//https://www.movable-type.co.uk/scripts/latlong.html
|
|
31
|
-
const Δ = squared(Math.sin(rad(φb - φa) / 2)) + Math.cos(rad(φa)) * Math.cos(rad(φb)) * squared(Math.sin(rad(λb - λa) / 2));
|
|
32
|
-
|
|
33
|
-
return EARTH_RADIUS * Math.atan2(Math.sqrt(Δ), Math.sqrt(1 - Δ)) * 2;
|
|
34
|
-
},
|
|
35
|
-
vincenty(...points) {
|
|
36
|
-
//https://www.movable-type.co.uk/scripts/latlong-vincenty.html
|
|
37
|
-
const [[λ1, φ1], [λ2, φ2]] = points.map((p) => p.map(rad));
|
|
38
|
-
const L = λ2 - λ1; // L = difference in longitude, U = reduced latitude, defined by tan U = (1-f)·tanφ.
|
|
39
|
-
const tanU1 = (1 - EARTH_INVERSE_FLATTENING) * Math.tan(φ1), cosU1 = 1 / Math.sqrt((1 + tanU1 * tanU1)), sinU1 = tanU1 * cosU1;
|
|
40
|
-
const tanU2 = (1 - EARTH_INVERSE_FLATTENING) * Math.tan(φ2), cosU2 = 1 / Math.sqrt((1 + tanU2 * tanU2)), sinU2 = tanU2 * cosU2;
|
|
41
|
-
|
|
42
|
-
const antipodal = Math.abs(L) > π / 2 || Math.abs(φ2 - φ1) > π / 2;
|
|
43
|
-
|
|
44
|
-
let λ = L;
|
|
45
|
-
let sinλ = null;
|
|
46
|
-
let cosλ = null; // λ = difference in longitude on an auxiliary sphere
|
|
47
|
-
let σ = antipodal ? π : 0;
|
|
48
|
-
let sinσ = 0;
|
|
49
|
-
let cosσ = antipodal ? -1 : 1
|
|
50
|
-
let sinSqσ = null; // σ = angular distance P₁ P₂ on the sphere
|
|
51
|
-
let cos2σₘ = 1; // σₘ = angular distance on the sphere from the equator to the midpoint of the line
|
|
52
|
-
let cosSqα = 1; // α = azimuth of the geodesic at the equator
|
|
53
|
-
let λʹ = null;
|
|
54
|
-
let iterations = 0;
|
|
55
|
-
|
|
56
|
-
do {
|
|
57
|
-
sinλ = Math.sin(λ);
|
|
58
|
-
cosλ = Math.cos(λ);
|
|
59
|
-
sinSqσ = (cosU2 * sinλ) ** 2 + (cosU1 * sinU2 - sinU1 * cosU2 * cosλ) ** 2;
|
|
60
|
-
if (Math.abs(sinSqσ) < 1e-24) break; // co-incident/antipodal points (σ < ≈0.006mm)
|
|
61
|
-
sinσ = Math.sqrt(sinSqσ);
|
|
62
|
-
cosσ = sinU1 * sinU2 + cosU1 * cosU2 * cosλ;
|
|
63
|
-
σ = Math.atan2(sinσ, cosσ);
|
|
64
|
-
const sinα = cosU1 * cosU2 * sinλ / sinσ;
|
|
65
|
-
cosSqα = 1 - sinα * sinα;
|
|
66
|
-
cos2σₘ = (cosSqα != 0) ? (cosσ - 2 * sinU1 * sinU2 / cosSqα) : 0; // on equatorial line cos²α = 0 (§6)
|
|
67
|
-
const C = EARTH_INVERSE_FLATTENING / 16 * cosSqα * (4 + EARTH_INVERSE_FLATTENING * (4 - 3 * cosSqα));
|
|
68
|
-
λʹ = λ;
|
|
69
|
-
λ = L + (1 - C) * EARTH_INVERSE_FLATTENING * sinα * (σ + C * sinσ * (cos2σₘ + C * cosσ * (-1 + 2 * cos2σₘ * cos2σₘ)));
|
|
70
|
-
// TODO: add tests
|
|
71
|
-
// const iterationCheck = antipodal ? Math.abs(λ) - π : Math.abs(λ);
|
|
72
|
-
// if (iterationCheck > π) throw new EvalError('λ > π');
|
|
73
|
-
} while (Math.abs(λ - λʹ) > 1e-12 && ++iterations < 1000); // TV: 'iterate until negligible change in λ' (≈0.006mm)
|
|
74
|
-
// TODO: add tests
|
|
75
|
-
// if (iterations >= 1000) throw new EvalError('Vincenty formula failed to converge');
|
|
76
|
-
|
|
77
|
-
const uSq = cosSqα * EARTH_RADIUS_FACTOR;
|
|
78
|
-
const A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
|
|
79
|
-
const B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
|
|
80
|
-
const Δσ = B * sinσ * (cos2σₘ + B / 4 * (cosσ * (-1 + 2 * cos2σₘ * cos2σₘ) - B / 6 * cos2σₘ * (-3 + 4 * sinσ * sinσ) * (-3 + 4 * cos2σₘ * cos2σₘ)));
|
|
81
|
-
|
|
82
|
-
return EARTH_RADIUS_MINOR * A * (σ - Δσ);
|
|
83
|
-
},
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
export type PointToPointCalculation = 'cartesian' | 'haversine' | 'vincenty' | ((a: Point['coordinates'], b: Point['coordinates']) => number);
|
|
87
|
-
|
|
88
|
-
export function getClosestPointOnLineByPoint(point: Point['coordinates'], line: [Point['coordinates'], Point['coordinates']]): Point['coordinates'] {
|
|
89
|
-
const [[px, py], [ax, ay], [bx, by]] = [point, ...line];
|
|
90
|
-
const [abx, aby] = [bx - ax, by - ay];
|
|
91
|
-
const [apx, apy] = [px - ax, py - ay];
|
|
92
|
-
const t = constrain((apx * abx + apy * aby) / (abx * abx + aby * aby), 0, 1);
|
|
93
|
-
|
|
94
|
-
return t === 0 || t === 1 ? line[t] : [ax + abx * t, ay + aby * t];
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export function getDistanceOfPointToPoint(a: Point['coordinates'], b: Point['coordinates'], calculation: PointToPointCalculation): number {
|
|
98
|
-
const calc = typeof calculation === 'function' ? calculation : PointToPoint[calculation];
|
|
99
|
-
|
|
100
|
-
if (typeof calc === 'function') {
|
|
101
|
-
return calc(a, b);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
throw new Error(`Not a PointToPoint calculation function ${calculation}`);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export function getDistanceOfPointToLine(point: Point['coordinates'], line: [Point['coordinates'], Point['coordinates']], calculation: PointToPointCalculation): number {
|
|
108
|
-
return getDistanceOfPointToPoint(point, getClosestPointOnLineByPoint(point, line), calculation);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export function getDistanceOfLineToLine(a: [Point['coordinates'], Point['coordinates']], b: [Point['coordinates'], Point['coordinates']], calculation: PointToPointCalculation): number {
|
|
112
|
-
return isLinesCrossing(a, b)
|
|
113
|
-
? 0
|
|
114
|
-
: Math.min(...a.map((a) => getDistanceOfPointToLine(a, b, calculation)), ...b.map((b) => getDistanceOfPointToLine(b, a, calculation)));
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export function isLinesCrossing(a: [Point['coordinates'], Point['coordinates']], b: [Point['coordinates'], Point['coordinates']]): boolean {
|
|
118
|
-
const [[a1x, a1y], [a2x, a2y]] = a;
|
|
119
|
-
const [[b1x, b1y], [b2x, b2y]] = b;
|
|
120
|
-
const [s1x, s1y, s2x, s2y] = [a2x - a1x, a2y - a1y, b2x - b1x, b2y - b1y];
|
|
121
|
-
const s = (-s1y * (a1x - b1x) + s1x * (a1y - b1y)) / (-s2x * s1y + s1x * s2y);
|
|
122
|
-
const t = (s2x * (a1y - b1y) - s2y * (a1x - b1x)) / (-s2x * s1y + s1x * s2y);
|
|
123
|
-
|
|
124
|
-
return s >= 0 && s <= 1 && t >= 0 && t <= 1;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export function isPointOnLine(point: Point['coordinates'], line: [Point['coordinates'], Point['coordinates']], threshold: number = 1e-14): boolean {
|
|
128
|
-
return getDistanceOfPointToLine(point, line, 'cartesian') < threshold;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export function isPointInRing(p: Point['coordinates'], ring: Array<Point['coordinates']>): boolean {
|
|
132
|
-
const { length } = ring;
|
|
133
|
-
const odd = ring
|
|
134
|
-
.reduce((odd, a, i) => {
|
|
135
|
-
const b = ring[(length + i - 1) % length];
|
|
136
|
-
|
|
137
|
-
return (a[1] < p[1] && b[1] >= p[1] || b[1] < p[1] && a[1] >= p[1]) && (a[0] <= p[0] || b[0] <= p[0])
|
|
138
|
-
? odd ^ Number(a[0] + (p[1] - a[1]) / (b[1] - a[1]) * (b[0] - a[0]) < p[0])
|
|
139
|
-
: odd;
|
|
140
|
-
}, 0);
|
|
141
|
-
|
|
142
|
-
return odd !== 0 || ring.slice(1).some((a, index) => isPointOnLine(p, [ring[index], a]));
|
|
143
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { GeoJSON } from '../GeoJSON/GeoJSON';
|
|
2
|
-
import { Point } from '../GeoJSON/Geometry/Point';
|
|
3
|
-
import { LineString } from '../GeoJSON/Geometry/LineString';
|
|
4
|
-
import { Polygon } from '../GeoJSON/Geometry/Polygon';
|
|
5
|
-
import { segments } from './Segments';
|
|
6
|
-
import { SimpleGeometryIterator } from '../Iterator/SimpleGeometry';
|
|
7
|
-
import { IterablePairIterator } from '../Iterator/IterablePair';
|
|
8
|
-
import { getDistanceOfLineToLine, getDistanceOfPointToLine, getDistanceOfPointToPoint, isPointInRing, PointToPointCalculation } from './Calculate';
|
|
9
|
-
|
|
10
|
-
const geometries = {
|
|
11
|
-
PointPoint(a: Point['coordinates'], b: Point['coordinates'], calculation: PointToPointCalculation): number {
|
|
12
|
-
return getDistanceOfPointToPoint(a, b, calculation);
|
|
13
|
-
},
|
|
14
|
-
LineStringPoint(a: LineString['coordinates'], b: Point['coordinates'], calculation: PointToPointCalculation): number {
|
|
15
|
-
return Math.min(...segments(a).map((line) => getDistanceOfPointToLine(b, line, calculation)));
|
|
16
|
-
},
|
|
17
|
-
LineStringLineString(a: LineString['coordinates'], b: LineString['coordinates'], calculation: PointToPointCalculation): number {
|
|
18
|
-
const sa = segments(a);
|
|
19
|
-
const sb = segments(b);
|
|
20
|
-
|
|
21
|
-
return sa.reduce((carry, a) => sb.reduce((carry, b) => carry > 0 ? Math.min(carry, getDistanceOfLineToLine(a, b, calculation)) : carry, carry), Infinity);
|
|
22
|
-
},
|
|
23
|
-
PolygonPoint([exterior, ...interior]: Polygon['coordinates'], b: Point['coordinates'], calculation: PointToPointCalculation): number {
|
|
24
|
-
if (isPointInRing(b, exterior)) {
|
|
25
|
-
const [excluded] = interior.filter((ring) => isPointInRing(b, ring));
|
|
26
|
-
|
|
27
|
-
return excluded ? this.LineStringPoint(excluded, b, calculation) : 0;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return this.LineStringPoint(exterior, b, calculation);
|
|
31
|
-
},
|
|
32
|
-
PolygonLineString(a: Polygon['coordinates'], b: LineString['coordinates'], calculation: PointToPointCalculation): number {
|
|
33
|
-
const [exterior, ...interior] = a;
|
|
34
|
-
const line = segments(b);
|
|
35
|
-
const ring = b.some((b) => isPointInRing(b, exterior))
|
|
36
|
-
? interior.find((a) => b.every((b) => isPointInRing(b, a)))
|
|
37
|
-
: exterior;
|
|
38
|
-
|
|
39
|
-
return ring
|
|
40
|
-
? Math.min(...segments(ring).map((a) => Math.min(...line.map((b) => getDistanceOfLineToLine(a, b, calculation)))))
|
|
41
|
-
: 0;
|
|
42
|
-
},
|
|
43
|
-
PolygonPolygon(a: Polygon['coordinates'], b: Polygon['coordinates'], calculation: PointToPointCalculation): number {
|
|
44
|
-
return Math.min(this.PolygonLineString(a, b[0], calculation), this.PolygonLineString(b, a[0], calculation));
|
|
45
|
-
},
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
export function distance(a: GeoJSON, b: GeoJSON, calculation: PointToPointCalculation = 'cartesian'): number {
|
|
49
|
-
return Math.min(...[...new IterablePairIterator(new SimpleGeometryIterator(a), new SimpleGeometryIterator(b))].map(([a, b]) => {
|
|
50
|
-
return a.type + b.type in geometries
|
|
51
|
-
? geometries[a.type + b.type](a.coordinates, b.coordinates, calculation)
|
|
52
|
-
: b.type + a.type in geometries
|
|
53
|
-
? geometries[b.type + a.type](b.coordinates, a.coordinates, calculation)
|
|
54
|
-
: Infinity
|
|
55
|
-
}));
|
|
56
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { Point } from '../GeoJSON/Geometry/Point';
|
|
2
|
-
import { LineString } from '../GeoJSON/Geometry/LineString';
|
|
3
|
-
import { Polygon } from '../GeoJSON/Geometry/Polygon';
|
|
4
|
-
import { GeoJSON } from '../GeoJSON/GeoJSON';
|
|
5
|
-
import { segments } from './Segments';
|
|
6
|
-
import { isLinesCrossing, isPointInRing, isPointOnLine } from "./Calculate";
|
|
7
|
-
import { SimpleGeometryIterator } from "../Iterator/SimpleGeometry";
|
|
8
|
-
import { IterablePairIterator } from "../Iterator/IterablePair";
|
|
9
|
-
|
|
10
|
-
const geometries = {
|
|
11
|
-
PointPoint(a: Point['coordinates'], b: Point['coordinates']): boolean {
|
|
12
|
-
return a.length >= 2 && b.length >= 2 && a.slice(0, 2).every((v, i) => v === b[i]);
|
|
13
|
-
},
|
|
14
|
-
LineStringPoint(a: LineString['coordinates'], b: Point['coordinates']): boolean {
|
|
15
|
-
return a.some((a) => this.PointPoint(a, b)) || segments(a).some((line) => isPointOnLine(b, line));
|
|
16
|
-
},
|
|
17
|
-
LineStringLineString(a: LineString['coordinates'], b: LineString['coordinates']): boolean {
|
|
18
|
-
const lines = segments(b);
|
|
19
|
-
|
|
20
|
-
return segments(a).some((a) => lines.some((b) => isLinesCrossing(a, b)));
|
|
21
|
-
},
|
|
22
|
-
PolygonPoint([exterior, ...interior]: Polygon['coordinates'], b: Point['coordinates']): boolean {
|
|
23
|
-
return (this.LineStringPoint(exterior, b) || isPointInRing(b, exterior)) && (!interior.length || interior.every((ring) => !isPointInRing(b, ring)));
|
|
24
|
-
},
|
|
25
|
-
PolygonLineString(a: Polygon['coordinates'], b: LineString['coordinates']): boolean {
|
|
26
|
-
return a.some((ring) => this.LineStringLineString(ring, b)) || b.some((point) => this.PolygonPoint(a, point));
|
|
27
|
-
},
|
|
28
|
-
PolygonPolygon(a: Polygon['coordinates'], b: Polygon['coordinates']): boolean {
|
|
29
|
-
return b.some((b1) => this.PolygonLineString(a, b1) || b1.some((b2) => this.PolygonPoint(a, b2)))
|
|
30
|
-
|| a.some((a1) => this.PolygonLineString(b, a1) || a1.some((a2) => this.PolygonPoint(b, a2)))
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export function intersect(a: GeoJSON, b: GeoJSON): boolean {
|
|
35
|
-
for (const [itA, itB] of new IterablePairIterator(new SimpleGeometryIterator(a), new SimpleGeometryIterator(b))) {
|
|
36
|
-
if ((itA.type + itB.type in geometries && geometries[itA.type + itB.type](itA.coordinates, itB.coordinates)) || (itB.type + itA.type in geometries && geometries[itB.type + itA.type](itB.coordinates, itA.coordinates))) {
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export function bounds<T extends number>(a: number, b: number): (value: number) => T {
|
|
2
|
-
const min = Math.min(a, b);
|
|
3
|
-
const max = Math.max(a, b);
|
|
4
|
-
const range = max - min;
|
|
5
|
-
const mod = (value: number): T => value < min ? mod(value + range) : value > max ? mod(value - range) : <T>value;
|
|
6
|
-
|
|
7
|
-
return (value: number): T => mod(value) as T;
|
|
8
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { isArrayOfType } from "@konfirm/guard";
|
|
2
|
-
import { isPosition, Position } from "../GeoJSON/Concept/Position";
|
|
3
|
-
|
|
4
|
-
function winding(positions: Array<Position>): number {
|
|
5
|
-
return positions.reduce((carry, [x, y], i, a) => {
|
|
6
|
-
const [nx, ny] = a[(i + 1) % a.length];
|
|
7
|
-
|
|
8
|
-
return carry + ((nx - x) * (ny + y));
|
|
9
|
-
}, 0);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const isPositionArray = isArrayOfType<Array<Position>>(isPosition);
|
|
13
|
-
|
|
14
|
-
export function isClockwiseWinding<T extends Array<Position>>(value: any): value is T {
|
|
15
|
-
return isPositionArray(value) && winding(value) <= 0;
|
|
16
|
-
}
|
|
17
|
-
export function isCounterClockwiseWinding<T extends Array<Position>>(value: any): value is T {
|
|
18
|
-
return isPositionArray(value) && winding(value) >= 0;
|
|
19
|
-
}
|
package/source/main.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
// intersect and distance functions
|
|
2
|
-
export { intersect } from './Domain/Utility/Intersect';
|
|
3
|
-
export { distance } from './Domain/Utility/Distance';
|
|
4
|
-
|
|
5
|
-
// SimpleGeometryIterator
|
|
6
|
-
export { SimpleGeometryIterator } from './Domain/Iterator/SimpleGeometry';
|
|
7
|
-
|
|
8
|
-
// the individual GeoJSON types and type guards
|
|
9
|
-
export { Position, isPosition, isStrictPosition } from './Domain/GeoJSON/Concept/Position';
|
|
10
|
-
export { Point, isPoint, isStrictPoint } from './Domain/GeoJSON/Geometry/Point';
|
|
11
|
-
export { MultiPoint, isMultiPoint, isStrictMultiPoint } from './Domain/GeoJSON/Geometry/MultiPoint';
|
|
12
|
-
export { LineString, isLineString, isStrictLineString } from './Domain/GeoJSON/Geometry/LineString';
|
|
13
|
-
export { MultiLineString, isMultiLineString, isStrictMultiLineString } from './Domain/GeoJSON/Geometry/MultiLineString';
|
|
14
|
-
export { Polygon, isPolygon, isStrictPolygon } from './Domain/GeoJSON/Geometry/Polygon';
|
|
15
|
-
export { MultiPolygon, isMultiPolygon, isStrictMultiPolygon } from './Domain/GeoJSON/Geometry/MultiPolygon';
|
|
16
|
-
export { GeometryCollection, isGeometryCollection, isStrictGeometryCollection } from './Domain/GeoJSON/GeometryCollection';
|
|
17
|
-
export { Geometry, isGeometry, isStrictGeometry } from './Domain/GeoJSON/Geometry';
|
|
18
|
-
export { Feature, isFeature, isStrictFeature } from './Domain/GeoJSON/Feature';
|
|
19
|
-
export { FeatureCollection, isFeatureCollection, isStrictFeatureCollection } from './Domain/GeoJSON/FeatureCollection';
|
|
20
|
-
export { GeoJSON, isGeoJSON, isStrictGeoJSON } from './Domain/GeoJSON/GeoJSON';
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import test from 'tape';
|
|
2
|
-
import { each } from 'template-literal-each';
|
|
3
|
-
import * as Export from '../../../../source/Domain/GeoJSON/Concept/Altitude';
|
|
4
|
-
import { exported } from '../../../helper/geometry';
|
|
5
|
-
|
|
6
|
-
exported('Domain/GeoJSON/Concept/Altitude', Export, 'isAltitude', 'isStrictAltitude');
|
|
7
|
-
|
|
8
|
-
const { isAltitude, isStrictAltitude } = Export;
|
|
9
|
-
|
|
10
|
-
test('Domain/GeoJSON/Concept/Altitude - isAltitude', (t) => {
|
|
11
|
-
each`
|
|
12
|
-
input | valid
|
|
13
|
-
-------------------|-------
|
|
14
|
-
${0} | yes
|
|
15
|
-
${0.0000000001} | yes
|
|
16
|
-
${1_234_567} | yes
|
|
17
|
-
${-6_371_008.7714} | yes
|
|
18
|
-
${-6_378_137} | yes
|
|
19
|
-
${20_180_000} | yes
|
|
20
|
-
${20_180_000.1} | yes
|
|
21
|
-
${-Infinity} | no
|
|
22
|
-
${Infinity} | no
|
|
23
|
-
${NaN} | no
|
|
24
|
-
${'1234'} | no
|
|
25
|
-
${false} | no
|
|
26
|
-
${true} | no
|
|
27
|
-
`(({ input, valid }) => {
|
|
28
|
-
t.equal(isAltitude(input), valid === 'yes', `${input} ${valid}`);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
t.end();
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
test('Domain/GeoJSON/Concept/Altitude - isStrictAltitude', (t) => {
|
|
35
|
-
each`
|
|
36
|
-
input | valid
|
|
37
|
-
-------------------|-------
|
|
38
|
-
${0} | yes
|
|
39
|
-
${0.0000000001} | yes
|
|
40
|
-
${1_234_567} | yes
|
|
41
|
-
${-6_371_008.7714} | yes
|
|
42
|
-
${-6_371_008.7715} | no
|
|
43
|
-
${-6_378_137} | no
|
|
44
|
-
${-6_378_137.1} | no
|
|
45
|
-
${20_180_000} | yes
|
|
46
|
-
${20_180_000.1} | no
|
|
47
|
-
${-Infinity} | no
|
|
48
|
-
${Infinity} | no
|
|
49
|
-
${NaN} | no
|
|
50
|
-
${'1234'} | no
|
|
51
|
-
${false} | no
|
|
52
|
-
${true} | no
|
|
53
|
-
`(({ input, valid }) => {
|
|
54
|
-
t.equal(isStrictAltitude(input), valid === 'yes', `${input} ${valid}`);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
t.end();
|
|
58
|
-
});
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import test from 'tape';
|
|
2
|
-
import { each } from 'template-literal-each';
|
|
3
|
-
import * as Export from '../../../../source/Domain/GeoJSON/Concept/BoundingBox';
|
|
4
|
-
import { exported } from '../../../helper/geometry';
|
|
5
|
-
|
|
6
|
-
exported('Domain/GeoJSON/Concept/BoundingBox', Export, 'isBoundingBox', 'isStrictBoundingBox');
|
|
7
|
-
|
|
8
|
-
const { isBoundingBox, isStrictBoundingBox } = Export;
|
|
9
|
-
|
|
10
|
-
test('Domain/GeoJSON/Concept/BoundingBox - isBoundingBox', (t) => {
|
|
11
|
-
each`
|
|
12
|
-
input | valid
|
|
13
|
-
-----------------------------------------|-------
|
|
14
|
-
${[-10.0, -10.0, 10.0, 10.0]} | yes
|
|
15
|
-
${[100.0, 0.0, 105.0, 1.0]} | yes
|
|
16
|
-
${[100.0, 0.0, -100.0, 105.0, 1.0, 0.0]} | yes
|
|
17
|
-
${[177.0, -20.0, -178.0, -16.0]} | yes
|
|
18
|
-
${[-178.0, -20.0, 177.0, -16.0]} | yes
|
|
19
|
-
${[-370.0, -190.0, 190.0, 370.0]} | yes
|
|
20
|
-
${[]} | no
|
|
21
|
-
${[0]} | no
|
|
22
|
-
${[-180]} | no
|
|
23
|
-
${[0, 0]} | no
|
|
24
|
-
${[-180, -90]} | no
|
|
25
|
-
${[0, 0, 0]} | no
|
|
26
|
-
${[-180, -90, 180]} | no
|
|
27
|
-
${[0, 0, 0, 0]} | yes
|
|
28
|
-
${[-180, -90, 180, 90]} | yes
|
|
29
|
-
${[0, 0, 0, 0, 0]} | no
|
|
30
|
-
${[-180, -90, 0, 180, 90]} | no
|
|
31
|
-
${[0, 0, 0, 0, 0, 0]} | yes
|
|
32
|
-
${[-180, -90, 0, 180, 90, 0]} | yes
|
|
33
|
-
${[180, 90, 0, -180, -90, 0]} | no
|
|
34
|
-
${[-180, 90, 0, 180, -90, 0]} | no
|
|
35
|
-
${[180, -90, 0, -180, 90, 0]} | yes
|
|
36
|
-
${[-181, -91, 0, 181, 91, 0]} | yes
|
|
37
|
-
`(({ input, valid }) => {
|
|
38
|
-
t.equal(isBoundingBox(input), valid === 'yes', `[${input}] isBoudingBox ${valid}`)
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
t.end();
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test('Domain/GeoJSON/Concept/BoundingBox - isStrictBoundingBox', (t) => {
|
|
45
|
-
each`
|
|
46
|
-
input | valid
|
|
47
|
-
-----------------------------------------|-------
|
|
48
|
-
${[-10.0, -10.0, 10.0, 10.0]} | yes
|
|
49
|
-
${[100.0, 0.0, 105.0, 1.0]} | yes
|
|
50
|
-
${[100.0, 0.0, -100.0, 105.0, 1.0, 0.0]} | yes
|
|
51
|
-
${[177.0, -20.0, -178.0, -16.0]} | yes
|
|
52
|
-
${[-178.0, -20.0, 177.0, -16.0]} | yes
|
|
53
|
-
${[-370.0, -190.0, 190.0, 370.0]} | no
|
|
54
|
-
${[]} | no
|
|
55
|
-
${[0]} | no
|
|
56
|
-
${[-180]} | no
|
|
57
|
-
${[0, 0]} | no
|
|
58
|
-
${[-180, -90]} | no
|
|
59
|
-
${[0, 0, 0]} | no
|
|
60
|
-
${[-180, -90, 180]} | no
|
|
61
|
-
${[0, 0, 0, 0]} | yes
|
|
62
|
-
${[-180, -90, 180, 90]} | yes
|
|
63
|
-
${[0, 0, 0, 0, 0]} | no
|
|
64
|
-
${[-180, -90, 0, 180, 90]} | no
|
|
65
|
-
${[0, 0, 0, 0, 0, 0]} | yes
|
|
66
|
-
${[-180, -90, 0, 180, 90, 0]} | yes
|
|
67
|
-
${[180, 90, 0, -180, -90, 0]} | no
|
|
68
|
-
${[180, 90, 0, -180, -90, 0]} | no
|
|
69
|
-
${[-180, 90, 0, 180, -90, 0]} | no
|
|
70
|
-
${[180, -90, 0, -180, 90, 0]} | yes
|
|
71
|
-
${[-181, -91, 0, 181, 91, 0]} | no
|
|
72
|
-
`(({ input, valid }) => {
|
|
73
|
-
t.equal(isStrictBoundingBox(input), valid === 'yes', `[${input}] isStrictBoudingBox ${valid}`)
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
t.end();
|
|
77
|
-
});
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import test from 'tape';
|
|
2
|
-
import { each } from 'template-literal-each';
|
|
3
|
-
import * as Export from '../../../../source/Domain/GeoJSON/Concept/ExteriorRing';
|
|
4
|
-
import { exported } from '../../../helper/geometry';
|
|
5
|
-
import { coordinates as Italy } from '../../../data/Italy';
|
|
6
|
-
import { coordinates as SanMarino, polygon } from '../../../data/SanMarino';
|
|
7
|
-
import { coordinates as HolySee } from '../../../data/HolySee';
|
|
8
|
-
|
|
9
|
-
exported('Domain/GeoJSON/Concept/ExteriorRing', Export, 'isExteriorRing', 'isStrictExteriorRing');
|
|
10
|
-
|
|
11
|
-
const { isExteriorRing, isStrictExteriorRing } = Export;
|
|
12
|
-
|
|
13
|
-
test('Domain/GeoJSON/Concept/ExteriorRing - isExteriorRing', (t) => {
|
|
14
|
-
each`
|
|
15
|
-
input | valid
|
|
16
|
-
-------------------------------------------------|----
|
|
17
|
-
${undefined} | no
|
|
18
|
-
${null} | no
|
|
19
|
-
${'[[1,0],[1,1],[0,1],[1,0]]'} | no
|
|
20
|
-
${[[1, 0], [1, 1], [0, 1], [0, 0.5], [1, 0]]} | yes
|
|
21
|
-
${[[1, 0], [0, 0.5], [0, 1], [1, 1], [1, 0]]} | yes
|
|
22
|
-
${[[1, 0], [1, 1], [0, 1], [1, 0]]} | yes
|
|
23
|
-
${[[1, 0], [1, 1], [0, 1], [0, 0]]} | no
|
|
24
|
-
${[[1, 0], [1, 1], [1, 0]]} | no
|
|
25
|
-
${[[1, 0], [1, 0]]} | no
|
|
26
|
-
${[[1, 0]]} | no
|
|
27
|
-
${[[-181, -91], [0, -91], [0, 91], [-181, -91]]} | yes
|
|
28
|
-
`(({ input, valid }) => {
|
|
29
|
-
t.equal(isExteriorRing(input), valid === 'yes', `[${input}] isExteriorRing ${valid}`);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
t.ok(Italy.every((polygon) => polygon.every(isExteriorRing)), 'coordinates for Italy polygon all match isExteriorRing');
|
|
33
|
-
t.notOk(SanMarino.every(isExteriorRing), 'coordinates for SanMarino does not match isExteriorRing');
|
|
34
|
-
t.notOk(HolySee.every(isExteriorRing), 'coordinates for HolySee does not match isExteriorRing');
|
|
35
|
-
|
|
36
|
-
t.end();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
test('Domain/GeoJSON/Concept/ExteriorRing - isStrictExteriorRing', (t) => {
|
|
40
|
-
each`
|
|
41
|
-
input | valid
|
|
42
|
-
-------------------------------------------------|----
|
|
43
|
-
${undefined} | no
|
|
44
|
-
${null} | no
|
|
45
|
-
${'[[1,0],[1,1],[0,1],[1,0]]'} | no
|
|
46
|
-
${[[1, 0], [1, 1], [0, 1], [0, 0.5], [1, 0]]} | no
|
|
47
|
-
${[[1, 0], [0, 0.5], [0, 1], [1, 1], [1, 0]]} | yes
|
|
48
|
-
${[[1, 0], [1, 1], [0, 1], [1, 0]]} | no
|
|
49
|
-
${[[1, 0], [1, 1], [0, 1], [0, 0]]} | no
|
|
50
|
-
${[[1, 0], [1, 1], [1, 0]]} | no
|
|
51
|
-
${[[1, 0], [1, 0]]} | no
|
|
52
|
-
${[[1, 0]]} | no
|
|
53
|
-
${[[-181, -91], [0, -91], [0, 91], [-181, -91]]} | no
|
|
54
|
-
`(({ input, valid }) => {
|
|
55
|
-
t.equal(isStrictExteriorRing(input), valid === 'yes', `[${input}] isStrictExteriorRing ${valid}`);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
t.notOk(Italy.every((polygon) => polygon.every(isStrictExteriorRing)), 'coordinates for Italy polygon do not match isStrictExteriorRing');
|
|
59
|
-
t.ok(Italy.every((polygon) => isStrictExteriorRing(polygon[0])), 'first polygon coordinates for Italy all match isStrictExteriorRing');
|
|
60
|
-
t.ok(Italy.filter((polygon) => polygon.length > 1).every((polygon) => !polygon.slice(1).some(isStrictExteriorRing)), 'second+ polygon coordinates for Italy none match isStrictExteriorRing')
|
|
61
|
-
t.notOk(SanMarino.every(isStrictExteriorRing), 'coordinates for SanMarino does not match isStrictExteriorRing');
|
|
62
|
-
t.notOk(HolySee.every(isStrictExteriorRing), 'coordinates for HolySee does not match isStrictExteriorRing');
|
|
63
|
-
|
|
64
|
-
t.end();
|
|
65
|
-
});
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import test from 'tape';
|
|
2
|
-
import { each } from 'template-literal-each';
|
|
3
|
-
import * as Export from '../../../../source/Domain/GeoJSON/Concept/GeoJSONObject';
|
|
4
|
-
import { exported } from '../../../helper/geometry';
|
|
5
|
-
|
|
6
|
-
exported('Domain/GeoJSON/Concept/GeoJSONObject', Export, 'isGeoJSONObject', 'isStrictGeoJSONObject');
|
|
7
|
-
|
|
8
|
-
const { isGeoJSONObject, isStrictGeoJSONObject } = Export;
|
|
9
|
-
|
|
10
|
-
test('Domain/GeoJSON/Concept/GeoJSONObject - isGeoJSONObject', (t) => {
|
|
11
|
-
each`
|
|
12
|
-
type | bbox | valid
|
|
13
|
-
-------------|-------------------------------|-------
|
|
14
|
-
Type | | yes
|
|
15
|
-
Type | ${[0, 0, 0, 0]} | yes
|
|
16
|
-
Type | ${[0, 0, 0, 0, 0, 0]} | yes
|
|
17
|
-
Type | ${[-181, -91, 0, 181, 91, 0]} | yes
|
|
18
|
-
${undefined} | | no
|
|
19
|
-
${null} | | no
|
|
20
|
-
${true} | | no
|
|
21
|
-
${false} | | no
|
|
22
|
-
${12345} | | no
|
|
23
|
-
`(({ type, bbox, valid }: any) => {
|
|
24
|
-
const validate = isGeoJSONObject(type);
|
|
25
|
-
const input = Object.assign({ type }, bbox ? { bbox } : {});
|
|
26
|
-
|
|
27
|
-
t.equal(typeof validate, 'function', `creates isGeoJSONObject validator for type ${JSON.stringify(type)}`);
|
|
28
|
-
t.equal(validate(input), valid === 'yes', `type ${JSON.stringify(type)} validates ${JSON.stringify(input)} ${valid}`);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
t.end();
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
test('Domain/GeoJSON/Concept/GeoJSONObject - isStrictGeoJSONObject', (t) => {
|
|
35
|
-
each`
|
|
36
|
-
type | bbox | valid
|
|
37
|
-
-------------|-------------------------------|-------
|
|
38
|
-
Type | | yes
|
|
39
|
-
Type | ${[0, 0, 0, 0]} | yes
|
|
40
|
-
Type | ${[0, 0, 0, 0, 0, 0]} | yes
|
|
41
|
-
Type | ${[-181, -91, 0, 181, 91, 0]} | no
|
|
42
|
-
${undefined} | | no
|
|
43
|
-
${null} | | no
|
|
44
|
-
${true} | | no
|
|
45
|
-
${false} | | no
|
|
46
|
-
${12345} | | no
|
|
47
|
-
`(({ type, bbox, valid }: any) => {
|
|
48
|
-
const validate = isStrictGeoJSONObject(type);
|
|
49
|
-
const input = Object.assign({ type }, bbox ? { bbox } : {});
|
|
50
|
-
|
|
51
|
-
t.equal(typeof validate, 'function', `creates isStrictGeoJSONObject validator for type ${JSON.stringify(type)}`);
|
|
52
|
-
t.equal(validate(input), valid === 'yes', `type ${JSON.stringify(type)} validates ${JSON.stringify(input)} ${valid}`);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
t.end();
|
|
56
|
-
});
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import test from 'tape';
|
|
2
|
-
import { each } from 'template-literal-each';
|
|
3
|
-
import * as Export from '../../../../source/Domain/GeoJSON/Concept/InteriorRing';
|
|
4
|
-
import { exported } from '../../../helper/geometry';
|
|
5
|
-
import { coordinates as Italy } from '../../../data/Italy';
|
|
6
|
-
import { coordinates as SanMarino, polygon } from '../../../data/SanMarino';
|
|
7
|
-
import { coordinates as HolySee } from '../../../data/HolySee';
|
|
8
|
-
|
|
9
|
-
exported('Domain/GeoJSON/Concept/InteriorRing', Export, 'isInteriorRing', 'isStrictInteriorRing');
|
|
10
|
-
|
|
11
|
-
const { isInteriorRing, isStrictInteriorRing } = Export;
|
|
12
|
-
|
|
13
|
-
test('Domain/GeoJSON/Concept/InteriorRing - isInteriorRing', (t) => {
|
|
14
|
-
each`
|
|
15
|
-
input | valid
|
|
16
|
-
-------------------------------------------------|----
|
|
17
|
-
${undefined} | no
|
|
18
|
-
${null} | no
|
|
19
|
-
${'[[1,0],[1,1],[0,1],[1,0]]'} | no
|
|
20
|
-
${[[1, 0], [1, 1], [0, 1], [0, 0.5], [1, 0]]} | yes
|
|
21
|
-
${[[1, 0], [0, 0.5], [0, 1], [1, 1], [1, 0]]} | yes
|
|
22
|
-
${[[1, 0], [1, 1], [0, 1], [1, 0]]} | yes
|
|
23
|
-
${[[1, 0], [1, 1], [0, 1], [0, 0]]} | no
|
|
24
|
-
${[[1, 0], [1, 1], [1, 0]]} | no
|
|
25
|
-
${[[1, 0], [1, 0]]} | no
|
|
26
|
-
${[[1, 0]]} | no
|
|
27
|
-
${[[-181, -91], [0, -91], [0, 91], [-181, -91]]} | yes
|
|
28
|
-
`(({ input, valid }) => {
|
|
29
|
-
t.equal(isInteriorRing(input), valid === 'yes', `[${input}] isInteriorRing ${valid}`);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
t.ok(Italy.every((polygon) => polygon.every(isInteriorRing)), 'coordinates for Italy polygon all match isInteriorRing');
|
|
33
|
-
t.notOk(SanMarino.every(isInteriorRing), 'coordinates for SanMarino does not match isInteriorRing');
|
|
34
|
-
t.notOk(HolySee.every(isInteriorRing), 'coordinates for HolySee does not match isInteriorRing');
|
|
35
|
-
|
|
36
|
-
t.end();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
test('Domain/GeoJSON/Concept/InteriorRing - isStrictInteriorRing', (t) => {
|
|
40
|
-
each`
|
|
41
|
-
input | valid
|
|
42
|
-
-------------------------------------------------|----
|
|
43
|
-
${undefined} | no
|
|
44
|
-
${null} | no
|
|
45
|
-
${'[[1,0],[1,1],[0,1],[1,0]]'} | no
|
|
46
|
-
${[[1, 0], [1, 1], [0, 1], [0, 0.5], [1, 0]]} | yes
|
|
47
|
-
${[[1, 0], [0, 0.5], [0, 1], [1, 1], [1, 0]]} | no
|
|
48
|
-
${[[1, 0], [1, 1], [0, 1], [1, 0]]} | yes
|
|
49
|
-
${[[1, 0], [1, 1], [0, 1], [0, 0]]} | no
|
|
50
|
-
${[[1, 0], [1, 1], [1, 0]]} | no
|
|
51
|
-
${[[1, 0], [1, 0]]} | no
|
|
52
|
-
${[[1, 0]]} | no
|
|
53
|
-
${[[-181, -91], [0, -91], [0, 91], [-181, -91]]} | no
|
|
54
|
-
`(({ input, valid }) => {
|
|
55
|
-
t.equal(isStrictInteriorRing(input), valid === 'yes', `[${input}] isStrictInteriorRing ${valid}`);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
t.notOk(Italy.every((polygon) => polygon.every(isStrictInteriorRing)), 'coordinates for Italy polygon do not match isStrictInteriorRing');
|
|
59
|
-
t.ok(Italy.every((polygon) => !isStrictInteriorRing(polygon[0])), 'first polygon coordinates for Italy none match isStrictInteriorRing');
|
|
60
|
-
t.ok(Italy.filter((polygon) => polygon.length > 1).every((polygon) => polygon.slice(1).every(isStrictInteriorRing)), 'second+ polygon coordinates for Italy none match isStrictInteriorRing')
|
|
61
|
-
t.notOk(SanMarino.every(isStrictInteriorRing), 'coordinates for SanMarino does not match isStrictInteriorRing');
|
|
62
|
-
t.notOk(HolySee.every(isStrictInteriorRing), 'coordinates for HolySee does not match isStrictInteriorRing');
|
|
63
|
-
|
|
64
|
-
t.end();
|
|
65
|
-
});
|