@mapbox/mapbox-gl-style-spec 14.25.0-rc.1 → 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 CHANGED
@@ -1300,6 +1300,24 @@
1300
1300
  doc: "Override the orientation of the model node in euler angles [x, y, z]."
1301
1301
  }
1302
1302
  };
1303
+ var modelLightOverrides = {
1304
+ "light-ambient-color": {
1305
+ type: "color",
1306
+ doc: "Override the color of ambient lights."
1307
+ },
1308
+ "light-ambient-intensity": {
1309
+ type: "number",
1310
+ doc: "Override the intensity of light-ambient-color (on a scale from 0 to 1)."
1311
+ },
1312
+ "light-directional-color": {
1313
+ type: "color",
1314
+ doc: "Override the color of directional lights."
1315
+ },
1316
+ "light-directional-intensity": {
1317
+ type: "number",
1318
+ doc: "Override the intensity of light-directional-color (on a scale from 0 to 1)."
1319
+ }
1320
+ };
1303
1321
  var modelNodeOverrides = {
1304
1322
  "*": {
1305
1323
  type: "modelNodeOverride",
@@ -1370,6 +1388,11 @@
1370
1388
  units: "degrees",
1371
1389
  doc: "Orientation of the model in euler angles [x, y, z]."
1372
1390
  },
1391
+ lightOverrides: {
1392
+ type: "modelLightOverrides",
1393
+ required: false,
1394
+ doc: "A collection of light overrides."
1395
+ },
1373
1396
  nodeOverrides: {
1374
1397
  type: "modelNodeOverrides",
1375
1398
  required: false,
@@ -6527,13 +6550,6 @@
6527
6550
  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."
6528
6551
  }
6529
6552
  },
6530
- transition: true,
6531
- expression: {
6532
- interpolated: true,
6533
- parameters: [
6534
- "zoom"
6535
- ]
6536
- },
6537
6553
  "sdk-support": {
6538
6554
  "basic functionality": {
6539
6555
  js: "3.0.0",
@@ -10522,29 +10538,6 @@
10522
10538
  },
10523
10539
  transition: true
10524
10540
  },
10525
- "model-lightmap-intensity": {
10526
- type: "number",
10527
- "default": 0,
10528
- minimum: 0,
10529
- doc: "Controls the intensity of the model lightmap contribution. Values less than or equal to 0.001 are treated as off.",
10530
- "private": true,
10531
- experimental: true,
10532
- expression: {
10533
- interpolated: true,
10534
- parameters: [
10535
- "zoom"
10536
- ]
10537
- },
10538
- "sdk-support": {
10539
- "basic functionality": {
10540
- js: "3.25.0",
10541
- android: "11.25.0",
10542
- ios: "11.25.0"
10543
- }
10544
- },
10545
- "property-type": "data-constant",
10546
- transition: true
10547
- },
10548
10541
  "model-type": {
10549
10542
  type: "enum",
10550
10543
  values: {
@@ -10965,6 +10958,7 @@
10965
10958
  source_video: source_video,
10966
10959
  source_image: source_image,
10967
10960
  modelNodeOverride: modelNodeOverride,
10961
+ modelLightOverrides: modelLightOverrides,
10968
10962
  modelNodeOverrides: modelNodeOverrides,
10969
10963
  modelMaterialOverride: modelMaterialOverride,
10970
10964
  modelMaterialOverrides: modelMaterialOverrides,
@@ -14009,7 +14003,7 @@
14009
14003
  overloadParams.push(params);
14010
14004
  overloadIndex++;
14011
14005
  if (signatureContext === null) {
14012
- signatureContext = new ParsingContext(context.registry, context.path, null, context.scope, [], context._scope, context.options, context.iconImageUseTheme);
14006
+ signatureContext = context._forkForSignature();
14013
14007
  } else {
14014
14008
  signatureContext.errors.length = 0;
14015
14009
  }
@@ -14772,485 +14766,6 @@
14772
14766
  }
14773
14767
  }
14774
14768
 
