@mapbox/mapbox-gl-style-spec 14.25.0 → 14.26.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/dist/index.cjs +280 -611
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.es.js +280 -611
- package/dist/index.es.js.map +1 -1
- package/expression/compound_expression.ts +2 -2
- package/expression/definitions/comparison.ts +2 -2
- package/expression/definitions/distance.ts +147 -63
- package/expression/definitions/match.ts +7 -8
- package/expression/is_constant.ts +8 -4
- package/expression/parsing_context.ts +68 -28
- package/function/index.ts +1 -1
- package/package.json +1 -2
- package/reference/v8.json +23 -7
- package/types.ts +8 -2
- package/util/geometry_util.ts +35 -34
- package/util/interpolate.ts +1 -1
- package/validate/validate.ts +3 -2
- package/validate/validate_appearance.ts +5 -4
- package/validate/validate_filter.ts +3 -2
- package/validate/validate_import.ts +3 -2
- package/validate/validate_layer.ts +4 -4
- package/validate/validate_option.ts +4 -5
- package/validate/validate_style.ts +4 -5
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {toString} from './types';
|
|
2
|
-
import ParsingContext from './parsing_context';
|
|
3
2
|
import assert from '../util/assert';
|
|
4
3
|
|
|
5
4
|
import type EvaluationContext from './evaluation_context';
|
|
5
|
+
import type ParsingContext from './parsing_context';
|
|
6
6
|
import type {Expression, ExpressionRegistry, SerializedExpression} from './expression';
|
|
7
7
|
import type {Type} from './types';
|
|
8
8
|
import type {Value} from './values';
|
|
@@ -89,7 +89,7 @@ class CompoundExpression implements Expression {
|
|
|
89
89
|
// errors between overload attempts; the other fields are
|
|
90
90
|
// identical across attempts.
|
|
91
91
|
if (signatureContext === null) {
|
|
92
|
-
signatureContext =
|
|
92
|
+
signatureContext = context._forkForSignature();
|
|
93
93
|
} else {
|
|
94
94
|
signatureContext.errors.length = 0;
|
|
95
95
|
}
|
|
@@ -102,12 +102,12 @@ function makeComparison(
|
|
|
102
102
|
let lhs = context.parse(args[1], 1, ValueType);
|
|
103
103
|
if (!lhs) return null;
|
|
104
104
|
if (!isComparableType(op, lhs.type)) {
|
|
105
|
-
return context.
|
|
105
|
+
return context.error(`"${op}" comparisons are not supported for type '${toString(lhs.type)}'.`, 1);
|
|
106
106
|
}
|
|
107
107
|
let rhs = context.parse(args[2], 2, ValueType);
|
|
108
108
|
if (!rhs) return null;
|
|
109
109
|
if (!isComparableType(op, rhs.type)) {
|
|
110
|
-
return context.
|
|
110
|
+
return context.error(`"${op}" comparisons are not supported for type '${toString(rhs.type)}'.`, 2);
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
if (
|
|
@@ -2,10 +2,94 @@ import {isValue} from '../values';
|
|
|
2
2
|
import {NumberType} from '../types';
|
|
3
3
|
import {classifyRings, updateBBox, boxWithinBox, pointWithinPolygon, segmentIntersectSegment} from '../../util/geometry_util';
|
|
4
4
|
import {lngFromMercatorX, latFromMercatorY} from '../../util/mercator';
|
|
5
|
-
import CheapRuler from "cheap-ruler";
|
|
6
5
|
import TinyQueue from "tinyqueue";
|
|
7
6
|
import EXTENT from '../../data/extent';
|
|
8
7
|
|
|
8
|
+
// Geodesic scale factors (cheap-ruler math): meters per degree lon/lat at a given latitude.
|
|
9
|
+
// Only the three distance operations used in this file are implemented.
|
|
10
|
+
const RE = 6378.137; // WGS84 equatorial radius (km)
|
|
11
|
+
const FE = 1 / 298.257223563; // WGS84 flattening
|
|
12
|
+
const E2 = FE * (2 - FE);
|
|
13
|
+
const RAD = Math.PI / 180;
|
|
14
|
+
|
|
15
|
+
function lngLatScale(lat: number): [number, number] {
|
|
16
|
+
const m = RAD * RE * 1000;
|
|
17
|
+
const coslat = Math.cos(lat * RAD);
|
|
18
|
+
const w2 = 1 / (1 - E2 * (1 - coslat * coslat));
|
|
19
|
+
const w = Math.sqrt(w2);
|
|
20
|
+
return [m * w * coslat, m * w * w2 * (1 - E2)]; // [kx, ky]
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function wrapLng(deg: number): number {
|
|
24
|
+
while (deg < -180) deg += 360;
|
|
25
|
+
while (deg > 180) deg -= 360;
|
|
26
|
+
return deg;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function rulerDistance(a: [number, number], b: [number, number], kx: number, ky: number): number {
|
|
30
|
+
const dx = wrapLng(a[0] - b[0]) * kx;
|
|
31
|
+
const dy = (a[1] - b[1]) * ky;
|
|
32
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function rulerPointToSegmentDistance(p: [number, number], a: [number, number], b: [number, number], kx: number, ky: number): number {
|
|
36
|
+
let x = a[0];
|
|
37
|
+
let y = a[1];
|
|
38
|
+
let dx = wrapLng(b[0] - x) * kx;
|
|
39
|
+
let dy = (b[1] - y) * ky;
|
|
40
|
+
|
|
41
|
+
if (dx !== 0 || dy !== 0) {
|
|
42
|
+
const t = (wrapLng(p[0] - x) * kx * dx + (p[1] - y) * ky * dy) / (dx * dx + dy * dy);
|
|
43
|
+
if (t > 1) {
|
|
44
|
+
x = b[0];
|
|
45
|
+
y = b[1];
|
|
46
|
+
} else if (t > 0) {
|
|
47
|
+
x += (dx / kx) * t;
|
|
48
|
+
y += (dy / ky) * t;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
dx = wrapLng(p[0] - x) * kx;
|
|
53
|
+
dy = (p[1] - y) * ky;
|
|
54
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function rulerPointOnLine(line: Array<[number, number]>, p: [number, number], kx: number, ky: number): [number, number] {
|
|
58
|
+
let minDist = Infinity;
|
|
59
|
+
let minX = line[0][0];
|
|
60
|
+
let minY = line[0][1];
|
|
61
|
+
|
|
62
|
+
for (let i = 0; i < line.length - 1; i++) {
|
|
63
|
+
let x = line[i][0];
|
|
64
|
+
let y = line[i][1];
|
|
65
|
+
let dx = wrapLng(line[i + 1][0] - x) * kx;
|
|
66
|
+
let dy = (line[i + 1][1] - y) * ky;
|
|
67
|
+
let t = 0;
|
|
68
|
+
|
|
69
|
+
if (dx !== 0 || dy !== 0) {
|
|
70
|
+
t = (wrapLng(p[0] - x) * kx * dx + (p[1] - y) * ky * dy) / (dx * dx + dy * dy);
|
|
71
|
+
if (t > 1) {
|
|
72
|
+
x = line[i + 1][0];
|
|
73
|
+
y = line[i + 1][1];
|
|
74
|
+
} else if (t > 0) {
|
|
75
|
+
x += (dx / kx) * t;
|
|
76
|
+
y += (dy / ky) * t;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
dx = wrapLng(p[0] - x) * kx;
|
|
81
|
+
dy = (p[1] - y) * ky;
|
|
82
|
+
const sqDist = dx * dx + dy * dy;
|
|
83
|
+
if (sqDist < minDist) {
|
|
84
|
+
minDist = sqDist;
|
|
85
|
+
minX = x;
|
|
86
|
+
minY = y;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return [minX, minY];
|
|
91
|
+
}
|
|
92
|
+
|
|
9
93
|
import type Point from "@mapbox/point-geometry";
|
|
10
94
|
import type ParsingContext from '../parsing_context';
|
|
11
95
|
import type {BBox} from '../../util/geometry_util';
|
|
@@ -102,7 +186,7 @@ function getPolygonBBox(polygon: Array<Array<[number, number]>>) {
|
|
|
102
186
|
// Calculate the distance between two bounding boxes.
|
|
103
187
|
// Calculate the delta in x and y direction, and use two fake points {0.0, 0.0} and {dx, dy} to calculate the distance.
|
|
104
188
|
// Distance will be 0.0 if bounding box are overlapping.
|
|
105
|
-
function bboxToBBoxDistance(bbox1: BBox, bbox2: BBox,
|
|
189
|
+
function bboxToBBoxDistance(bbox1: BBox, bbox2: BBox, kx: number, ky: number) {
|
|
106
190
|
if (isDefaultBBOX(bbox1) || isDefaultBBOX(bbox2)) {
|
|
107
191
|
return NaN;
|
|
108
192
|
}
|
|
@@ -124,7 +208,7 @@ function bboxToBBoxDistance(bbox1: BBox, bbox2: BBox, ruler: CheapRuler) {
|
|
|
124
208
|
if (bbox1[3] < bbox2[1]) {
|
|
125
209
|
dy = bbox2[1] - bbox1[3];
|
|
126
210
|
}
|
|
127
|
-
return
|
|
211
|
+
return rulerDistance([0.0, 0.0], [dx, dy], kx, ky);
|
|
128
212
|
}
|
|
129
213
|
|
|
130
214
|
export function getLngLatPoint(coord: Point, canonical: CanonicalTileID, extent: number = EXTENT): [number, number] {
|
|
@@ -142,35 +226,35 @@ function getLngLatPoints(coordinates: Array<Point>, canonical: CanonicalTileID):
|
|
|
142
226
|
return coords;
|
|
143
227
|
}
|
|
144
228
|
|
|
145
|
-
function pointToLineDistance(point: [number, number], line: Array<[number, number]>,
|
|
146
|
-
const nearestPoint =
|
|
147
|
-
return
|
|
229
|
+
function pointToLineDistance(point: [number, number], line: Array<[number, number]>, kx: number, ky: number) {
|
|
230
|
+
const nearestPoint = rulerPointOnLine(line, point, kx, ky);
|
|
231
|
+
return rulerDistance(point, nearestPoint, kx, ky);
|
|
148
232
|
}
|
|
149
233
|
|
|
150
|
-
function pointsToLineDistance(points: Array<[number, number]>, rangeA: IndexRange, line: Array<[number, number]>, rangeB: IndexRange,
|
|
234
|
+
function pointsToLineDistance(points: Array<[number, number]>, rangeA: IndexRange, line: Array<[number, number]>, rangeB: IndexRange, kx: number, ky: number) {
|
|
151
235
|
const subLine = line.slice(rangeB[0], rangeB[1] + 1);
|
|
152
236
|
let dist = Infinity;
|
|
153
237
|
for (let i = rangeA[0]; i <= rangeA[1]; ++i) {
|
|
154
|
-
if ((dist = Math.min(dist, pointToLineDistance(points[i], subLine,
|
|
238
|
+
if ((dist = Math.min(dist, pointToLineDistance(points[i], subLine, kx, ky))) === 0.0) return 0.0;
|
|
155
239
|
}
|
|
156
240
|
return dist;
|
|
157
241
|
}
|
|
158
242
|
|
|
159
243
|
// precondition is two segments are not intersecting with each other
|
|
160
|
-
function segmentToSegmentDistance(p1: [number, number], p2: [number, number], q1: [number, number], q2: [number, number],
|
|
244
|
+
function segmentToSegmentDistance(p1: [number, number], p2: [number, number], q1: [number, number], q2: [number, number], kx: number, ky: number) {
|
|
161
245
|
const dist1 = Math.min(
|
|
162
|
-
|
|
163
|
-
|
|
246
|
+
rulerPointToSegmentDistance(p1, q1, q2, kx, ky),
|
|
247
|
+
rulerPointToSegmentDistance(p2, q1, q2, kx, ky)
|
|
164
248
|
);
|
|
165
249
|
const dist2 = Math.min(
|
|
166
|
-
|
|
167
|
-
|
|
250
|
+
rulerPointToSegmentDistance(q1, p1, p2, kx, ky),
|
|
251
|
+
rulerPointToSegmentDistance(q2, p1, p2, kx, ky)
|
|
168
252
|
);
|
|
169
253
|
|
|
170
254
|
return Math.min(dist1, dist2);
|
|
171
255
|
}
|
|
172
256
|
|
|
173
|
-
function lineToLineDistance(line1: Array<[number, number]>, range1: IndexRange, line2: Array<[number, number]>, range2: IndexRange,
|
|
257
|
+
function lineToLineDistance(line1: Array<[number, number]>, range1: IndexRange, line2: Array<[number, number]>, range2: IndexRange, kx: number, ky: number) {
|
|
174
258
|
if (!isRangeSafe(range1, line1.length) || !isRangeSafe(range2, line2.length)) {
|
|
175
259
|
return NaN;
|
|
176
260
|
}
|
|
@@ -178,26 +262,26 @@ function lineToLineDistance(line1: Array<[number, number]>, range1: IndexRange,
|
|
|
178
262
|
for (let i = range1[0]; i < range1[1]; ++i) {
|
|
179
263
|
for (let j = range2[0]; j < range2[1]; ++j) {
|
|
180
264
|
if (segmentIntersectSegment(line1[i], line1[i + 1], line2[j], line2[j + 1])) return 0.0;
|
|
181
|
-
dist = Math.min(dist, segmentToSegmentDistance(line1[i], line1[i + 1], line2[j], line2[j + 1],
|
|
265
|
+
dist = Math.min(dist, segmentToSegmentDistance(line1[i], line1[i + 1], line2[j], line2[j + 1], kx, ky));
|
|
182
266
|
}
|
|
183
267
|
}
|
|
184
268
|
return dist;
|
|
185
269
|
}
|
|
186
270
|
|
|
187
|
-
function pointsToPointsDistance(pointSet1: Array<[number, number]>, range1: IndexRange, pointSet2: Array<[number, number]>, range2: IndexRange,
|
|
271
|
+
function pointsToPointsDistance(pointSet1: Array<[number, number]>, range1: IndexRange, pointSet2: Array<[number, number]>, range2: IndexRange, kx: number, ky: number) {
|
|
188
272
|
if (!isRangeSafe(range1, pointSet1.length) || !isRangeSafe(range2, pointSet2.length)) {
|
|
189
273
|
return NaN;
|
|
190
274
|
}
|
|
191
275
|
let dist = Infinity;
|
|
192
276
|
for (let i = range1[0]; i <= range1[1]; ++i) {
|
|
193
277
|
for (let j = range2[0]; j <= range2[1]; ++j) {
|
|
194
|
-
if ((dist = Math.min(dist,
|
|
278
|
+
if ((dist = Math.min(dist, rulerDistance(pointSet1[i], pointSet2[j], kx, ky))) === 0.0) return dist;
|
|
195
279
|
}
|
|
196
280
|
}
|
|
197
281
|
return dist;
|
|
198
282
|
}
|
|
199
283
|
|
|
200
|
-
function pointToPolygonDistance(point: [number, number], polygon: Array<Array<[number, number]>>,
|
|
284
|
+
function pointToPolygonDistance(point: [number, number], polygon: Array<Array<[number, number]>>, kx: number, ky: number) {
|
|
201
285
|
if (pointWithinPolygon(point, polygon, true /*trueOnBoundary*/)) return 0.0;
|
|
202
286
|
let dist = Infinity;
|
|
203
287
|
for (const ring of polygon) {
|
|
@@ -207,14 +291,14 @@ function pointToPolygonDistance(point: [number, number], polygon: Array<Array<[n
|
|
|
207
291
|
return NaN;
|
|
208
292
|
}
|
|
209
293
|
if (ring[0] !== ring[ringLen - 1]) {
|
|
210
|
-
if ((dist = Math.min(dist,
|
|
294
|
+
if ((dist = Math.min(dist, rulerPointToSegmentDistance(point, ring[ringLen - 1], ring[0], kx, ky))) === 0.0) return dist;
|
|
211
295
|
}
|
|
212
|
-
if ((dist = Math.min(dist, pointToLineDistance(point, ring,
|
|
296
|
+
if ((dist = Math.min(dist, pointToLineDistance(point, ring, kx, ky))) === 0.0) return dist;
|
|
213
297
|
}
|
|
214
298
|
return dist;
|
|
215
299
|
}
|
|
216
300
|
|
|
217
|
-
function lineToPolygonDistance(line: Array<[number, number]>, range: IndexRange, polygon: Array<Array<[number, number]>>,
|
|
301
|
+
function lineToPolygonDistance(line: Array<[number, number]>, range: IndexRange, polygon: Array<Array<[number, number]>>, kx: number, ky: number) {
|
|
218
302
|
if (!isRangeSafe(range, line.length)) {
|
|
219
303
|
return NaN;
|
|
220
304
|
}
|
|
@@ -226,7 +310,7 @@ function lineToPolygonDistance(line: Array<[number, number]>, range: IndexRange,
|
|
|
226
310
|
for (const ring of polygon) {
|
|
227
311
|
for (let j = 0, len = ring.length, k = len - 1; j < len; k = j++) {
|
|
228
312
|
if (segmentIntersectSegment(line[i], line[i + 1], ring[k], ring[j])) return 0.0;
|
|
229
|
-
dist = Math.min(dist, segmentToSegmentDistance(line[i], line[i + 1], ring[k], ring[j],
|
|
313
|
+
dist = Math.min(dist, segmentToSegmentDistance(line[i], line[i + 1], ring[k], ring[j], kx, ky));
|
|
230
314
|
}
|
|
231
315
|
}
|
|
232
316
|
}
|
|
@@ -242,10 +326,10 @@ function polygonIntersect(polygon1: Array<Array<[number, number]>>, polygon2: Ar
|
|
|
242
326
|
return false;
|
|
243
327
|
}
|
|
244
328
|
|
|
245
|
-
function polygonToPolygonDistance(polygon1: Array<Array<[number, number]>>, polygon2: Array<Array<[number, number]>>,
|
|
329
|
+
function polygonToPolygonDistance(polygon1: Array<Array<[number, number]>>, polygon2: Array<Array<[number, number]>>, kx: number, ky: number, currentMiniDist: number = Infinity) {
|
|
246
330
|
const bbox1 = getPolygonBBox(polygon1);
|
|
247
331
|
const bbox2 = getPolygonBBox(polygon2);
|
|
248
|
-
if (currentMiniDist !== Infinity && bboxToBBoxDistance(bbox1, bbox2,
|
|
332
|
+
if (currentMiniDist !== Infinity && bboxToBBoxDistance(bbox1, bbox2, kx, ky) >= currentMiniDist) {
|
|
249
333
|
return currentMiniDist;
|
|
250
334
|
}
|
|
251
335
|
if (boxWithinBox(bbox1, bbox2)) {
|
|
@@ -259,7 +343,7 @@ function polygonToPolygonDistance(polygon1: Array<Array<[number, number]>>, poly
|
|
|
259
343
|
for (const ring2 of polygon2) {
|
|
260
344
|
for (let j = 0, len2 = ring2.length, k = len2 - 1; j < len2; k = j++) {
|
|
261
345
|
if (segmentIntersectSegment(ring1[l], ring1[i], ring2[k], ring2[j])) return 0.0;
|
|
262
|
-
dist = Math.min(dist, segmentToSegmentDistance(ring1[l], ring1[i], ring2[k], ring2[j],
|
|
346
|
+
dist = Math.min(dist, segmentToSegmentDistance(ring1[l], ring1[i], ring2[k], ring2[j], kx, ky));
|
|
263
347
|
}
|
|
264
348
|
}
|
|
265
349
|
}
|
|
@@ -267,17 +351,17 @@ function polygonToPolygonDistance(polygon1: Array<Array<[number, number]>>, poly
|
|
|
267
351
|
return dist;
|
|
268
352
|
}
|
|
269
353
|
|
|
270
|
-
function updateQueue(distQueue: TinyQueue<DistPair>, miniDist: number,
|
|
354
|
+
function updateQueue(distQueue: TinyQueue<DistPair>, miniDist: number, kx: number, ky: number, pointSet1: Array<[number, number]>, pointSet2: Array<[number, number]>, r1: IndexRange | null, r2: IndexRange | null) {
|
|
271
355
|
if (r1 === null || r2 === null) return;
|
|
272
|
-
const tempDist = bboxToBBoxDistance(getBBox(pointSet1, r1), getBBox(pointSet2, r2),
|
|
356
|
+
const tempDist = bboxToBBoxDistance(getBBox(pointSet1, r1), getBBox(pointSet2, r2), kx, ky);
|
|
273
357
|
// Insert new pair to the queue if the bbox distance is less than miniDist, the pair with biggest distance will be at the top
|
|
274
358
|
if (tempDist < miniDist) distQueue.push({dist: tempDist, range1: r1, range2: r2});
|
|
275
359
|
}
|
|
276
360
|
|
|
277
361
|
// Divide and conquer, the time complexity is O(n*lgn), faster than Brute force O(n*n)
|
|
278
362
|
// Most of the time, use index for in-place processing.
|
|
279
|
-
function pointSetToPolygonDistance(pointSets: Array<[number, number]>, isLine: boolean, polygon: Array<Array<[number, number]>>,
|
|
280
|
-
let miniDist = Math.min(
|
|
363
|
+
function pointSetToPolygonDistance(pointSets: Array<[number, number]>, isLine: boolean, polygon: Array<Array<[number, number]>>, kx: number, ky: number, currentMiniDist: number = Infinity) {
|
|
364
|
+
let miniDist = Math.min(rulerDistance(pointSets[0], polygon[0][0], kx, ky), currentMiniDist);
|
|
281
365
|
if (miniDist === 0.0) return miniDist;
|
|
282
366
|
const initialDistPair: DistPair = {
|
|
283
367
|
dist: 0,
|
|
@@ -297,22 +381,22 @@ function pointSetToPolygonDistance(pointSets: Array<[number, number]>, isLine: b
|
|
|
297
381
|
if (getRangeSize(range) <= setThreshold) {
|
|
298
382
|
if (!isRangeSafe(range, pointSets.length)) return NaN;
|
|
299
383
|
if (isLine) {
|
|
300
|
-
const tempDist = lineToPolygonDistance(pointSets, range, polygon,
|
|
384
|
+
const tempDist = lineToPolygonDistance(pointSets, range, polygon, kx, ky);
|
|
301
385
|
if ((miniDist = Math.min(miniDist, tempDist)) === 0.0) return miniDist;
|
|
302
386
|
} else {
|
|
303
387
|
for (let i = range[0]; i <= range[1]; ++i) {
|
|
304
|
-
const tempDist = pointToPolygonDistance(pointSets[i], polygon,
|
|
388
|
+
const tempDist = pointToPolygonDistance(pointSets[i], polygon, kx, ky);
|
|
305
389
|
if ((miniDist = Math.min(miniDist, tempDist)) === 0.0) return miniDist;
|
|
306
390
|
}
|
|
307
391
|
}
|
|
308
392
|
} else {
|
|
309
393
|
const newRanges = splitRange(range, isLine);
|
|
310
394
|
if (newRanges[0] !== null) {
|
|
311
|
-
const tempDist = bboxToBBoxDistance(getBBox(pointSets, newRanges[0]), polyBBox,
|
|
395
|
+
const tempDist = bboxToBBoxDistance(getBBox(pointSets, newRanges[0]), polyBBox, kx, ky);
|
|
312
396
|
if (tempDist < miniDist) distQueue.push({dist: tempDist, range1: newRanges[0], range2: [0, 0]});
|
|
313
397
|
}
|
|
314
398
|
if (newRanges[1] !== null) {
|
|
315
|
-
const tempDist = bboxToBBoxDistance(getBBox(pointSets, newRanges[1]), polyBBox,
|
|
399
|
+
const tempDist = bboxToBBoxDistance(getBBox(pointSets, newRanges[1]), polyBBox, kx, ky);
|
|
316
400
|
if (tempDist < miniDist) distQueue.push({dist: tempDist, range1: newRanges[1], range2: [0, 0]});
|
|
317
401
|
}
|
|
318
402
|
}
|
|
@@ -320,8 +404,8 @@ function pointSetToPolygonDistance(pointSets: Array<[number, number]>, isLine: b
|
|
|
320
404
|
return miniDist;
|
|
321
405
|
}
|
|
322
406
|
|
|
323
|
-
function pointSetsDistance(pointSet1: Array<[number, number]>, isLine1: boolean, pointSet2: Array<[number, number]>, isLine2: boolean,
|
|
324
|
-
let miniDist = Math.min(currentMiniDist,
|
|
407
|
+
function pointSetsDistance(pointSet1: Array<[number, number]>, isLine1: boolean, pointSet2: Array<[number, number]>, isLine2: boolean, kx: number, ky: number, currentMiniDist: number = Infinity) {
|
|
408
|
+
let miniDist = Math.min(currentMiniDist, rulerDistance(pointSet1[0], pointSet2[0], kx, ky));
|
|
325
409
|
if (miniDist === 0.0) return miniDist;
|
|
326
410
|
const initialDistPair: DistPair = {
|
|
327
411
|
dist: 0,
|
|
@@ -344,55 +428,55 @@ function pointSetsDistance(pointSet1: Array<[number, number]>, isLine1: boolean,
|
|
|
344
428
|
return NaN;
|
|
345
429
|
}
|
|
346
430
|
if (isLine1 && isLine2) {
|
|
347
|
-
miniDist = Math.min(miniDist, lineToLineDistance(pointSet1, rangeA, pointSet2, rangeB,
|
|
431
|
+
miniDist = Math.min(miniDist, lineToLineDistance(pointSet1, rangeA, pointSet2, rangeB, kx, ky));
|
|
348
432
|
} else if (!isLine1 && !isLine2) {
|
|
349
|
-
miniDist = Math.min(miniDist, pointsToPointsDistance(pointSet1, rangeA, pointSet2, rangeB,
|
|
433
|
+
miniDist = Math.min(miniDist, pointsToPointsDistance(pointSet1, rangeA, pointSet2, rangeB, kx, ky));
|
|
350
434
|
} else if (isLine1 && !isLine2) {
|
|
351
|
-
miniDist = Math.min(miniDist, pointsToLineDistance(pointSet2, rangeB, pointSet1, rangeA,
|
|
435
|
+
miniDist = Math.min(miniDist, pointsToLineDistance(pointSet2, rangeB, pointSet1, rangeA, kx, ky));
|
|
352
436
|
} else if (!isLine1 && isLine2) {
|
|
353
|
-
miniDist = Math.min(miniDist, pointsToLineDistance(pointSet1, rangeA, pointSet2, rangeB,
|
|
437
|
+
miniDist = Math.min(miniDist, pointsToLineDistance(pointSet1, rangeA, pointSet2, rangeB, kx, ky));
|
|
354
438
|
}
|
|
355
439
|
if (miniDist === 0.0) return miniDist;
|
|
356
440
|
} else {
|
|
357
441
|
const newRangesA = splitRange(rangeA, isLine1);
|
|
358
442
|
const newRangesB = splitRange(rangeB, isLine2);
|
|
359
|
-
updateQueue(distQueue, miniDist,
|
|
360
|
-
updateQueue(distQueue, miniDist,
|
|
361
|
-
updateQueue(distQueue, miniDist,
|
|
362
|
-
updateQueue(distQueue, miniDist,
|
|
443
|
+
updateQueue(distQueue, miniDist, kx, ky, pointSet1, pointSet2, newRangesA[0], newRangesB[0]);
|
|
444
|
+
updateQueue(distQueue, miniDist, kx, ky, pointSet1, pointSet2, newRangesA[0], newRangesB[1]);
|
|
445
|
+
updateQueue(distQueue, miniDist, kx, ky, pointSet1, pointSet2, newRangesA[1], newRangesB[0]);
|
|
446
|
+
updateQueue(distQueue, miniDist, kx, ky, pointSet1, pointSet2, newRangesA[1], newRangesB[1]);
|
|
363
447
|
}
|
|
364
448
|
}
|
|
365
449
|
return miniDist;
|
|
366
450
|
}
|
|
367
451
|
|
|
368
|
-
function pointSetToLinesDistance(pointSet: Array<[number, number]>, isLine: boolean, lines: Array<Array<[number, number]>>,
|
|
452
|
+
function pointSetToLinesDistance(pointSet: Array<[number, number]>, isLine: boolean, lines: Array<Array<[number, number]>>, kx: number, ky: number, currentMiniDist: number = Infinity) {
|
|
369
453
|
let dist = currentMiniDist;
|
|
370
454
|
const bbox1 = getBBox(pointSet, [0, pointSet.length - 1]);
|
|
371
455
|
for (const line of lines) {
|
|
372
|
-
if (dist !== Infinity && bboxToBBoxDistance(bbox1, getBBox(line, [0, line.length - 1]),
|
|
373
|
-
dist = Math.min(dist, pointSetsDistance(pointSet, isLine, line, true /*isLine*/,
|
|
456
|
+
if (dist !== Infinity && bboxToBBoxDistance(bbox1, getBBox(line, [0, line.length - 1]), kx, ky) >= dist) continue;
|
|
457
|
+
dist = Math.min(dist, pointSetsDistance(pointSet, isLine, line, true /*isLine*/, kx, ky, dist));
|
|
374
458
|
if (dist === 0.0) return dist;
|
|
375
459
|
}
|
|
376
460
|
return dist;
|
|
377
461
|
}
|
|
378
462
|
|
|
379
|
-
function pointSetToPolygonsDistance(points: Array<[number, number]>, isLine: boolean, polygons: Array<Array<Array<[number, number]>>>,
|
|
463
|
+
function pointSetToPolygonsDistance(points: Array<[number, number]>, isLine: boolean, polygons: Array<Array<Array<[number, number]>>>, kx: number, ky: number, currentMiniDist: number = Infinity) {
|
|
380
464
|
let dist = currentMiniDist;
|
|
381
465
|
const bbox1 = getBBox(points, [0, points.length - 1]);
|
|
382
466
|
for (const polygon of polygons) {
|
|
383
|
-
if (dist !== Infinity && bboxToBBoxDistance(bbox1, getPolygonBBox(polygon),
|
|
384
|
-
const tempDist = pointSetToPolygonDistance(points, isLine, polygon,
|
|
467
|
+
if (dist !== Infinity && bboxToBBoxDistance(bbox1, getPolygonBBox(polygon), kx, ky) >= dist) continue;
|
|
468
|
+
const tempDist = pointSetToPolygonDistance(points, isLine, polygon, kx, ky, dist);
|
|
385
469
|
if (isNaN(tempDist)) return tempDist;
|
|
386
470
|
if ((dist = Math.min(dist, tempDist)) === 0.0) return dist;
|
|
387
471
|
}
|
|
388
472
|
return dist;
|
|
389
473
|
}
|
|
390
474
|
|
|
391
|
-
function polygonsToPolygonsDistance(polygons1: Array<Array<Array<[number, number]>>>, polygons2: Array<Array<Array<[number, number]>>>,
|
|
475
|
+
function polygonsToPolygonsDistance(polygons1: Array<Array<Array<[number, number]>>>, polygons2: Array<Array<Array<[number, number]>>>, kx: number, ky: number) {
|
|
392
476
|
let dist = Infinity;
|
|
393
477
|
for (const polygon1 of polygons1) {
|
|
394
478
|
for (const polygon2 of polygons2) {
|
|
395
|
-
const tempDist = polygonToPolygonDistance(polygon1, polygon2,
|
|
479
|
+
const tempDist = polygonToPolygonDistance(polygon1, polygon2, kx, ky, dist);
|
|
396
480
|
if (isNaN(tempDist)) return tempDist;
|
|
397
481
|
if ((dist = Math.min(dist, tempDist)) === 0.0) return dist;
|
|
398
482
|
}
|
|
@@ -407,18 +491,18 @@ function pointsToGeometryDistance(originGeometry: Array<Array<Point>>, canonical
|
|
|
407
491
|
lngLatPoints.push(getLngLatPoint(point, canonical));
|
|
408
492
|
}
|
|
409
493
|
}
|
|
410
|
-
const
|
|
494
|
+
const [kx, ky] = lngLatScale(lngLatPoints[0][1]);
|
|
411
495
|
if (geometry.type === 'Point' || geometry.type === 'MultiPoint' || geometry.type === 'LineString') {
|
|
412
496
|
return pointSetsDistance(lngLatPoints, false /*isLine*/,
|
|
413
497
|
(geometry.type === 'Point' ? [geometry.coordinates] : geometry.coordinates) as Array<[number, number]>,
|
|
414
|
-
geometry.type === 'LineString' /*isLine*/,
|
|
498
|
+
geometry.type === 'LineString' /*isLine*/, kx, ky);
|
|
415
499
|
}
|
|
416
500
|
if (geometry.type === 'MultiLineString') {
|
|
417
|
-
return pointSetToLinesDistance(lngLatPoints, false /*isLine*/, geometry.coordinates as Array<Array<[number, number]>>,
|
|
501
|
+
return pointSetToLinesDistance(lngLatPoints, false /*isLine*/, geometry.coordinates as Array<Array<[number, number]>>, kx, ky);
|
|
418
502
|
}
|
|
419
503
|
if (geometry.type === 'Polygon' || geometry.type === 'MultiPolygon') {
|
|
420
504
|
return pointSetToPolygonsDistance(lngLatPoints, false /*isLine*/,
|
|
421
|
-
(geometry.type === 'Polygon' ? [geometry.coordinates] : geometry.coordinates) as Array<Array<Array<[number, number]>>>,
|
|
505
|
+
(geometry.type === 'Polygon' ? [geometry.coordinates] : geometry.coordinates) as Array<Array<Array<[number, number]>>>, kx, ky);
|
|
422
506
|
}
|
|
423
507
|
return null;
|
|
424
508
|
}
|
|
@@ -432,16 +516,16 @@ function linesToGeometryDistance(originGeometry: Array<Array<Point>>, canonical:
|
|
|
432
516
|
}
|
|
433
517
|
lngLatLines.push(lngLatLine);
|
|
434
518
|
}
|
|
435
|
-
const
|
|
519
|
+
const [kx, ky] = lngLatScale(lngLatLines[0][0][1]);
|
|
436
520
|
if (geometry.type === 'Point' || geometry.type === 'MultiPoint' || geometry.type === 'LineString') {
|
|
437
521
|
return pointSetToLinesDistance(
|
|
438
522
|
(geometry.type === 'Point' ? [geometry.coordinates] : geometry.coordinates) as Array<[number, number]>,
|
|
439
|
-
geometry.type === 'LineString' /*isLine*/, lngLatLines,
|
|
523
|
+
geometry.type === 'LineString' /*isLine*/, lngLatLines, kx, ky);
|
|
440
524
|
}
|
|
441
525
|
if (geometry.type === 'MultiLineString') {
|
|
442
526
|
let dist = Infinity;
|
|
443
527
|
for (let i = 0; i < geometry.coordinates.length; i++) {
|
|
444
|
-
const tempDist = pointSetToLinesDistance(geometry.coordinates[i] as Array<[number, number]>, true /*isLine*/, lngLatLines,
|
|
528
|
+
const tempDist = pointSetToLinesDistance(geometry.coordinates[i] as Array<[number, number]>, true /*isLine*/, lngLatLines, kx, ky, dist);
|
|
445
529
|
if (isNaN(tempDist)) return tempDist;
|
|
446
530
|
if ((dist = Math.min(dist, tempDist)) === 0.0) return dist;
|
|
447
531
|
}
|
|
@@ -452,7 +536,7 @@ function linesToGeometryDistance(originGeometry: Array<Array<Point>>, canonical:
|
|
|
452
536
|
for (let i = 0; i < lngLatLines.length; i++) {
|
|
453
537
|
const tempDist = pointSetToPolygonsDistance(lngLatLines[i], true /*isLine*/,
|
|
454
538
|
(geometry.type === 'Polygon' ? [geometry.coordinates] : geometry.coordinates) as Array<Array<Array<[number, number]>>>,
|
|
455
|
-
|
|
539
|
+
kx, ky, dist);
|
|
456
540
|
if (isNaN(tempDist)) return tempDist;
|
|
457
541
|
if ((dist = Math.min(dist, tempDist)) === 0.0) return dist;
|
|
458
542
|
}
|
|
@@ -470,16 +554,16 @@ function polygonsToGeometryDistance(originGeometry: Array<Array<Point>>, canonic
|
|
|
470
554
|
}
|
|
471
555
|
lngLatPolygons.push(lngLatPolygon);
|
|
472
556
|
}
|
|
473
|
-
const
|
|
557
|
+
const [kx, ky] = lngLatScale(lngLatPolygons[0][0][0][1]);
|
|
474
558
|
if (geometry.type === 'Point' || geometry.type === 'MultiPoint' || geometry.type === 'LineString') {
|
|
475
559
|
return pointSetToPolygonsDistance(
|
|
476
560
|
(geometry.type === 'Point' ? [geometry.coordinates] : geometry.coordinates) as Array<[number, number]>,
|
|
477
|
-
geometry.type === 'LineString' /*isLine*/, lngLatPolygons,
|
|
561
|
+
geometry.type === 'LineString' /*isLine*/, lngLatPolygons, kx, ky);
|
|
478
562
|
}
|
|
479
563
|
if (geometry.type === 'MultiLineString') {
|
|
480
564
|
let dist = Infinity;
|
|
481
565
|
for (let i = 0; i < geometry.coordinates.length; i++) {
|
|
482
|
-
const tempDist = pointSetToPolygonsDistance(geometry.coordinates[i] as Array<[number, number]>, true /*isLine*/, lngLatPolygons,
|
|
566
|
+
const tempDist = pointSetToPolygonsDistance(geometry.coordinates[i] as Array<[number, number]>, true /*isLine*/, lngLatPolygons, kx, ky, dist);
|
|
483
567
|
if (isNaN(tempDist)) return tempDist;
|
|
484
568
|
if ((dist = Math.min(dist, tempDist)) === 0.0) return dist;
|
|
485
569
|
}
|
|
@@ -488,7 +572,7 @@ function polygonsToGeometryDistance(originGeometry: Array<Array<Point>>, canonic
|
|
|
488
572
|
if (geometry.type === 'Polygon' || geometry.type === 'MultiPolygon') {
|
|
489
573
|
return polygonsToPolygonsDistance(
|
|
490
574
|
(geometry.type === 'Polygon' ? [geometry.coordinates] : geometry.coordinates) as Array<Array<Array<[number, number]>>>,
|
|
491
|
-
lngLatPolygons,
|
|
575
|
+
lngLatPolygons, kx, ky);
|
|
492
576
|
}
|
|
493
577
|
return null;
|
|
494
578
|
}
|
|
@@ -50,28 +50,27 @@ class Match implements Expression {
|
|
|
50
50
|
labels = [labels];
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
const labelContext = context.concat(i);
|
|
54
53
|
if ((labels as unknown[]).length === 0) {
|
|
55
|
-
return
|
|
54
|
+
return context.error('Expected at least one branch label.', i);
|
|
56
55
|
}
|
|
57
56
|
|
|
58
57
|
for (const label of (labels as unknown[])) {
|
|
59
58
|
if (typeof label !== 'number' && typeof label !== 'string') {
|
|
60
|
-
return
|
|
59
|
+
return context.error(`Branch labels must be numbers or strings.`, i);
|
|
61
60
|
} else if (typeof label === 'number' && Math.abs(label) > Number.MAX_SAFE_INTEGER) {
|
|
62
|
-
return
|
|
61
|
+
return context.error(`Branch labels must be integers no larger than ${Number.MAX_SAFE_INTEGER}.`, i);
|
|
63
62
|
|
|
64
63
|
} else if (typeof label === 'number' && Math.floor(label) !== label) {
|
|
65
|
-
return
|
|
64
|
+
return context.error(`Numeric branch labels must be integer values.`, i);
|
|
66
65
|
|
|
67
66
|
} else if (!inputType) {
|
|
68
67
|
inputType = typeOf(label);
|
|
69
|
-
} else if (
|
|
68
|
+
} else if (context.checkSubtype(inputType, typeOf(label), i)) {
|
|
70
69
|
return null;
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
if (typeof cases[String(label)] !== 'undefined') {
|
|
74
|
-
return
|
|
73
|
+
return context.error('Branch labels must be unique.', i);
|
|
75
74
|
}
|
|
76
75
|
|
|
77
76
|
cases[String(label)] = outputs.length;
|
|
@@ -91,7 +90,7 @@ class Match implements Expression {
|
|
|
91
90
|
|
|
92
91
|
assert(inputType && outputType);
|
|
93
92
|
|
|
94
|
-
if (input.type.kind !== 'value' && context.
|
|
93
|
+
if (input.type.kind !== 'value' && context.checkSubtype((inputType), input.type, 1)) {
|
|
95
94
|
return null;
|
|
96
95
|
}
|
|
97
96
|
|
|
@@ -56,13 +56,17 @@ function isStateConstant(e: Expression): boolean {
|
|
|
56
56
|
return result;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
function
|
|
60
|
-
if (e instanceof CompoundExpression && properties.
|
|
59
|
+
function isGlobalPropertyConstantSet(e: Expression, properties: ReadonlySet<string>): boolean {
|
|
60
|
+
if (e instanceof CompoundExpression && properties.has(e.name)) { return false; }
|
|
61
61
|
let result = true;
|
|
62
62
|
e.eachChild((arg) => {
|
|
63
|
-
if (result && !
|
|
63
|
+
if (result && !isGlobalPropertyConstantSet(arg, properties)) { result = false; }
|
|
64
64
|
});
|
|
65
65
|
return result;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
function isGlobalPropertyConstant(e: Expression, properties: Array<string>): boolean {
|
|
69
|
+
return isGlobalPropertyConstantSet(e, new Set(properties));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export {isFeatureConstant, isGlobalPropertyConstant, isGlobalPropertyConstantSet, isStateConstant};
|