@konfirm/geojson 1.0.0 → 1.0.1

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.
Files changed (127) hide show
  1. package/README.md +7 -7
  2. package/dist/{geojson.d.ts → main.d.mts} +18 -79
  3. package/dist/main.d.ts +137 -15
  4. package/dist/main.global.js +853 -0
  5. package/dist/main.global.js.map +1 -0
  6. package/dist/main.js +824 -0
  7. package/dist/main.js.map +1 -0
  8. package/dist/main.mjs +772 -0
  9. package/dist/main.mjs.map +1 -0
  10. package/package.json +101 -63
  11. package/.editorconfig +0 -16
  12. package/.github/workflows/release.yml +0 -21
  13. package/.github/workflows/tests.yml +0 -56
  14. package/CHANGELOG.md +0 -21
  15. package/dist/Domain/Constants.d.ts +0 -5
  16. package/dist/Domain/GeoJSON/Concept/Altitude.d.ts +0 -3
  17. package/dist/Domain/GeoJSON/Concept/BoundingBox.d.ts +0 -6
  18. package/dist/Domain/GeoJSON/Concept/ExteriorRing.d.ts +0 -4
  19. package/dist/Domain/GeoJSON/Concept/GeoJSONObject.d.ts +0 -11
  20. package/dist/Domain/GeoJSON/Concept/InteriorRing.d.ts +0 -4
  21. package/dist/Domain/GeoJSON/Concept/Latitude.d.ts +0 -3
  22. package/dist/Domain/GeoJSON/Concept/LinearRing.d.ts +0 -4
  23. package/dist/Domain/GeoJSON/Concept/Longitude.d.ts +0 -3
  24. package/dist/Domain/GeoJSON/Concept/Position.d.ts +0 -7
  25. package/dist/Domain/GeoJSON/Feature.d.ts +0 -12
  26. package/dist/Domain/GeoJSON/FeatureCollection.d.ts +0 -8
  27. package/dist/Domain/GeoJSON/GeoJSON.d.ts +0 -7
  28. package/dist/Domain/GeoJSON/Geometry/LineString.d.ts +0 -11
  29. package/dist/Domain/GeoJSON/Geometry/MultiLineString.d.ts +0 -7
  30. package/dist/Domain/GeoJSON/Geometry/MultiPoint.d.ts +0 -8
  31. package/dist/Domain/GeoJSON/Geometry/MultiPolygon.d.ts +0 -7
  32. package/dist/Domain/GeoJSON/Geometry/Point.d.ts +0 -11
  33. package/dist/Domain/GeoJSON/Geometry/Polygon.d.ts +0 -11
  34. package/dist/Domain/GeoJSON/Geometry.d.ts +0 -9
  35. package/dist/Domain/GeoJSON/GeometryCollection.d.ts +0 -8
  36. package/dist/Domain/GeoJSON/GeometryObject.d.ts +0 -12
  37. package/dist/Domain/Guards/Number.d.ts +0 -3
  38. package/dist/Domain/Guards/Tuple.d.ts +0 -3
  39. package/dist/Domain/Iterator/IterablePair.d.ts +0 -32
  40. package/dist/Domain/Iterator/SimpleGeometry.d.ts +0 -90
  41. package/dist/Domain/Utility/Calculate.d.ts +0 -9
  42. package/dist/Domain/Utility/Distance.d.ts +0 -3
  43. package/dist/Domain/Utility/Intersect.d.ts +0 -2
  44. package/dist/Domain/Utility/Segments.d.ts +0 -2
  45. package/dist/Domain/Utility/Winding.d.ts +0 -3
  46. package/dist/geojson.cjs.js +0 -655
  47. package/dist/geojson.cjs.min.js +0 -1
  48. package/dist/geojson.es.js +0 -627
  49. package/dist/geojson.es.min.js +0 -1
  50. package/dist/geojson.js +0 -660
  51. package/dist/geojson.min.js +0 -1
  52. package/rollup.config.mjs +0 -43
  53. package/source/Domain/Constants.ts +0 -5
  54. package/source/Domain/GeoJSON/Concept/Altitude.ts +0 -9
  55. package/source/Domain/GeoJSON/Concept/BoundingBox.ts +0 -31
  56. package/source/Domain/GeoJSON/Concept/ExteriorRing.ts +0 -12
  57. package/source/Domain/GeoJSON/Concept/GeoJSONObject.ts +0 -23
  58. package/source/Domain/GeoJSON/Concept/InteriorRing.ts +0 -12
  59. package/source/Domain/GeoJSON/Concept/Latitude.ts +0 -7
  60. package/source/Domain/GeoJSON/Concept/LinearRing.ts +0 -14
  61. package/source/Domain/GeoJSON/Concept/Longitude.ts +0 -7
  62. package/source/Domain/GeoJSON/Concept/Position.ts +0 -18
  63. package/source/Domain/GeoJSON/Feature.ts +0 -24
  64. package/source/Domain/GeoJSON/FeatureCollection.ts +0 -16
  65. package/source/Domain/GeoJSON/GeoJSON.ts +0 -9
  66. package/source/Domain/GeoJSON/Geometry/LineString.ts +0 -12
  67. package/source/Domain/GeoJSON/Geometry/MultiLineString.ts +0 -9
  68. package/source/Domain/GeoJSON/Geometry/MultiPoint.ts +0 -10
  69. package/source/Domain/GeoJSON/Geometry/MultiPolygon.ts +0 -9
  70. package/source/Domain/GeoJSON/Geometry/Point.ts +0 -12
  71. package/source/Domain/GeoJSON/Geometry/Polygon.ts +0 -20
  72. package/source/Domain/GeoJSON/Geometry.ts +0 -11
  73. package/source/Domain/GeoJSON/GeometryCollection.ts +0 -23
  74. package/source/Domain/GeoJSON/GeometryObject.ts +0 -20
  75. package/source/Domain/Guards/Number.ts +0 -13
  76. package/source/Domain/Guards/Tuple.ts +0 -6
  77. package/source/Domain/Guards/Utility.ts +0 -1
  78. package/source/Domain/Iterator/IterablePair.ts +0 -47
  79. package/source/Domain/Iterator/SimpleGeometry.ts +0 -137
  80. package/source/Domain/Utility/Calculate.ts +0 -143
  81. package/source/Domain/Utility/Distance.ts +0 -56
  82. package/source/Domain/Utility/Intersect.ts +0 -42
  83. package/source/Domain/Utility/Numeric.ts +0 -8
  84. package/source/Domain/Utility/Segments.ts +0 -5
  85. package/source/Domain/Utility/Winding.ts +0 -19
  86. package/source/main.ts +0 -20
  87. package/test/Domain/GeoJSON/Concept/Altitude.ts +0 -58
  88. package/test/Domain/GeoJSON/Concept/BoundingBox.ts +0 -77
  89. package/test/Domain/GeoJSON/Concept/ExteriorRing.ts +0 -65
  90. package/test/Domain/GeoJSON/Concept/GeoJSONObject.ts +0 -56
  91. package/test/Domain/GeoJSON/Concept/InteriorRing.ts +0 -65
  92. package/test/Domain/GeoJSON/Concept/Latitude.ts +0 -56
  93. package/test/Domain/GeoJSON/Concept/LinearRing.ts +0 -63
  94. package/test/Domain/GeoJSON/Concept/Longitude.ts +0 -56
  95. package/test/Domain/GeoJSON/Concept/Position.ts +0 -56
  96. package/test/Domain/GeoJSON/Feature.ts +0 -9
  97. package/test/Domain/GeoJSON/FeatureCollection.ts +0 -9
  98. package/test/Domain/GeoJSON/GeoJSON.ts +0 -21
  99. package/test/Domain/GeoJSON/Geometry/LineString.ts +0 -11
  100. package/test/Domain/GeoJSON/Geometry/MultiLineString.ts +0 -11
  101. package/test/Domain/GeoJSON/Geometry/MultiPoint.ts +0 -11
  102. package/test/Domain/GeoJSON/Geometry/MultiPolygon.ts +0 -11
  103. package/test/Domain/GeoJSON/Geometry/Point.ts +0 -11
  104. package/test/Domain/GeoJSON/Geometry/Polygon.ts +0 -11
  105. package/test/Domain/GeoJSON/Geometry.ts +0 -9
  106. package/test/Domain/GeoJSON/GeometryCollection.ts +0 -9
  107. package/test/Domain/GeoJSON/GeometryObject.ts +0 -4
  108. package/test/Domain/Guards/Number.ts +0 -49
  109. package/test/Domain/Guards/Tuple.ts +0 -27
  110. package/test/Domain/Iterator/IterablePair.ts +0 -203
  111. package/test/Domain/Iterator/SimpleGeometry.ts +0 -195
  112. package/test/Domain/Utility/Calculate.ts +0 -178
  113. package/test/Domain/Utility/Distance.ts +0 -19
  114. package/test/Domain/Utility/Intersect.ts +0 -54
  115. package/test/Domain/Utility/Numeric.ts +0 -30
  116. package/test/Domain/Utility/Winding.ts +0 -52
  117. package/test/README.ts +0 -123
  118. package/test/data/Distance.ts +0 -51
  119. package/test/data/HolySee.ts +0 -74
  120. package/test/data/Intersect.ts +0 -300
  121. package/test/data/Italy.ts +0 -2883
  122. package/test/data/SanMarino.ts +0 -83
  123. package/test/data/Shapes.ts +0 -107
  124. package/test/helper/geometry.ts +0 -76
  125. package/test/helper/malform.ts +0 -82
  126. package/test/main.ts +0 -4
  127. 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,5 +0,0 @@
1
- import { Point } from '../GeoJSON/Geometry/Point';
2
-
3
- export function segments(line: Array<Point['coordinates']>): Array<[Point['coordinates'], Point['coordinates']]> {
4
- return line.slice(1).map((point, index) => [line[index], point]);
5
- }
@@ -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
- });