14775
- const factors = {
14776
- kilometers: 1,
14777
- miles: 1000 / 1609.344,
14778
- nauticalmiles: 1000 / 1852,
14779
- meters: 1000,
14780
- metres: 1000,
14781
- yards: 1000 / 0.9144,
14782
- feet: 1000 / 0.3048,
14783
- inches: 1000 / 0.0254
14784
- };
14785
-
14786
- // Values that define WGS84 ellipsoid model of the Earth
14787
- const RE = 6378.137; // equatorial radius
14788
- const FE = 1 / 298.257223563; // flattening
14789
-
14790
- const E2 = FE * (2 - FE);
14791
- const RAD = Math.PI / 180;
14792
-
14793
- /**
14794
- * A collection of very fast approximations to common geodesic measurements. Useful for performance-sensitive code that measures things on a city scale.
14795
- */
14796
- class CheapRuler {
14797
- /**
14798
- * Creates a ruler object from tile coordinates (y and z).
14799
- *
14800
- * @param {number} y
14801
- * @param {number} z
14802
- * @param {keyof typeof factors} [units='kilometers']
14803
- * @returns {CheapRuler}
14804
- * @example
14805
- * const ruler = cheapRuler.fromTile(1567, 12);
14806
- * //=ruler
14807
- */
14808
- static fromTile(y, z, units) {
14809
- const n = Math.PI * (1 - 2 * (y + 0.5) / Math.pow(2, z));
14810
- const lat = Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))) / RAD;
14811
- return new CheapRuler(lat, units);
14812
- }
14813
-
14814
- /**
14815
- * Multipliers for converting between units.
14816
- *
14817
- * @example
14818
- * // convert 50 meters to yards
14819
- * 50 * CheapRuler.units.yards / CheapRuler.units.meters;
14820
- */
14821
- static get units() {
14822
- return factors;
14823
- }
14824
-
14825
- /**
14826
- * Creates a ruler instance for very fast approximations to common geodesic measurements around a certain latitude.
14827
- *
14828
- * @param {number} lat latitude
14829
- * @param {keyof typeof factors} [units='kilometers']
14830
- * @example
14831
- * const ruler = cheapRuler(35.05, 'miles');
14832
- * //=ruler
14833
- */
14834
- constructor(lat, units) {
14835
- if (lat === undefined) throw new Error('No latitude given.');
14836
- if (units && !factors[units]) throw new Error(`Unknown unit ${ units }. Use one of: ${ Object.keys(factors).join(', ')}`);
14837
-
14838
- // Curvature formulas from https://en.wikipedia.org/wiki/Earth_radius#Meridional
14839
- const m = RAD * RE * (units ? factors[units] : 1);
14840
- const coslat = Math.cos(lat * RAD);
14841
- const w2 = 1 / (1 - E2 * (1 - coslat * coslat));
14842
- const w = Math.sqrt(w2);
14843
-
14844
- // multipliers for converting longitude and latitude degrees into distance
14845
- this.kx = m * w * coslat; // based on normal radius of curvature
14846
- this.ky = m * w * w2 * (1 - E2); // based on meridonal radius of curvature
14847
- }
14848
-
14849
- /**
14850
- * Given two points of the form [longitude, latitude], returns the distance.
14851
- *
14852
- * @param {[number, number]} a point [longitude, latitude]
14853
- * @param {[number, number]} b point [longitude, latitude]
14854
- * @returns {number} distance
14855
- * @example
14856
- * const distance = ruler.distance([30.5, 50.5], [30.51, 50.49]);
14857
- * //=distance
14858
- */
14859
- distance(a, b) {
14860
- const dx = wrap(a[0] - b[0]) * this.kx;
14861
- const dy = (a[1] - b[1]) * this.ky;
14862
- return Math.sqrt(dx * dx + dy * dy);
14863
- }
14864
-
14865
- /**
14866
- * Returns the bearing between two points in angles.
14867
- *
14868
- * @param {[number, number]} a point [longitude, latitude]
14869
- * @param {[number, number]} b point [longitude, latitude]
14870
- * @returns {number} bearing
14871
- * @example
14872
- * const bearing = ruler.bearing([30.5, 50.5], [30.51, 50.49]);
14873
- * //=bearing
14874
- */
14875
- bearing(a, b) {
14876
- const dx = wrap(b[0] - a[0]) * this.kx;
14877
- const dy = (b[1] - a[1]) * this.ky;
14878
- return Math.atan2(dx, dy) / RAD;
14879
- }
14880
-
14881
- /**
14882
- * Returns a new point given distance and bearing from the starting point.
14883
- *
14884
- * @param {[number, number]} p point [longitude, latitude]
14885
- * @param {number} dist distance
14886
- * @param {number} bearing
14887
- * @returns {[number, number]} point [longitude, latitude]
14888
- * @example
14889
- * const point = ruler.destination([30.5, 50.5], 0.1, 90);
14890
- * //=point
14891
- */
14892
- destination(p, dist, bearing) {
14893
- const a = bearing * RAD;
14894
- return this.offset(p,
14895
- Math.sin(a) * dist,
14896
- Math.cos(a) * dist);
14897
- }
14898
-
14899
- /**
14900
- * Returns a new point given easting and northing offsets (in ruler units) from the starting point.
14901
- *
14902
- * @param {[number, number]} p point [longitude, latitude]
14903
- * @param {number} dx easting
14904
- * @param {number} dy northing
14905
- * @returns {[number, number]} point [longitude, latitude]
14906
- * @example
14907
- * const point = ruler.offset([30.5, 50.5], 10, 10);
14908
- * //=point
14909
- */
14910
- offset(p, dx, dy) {
14911
- return [
14912
- p[0] + dx / this.kx,
14913
- p[1] + dy / this.ky
14914
- ];
14915
- }
14916
-
14917
- /**
14918
- * Given a line (an array of points), returns the total line distance.
14919
- *
14920
- * @param {[number, number][]} points [longitude, latitude]
14921
- * @returns {number} total line distance
14922
- * @example
14923
- * const length = ruler.lineDistance([
14924
- * [-67.031, 50.458], [-67.031, 50.534],
14925
- * [-66.929, 50.534], [-66.929, 50.458]
14926
- * ]);
14927
- * //=length
14928
- */
14929
- lineDistance(points) {
14930
- let total = 0;
14931
- for (let i = 0; i < points.length - 1; i++) {
14932
- total += this.distance(points[i], points[i + 1]);
14933
- }
14934
- return total;
14935
- }
14936
-
14937
- /**
14938
- * Given a polygon (an array of rings, where each ring is an array of points), returns the area.
14939
- *
14940
- * @param {[number, number][][]} polygon
14941
- * @returns {number} area value in the specified units (square kilometers by default)
14942
- * @example
14943
- * const area = ruler.area([[
14944
- * [-67.031, 50.458], [-67.031, 50.534], [-66.929, 50.534],
14945
- * [-66.929, 50.458], [-67.031, 50.458]
14946
- * ]]);
14947
- * //=area
14948
- */
14949
- area(polygon) {
14950
- let sum = 0;
14951
-
14952
- for (let i = 0; i < polygon.length; i++) {
14953
- const ring = polygon[i];
14954
-
14955
- for (let j = 0, len = ring.length, k = len - 1; j < len; k = j++) {
14956
- sum += wrap(ring[j][0] - ring[k][0]) * (ring[j][1] + ring[k][1]) * (i ? -1 : 1);
14957
- }
14958
- }
14959
-
14960
- return (Math.abs(sum) / 2) * this.kx * this.ky;
14961
- }
14962
-
14963
- /**
14964
- * Returns the point at a specified distance along the line.
14965
- *
14966
- * @param {[number, number][]} line
14967
- * @param {number} dist distance
14968
- * @returns {[number, number]} point [longitude, latitude]
14969
- * @example
14970
- * const point = ruler.along(line, 2.5);
14971
- * //=point
14972
- */
14973
- along(line, dist) {
14974
- let sum = 0;
14975
-
14976
- if (dist <= 0) return line[0];
14977
-
14978
- for (let i = 0; i < line.length - 1; i++) {
14979
- const p0 = line[i];
14980
- const p1 = line[i + 1];
14981
- const d = this.distance(p0, p1);
14982
- sum += d;
14983
- if (sum > dist) return interpolate$1(p0, p1, (dist - (sum - d)) / d);
14984
- }
14985
-
14986
- return line[line.length - 1];
14987
- }
14988
-
14989
- /**
14990
- * Returns the distance from a point `p` to a line segment `a` to `b`.
14991
- *
14992
- * @pointToSegmentDistance
14993
- * @param {[number, number]} p point [longitude, latitude]
14994
- * @param {[number, number]} a segment point 1 [longitude, latitude]
14995
- * @param {[number, number]} b segment point 2 [longitude, latitude]
14996
- * @returns {number} distance
14997
- * @example
14998
- * const distance = ruler.pointToSegmentDistance([-67.04, 50.5], [-67.05, 50.57], [-67.03, 50.54]);
14999
- * //=distance
15000
- */
15001
- pointToSegmentDistance(p, a, b) {
15002
- let [x, y] = a;
15003
- let dx = wrap(b[0] - x) * this.kx;
15004
- let dy = (b[1] - y) * this.ky;
15005
-
15006
- if (dx !== 0 || dy !== 0) {
15007
- const t = (wrap(p[0] - x) * this.kx * dx + (p[1] - y) * this.ky * dy) / (dx * dx + dy * dy);
15008
-
15009
- if (t > 1) {
15010
- x = b[0];
15011
- y = b[1];
15012
-
15013
- } else if (t > 0) {
15014
- x += (dx / this.kx) * t;
15015
- y += (dy / this.ky) * t;
15016
- }
15017
- }
15018
-
15019
- dx = wrap(p[0] - x) * this.kx;
15020
- dy = (p[1] - y) * this.ky;
15021
-
15022
- return Math.sqrt(dx * dx + dy * dy);
15023
- }
15024
-
15025
- /**
15026
- * Returns an object of the form {point, index, t}, where point is closest point on the line
15027
- * from the given point, index is the start index of the segment with the closest point,
15028
- * and t is a parameter from 0 to 1 that indicates where the closest point is on that segment.
15029
- *
15030
- * @param {[number, number][]} line
15031
- * @param {[number, number]} p point [longitude, latitude]
15032
- * @returns {{point: [number, number], index: number, t: number}} {point, index, t}
15033
- * @example
15034
- * const point = ruler.pointOnLine(line, [-67.04, 50.5]).point;
15035
- * //=point
15036
- */
15037
- pointOnLine(line, p) {
15038
- let minDist = Infinity;
15039
- let minX = line[0][0];
15040
- let minY = line[0][1];
15041
- let minI = 0;
15042
- let minT = 0;
15043
-
15044
- for (let i = 0; i < line.length - 1; i++) {
15045
-
15046
- let x = line[i][0];
15047
- let y = line[i][1];
15048
- let dx = wrap(line[i + 1][0] - x) * this.kx;
15049
- let dy = (line[i + 1][1] - y) * this.ky;
15050
- let t = 0;
15051
-
15052
- if (dx !== 0 || dy !== 0) {
15053
- t = (wrap(p[0] - x) * this.kx * dx + (p[1] - y) * this.ky * dy) / (dx * dx + dy * dy);
15054
-
15055
- if (t > 1) {
15056
- x = line[i + 1][0];
15057
- y = line[i + 1][1];
15058
-
15059
- } else if (t > 0) {
15060
- x += (dx / this.kx) * t;
15061
- y += (dy / this.ky) * t;
15062
- }
15063
- }
15064
-
15065
- dx = wrap(p[0] - x) * this.kx;
15066
- dy = (p[1] - y) * this.ky;
15067
-
15068
- const sqDist = dx * dx + dy * dy;
15069
- if (sqDist < minDist) {
15070
- minDist = sqDist;
15071
- minX = x;
15072
- minY = y;
15073
- minI = i;
15074
- minT = t;
15075
- }
15076
- }
15077
-
15078
- return {
15079
- point: [minX, minY],
15080
- index: minI,
15081
- t: Math.max(0, Math.min(1, minT))
15082
- };
15083
- }
15084
-
15085
- /**
15086
- * Returns a part of the given line between the start and the stop points (or their closest points on the line).
15087
- *
15088
- * @param {[number, number]} start point [longitude, latitude]
15089
- * @param {[number, number]} stop point [longitude, latitude]
15090
- * @param {[number, number][]} line
15091
- * @returns {[number, number][]} line part of a line
15092
- * @example
15093
- * const line2 = ruler.lineSlice([-67.04, 50.5], [-67.05, 50.56], line1);
15094
- * //=line2
15095
- */
15096
- lineSlice(start, stop, line) {
15097
- let p1 = this.pointOnLine(line, start);
15098
- let p2 = this.pointOnLine(line, stop);
15099
-
15100
- if (p1.index > p2.index || (p1.index === p2.index && p1.t > p2.t)) {
15101
- const tmp = p1;
15102
- p1 = p2;
15103
- p2 = tmp;
15104
- }
15105
-
15106
- const slice = [p1.point];
15107
-
15108
- const l = p1.index + 1;
15109
- const r = p2.index;
15110
-
15111
- if (!equals(line[l], slice[0]) && l <= r)
15112
- slice.push(line[l]);
15113
-
15114
- for (let i = l + 1; i <= r; i++) {
15115
- slice.push(line[i]);
15116
- }
15117
-
15118
- if (!equals(line[r], p2.point))
15119
- slice.push(p2.point);
15120
-
15121
- return slice;
15122
- }
15123
-
15124
- /**
15125
- * Returns a part of the given line between the start and the stop points indicated by distance along the line.
15126
- *
15127
- * @param {number} start start distance
15128
- * @param {number} stop stop distance
15129
- * @param {[number, number][]} line
15130
- * @returns {[number, number][]} part of a line
15131
- * @example
15132
- * const line2 = ruler.lineSliceAlong(10, 20, line1);
15133
- * //=line2
15134
- */
15135
- lineSliceAlong(start, stop, line) {
15136
- let sum = 0;
15137
- const slice = [];
15138
-
15139
- for (let i = 0; i < line.length - 1; i++) {
15140
- const p0 = line[i];
15141
- const p1 = line[i + 1];
15142
- const d = this.distance(p0, p1);
15143
-
15144
- sum += d;
15145
-
15146
- if (sum > start && slice.length === 0) {
15147
- slice.push(interpolate$1(p0, p1, (start - (sum - d)) / d));
15148
- }
15149
-
15150
- if (sum >= stop) {
15151
- slice.push(interpolate$1(p0, p1, (stop - (sum - d)) / d));
15152
- return slice;
15153
- }
15154
-
15155
- if (sum > start) slice.push(p1);
15156
- }
15157
-
15158
- return slice;
15159
- }
15160
-
15161
- /**
15162
- * Given a point, returns a bounding box object ([w, s, e, n]) created from the given point buffered by a given distance.
15163
- *
15164
- * @param {[number, number]} p point [longitude, latitude]
15165
- * @param {number} buffer
15166
- * @returns {[number, number, number, number]} bbox ([w, s, e, n])
15167
- * @example
15168
- * const bbox = ruler.bufferPoint([30.5, 50.5], 0.01);
15169
- * //=bbox
15170
- */
15171
- bufferPoint(p, buffer) {
15172
- const v = buffer / this.ky;
15173
- const h = buffer / this.kx;
15174
- return [
15175
- p[0] - h,
15176
- p[1] - v,
15177
- p[0] + h,
15178
- p[1] + v
15179
- ];
15180
- }
15181
-
15182
- /**
15183
- * Given a bounding box, returns the box buffered by a given distance.
15184
- *
15185
- * @param {[number, number, number, number]} bbox ([w, s, e, n])
15186
- * @param {number} buffer
15187
- * @returns {[number, number, number, number]} bbox ([w, s, e, n])
15188
- * @example
15189
- * const bbox = ruler.bufferBBox([30.5, 50.5, 31, 51], 0.2);
15190
- * //=bbox
15191
- */
15192
- bufferBBox(bbox, buffer) {
15193
- const v = buffer / this.ky;
15194
- const h = buffer / this.kx;
15195
- return [
15196
- bbox[0] - h,
15197
- bbox[1] - v,
15198
- bbox[2] + h,
15199
- bbox[3] + v
15200
- ];
15201
- }
15202
-
15203
- /**
15204
- * Returns true if the given point is inside in the given bounding box, otherwise false.
15205
- *
15206
- * @param {[number, number]} p point [longitude, latitude]
15207
- * @param {[number, number, number, number]} bbox ([w, s, e, n])
15208
- * @returns {boolean}
15209
- * @example
15210
- * const inside = ruler.insideBBox([30.5, 50.5], [30, 50, 31, 51]);
15211
- * //=inside
15212
- */
15213
- insideBBox(p, bbox) { // eslint-disable-line
15214
- return wrap(p[0] - bbox[0]) >= 0 &&
15215
- wrap(p[0] - bbox[2]) <= 0 &&
15216
- p[1] >= bbox[1] &&
15217
- p[1] <= bbox[3];
15218
- }
15219
- }
15220
-
15221
- /**
15222
- * @param {[number, number]} a
15223
- * @param {[number, number]} b
15224
- */
15225
- function equals(a, b) {
15226
- return a[0] === b[0] && a[1] === b[1];
15227
- }
15228
-
15229
- /**
15230
- * @param {[number, number]} a
15231
- * @param {[number, number]} b
15232
- * @param {number} t
15233
- * @returns {[number, number]}
15234
- */
15235
- function interpolate$1(a, b, t) {
15236
- const dx = wrap(b[0] - a[0]);
15237
- const dy = b[1] - a[1];
15238
- return [
15239
- a[0] + dx * t,
15240
- a[1] + dy * t
15241
- ];
15242
- }
15243
-
15244
- /**
15245
- * normalize a degree value into [-180..180] range
15246
- * @param {number} deg
15247
- */
15248
- function wrap(deg) {
15249
- while (deg < -180) deg += 360;
15250
- while (deg > 180) deg -= 360;
15251
- return deg;
15252
- }
15253
-
15254
14769
  class TinyQueue {
15255
14770
  constructor(data = [], compare = (a, b) => (a < b ? -1 : a > b ? 1 : 0)) {
15256
14771
  this.data = data;
@@ -15324,6 +14839,77 @@
15324
14839
 
15325
14840
  var EXTENT = 8192;
15326
14841
 
14842
+ const RE = 6378.137;
14843
+ const FE = 1 / 298.257223563;
14844
+ const E2 = FE * (2 - FE);
14845
+ const RAD = Math.PI / 180;
14846
+ function lngLatScale(lat) {
14847
+ const m = RAD * RE * 1e3;
14848
+ const coslat = Math.cos(lat * RAD);
14849
+ const w2 = 1 / (1 - E2 * (1 - coslat * coslat));
14850
+ const w = Math.sqrt(w2);
14851
+ return [m * w * coslat, m * w * w2 * (1 - E2)];
14852
+ }
14853
+ function wrapLng(deg) {
14854
+ while (deg < -180) deg += 360;
14855
+ while (deg > 180) deg -= 360;
14856
+ return deg;
14857
+ }
14858
+ function rulerDistance(a, b, kx, ky) {
14859
+ const dx = wrapLng(a[0] - b[0]) * kx;
14860
+ const dy = (a[1] - b[1]) * ky;
14861
+ return Math.sqrt(dx * dx + dy * dy);
14862
+ }
14863
+ function rulerPointToSegmentDistance(p, a, b, kx, ky) {
14864
+ let x = a[0];
14865
+ let y = a[1];
14866
+ let dx = wrapLng(b[0] - x) * kx;
14867
+ let dy = (b[1] - y) * ky;
14868
+ if (dx !== 0 || dy !== 0) {
14869
+ const t = (wrapLng(p[0] - x) * kx * dx + (p[1] - y) * ky * dy) / (dx * dx + dy * dy);
14870
+ if (t > 1) {
14871
+ x = b[0];
14872
+ y = b[1];
14873
+ } else if (t > 0) {
14874
+ x += dx / kx * t;
14875
+ y += dy / ky * t;
14876
+ }
14877
+ }
14878
+ dx = wrapLng(p[0] - x) * kx;
14879
+ dy = (p[1] - y) * ky;
14880
+ return Math.sqrt(dx * dx + dy * dy);
14881
+ }
14882
+ function rulerPointOnLine(line, p, kx, ky) {
14883
+ let minDist = Infinity;
14884
+ let minX = line[0][0];
14885
+ let minY = line[0][1];
14886
+ for (let i = 0; i < line.length - 1; i++) {
14887
+ let x = line[i][0];
14888
+ let y = line[i][1];
14889
+ let dx = wrapLng(line[i + 1][0] - x) * kx;
14890
+ let dy = (line[i + 1][1] - y) * ky;
14891
+ let t = 0;
14892
+ if (dx !== 0 || dy !== 0) {
14893
+ t = (wrapLng(p[0] - x) * kx * dx + (p[1] - y) * ky * dy) / (dx * dx + dy * dy);
14894
+ if (t > 1) {
14895
+ x = line[i + 1][0];
14896
+ y = line[i + 1][1];
14897
+ } else if (t > 0) {
14898
+ x += dx / kx * t;
14899
+ y += dy / ky * t;
14900
+ }
14901
+ }
14902
+ dx = wrapLng(p[0] - x) * kx;
14903
+ dy = (p[1] - y) * ky;
14904
+ const sqDist = dx * dx + dy * dy;
14905
+ if (sqDist < minDist) {
14906
+ minDist = sqDist;
14907
+ minX = x;
14908
+ minY = y;
14909
+ }
14910
+ }
14911
+ return [minX, minY];
14912
+ }
15327
14913
  function compareMax(a, b) {
15328
14914
  return b.dist - a.dist;
15329
14915
  }
@@ -15389,7 +14975,7 @@
15389
14975
  }
15390
14976
  return bbox;
15391
14977
  }
