@mapbox/mapbox-gl-style-spec 14.25.0 → 14.26.0-rc.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.
- 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
|
@@ -10,7 +10,7 @@ import CollatorExpression from './definitions/collator';
|
|
|
10
10
|
import Within from './definitions/within';
|
|
11
11
|
import Distance from './definitions/distance';
|
|
12
12
|
import Config from './definitions/config';
|
|
13
|
-
import {
|
|
13
|
+
import {isGlobalPropertyConstantSet, isFeatureConstant} from './is_constant';
|
|
14
14
|
import Var from './definitions/var';
|
|
15
15
|
|
|
16
16
|
import type {Expression, ExpressionRegistry} from './expression';
|
|
@@ -36,9 +36,6 @@ class ParsingContext {
|
|
|
36
36
|
// `expectedType`.
|
|
37
37
|
expectedType: Type | null | undefined;
|
|
38
38
|
|
|
39
|
-
// `key` is only consulted on the error path, so compute it lazily.
|
|
40
|
-
private _key: string | undefined;
|
|
41
|
-
|
|
42
39
|
constructor(
|
|
43
40
|
registry: ExpressionRegistry,
|
|
44
41
|
path: Array<number | string> = [],
|
|
@@ -60,16 +57,12 @@ class ParsingContext {
|
|
|
60
57
|
}
|
|
61
58
|
|
|
62
59
|
get key(): string {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const part = path[i];
|
|
68
|
-
key += typeof part === 'string' ? `['${part}']` : `[${part}]`;
|
|
69
|
-
}
|
|
70
|
-
this._key = key;
|
|
60
|
+
let key = '';
|
|
61
|
+
for (let i = 0; i < this.path.length; i++) {
|
|
62
|
+
const part = this.path[i];
|
|
63
|
+
key += typeof part === 'string' ? `['${part}']` : `[${part}]`;
|
|
71
64
|
}
|
|
72
|
-
return
|
|
65
|
+
return key;
|
|
73
66
|
}
|
|
74
67
|
|
|
75
68
|
/**
|
|
@@ -89,7 +82,17 @@ class ParsingContext {
|
|
|
89
82
|
} = {},
|
|
90
83
|
): Expression | null | void {
|
|
91
84
|
if (index || expectedType) {
|
|
92
|
-
|
|
85
|
+
const prevExpectedType = this.expectedType;
|
|
86
|
+
const prevScope = this.scope;
|
|
87
|
+
if (bindings) this.scope = this.scope.concat(bindings);
|
|
88
|
+
this.expectedType = expectedType || null;
|
|
89
|
+
const pushed = typeof index === 'number';
|
|
90
|
+
if (pushed) this.path.push(index);
|
|
91
|
+
const result = this._parse(expr, options);
|
|
92
|
+
if (pushed) this.path.pop();
|
|
93
|
+
this.expectedType = prevExpectedType;
|
|
94
|
+
this.scope = prevScope;
|
|
95
|
+
return result;
|
|
93
96
|
}
|
|
94
97
|
return this._parse(expr, options);
|
|
95
98
|
}
|
|
@@ -112,7 +115,18 @@ class ParsingContext {
|
|
|
112
115
|
typeAnnotation?: 'assert' | 'coerce' | 'omit';
|
|
113
116
|
} = {},
|
|
114
117
|
): Expression | null | void {
|
|
115
|
-
|
|
118
|
+
const prevExpectedType = this.expectedType;
|
|
119
|
+
const prevScope = this.scope;
|
|
120
|
+
if (bindings) this.scope = this.scope.concat(bindings);
|
|
121
|
+
this.expectedType = expectedType || null;
|
|
122
|
+
this.path.push(index);
|
|
123
|
+
this.path.push(key);
|
|
124
|
+
const result = this._parse(expr, options);
|
|
125
|
+
this.path.pop();
|
|
126
|
+
this.path.pop();
|
|
127
|
+
this.expectedType = prevExpectedType;
|
|
128
|
+
this.scope = prevScope;
|
|
129
|
+
return result;
|
|
116
130
|
}
|
|
117
131
|
|
|
118
132
|
_parse(
|
|
@@ -125,16 +139,6 @@ class ParsingContext {
|
|
|
125
139
|
expr = ['literal', expr];
|
|
126
140
|
}
|
|
127
141
|
|
|
128
|
-
function annotate(parsed: Expression, type: Type, typeAnnotation: 'assert' | 'coerce' | 'omit') {
|
|
129
|
-
if (typeAnnotation === 'assert') {
|
|
130
|
-
return new Assertion(type, [parsed]);
|
|
131
|
-
} else if (typeAnnotation === 'coerce') {
|
|
132
|
-
return new Coercion(type, [parsed]);
|
|
133
|
-
} else {
|
|
134
|
-
return parsed;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
142
|
if (Array.isArray(expr)) {
|
|
139
143
|
if (expr.length === 0) {
|
|
140
144
|
return this.error(`Expected an array with at least one element. If you wanted a literal array, use ["literal", []].`);
|
|
@@ -209,9 +213,10 @@ class ParsingContext {
|
|
|
209
213
|
expectedType?: Type | null,
|
|
210
214
|
bindings?: Array<[string, Expression]>,
|
|
211
215
|
): ParsingContext {
|
|
212
|
-
let path = typeof index === 'number' ? this.path.concat(index) : this.path;
|
|
213
|
-
path = typeof key === 'string' ? path.concat(key) : path;
|
|
214
216
|
const scope = bindings ? this.scope.concat(bindings) : this.scope;
|
|
217
|
+
const path = this.path.slice();
|
|
218
|
+
if (typeof index === 'number') path.push(index);
|
|
219
|
+
if (typeof key === 'string') path.push(key);
|
|
215
220
|
return new ParsingContext(
|
|
216
221
|
this.registry,
|
|
217
222
|
path,
|
|
@@ -224,6 +229,25 @@ class ParsingContext {
|
|
|
224
229
|
);
|
|
225
230
|
}
|
|
226
231
|
|
|
232
|
+
/**
|
|
233
|
+
* Returns a fresh context that shares the same path position as this one
|
|
234
|
+
* but has an empty errors array. Used by CompoundExpression to probe
|
|
235
|
+
* overload signatures without polluting the parent errors list.
|
|
236
|
+
* @private
|
|
237
|
+
*/
|
|
238
|
+
_forkForSignature(): ParsingContext {
|
|
239
|
+
return new ParsingContext(
|
|
240
|
+
this.registry,
|
|
241
|
+
this.path.slice(),
|
|
242
|
+
null,
|
|
243
|
+
this.scope,
|
|
244
|
+
[],
|
|
245
|
+
this._scope,
|
|
246
|
+
this.options,
|
|
247
|
+
this.iconImageUseTheme
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
|
|
227
251
|
/**
|
|
228
252
|
* Push a parsing (or type checking) error into the `this.errors`
|
|
229
253
|
* @param error The message
|
|
@@ -249,6 +273,22 @@ class ParsingContext {
|
|
|
249
273
|
|
|
250
274
|
export default ParsingContext;
|
|
251
275
|
|
|
276
|
+
const CONSTANT_FOLD_EXCLUDED_GLOBALS = new Set([
|
|
277
|
+
'zoom', 'heatmap-density', 'worldview', 'line-progress', 'raster-value',
|
|
278
|
+
'sky-radial-progress', 'accumulated', 'is-supported-script', 'pitch',
|
|
279
|
+
'distance-from-center', 'measure-light', 'raster-particle-speed', 'is-active-floor',
|
|
280
|
+
]);
|
|
281
|
+
|
|
282
|
+
function annotate(parsed: Expression, type: Type, typeAnnotation: 'assert' | 'coerce' | 'omit') {
|
|
283
|
+
if (typeAnnotation === 'assert') {
|
|
284
|
+
return new Assertion(type, [parsed]);
|
|
285
|
+
} else if (typeAnnotation === 'coerce') {
|
|
286
|
+
return new Coercion(type, [parsed]);
|
|
287
|
+
} else {
|
|
288
|
+
return parsed;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
252
292
|
function isConstant(expression: Expression) {
|
|
253
293
|
if (expression instanceof Var) {
|
|
254
294
|
return isConstant(expression.boundExpression);
|
|
@@ -290,5 +330,5 @@ function isConstant(expression: Expression) {
|
|
|
290
330
|
}
|
|
291
331
|
|
|
292
332
|
return isFeatureConstant(expression) &&
|
|
293
|
-
|
|
333
|
+
isGlobalPropertyConstantSet(expression, CONSTANT_FOLD_EXCLUDED_GLOBALS);
|
|
294
334
|
}
|
package/function/index.ts
CHANGED
|
@@ -33,7 +33,7 @@ export function createFunction(parameters, propertySpec) {
|
|
|
33
33
|
|
|
34
34
|
if (isColor) {
|
|
35
35
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
36
|
-
parameters =
|
|
36
|
+
parameters = {...parameters};
|
|
37
37
|
|
|
38
38
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
39
39
|
if (parameters.stops) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mapbox/mapbox-gl-style-spec",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.26.0-rc.1",
|
|
4
4
|
"description": "a specification for mapbox gl styles",
|
|
5
5
|
"author": "Mapbox",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
@@ -46,7 +46,6 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@mapbox/point-geometry": "^1.1.0",
|
|
48
48
|
"@mapbox/unitbezier": "^1.0.0",
|
|
49
|
-
"cheap-ruler": "^4.0.0",
|
|
50
49
|
"csscolorparser": "~1.0.3",
|
|
51
50
|
"json-stringify-pretty-compact": "^4.0.0",
|
|
52
51
|
"quickselect": "^3.0.0",
|
package/reference/v8.json
CHANGED
|
@@ -1335,6 +1335,24 @@
|
|
|
1335
1335
|
"units": "degrees",
|
|
1336
1336
|
"doc": "Override the orientation of the model node in euler angles [x, y, z]."
|
|
1337
1337
|
}
|
|
1338
|
+
},
|
|
1339
|
+
"modelLightOverrides": {
|
|
1340
|
+
"light-ambient-color": {
|
|
1341
|
+
"type": "color",
|
|
1342
|
+
"doc": "Override the color of ambient lights."
|
|
1343
|
+
},
|
|
1344
|
+
"light-ambient-intensity": {
|
|
1345
|
+
"type": "number",
|
|
1346
|
+
"doc": "Override the intensity of light-ambient-color (on a scale from 0 to 1)."
|
|
1347
|
+
},
|
|
1348
|
+
"light-directional-color": {
|
|
1349
|
+
"type": "color",
|
|
1350
|
+
"doc": "Override the color of directional lights."
|
|
1351
|
+
},
|
|
1352
|
+
"light-directional-intensity": {
|
|
1353
|
+
"type": "number",
|
|
1354
|
+
"doc": "Override the intensity of light-directional-color (on a scale from 0 to 1)."
|
|
1355
|
+
}
|
|
1338
1356
|
},
|
|
1339
1357
|
"modelNodeOverrides": {
|
|
1340
1358
|
"*": {
|
|
@@ -1393,6 +1411,11 @@
|
|
|
1393
1411
|
"units": "degrees",
|
|
1394
1412
|
"doc": "Orientation of the model in euler angles [x, y, z]."
|
|
1395
1413
|
},
|
|
1414
|
+
"lightOverrides": {
|
|
1415
|
+
"type": "modelLightOverrides",
|
|
1416
|
+
"required": false,
|
|
1417
|
+
"doc": "A collection of light overrides."
|
|
1418
|
+
},
|
|
1396
1419
|
"nodeOverrides": {
|
|
1397
1420
|
"type": "modelNodeOverrides",
|
|
1398
1421
|
"required": false,
|
|
@@ -6653,13 +6676,6 @@
|
|
|
6653
6676
|
"doc": "Projection where objects are of the same scale regardless of whether they are far away or near to the camera. Parallel lines remains parallel and there is no vanishing point."
|
|
6654
6677
|
}
|
|
6655
6678
|
},
|
|
6656
|
-
"transition": true,
|
|
6657
|
-
"expression": {
|
|
6658
|
-
"interpolated": true,
|
|
6659
|
-
"parameters": [
|
|
6660
|
-
"zoom"
|
|
6661
|
-
]
|
|
6662
|
-
},
|
|
6663
6679
|
"sdk-support": {
|
|
6664
6680
|
"basic functionality": {
|
|
6665
6681
|
"js": "3.0.0",
|
package/types.ts
CHANGED
|
@@ -130,6 +130,12 @@ export type ModelsSpecification = {
|
|
|
130
130
|
[_: string]: ModelSpecification
|
|
131
131
|
};
|
|
132
132
|
|
|
133
|
+
export type ModelLightOverridesSpecification = {
|
|
134
|
+
"light-ambient-color"?: ColorSpecification,
|
|
135
|
+
"light-ambient-intensity"?: number,
|
|
136
|
+
"light-directional-color"?: ColorSpecification,
|
|
137
|
+
"light-directional-intensity"?: number
|
|
138
|
+
};
|
|
133
139
|
export type ModelNodeOverrideSpecification = {
|
|
134
140
|
"orientation"?: [number, number, number]
|
|
135
141
|
};
|
|
@@ -152,6 +158,7 @@ export type ModelSourceModelSpecification = {
|
|
|
152
158
|
"uri": string,
|
|
153
159
|
"position"?: [number, number],
|
|
154
160
|
"orientation"?: [number, number, number],
|
|
161
|
+
"lightOverrides"?: ModelLightOverridesSpecification,
|
|
155
162
|
"nodeOverrides"?: ModelNodeOverridesSpecification,
|
|
156
163
|
"materialOverrides"?: ModelMaterialOverridesSpecification,
|
|
157
164
|
"nodeOverrideNames"?: Array<string>,
|
|
@@ -310,8 +317,7 @@ export type RainSpecification = {
|
|
|
310
317
|
};
|
|
311
318
|
|
|
312
319
|
export type CameraSpecification = {
|
|
313
|
-
"camera-projection"?:
|
|
314
|
-
"camera-projection-transition"?: TransitionSpecification
|
|
320
|
+
"camera-projection"?: "perspective" | "orthographic"
|
|
315
321
|
};
|
|
316
322
|
|
|
317
323
|
export type ColorThemeSpecification = {
|
package/util/geometry_util.ts
CHANGED
|
@@ -14,15 +14,15 @@ export type BBox = [number, number, number, number];
|
|
|
14
14
|
export function calculateSignedArea(ring: Ring): number {
|
|
15
15
|
let sum = 0;
|
|
16
16
|
for (let i = 0, len = ring.length, j = len - 1, p1: Point, p2: Point; i < len; j = i++) {
|
|
17
|
-
p1 = ring[i];
|
|
18
|
-
p2 = ring[j];
|
|
17
|
+
p1 = ring[i] as Point;
|
|
18
|
+
p2 = ring[j] as Point;
|
|
19
19
|
sum += (p2.x - p1.x) * (p1.y + p2.y);
|
|
20
20
|
}
|
|
21
21
|
return sum;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
function compareAreas(a: Ring, b: Ring): number {
|
|
25
|
-
return b.area - a.area;
|
|
25
|
+
return (b.area as number) - (a.area as number);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// classifies an array of rings into polygons with outer rings and holes
|
|
@@ -32,22 +32,22 @@ export function classifyRings(rings: Array<Ring>, maxRings: number): Array<Array
|
|
|
32
32
|
if (len <= 1) return [rings];
|
|
33
33
|
|
|
34
34
|
const polygons: Array<Array<Ring>> = [];
|
|
35
|
-
let polygon: Array<Ring
|
|
36
|
-
ccw: boolean;
|
|
35
|
+
let polygon: Array<Ring> | undefined,
|
|
36
|
+
ccw: boolean | undefined;
|
|
37
37
|
|
|
38
38
|
for (let i = 0; i < len; i++) {
|
|
39
|
-
const area = calculateSignedArea(rings[i]);
|
|
39
|
+
const area = calculateSignedArea(rings[i] as Ring);
|
|
40
40
|
if (area === 0) continue;
|
|
41
41
|
|
|
42
|
-
rings[i].area = Math.abs(area);
|
|
42
|
+
(rings[i] as Ring).area = Math.abs(area);
|
|
43
43
|
|
|
44
44
|
if (ccw === undefined) ccw = area < 0;
|
|
45
45
|
|
|
46
46
|
if (ccw === area < 0) {
|
|
47
47
|
if (polygon) polygons.push(polygon);
|
|
48
|
-
polygon = [rings[i]];
|
|
48
|
+
polygon = [rings[i] as Ring];
|
|
49
49
|
} else {
|
|
50
|
-
(polygon).push(rings[i]);
|
|
50
|
+
(polygon as Array<Ring>).push(rings[i] as Ring);
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
if (polygon) polygons.push(polygon);
|
|
@@ -56,9 +56,10 @@ export function classifyRings(rings: Array<Ring>, maxRings: number): Array<Array
|
|
|
56
56
|
// reason, we limit strip out all but the `maxRings` largest rings.
|
|
57
57
|
if (maxRings > 1) {
|
|
58
58
|
for (let j = 0; j < polygons.length; j++) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
const currentPolygon = polygons[j] as Array<Ring>;
|
|
60
|
+
if (currentPolygon.length <= maxRings) continue;
|
|
61
|
+
quickselect(currentPolygon, maxRings, 1, currentPolygon.length - 1, compareAreas);
|
|
62
|
+
polygons[j] = currentPolygon.slice(0, maxRings);
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
65
|
|
|
@@ -66,10 +67,10 @@ export function classifyRings(rings: Array<Ring>, maxRings: number): Array<Array
|
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
export function updateBBox(bbox: BBox, coord: GeoJSON.Position) {
|
|
69
|
-
bbox[0] = Math.min(bbox[0], coord[0]);
|
|
70
|
-
bbox[1] = Math.min(bbox[1], coord[1]);
|
|
71
|
-
bbox[2] = Math.max(bbox[2], coord[0]);
|
|
72
|
-
bbox[3] = Math.max(bbox[3], coord[1]);
|
|
70
|
+
bbox[0] = Math.min(bbox[0], coord[0] as number);
|
|
71
|
+
bbox[1] = Math.min(bbox[1], coord[1] as number);
|
|
72
|
+
bbox[2] = Math.max(bbox[2], coord[0] as number);
|
|
73
|
+
bbox[3] = Math.max(bbox[3], coord[1] as number);
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
export function boxWithinBox(bbox1: BBox, bbox2: BBox): boolean {
|
|
@@ -81,15 +82,15 @@ export function boxWithinBox(bbox1: BBox, bbox2: BBox): boolean {
|
|
|
81
82
|
}
|
|
82
83
|
|
|
83
84
|
function onBoundary(p: GeoJSON.Position, p1: GeoJSON.Position, p2: GeoJSON.Position) {
|
|
84
|
-
const x1 = p[0] - p1[0];
|
|
85
|
-
const y1 = p[1] - p1[1];
|
|
86
|
-
const x2 = p[0] - p2[0];
|
|
87
|
-
const y2 = p[1] - p2[1];
|
|
85
|
+
const x1 = (p[0] as number) - (p1[0] as number);
|
|
86
|
+
const y1 = (p[1] as number) - (p1[1] as number);
|
|
87
|
+
const x2 = (p[0] as number) - (p2[0] as number);
|
|
88
|
+
const y2 = (p[1] as number) - (p2[1] as number);
|
|
88
89
|
return (x1 * y2 - x2 * y1 === 0) && (x1 * x2 <= 0) && (y1 * y2 <= 0);
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
function rayIntersect(p: GeoJSON.Position, p1: GeoJSON.Position, p2: GeoJSON.Position) {
|
|
92
|
-
return ((p1[1] > p[1]) !== (p2[1] > p[1])) && (p[0] < (p2[0] - p1[0]) * (p[1] - p1[1]) / (p2[1] - p1[1]) + p1[0]);
|
|
93
|
+
return (((p1[1] as number) > (p[1] as number)) !== ((p2[1] as number) > (p[1] as number))) && ((p[0] as number) < ((p2[0] as number) - (p1[0] as number)) * ((p[1] as number) - (p1[1] as number)) / ((p2[1] as number) - (p1[1] as number)) + (p1[0] as number));
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
// ray casting algorithm for detecting if point is in polygon
|
|
@@ -100,10 +101,10 @@ export function pointWithinPolygon(
|
|
|
100
101
|
): boolean {
|
|
101
102
|
let inside = false;
|
|
102
103
|
for (let i = 0, len = rings.length; i < len; i++) {
|
|
103
|
-
const ring = rings[i]
|
|
104
|
+
const ring = rings[i] as Array<GeoJSON.Position>;
|
|
104
105
|
for (let j = 0, len2 = ring.length, k = len2 - 1; j < len2; k = j++) {
|
|
105
|
-
const q1 = ring[k];
|
|
106
|
-
const q2 = ring[j];
|
|
106
|
+
const q1 = ring[k] as GeoJSON.Position;
|
|
107
|
+
const q2 = ring[j] as GeoJSON.Position;
|
|
107
108
|
if (onBoundary(point, q1, q2)) return trueOnBoundary;
|
|
108
109
|
if (rayIntersect(point, q1, q2)) inside = !inside;
|
|
109
110
|
}
|
|
@@ -112,18 +113,18 @@ export function pointWithinPolygon(
|
|
|
112
113
|
}
|
|
113
114
|
|
|
114
115
|
function perp(v1: GeoJSON.Position, v2: GeoJSON.Position) {
|
|
115
|
-
return v1[0] * v2[1] - v1[1] * v2[0];
|
|
116
|
+
return (v1[0] as number) * (v2[1] as number) - (v1[1] as number) * (v2[0] as number);
|
|
116
117
|
}
|
|
117
118
|
|
|
118
119
|
// check if p1 and p2 are in different sides of line segment q1->q2
|
|
119
120
|
function twoSided(p1: GeoJSON.Position, p2: GeoJSON.Position, q1: GeoJSON.Position, q2: GeoJSON.Position) {
|
|
120
121
|
// q1->p1 (x1, y1), q1->p2 (x2, y2), q1->q2 (x3, y3)
|
|
121
|
-
const x1 = p1[0] - q1[0];
|
|
122
|
-
const y1 = p1[1] - q1[1];
|
|
123
|
-
const x2 = p2[0] - q1[0];
|
|
124
|
-
const y2 = p2[1] - q1[1];
|
|
125
|
-
const x3 = q2[0] - q1[0];
|
|
126
|
-
const y3 = q2[1] - q1[1];
|
|
122
|
+
const x1 = (p1[0] as number) - (q1[0] as number);
|
|
123
|
+
const y1 = (p1[1] as number) - (q1[1] as number);
|
|
124
|
+
const x2 = (p2[0] as number) - (q1[0] as number);
|
|
125
|
+
const y2 = (p2[1] as number) - (q1[1] as number);
|
|
126
|
+
const x3 = (q2[0] as number) - (q1[0] as number);
|
|
127
|
+
const y3 = (q2[1] as number) - (q1[1] as number);
|
|
127
128
|
const det1 = x1 * y3 - x3 * y1;
|
|
128
129
|
const det2 = x2 * y3 - x3 * y2;
|
|
129
130
|
if ((det1 > 0 && det2 < 0) || (det1 < 0 && det2 > 0)) return true;
|
|
@@ -139,8 +140,8 @@ export function segmentIntersectSegment(
|
|
|
139
140
|
// check if two segments are parallel or not
|
|
140
141
|
// precondition is end point a, b is inside polygon, if line a->b is
|
|
141
142
|
// parallel to polygon edge c->d, then a->b won't intersect with c->d
|
|
142
|
-
const vectorP = [b[0] - a[0], b[1] - a[1]];
|
|
143
|
-
const vectorQ = [d[0] - c[0], d[1] - c[1]];
|
|
143
|
+
const vectorP = [(b[0] as number) - (a[0] as number), (b[1] as number) - (a[1] as number)];
|
|
144
|
+
const vectorQ = [(d[0] as number) - (c[0] as number), (d[1] as number) - (c[1] as number)];
|
|
144
145
|
if (perp(vectorQ, vectorP) === 0) return false;
|
|
145
146
|
|
|
146
147
|
// If lines are intersecting with each other, the relative location should be:
|
|
@@ -159,7 +160,7 @@ export function computeBounds(points: Point[][]): Bounds {
|
|
|
159
160
|
const min = new Point(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);
|
|
160
161
|
const max = new Point(Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY);
|
|
161
162
|
|
|
162
|
-
for (const point of points[0]) {
|
|
163
|
+
for (const point of points[0] as Point[]) {
|
|
163
164
|
if (min.x > point.x) min.x = point.x;
|
|
164
165
|
if (min.y > point.y) min.y = point.y;
|
|
165
166
|
if (max.x < point.x) max.x = point.x;
|
package/util/interpolate.ts
CHANGED
|
@@ -14,6 +14,6 @@ export function color(from: Color, to: Color, t: number): Color {
|
|
|
14
14
|
|
|
15
15
|
export function array(from: Array<number>, to: Array<number>, t: number): Array<number> {
|
|
16
16
|
return from.map((d, i) => {
|
|
17
|
-
return number(d, to[i], t);
|
|
17
|
+
return number(d, to[i] as number, t);
|
|
18
18
|
});
|
|
19
19
|
}
|
package/validate/validate.ts
CHANGED
|
@@ -117,10 +117,11 @@ export default function validate(options: ValidatorOptions, arrayAsExpression: b
|
|
|
117
117
|
return errors;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
const errors = validateObject(
|
|
120
|
+
const errors = validateObject({
|
|
121
|
+
...options,
|
|
121
122
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
122
123
|
valueSpec: valueSpec.type ? styleSpec[valueSpec.type] : valueSpec
|
|
123
|
-
})
|
|
124
|
+
});
|
|
124
125
|
|
|
125
126
|
return errors;
|
|
126
127
|
}
|
|
@@ -33,8 +33,8 @@ export default function validateAppearance(options: AppearanceValidatorOptions):
|
|
|
33
33
|
style: options.style,
|
|
34
34
|
styleSpec: options.styleSpec,
|
|
35
35
|
objectElementValidators: {
|
|
36
|
-
condition: (options) => validateCondition(
|
|
37
|
-
properties: (options) => validateProperties(
|
|
36
|
+
condition: (options) => validateCondition({layer, layerType, ...options}),
|
|
37
|
+
properties: (options) => validateProperties({layer, layerType, ...options}),
|
|
38
38
|
}
|
|
39
39
|
});
|
|
40
40
|
|
|
@@ -65,7 +65,8 @@ function validateProperties(options: AppearanceValidatorOptions): Array<Validati
|
|
|
65
65
|
continue;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
const propertyValidationOptions =
|
|
68
|
+
const propertyValidationOptions = {
|
|
69
|
+
...options,
|
|
69
70
|
key: `${options.key}.${propertyKey}`,
|
|
70
71
|
object: properties,
|
|
71
72
|
objectKey: propertyKey,
|
|
@@ -73,7 +74,7 @@ function validateProperties(options: AppearanceValidatorOptions): Array<Validati
|
|
|
73
74
|
layerType,
|
|
74
75
|
value: properties[propertyKey] as unknown,
|
|
75
76
|
valueSpec: (propertyType === 'paint' ? paintProperties[propertyKey] : layoutProperties[propertyKey]),
|
|
76
|
-
}
|
|
77
|
+
};
|
|
77
78
|
|
|
78
79
|
errors.push(...validateProperty(propertyValidationOptions, propertyType));
|
|
79
80
|
}
|
|
@@ -25,11 +25,12 @@ export default function validateFilter(options: FilterValidatorOptions): Validat
|
|
|
25
25
|
// We default to a layerType of `fill` because that points to a non-dynamic filter definition within the style-spec.
|
|
26
26
|
const layerType = options.layerType || 'fill';
|
|
27
27
|
|
|
28
|
-
return validateExpression(
|
|
28
|
+
return validateExpression({
|
|
29
|
+
...options,
|
|
29
30
|
expressionContext: 'filter' as const,
|
|
30
31
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
31
32
|
valueSpec: options.styleSpec[`filter_${layerType}`]
|
|
32
|
-
})
|
|
33
|
+
});
|
|
33
34
|
} else {
|
|
34
35
|
return validateNonExpressionFilter(options);
|
|
35
36
|
}
|
|
@@ -30,11 +30,12 @@ export default function validateImport(options: ImportValidatorOptions): Validat
|
|
|
30
30
|
enumerable: false
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
let errors = validateObject(
|
|
33
|
+
let errors = validateObject({
|
|
34
|
+
...options,
|
|
34
35
|
value: importSpec,
|
|
35
36
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
36
37
|
valueSpec: styleSpec.import
|
|
37
|
-
})
|
|
38
|
+
});
|
|
38
39
|
|
|
39
40
|
// Empty string is reserved for the root style id
|
|
40
41
|
if (unbundle(importSpec.id) === '') {
|
|
@@ -132,7 +132,7 @@ export default function validateLayer(options: LayerValidatorOptions): Validatio
|
|
|
132
132
|
});
|
|
133
133
|
},
|
|
134
134
|
filter(options) {
|
|
135
|
-
return validateFilter(
|
|
135
|
+
return validateFilter({layerType: type, ...options});
|
|
136
136
|
},
|
|
137
137
|
layout(options) {
|
|
138
138
|
return validateObject({
|
|
@@ -144,7 +144,7 @@ export default function validateLayer(options: LayerValidatorOptions): Validatio
|
|
|
144
144
|
styleSpec: options.styleSpec,
|
|
145
145
|
objectElementValidators: {
|
|
146
146
|
'*'(options: PropertyValidatorOptions) {
|
|
147
|
-
return validateLayoutProperty(
|
|
147
|
+
return validateLayoutProperty({layerType: type, ...options});
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
});
|
|
@@ -159,7 +159,7 @@ export default function validateLayer(options: LayerValidatorOptions): Validatio
|
|
|
159
159
|
styleSpec: options.styleSpec,
|
|
160
160
|
objectElementValidators: {
|
|
161
161
|
'*'(options: PropertyValidatorOptions) {
|
|
162
|
-
return validatePaintProperty(
|
|
162
|
+
return validatePaintProperty({layerType: type, layer, ...options});
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
165
|
});
|
|
@@ -172,7 +172,7 @@ export default function validateLayer(options: LayerValidatorOptions): Validatio
|
|
|
172
172
|
valueSpec: options.valueSpec,
|
|
173
173
|
style: options.style,
|
|
174
174
|
styleSpec: options.styleSpec,
|
|
175
|
-
arrayElementValidator: (options) => validateAppearance(
|
|
175
|
+
arrayElementValidator: (options) => validateAppearance(({layerType: type, layer, ...(options as object)}) as AppearanceValidatorOptions)
|
|
176
176
|
});
|
|
177
177
|
// Check non-repeated names on a given layer
|
|
178
178
|
const appearances = Array.isArray(options.value) ? options.value : [];
|
|
@@ -19,7 +19,8 @@ export default function validateOption(options: ValidatorOptions): ValidationErr
|
|
|
19
19
|
const isArrayOption = isObject(optionValue) && unbundle(optionValue.array) === true;
|
|
20
20
|
const declaredType = !isArrayOption && isObject(optionValue) ? unbundle(optionValue.type) : undefined;
|
|
21
21
|
|
|
22
|
-
return validateObject(
|
|
22
|
+
return validateObject({
|
|
23
|
+
...options,
|
|
23
24
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
24
25
|
valueSpec: styleSpec.option,
|
|
25
26
|
objectElementValidators: declaredType ? {
|
|
@@ -28,10 +29,8 @@ export default function validateOption(options: ValidatorOptions): ValidationErr
|
|
|
28
29
|
// permissive validation, mirroring the runtime parser's narrowing
|
|
29
30
|
// in style.ts/parser.cpp.
|
|
30
31
|
default: (elementOptions: ValidatorOptions): ValidationError[] => (Array.isArray(elementOptions.value) ?
|
|
31
|
-
validateSpec(
|
|
32
|
-
valueSpec: Object.assign({}, elementOptions.valueSpec, {type: declaredType}),
|
|
33
|
-
})) :
|
|
32
|
+
validateSpec({...elementOptions, valueSpec: {...elementOptions.valueSpec, type: declaredType} as typeof elementOptions.valueSpec}) :
|
|
34
33
|
validateSpec(elementOptions)),
|
|
35
34
|
} : undefined,
|
|
36
|
-
})
|
|
35
|
+
});
|
|
37
36
|
}
|
|
@@ -14,12 +14,11 @@ export default function validateStyle(style: unknown, styleSpec: StyleReference
|
|
|
14
14
|
key: options.key || '',
|
|
15
15
|
value: style,
|
|
16
16
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
17
|
-
valueSpec:
|
|
18
|
-
|
|
19
|
-
styleSpec.$root,
|
|
17
|
+
valueSpec: {
|
|
18
|
+
...styleSpec.$root,
|
|
20
19
|
// Skip validation of the root properties that are not defined in the style spec (e.g. 'owner').
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
'*': {type: '*'},
|
|
21
|
+
},
|
|
23
22
|
styleSpec,
|
|
24
23
|
style,
|
|
25
24
|
objectElementValidators: {
|