15392
- function bboxToBBoxDistance(bbox1, bbox2, ruler) {
14978
+ function bboxToBBoxDistance(bbox1, bbox2, kx, ky) {
15393
14979
  if (isDefaultBBOX(bbox1) || isDefaultBBOX(bbox2)) {
15394
14980
  return NaN;
15395
14981
  }
@@ -15407,7 +14993,7 @@
15407
14993
  if (bbox1[3] < bbox2[1]) {
15408
14994
  dy = bbox2[1] - bbox1[3];
15409
14995
  }
15410
- return ruler.distance([0, 0], [dx, dy]);
14996
+ return rulerDistance([0, 0], [dx, dy], kx, ky);
15411
14997
  }
15412
14998
  function getLngLatPoint(coord, canonical, extent = EXTENT) {
15413
14999
  const tilesAtZoom = Math.pow(2, canonical.z);
@@ -15422,30 +15008,30 @@
15422
15008
  }
15423
15009
  return coords;
15424
15010
  }
15425
- function pointToLineDistance(point, line, ruler) {
15426
- const nearestPoint = ruler.pointOnLine(line, point).point;
15427
- return ruler.distance(point, nearestPoint);
15011
+ function pointToLineDistance(point, line, kx, ky) {
15012
+ const nearestPoint = rulerPointOnLine(line, point, kx, ky);
15013
+ return rulerDistance(point, nearestPoint, kx, ky);
15428
15014
  }
15429
- function pointsToLineDistance(points, rangeA, line, rangeB, ruler) {
15015
+ function pointsToLineDistance(points, rangeA, line, rangeB, kx, ky) {
15430
15016
  const subLine = line.slice(rangeB[0], rangeB[1] + 1);
15431
15017
  let dist = Infinity;
15432
15018
  for (let i = rangeA[0]; i <= rangeA[1]; ++i) {
15433
- if ((dist = Math.min(dist, pointToLineDistance(points[i], subLine, ruler))) === 0) return 0;
15019
+ if ((dist = Math.min(dist, pointToLineDistance(points[i], subLine, kx, ky))) === 0) return 0;
15434
15020
  }
15435
15021
  return dist;
15436
15022
  }
15437
- function segmentToSegmentDistance(p1, p2, q1, q2, ruler) {
15023
+ function segmentToSegmentDistance(p1, p2, q1, q2, kx, ky) {
15438
15024
  const dist1 = Math.min(
15439
- ruler.pointToSegmentDistance(p1, q1, q2),
15440
- ruler.pointToSegmentDistance(p2, q1, q2)
15025
+ rulerPointToSegmentDistance(p1, q1, q2, kx, ky),
15026
+ rulerPointToSegmentDistance(p2, q1, q2, kx, ky)
15441
15027
  );
15442
15028
  const dist2 = Math.min(
15443
- ruler.pointToSegmentDistance(q1, p1, p2),
15444
- ruler.pointToSegmentDistance(q2, p1, p2)
15029
+ rulerPointToSegmentDistance(q1, p1, p2, kx, ky),
15030
+ rulerPointToSegmentDistance(q2, p1, p2, kx, ky)
15445
15031
  );
15446
15032
  return Math.min(dist1, dist2);
15447
15033
  }
15448
- function lineToLineDistance(line1, range1, line2, range2, ruler) {
15034
+ function lineToLineDistance(line1, range1, line2, range2, kx, ky) {
15449
15035
  if (!isRangeSafe(range1, line1.length) || !isRangeSafe(range2, line2.length)) {
15450
15036
  return NaN;
15451
15037
  }
@@ -15453,24 +15039,24 @@
15453
15039
  for (let i = range1[0]; i < range1[1]; ++i) {
15454
15040
  for (let j = range2[0]; j < range2[1]; ++j) {
15455
15041
  if (segmentIntersectSegment(line1[i], line1[i + 1], line2[j], line2[j + 1])) return 0;
15456
- dist = Math.min(dist, segmentToSegmentDistance(line1[i], line1[i + 1], line2[j], line2[j + 1], ruler));
15042
+ dist = Math.min(dist, segmentToSegmentDistance(line1[i], line1[i + 1], line2[j], line2[j + 1], kx, ky));
15457
15043
  }
15458
15044
  }
15459
15045
  return dist;
15460
15046
  }
15461
- function pointsToPointsDistance(pointSet1, range1, pointSet2, range2, ruler) {
15047
+ function pointsToPointsDistance(pointSet1, range1, pointSet2, range2, kx, ky) {
15462
15048
  if (!isRangeSafe(range1, pointSet1.length) || !isRangeSafe(range2, pointSet2.length)) {
15463
15049
  return NaN;
15464
15050
  }
15465
15051
  let dist = Infinity;
15466
15052
  for (let i = range1[0]; i <= range1[1]; ++i) {
15467
15053
  for (let j = range2[0]; j <= range2[1]; ++j) {
15468
- if ((dist = Math.min(dist, ruler.distance(pointSet1[i], pointSet2[j]))) === 0) return dist;
15054
+ if ((dist = Math.min(dist, rulerDistance(pointSet1[i], pointSet2[j], kx, ky))) === 0) return dist;
15469
15055
  }
15470
15056
  }
15471
15057
  return dist;
15472
15058
  }
15473
- function pointToPolygonDistance(point, polygon, ruler) {
15059
+ function pointToPolygonDistance(point, polygon, kx, ky) {
15474
15060
  if (pointWithinPolygon(
15475
15061
  point,
15476
15062
  polygon,
@@ -15485,13 +15071,13 @@
15485
15071
  return NaN;
15486
15072
  }
15487
15073
  if (ring[0] !== ring[ringLen - 1]) {
15488
- if ((dist = Math.min(dist, ruler.pointToSegmentDistance(point, ring[ringLen - 1], ring[0]))) === 0) return dist;
15074
+ if ((dist = Math.min(dist, rulerPointToSegmentDistance(point, ring[ringLen - 1], ring[0], kx, ky))) === 0) return dist;
15489
15075
  }
15490
- if ((dist = Math.min(dist, pointToLineDistance(point, ring, ruler))) === 0) return dist;
15076
+ if ((dist = Math.min(dist, pointToLineDistance(point, ring, kx, ky))) === 0) return dist;
15491
15077
  }
15492
15078
  return dist;
15493
15079
  }
15494
- function lineToPolygonDistance(line, range, polygon, ruler) {
15080
+ function lineToPolygonDistance(line, range, polygon, kx, ky) {
15495
15081
  if (!isRangeSafe(range, line.length)) {
15496
15082
  return NaN;
15497
15083
  }
@@ -15508,7 +15094,7 @@
15508
15094
  for (const ring of polygon) {
15509
15095
  for (let j = 0, len = ring.length, k = len - 1; j < len; k = j++) {
15510
15096
  if (segmentIntersectSegment(line[i], line[i + 1], ring[k], ring[j])) return 0;
15511
- dist = Math.min(dist, segmentToSegmentDistance(line[i], line[i + 1], ring[k], ring[j], ruler));
15097
+ dist = Math.min(dist, segmentToSegmentDistance(line[i], line[i + 1], ring[k], ring[j], kx, ky));
15512
15098
  }
15513
15099
  }
15514
15100
  }
@@ -15527,10 +15113,10 @@
15527
15113
  }
15528
15114
  return false;
15529
15115
  }
15530
- function polygonToPolygonDistance(polygon1, polygon2, ruler, currentMiniDist = Infinity) {
15116
+ function polygonToPolygonDistance(polygon1, polygon2, kx, ky, currentMiniDist = Infinity) {
15531
15117
  const bbox1 = getPolygonBBox(polygon1);
15532
15118
  const bbox2 = getPolygonBBox(polygon2);
15533
- if (currentMiniDist !== Infinity && bboxToBBoxDistance(bbox1, bbox2, ruler) >= currentMiniDist) {
15119
+ if (currentMiniDist !== Infinity && bboxToBBoxDistance(bbox1, bbox2, kx, ky) >= currentMiniDist) {
15534
15120
  return currentMiniDist;
15535
15121
  }
15536
15122
  if (boxWithinBox(bbox1, bbox2)) {
@@ -15544,20 +15130,20 @@
15544
15130
  for (const ring2 of polygon2) {
15545
15131
  for (let j = 0, len2 = ring2.length, k = len2 - 1; j < len2; k = j++) {
15546
15132
  if (segmentIntersectSegment(ring1[l], ring1[i], ring2[k], ring2[j])) return 0;
15547
- dist = Math.min(dist, segmentToSegmentDistance(ring1[l], ring1[i], ring2[k], ring2[j], ruler));
15133
+ dist = Math.min(dist, segmentToSegmentDistance(ring1[l], ring1[i], ring2[k], ring2[j], kx, ky));
15548
15134
  }
15549
15135
  }
15550
15136
  }
15551
15137
  }
15552
15138
  return dist;
15553
15139
  }
15554
- function updateQueue(distQueue, miniDist, ruler, pointSet1, pointSet2, r1, r2) {
15140
+ function updateQueue(distQueue, miniDist, kx, ky, pointSet1, pointSet2, r1, r2) {
15555
15141
  if (r1 === null || r2 === null) return;
15556
- const tempDist = bboxToBBoxDistance(getBBox(pointSet1, r1), getBBox(pointSet2, r2), ruler);
15142
+ const tempDist = bboxToBBoxDistance(getBBox(pointSet1, r1), getBBox(pointSet2, r2), kx, ky);
15557
15143
  if (tempDist < miniDist) distQueue.push({ dist: tempDist, range1: r1, range2: r2 });
15558
15144
  }
15559
- function pointSetToPolygonDistance(pointSets, isLine, polygon, ruler, currentMiniDist = Infinity) {
15560
- let miniDist = Math.min(ruler.distance(pointSets[0], polygon[0][0]), currentMiniDist);
15145
+ function pointSetToPolygonDistance(pointSets, isLine, polygon, kx, ky, currentMiniDist = Infinity) {
15146
+ let miniDist = Math.min(rulerDistance(pointSets[0], polygon[0][0], kx, ky), currentMiniDist);
15561
15147
  if (miniDist === 0) return miniDist;
15562
15148
  const initialDistPair = {
15563
15149
  dist: 0,
@@ -15574,30 +15160,30 @@
15574
15160
  if (getRangeSize(range) <= setThreshold) {
15575
15161
  if (!isRangeSafe(range, pointSets.length)) return NaN;
15576
15162
  if (isLine) {
15577
- const tempDist = lineToPolygonDistance(pointSets, range, polygon, ruler);
15163
+ const tempDist = lineToPolygonDistance(pointSets, range, polygon, kx, ky);
15578
15164
  if ((miniDist = Math.min(miniDist, tempDist)) === 0) return miniDist;
15579
15165
  } else {
15580
15166
  for (let i = range[0]; i <= range[1]; ++i) {
15581
- const tempDist = pointToPolygonDistance(pointSets[i], polygon, ruler);
15167
+ const tempDist = pointToPolygonDistance(pointSets[i], polygon, kx, ky);
15582
15168
  if ((miniDist = Math.min(miniDist, tempDist)) === 0) return miniDist;
15583
15169
  }
15584
15170
  }
15585
15171
  } else {
15586
15172
  const newRanges = splitRange(range, isLine);
15587
15173
  if (newRanges[0] !== null) {
15588
- const tempDist = bboxToBBoxDistance(getBBox(pointSets, newRanges[0]), polyBBox, ruler);
15174
+ const tempDist = bboxToBBoxDistance(getBBox(pointSets, newRanges[0]), polyBBox, kx, ky);
15589
15175
  if (tempDist < miniDist) distQueue.push({ dist: tempDist, range1: newRanges[0], range2: [0, 0] });
15590
15176
  }
15591
15177
  if (newRanges[1] !== null) {
15592
- const tempDist = bboxToBBoxDistance(getBBox(pointSets, newRanges[1]), polyBBox, ruler);
15178
+ const tempDist = bboxToBBoxDistance(getBBox(pointSets, newRanges[1]), polyBBox, kx, ky);
15593
15179
  if (tempDist < miniDist) distQueue.push({ dist: tempDist, range1: newRanges[1], range2: [0, 0] });
15594
15180
  }
15595
15181
  }
15596
15182
  }
15597
15183
  return miniDist;
15598
15184
  }
15599
- function pointSetsDistance(pointSet1, isLine1, pointSet2, isLine2, ruler, currentMiniDist = Infinity) {
15600
- let miniDist = Math.min(currentMiniDist, ruler.distance(pointSet1[0], pointSet2[0]));
15185
+ function pointSetsDistance(pointSet1, isLine1, pointSet2, isLine2, kx, ky, currentMiniDist = Infinity) {
15186
+ let miniDist = Math.min(currentMiniDist, rulerDistance(pointSet1[0], pointSet2[0], kx, ky));
15601
15187
  if (miniDist === 0) return miniDist;
15602
15188
  const initialDistPair = {
15603
15189
  dist: 0,
@@ -15617,52 +15203,52 @@
15617
15203
  return NaN;
15618
15204
  }
15619
15205
  if (isLine1 && isLine2) {
15620
- miniDist = Math.min(miniDist, lineToLineDistance(pointSet1, rangeA, pointSet2, rangeB, ruler));
15206
+ miniDist = Math.min(miniDist, lineToLineDistance(pointSet1, rangeA, pointSet2, rangeB, kx, ky));
15621
15207
  } else if (!isLine1 && !isLine2) {
15622
- miniDist = Math.min(miniDist, pointsToPointsDistance(pointSet1, rangeA, pointSet2, rangeB, ruler));
15208
+ miniDist = Math.min(miniDist, pointsToPointsDistance(pointSet1, rangeA, pointSet2, rangeB, kx, ky));
15623
15209
  } else if (isLine1 && !isLine2) {
15624
- miniDist = Math.min(miniDist, pointsToLineDistance(pointSet2, rangeB, pointSet1, rangeA, ruler));
15210
+ miniDist = Math.min(miniDist, pointsToLineDistance(pointSet2, rangeB, pointSet1, rangeA, kx, ky));
15625
15211
  } else if (!isLine1 && isLine2) {
15626
- miniDist = Math.min(miniDist, pointsToLineDistance(pointSet1, rangeA, pointSet2, rangeB, ruler));
15212
+ miniDist = Math.min(miniDist, pointsToLineDistance(pointSet1, rangeA, pointSet2, rangeB, kx, ky));
15627
15213
  }
15628
15214
  if (miniDist === 0) return miniDist;
15629
15215
  } else {
15630
15216
  const newRangesA = splitRange(rangeA, isLine1);
15631
15217
  const newRangesB = splitRange(rangeB, isLine2);
15632
- updateQueue(distQueue, miniDist, ruler, pointSet1, pointSet2, newRangesA[0], newRangesB[0]);
15633
- updateQueue(distQueue, miniDist, ruler, pointSet1, pointSet2, newRangesA[0], newRangesB[1]);
15634
- updateQueue(distQueue, miniDist, ruler, pointSet1, pointSet2, newRangesA[1], newRangesB[0]);
15635
- updateQueue(distQueue, miniDist, ruler, pointSet1, pointSet2, newRangesA[1], newRangesB[1]);
15218
+ updateQueue(distQueue, miniDist, kx, ky, pointSet1, pointSet2, newRangesA[0], newRangesB[0]);
15219
+ updateQueue(distQueue, miniDist, kx, ky, pointSet1, pointSet2, newRangesA[0], newRangesB[1]);
15220
+ updateQueue(distQueue, miniDist, kx, ky, pointSet1, pointSet2, newRangesA[1], newRangesB[0]);
15221
+ updateQueue(distQueue, miniDist, kx, ky, pointSet1, pointSet2, newRangesA[1], newRangesB[1]);
15636
15222
  }
15637
15223
  }
15638
15224
  return miniDist;
15639
15225
  }
15640
- function pointSetToLinesDistance(pointSet, isLine, lines, ruler, currentMiniDist = Infinity) {
15226
+ function pointSetToLinesDistance(pointSet, isLine, lines, kx, ky, currentMiniDist = Infinity) {
15641
15227
  let dist = currentMiniDist;
15642
15228
  const bbox1 = getBBox(pointSet, [0, pointSet.length - 1]);
15643
15229
  for (const line of lines) {
15644
- if (dist !== Infinity && bboxToBBoxDistance(bbox1, getBBox(line, [0, line.length - 1]), ruler) >= dist) continue;
15645
- dist = Math.min(dist, pointSetsDistance(pointSet, isLine, line, true, ruler, dist));
15230
+ if (dist !== Infinity && bboxToBBoxDistance(bbox1, getBBox(line, [0, line.length - 1]), kx, ky) >= dist) continue;
15231
+ dist = Math.min(dist, pointSetsDistance(pointSet, isLine, line, true, kx, ky, dist));
15646
15232
  if (dist === 0) return dist;
15647
15233
  }
15648
15234
  return dist;
15649
15235
  }
15650
- function pointSetToPolygonsDistance(points, isLine, polygons, ruler, currentMiniDist = Infinity) {
15236
+ function pointSetToPolygonsDistance(points, isLine, polygons, kx, ky, currentMiniDist = Infinity) {
15651
15237
  let dist = currentMiniDist;
15652
15238
  const bbox1 = getBBox(points, [0, points.length - 1]);
15653
15239
  for (const polygon of polygons) {
15654
- if (dist !== Infinity && bboxToBBoxDistance(bbox1, getPolygonBBox(polygon), ruler) >= dist) continue;
15655
- const tempDist = pointSetToPolygonDistance(points, isLine, polygon, ruler, dist);
15240
+ if (dist !== Infinity && bboxToBBoxDistance(bbox1, getPolygonBBox(polygon), kx, ky) >= dist) continue;
15241
+ const tempDist = pointSetToPolygonDistance(points, isLine, polygon, kx, ky, dist);
15656
15242
  if (isNaN(tempDist)) return tempDist;
15657
15243
  if ((dist = Math.min(dist, tempDist)) === 0) return dist;
15658
15244
  }
15659
15245
  return dist;
15660
15246
  }
15661
- function polygonsToPolygonsDistance(polygons1, polygons2, ruler) {
15247
+ function polygonsToPolygonsDistance(polygons1, polygons2, kx, ky) {
15662
15248
  let dist = Infinity;
15663
15249
  for (const polygon1 of polygons1) {
15664
15250
  for (const polygon2 of polygons2) {
15665
- const tempDist = polygonToPolygonDistance(polygon1, polygon2, ruler, dist);
15251
+ const tempDist = polygonToPolygonDistance(polygon1, polygon2, kx, ky, dist);
15666
15252
  if (isNaN(tempDist)) return tempDist;
15667
15253
  if ((dist = Math.min(dist, tempDist)) === 0) return dist;
15668
15254
  }
@@ -15676,25 +15262,27 @@
15676
15262
  lngLatPoints.push(getLngLatPoint(point, canonical));
15677
15263
  }
15678
15264
  }
15679
- const ruler = new CheapRuler(lngLatPoints[0][1], "meters");
15265
+ const [kx, ky] = lngLatScale(lngLatPoints[0][1]);
15680
15266
  if (geometry.type === "Point" || geometry.type === "MultiPoint" || geometry.type === "LineString") {
15681
15267
  return pointSetsDistance(
15682
15268
  lngLatPoints,
15683
15269
  false,
15684
15270
  geometry.type === "Point" ? [geometry.coordinates] : geometry.coordinates,
15685
15271
  geometry.type === "LineString",
15686
- ruler
15272
+ kx,
15273
+ ky
15687
15274
  );
15688
15275
  }
15689
15276
  if (geometry.type === "MultiLineString") {
15690
- return pointSetToLinesDistance(lngLatPoints, false, geometry.coordinates, ruler);
15277
+ return pointSetToLinesDistance(lngLatPoints, false, geometry.coordinates, kx, ky);
15691
15278
  }
15692
15279
  if (geometry.type === "Polygon" || geometry.type === "MultiPolygon") {
15693
15280
  return pointSetToPolygonsDistance(
15694
15281
  lngLatPoints,
15695
15282
  false,
15696
15283
  geometry.type === "Polygon" ? [geometry.coordinates] : geometry.coordinates,
15697
- ruler
15284
+ kx,
15285
+ ky
15698
15286
  );
15699
15287
  }
15700
15288
  return null;
@@ -15708,19 +15296,20 @@
15708
15296
  }
15709
15297
  lngLatLines.push(lngLatLine);
15710
15298
  }
15711
- const ruler = new CheapRuler(lngLatLines[0][0][1], "meters");
15299
+ const [kx, ky] = lngLatScale(lngLatLines[0][0][1]);
15712
15300
  if (geometry.type === "Point" || geometry.type === "MultiPoint" || geometry.type === "LineString") {
15713
15301
  return pointSetToLinesDistance(
15714
15302
  geometry.type === "Point" ? [geometry.coordinates] : geometry.coordinates,
15715
15303
  geometry.type === "LineString",
15716
15304
  lngLatLines,
15717
- ruler
15305
+ kx,
15306
+ ky
15718
15307
  );
15719
15308
  }
15720
15309
  if (geometry.type === "MultiLineString") {
15721
15310
  let dist = Infinity;
15722
15311
  for (let i = 0; i < geometry.coordinates.length; i++) {
15723
- const tempDist = pointSetToLinesDistance(geometry.coordinates[i], true, lngLatLines, ruler, dist);
15312
+ const tempDist = pointSetToLinesDistance(geometry.coordinates[i], true, lngLatLines, kx, ky, dist);
15724
15313
  if (isNaN(tempDist)) return tempDist;
15725
15314
  if ((dist = Math.min(dist, tempDist)) === 0) return dist;
15726
15315
  }
@@ -15733,7 +15322,8 @@
15733
15322
  lngLatLines[i],
15734
15323
  true,
15735
15324
  geometry.type === "Polygon" ? [geometry.coordinates] : geometry.coordinates,
15736
- ruler,
15325
+ kx,
15326
+ ky,
15737
15327
  dist
15738
15328
  );
15739
15329
  if (isNaN(tempDist)) return tempDist;
@@ -15752,19 +15342,20 @@
15752
15342
  }
15753
15343
  lngLatPolygons.push(lngLatPolygon);
15754
15344
  }
15755
- const ruler = new CheapRuler(lngLatPolygons[0][0][0][1], "meters");
15345
+ const [kx, ky] = lngLatScale(lngLatPolygons[0][0][0][1]);
15756
15346
  if (geometry.type === "Point" || geometry.type === "MultiPoint" || geometry.type === "LineString") {
15757
15347
  return pointSetToPolygonsDistance(
15758
15348
  geometry.type === "Point" ? [geometry.coordinates] : geometry.coordinates,
15759
15349
  geometry.type === "LineString",
15760
15350
  lngLatPolygons,
15761
- ruler
15351
+ kx,
15352
+ ky
15762
15353
  );
15763
15354
  }
15764
15355
  if (geometry.type === "MultiLineString") {
15765
15356
  let dist = Infinity;
15766
15357
  for (let i = 0; i < geometry.coordinates.length; i++) {
15767
- const tempDist = pointSetToPolygonsDistance(geometry.coordinates[i], true, lngLatPolygons, ruler, dist);
15358
+ const tempDist = pointSetToPolygonsDistance(geometry.coordinates[i], true, lngLatPolygons, kx, ky, dist);
15768
15359
  if (isNaN(tempDist)) return tempDist;
15769
15360
  if ((dist = Math.min(dist, tempDist)) === 0) return dist;
15770
15361
  }
@@ -15774,7 +15365,8 @@
15774
15365
  return polygonsToPolygonsDistance(
15775
15366
  geometry.type === "Polygon" ? [geometry.coordinates] : geometry.coordinates,
15776
15367
  lngLatPolygons,
15777
- ruler
15368
+ kx,
15369
+ ky
15778
15370
  );
15779
15371
  }
15780
15372
  return null;
@@ -15886,18 +15478,21 @@
15886
15478
  });
15887
15479
  return result;
15888
15480
  }
15889
- function isGlobalPropertyConstant(e, properties) {
15890
- if (e instanceof CompoundExpression && properties.includes(e.name)) {
15481
+ function isGlobalPropertyConstantSet(e, properties) {
15482
+ if (e instanceof CompoundExpression && properties.has(e.name)) {
15891
15483
  return false;
15892
15484
  }
15893
15485
  let result = true;
15894
15486
  e.eachChild((arg) => {
15895
- if (result && !isGlobalPropertyConstant(arg, properties)) {
15487
+ if (result && !isGlobalPropertyConstantSet(arg, properties)) {
15896
15488
  result = false;
15897
15489
  }
15898
15490
  });
15899
15491
  return result;
15900
15492
  }
15493
+ function isGlobalPropertyConstant(e, properties) {
15494
+ return isGlobalPropertyConstantSet(e, new Set(properties));
15495
+ }
15901
15496
 
15902
15497
  const FQIDSeparator = "";
15903
15498
  function makeConfigFQID(id, ownScope, contextScope) {
@@ -16064,16 +15659,12 @@
16064
15659
  this.iconImageUseTheme = iconImageUseTheme;
16065
15660
  }
16066
15661
  get key() {
16067
- if (this._key === void 0) {
16068
- const path = this.path;
16069
- let key = "";
16070
- for (let i = 0; i < path.length; i++) {
16071
- const part = path[i];
16072
- key += typeof part === "string" ? `['${part}']` : `[${part}]`;
16073
- }
16074
- this._key = key;
15662
+ let key = "";
15663
+ for (let i = 0; i < this.path.length; i++) {
15664
+ const part = this.path[i];
15665
+ key += typeof part === "string" ? `['${part}']` : `[${part}]`;
16075
15666
  }
16076
- return this._key;
15667
+ return key;
16077
15668
  }
16078
15669
  /**
16079
15670
  * @param expr the JSON expression to parse
@@ -16084,7 +15675,17 @@
16084
15675
  */
16085
15676
  parse(expr, index, expectedType, bindings, options = {}) {
16086
15677
  if (index || expectedType) {
16087
- return this.concat(index, null, expectedType, bindings)._parse(expr, options);
15678
+ const prevExpectedType = this.expectedType;
15679
+ const prevScope = this.scope;
15680
+ if (bindings) this.scope = this.scope.concat(bindings);
15681
+ this.expectedType = expectedType || null;
15682
+ const pushed = typeof index === "number";
15683
+ if (pushed) this.path.push(index);
15684
+ const result = this._parse(expr, options);
15685
+ if (pushed) this.path.pop();
15686
+ this.expectedType = prevExpectedType;
15687
+ this.scope = prevScope;
15688
+ return result;
16088
15689
  }
16089
15690
  return this._parse(expr, options);
16090
15691
  }
@@ -16097,21 +15698,23 @@
16097
15698
  * @private
16098
15699
  */
16099
15700
  parseObjectValue(expr, index, key, expectedType, bindings, options = {}) {
16100
- return this.concat(index, key, expectedType, bindings)._parse(expr, options);
15701
+ const prevExpectedType = this.expectedType;
15702
+ const prevScope = this.scope;
15703
+ if (bindings) this.scope = this.scope.concat(bindings);
15704
+ this.expectedType = expectedType || null;
15705
+ this.path.push(index);
15706
+ this.path.push(key);
15707
+ const result = this._parse(expr, options);
15708
+ this.path.pop();
15709
+ this.path.pop();
15710
+ this.expectedType = prevExpectedType;
15711
+ this.scope = prevScope;
15712
+ return result;
16101
15713
  }
16102
15714
  _parse(expr, options) {
16103
15715
  if (expr === null || typeof expr === "string" || typeof expr === "boolean" || typeof expr === "number") {
16104
15716
  expr = ["literal", expr];
16105
15717
  }
16106
- function annotate(parsed, type, typeAnnotation) {
16107
- if (typeAnnotation === "assert") {
16108
- return new Assertion(type, [parsed]);
16109
- } else if (typeAnnotation === "coerce") {
16110
- return new Coercion(type, [parsed]);
16111
- } else {
16112
- return parsed;
16113
- }
16114
- }
16115
15718
  if (Array.isArray(expr)) {
16116
15719
  if (expr.length === 0) {
16117
15720
  return this.error(`Expected an array with at least one element. If you wanted a literal array, use ["literal", []].`);
@@ -16160,9 +15763,10 @@
16160
15763
  * @private
16161
15764
  */
16162
15765
  concat(index, key, expectedType, bindings) {
16163
- let path = typeof index === "number" ? this.path.concat(index) : this.path;
16164
- path = typeof key === "string" ? path.concat(key) : path;
16165
15766
  const scope = bindings ? this.scope.concat(bindings) : this.scope;
15767
+ const path = this.path.slice();
15768
+ if (typeof index === "number") path.push(index);
15769
+ if (typeof key === "string") path.push(key);
16166
15770
  return new ParsingContext(
16167
15771
  this.registry,
16168
15772
  path,
@@ -16174,6 +15778,24 @@
16174
15778
  this.iconImageUseTheme
16175
15779
  );
16176
15780
  }
15781
+ /**
15782
+ * Returns a fresh context that shares the same path position as this one
15783
+ * but has an empty errors array. Used by CompoundExpression to probe
15784
+ * overload signatures without polluting the parent errors list.
15785
+ * @private
15786
+ */
15787
+ _forkForSignature() {
15788
+ return new ParsingContext(
15789
+ this.registry,
15790
+ this.path.slice(),
15791
+ null,
15792
+ this.scope,
15793
+ [],
15794
+ this._scope,
15795
+ this.options,
15796
+ this.iconImageUseTheme
15797
+ );
15798
+ }
16177
15799
  /**
16178
15800
  * Push a parsing (or type checking) error into the `this.errors`
16179
15801
  * @param error The message
@@ -16195,6 +15817,30 @@
16195
15817
  return error;
16196
15818
  }
16197
15819
  }
15820
+ const CONSTANT_FOLD_EXCLUDED_GLOBALS = /* @__PURE__ */ new Set([
15821
+ "zoom",
15822
+ "heatmap-density",
15823
+ "worldview",
15824
+ "line-progress",
15825
+ "raster-value",
15826
+ "sky-radial-progress",
15827
+ "accumulated",
15828
+ "is-supported-script",
15829
+ "pitch",
15830
+ "distance-from-center",
15831
+ "measure-light",
15832
+ "raster-particle-speed",
15833
+ "is-active-floor"
15834
+ ]);
15835
+ function annotate(parsed, type, typeAnnotation) {
15836
+ if (typeAnnotation === "assert") {
15837
+ return new Assertion(type, [parsed]);
15838
+ } else if (typeAnnotation === "coerce") {
15839
+ return new Coercion(type, [parsed]);
15840
+ } else {
15841
+ return parsed;
15842
+ }
15843
+ }
16198
15844
  function isConstant(expression) {
16199
15845
  if (expression instanceof Var) {
16200
15846
  return isConstant(expression.boundExpression);
@@ -16221,7 +15867,7 @@
16221
15867
  if (!childrenConstant) {
16222
15868
  return false;
16223
15869
  }
16224
- return isFeatureConstant(expression) && isGlobalPropertyConstant(expression, ["zoom", "heatmap-density", "worldview", "line-progress", "raster-value", "sky-radial-progress", "accumulated", "is-supported-script", "pitch", "distance-from-center", "measure-light", "raster-particle-speed", "is-active-floor"]);
15870
+ return isFeatureConstant(expression) && isGlobalPropertyConstantSet(expression, CONSTANT_FOLD_EXCLUDED_GLOBALS);
16225
15871
  }
16226
15872
 
16227
15873
  function findStopLessThanOrEqualTo(stops, input) {
@@ -16986,24 +16632,23 @@
16986
16632
  if (!Array.isArray(labels)) {
16987
16633
  labels = [labels];
16988
16634
  }
16989
- const labelContext = context.concat(i);
16990
16635
  if (labels.length === 0) {
16991
- return labelContext.error("Expected at least one branch label.");
16636
+ return context.error("Expected at least one branch label.", i);
16992
16637
  }
16993
16638
  for (const label of labels) {
16994
16639
  if (typeof label !== "number" && typeof label !== "string") {
16995
- return labelContext.error(`Branch labels must be numbers or strings.`);
16640
+ return context.error(`Branch labels must be numbers or strings.`, i);
16996
16641
  } else if (typeof label === "number" && Math.abs(label) > Number.MAX_SAFE_INTEGER) {
16997
- return labelContext.error(`Branch labels must be integers no larger than ${Number.MAX_SAFE_INTEGER}.`);
16642
+ return context.error(`Branch labels must be integers no larger than ${Number.MAX_SAFE_INTEGER}.`, i);
16998
16643
  } else if (typeof label === "number" && Math.floor(label) !== label) {
16999
- return labelContext.error(`Numeric branch labels must be integer values.`);
16644
+ return context.error(`Numeric branch labels must be integer values.`, i);
17000
16645
  } else if (!inputType) {
17001
16646
  inputType = typeOf(label);
17002
- } else if (labelContext.checkSubtype(inputType, typeOf(label))) {
16647
+ } else if (context.checkSubtype(inputType, typeOf(label), i)) {
17003
16648
  return null;
17004
16649
  }
17005
16650
  if (typeof cases[String(label)] !== "undefined") {
17006
- return labelContext.error("Branch labels must be unique.");
16651
+ return context.error("Branch labels must be unique.", i);
17007
16652
  }
17008
16653
  cases[String(label)] = outputs.length;
17009
16654
  }
@@ -17016,7 +16661,7 @@
17016
16661
  if (!input) return null;
17017
16662
  const otherwise = context.parse(args.at(-1), args.length - 1, outputType);
17018
16663
  if (!otherwise) return null;
17019
- if (input.type.kind !== "value" && context.concat(1).checkSubtype(inputType, input.type)) {
16664
+ if (input.type.kind !== "value" && context.checkSubtype(inputType, input.type, 1)) {
17020
16665
  return null;
17021
16666
  }
17022
16667
  return new Match(inputType, outputType, input, cases, outputs, otherwise);
@@ -17274,12 +16919,12 @@
17274
16919
  let lhs = context.parse(args[1], 1, ValueType);
17275
16920
  if (!lhs) return null;
17276
16921
  if (!isComparableType(op2, lhs.type)) {
17277
- return context.concat(1).error(`"${op2}" comparisons are not supported for type '${toString$1(lhs.type)}'.`);
16922
+ return context.error(`"${op2}" comparisons are not supported for type '${toString$1(lhs.type)}'.`, 1);
17278
16923
  }
17279
16924
  let rhs = context.parse(args[2], 2, ValueType);
17280
16925
  if (!rhs) return null;
17281
16926
  if (!isComparableType(op2, rhs.type)) {
17282
- return context.concat(2).error(`"${op2}" comparisons are not supported for type '${toString$1(rhs.type)}'.`);
16927
+ return context.error(`"${op2}" comparisons are not supported for type '${toString$1(rhs.type)}'.`, 2);
17283
16928
  }
17284
16929
  if (lhs.type.kind !== rhs.type.kind && lhs.type.kind !== "value" && rhs.type.kind !== "value") {
17285
16930
  return context.error(`Cannot compare types '${toString$1(lhs.type)}' and '${toString$1(rhs.type)}'.`);
@@ -18234,7 +17879,7 @@
18234
17879
  const zoomDependent = zoomAndFeatureDependent || !featureDependent;
18235
17880
  const type = parameters.type || (supportsInterpolation(propertySpec) ? "exponential" : "interval");
18236
17881
  if (isColor) {
18237
- parameters = Object.assign({}, parameters);
17882
+ parameters = { ...parameters };
18238
17883
  if (parameters.stops) {
18239
17884
  parameters.stops = parameters.stops.map((stop) => {
18240
17885
  return [stop[0], Color.parse(stop[1])];
@@ -19893,11 +19538,12 @@ ${JSON.stringify(filterExp, null, 2)}
19893
19538
  value: value.__line__,
19894
19539
  enumerable: false
19895
19540
  });
19896
- let errors = validateObject(Object.assign({}, options, {
19541
+ let errors = validateObject({
19542
+ ...options,
19897
19543
  value: importSpec,
19898
19544
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
19899
19545
  valueSpec: styleSpec.import
19900
- }));
19546
+ });
19901
19547
  if (unbundle(importSpec.id) === "") {
19902
19548
  const key2 = `${options.key}.id`;
19903
19549
  errors.push(new ValidationError(key2, importSpec, `import id can't be an empty string`));
@@ -19918,7 +19564,8 @@ ${JSON.stringify(filterExp, null, 2)}
19918
19564
  const optionValue = options.value;
19919
19565
  const isArrayOption = isObject(optionValue) && unbundle(optionValue.array) === true;
19920
19566
  const declaredType = !isArrayOption && isObject(optionValue) ? unbundle(optionValue.type) : void 0;
19921
- return validateObject(Object.assign({}, options, {
19567
+ return validateObject({
19568
+ ...options,
19922
19569
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
19923
19570
  valueSpec: styleSpec.option,
19924
19571
  objectElementValidators: declaredType ? {
@@ -19926,11 +19573,9 @@ ${JSON.stringify(filterExp, null, 2)}
19926
19573
  // expression (array-form). Primitive defaults keep the previous
19927
19574
  // permissive validation, mirroring the runtime parser's narrowing
19928
19575
  // in style.ts/parser.cpp.
19929
- default: (elementOptions) => Array.isArray(elementOptions.value) ? validate(Object.assign({}, elementOptions, {
19930
- valueSpec: Object.assign({}, elementOptions.valueSpec, { type: declaredType })
19931
- })) : validate(elementOptions)
19576
+ default: (elementOptions) => Array.isArray(elementOptions.value) ? validate({ ...elementOptions, valueSpec: { ...elementOptions.valueSpec, type: declaredType } }) : validate(elementOptions)
19932
19577
  } : void 0
19933
- }));
19578
+ });
19934
19579
  }
19935
19580
 
19936
19581
  function validateArray(options) {
@@ -20319,11 +19964,12 @@ ${JSON.stringify(filterExp, null, 2)}
20319
19964
  function validateFilter(options) {
20320
19965
  if (isExpressionFilter(deepUnbundle(options.value))) {
20321
19966
  const layerType = options.layerType || "fill";
20322
- return validateExpression(Object.assign({}, options, {
19967
+ return validateExpression({
19968
+ ...options,
20323
19969
  expressionContext: "filter",
20324
19970
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
20325
19971
  valueSpec: options.styleSpec[`filter_${layerType}`]
20326
- }));
19972
+ });
20327
19973
  } else {
20328
19974
  return validateNonExpressionFilter(options);
20329
19975
  }
@@ -20520,8 +20166,8 @@ Use an identity property function instead: ${example}.`
20520
20166
  style: options.style,
20521
20167
  styleSpec: options.styleSpec,
20522
20168
  objectElementValidators: {
20523
- condition: (options2) => validateCondition(Object.assign({ layer, layerType }, options2)),
20524
- properties: (options2) => validateProperties(Object.assign({ layer, layerType }, options2))
20169
+ condition: (options2) => validateCondition({ ...options2 }),
20170
+ properties: (options2) => validateProperties({ layer, layerType, ...options2 })
20525
20171
  }
20526
20172
  });
20527
20173
  if (name !== "hidden" && condition === void 0) {
@@ -20541,15 +20187,15 @@ Use an identity property function instead: ${example}.`
20541
20187
  errors.push(new ValidationError(options.key, propertyKey, `unknown property "${propertyKey}" for layer type "${layerType}"`));
20542
20188
  continue;
20543
20189
  }
20544
- const propertyValidationOptions = Object.assign({}, options, {
20190
+ const propertyValidationOptions = {
20191
+ ...options,
20545
20192
  key: `${options.key}.${propertyKey}`,
20546
- object: properties,
20547
20193
  objectKey: propertyKey,
20548
20194
  layer,
20549
20195
  layerType,
20550
20196
  value: properties[propertyKey],
20551
20197
  valueSpec: propertyType === "paint" ? paintProperties[propertyKey] : layoutProperties[propertyKey]
20552
- });
20198
+ };
20553
20199
  errors.push(...validateProperty(propertyValidationOptions, propertyType));
20554
20200
  }
20555
20201
  return errors;
@@ -20671,7 +20317,7 @@ Use an identity property function instead: ${example}.`
20671
20317
  });
20672
20318
  },
20673
20319
  filter(options2) {
20674
- return validateFilter(Object.assign({ layerType: type }, options2));
20320
+ return validateFilter({ layerType: type, ...options2 });
20675
20321
  },
20676
20322
  layout(options2) {
20677
20323
  return validateObject({
@@ -20683,7 +20329,7 @@ Use an identity property function instead: ${example}.`
20683
20329
  styleSpec: options2.styleSpec,
20684
20330
  objectElementValidators: {
20685
20331
  "*"(options3) {
20686
- return validateLayoutProperty(Object.assign({ layerType: type }, options3));
20332
+ return validateLayoutProperty({ layerType: type, ...options3 });
20687
20333
  }
20688
20334
  }
20689
20335
  });
@@ -20698,7 +20344,7 @@ Use an identity property function instead: ${example}.`
20698
20344
  styleSpec: options2.styleSpec,
20699
20345
  objectElementValidators: {
20700
20346
  "*"(options3) {
20701
- return validatePaintProperty(Object.assign({ layerType: type, layer }, options3));
20347
+ return validatePaintProperty({ layerType: type, layer, ...options3 });
20702
20348
  }
20703
20349
  }
20704
20350
  });
@@ -20710,7 +20356,7 @@ Use an identity property function instead: ${example}.`
20710
20356
  valueSpec: options2.valueSpec,
20711
20357
  style: options2.style,
20712
20358
  styleSpec: options2.styleSpec,
20713
- arrayElementValidator: (options3) => validateAppearance(Object.assign({ layerType: type, layer }, options3))
20359
+ arrayElementValidator: (options3) => validateAppearance({ layerType: type, layer, ...options3 })
20714
20360
  });
20715
20361
  const appearances = Array.isArray(options2.value) ? options2.value : [];
20716
20362
  const dedupedNames = /* @__PURE__ */ new Set();
@@ -21272,10 +20918,11 @@ Use an identity property function instead: ${example}.`
21272
20918
  }
21273
20919
  return errors2;
21274
20920
  }
21275
- const errors = validateObject(Object.assign({}, options, {
20921
+ const errors = validateObject({
20922
+ ...options,
21276
20923
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
21277
20924
  valueSpec: valueSpec.type ? styleSpec[valueSpec.type] : valueSpec
21278
- }));
20925
+ });
21279
20926
  return errors;
21280
20927
  }
21281
20928
 
@@ -21351,12 +20998,11 @@ Use an identity property function instead: ${example}.`
21351
20998
  key: options.key || "",
21352
20999
  value: style,
21353
21000
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
21354
- valueSpec: Object.assign(
21355
- {},
21356
- styleSpec.$root,
21001
+ valueSpec: {
21002
+ ...styleSpec.$root,
21357
21003
  // Skip validation of the root properties that are not defined in the style spec (e.g. 'owner').
21358
- { "*": { type: "*" } }
21359
- ),
21004
+ "*": { type: "*" }
21005
+ },
21360
21006
  styleSpec,
21361
21007
  style,
21362
21008
  objectElementValidators: {