maplibre-gl 2.3.0 → 2.4.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.
Files changed (79) hide show
  1. package/build/generate-query-test-fixtures.ts +3 -2
  2. package/build/generate-struct-arrays.ts +0 -2
  3. package/build/generate-style-spec.ts +12 -17
  4. package/build/rollup_plugins.ts +0 -4
  5. package/dist/maplibre-gl-csp-worker.js +1 -1
  6. package/dist/maplibre-gl-csp.js +1 -1
  7. package/dist/maplibre-gl-dev.js +179 -1369
  8. package/dist/maplibre-gl.d.ts +15 -16
  9. package/dist/maplibre-gl.js +4 -4
  10. package/dist/style-spec/index.d.ts +3 -16
  11. package/package.json +20 -21
  12. package/src/data/array_types.g.ts +0 -5
  13. package/src/data/bucket/fill_bucket.ts +0 -2
  14. package/src/data/bucket/fill_extrusion_bucket.ts +0 -2
  15. package/src/data/feature_position_map.ts +1 -2
  16. package/src/gl/framebuffer.ts +3 -2
  17. package/src/gl/index_buffer.ts +1 -2
  18. package/src/gl/vertex_buffer.ts +1 -2
  19. package/src/index.ts +1 -3
  20. package/src/render/draw_debug.ts +1 -1
  21. package/src/render/draw_fill.ts +9 -1
  22. package/src/render/draw_fill_extrusion.ts +8 -1
  23. package/src/render/draw_heatmap.ts +5 -3
  24. package/src/render/draw_hillshade.ts +17 -2
  25. package/src/render/image_manager.ts +5 -7
  26. package/src/render/program/line_program.ts +1 -1
  27. package/src/render/program/pattern.ts +0 -2
  28. package/src/render/program.ts +12 -9
  29. package/src/render/vertex_array_object.ts +1 -3
  30. package/src/source/geojson_worker_source.ts +0 -4
  31. package/src/source/query_features.ts +0 -3
  32. package/src/source/rtl_text_plugin.ts +3 -4
  33. package/src/source/source_cache.ts +0 -2
  34. package/src/source/tile_id.ts +8 -8
  35. package/src/source/worker.ts +0 -7
  36. package/src/source/worker_tile.ts +3 -2
  37. package/src/style/format_section_override.ts +1 -2
  38. package/src/style/properties.ts +1 -3
  39. package/src/style/style.ts +6 -5
  40. package/src/style/style_layer/custom_style_layer.ts +1 -2
  41. package/src/style/style_layer/symbol_style_layer.ts +5 -8
  42. package/src/style-spec/CHANGELOG.md +2 -2
  43. package/src/style-spec/expression/compound_expression.ts +0 -4
  44. package/src/style-spec/expression/definitions/assertion.ts +2 -4
  45. package/src/style-spec/expression/definitions/case.ts +1 -2
  46. package/src/style-spec/expression/definitions/coalesce.ts +1 -3
  47. package/src/style-spec/expression/definitions/coercion.ts +2 -4
  48. package/src/style-spec/expression/definitions/match.ts +0 -3
  49. package/src/style-spec/expression/index.ts +0 -2
  50. package/src/style-spec/expression/values.ts +0 -2
  51. package/src/style-spec/feature_filter/feature_filter.test.ts +39 -2
  52. package/src/style-spec/function/convert.ts +1 -3
  53. package/src/style-spec/types.g.ts +12 -17
  54. package/src/symbol/collision_index.ts +0 -3
  55. package/src/symbol/path_interpolator.ts +0 -2
  56. package/src/symbol/placement.ts +14 -9
  57. package/src/symbol/shaping.ts +0 -4
  58. package/src/ui/camera.test.ts +64 -1
  59. package/src/ui/camera.ts +36 -10
  60. package/src/ui/control/attribution_control.test.ts +62 -0
  61. package/src/ui/control/attribution_control.ts +4 -2
  62. package/src/ui/control/geolocate_control.ts +4 -6
  63. package/src/ui/control/terrain_control.test.ts +60 -0
  64. package/src/ui/handler/handler_util.ts +1 -2
  65. package/src/ui/handler/map_event.test.ts +65 -1
  66. package/src/ui/handler/map_event.ts +4 -1
  67. package/src/ui/handler/scroll_zoom.ts +0 -2
  68. package/src/ui/handler_manager.ts +0 -2
  69. package/src/ui/map.test.ts +105 -0
  70. package/src/ui/map.ts +8 -1
  71. package/src/util/ajax.ts +1 -2
  72. package/src/util/color_ramp.ts +1 -2
  73. package/src/util/dictionary_coder.ts +1 -3
  74. package/src/util/dispatcher.ts +1 -4
  75. package/src/util/dom.ts +0 -3
  76. package/src/util/image.ts +1 -3
  77. package/src/util/struct_array.ts +0 -5
  78. package/src/util/task_queue.ts +1 -3
  79. package/src/util/web_worker_transfer.ts +5 -6
@@ -13,6 +13,9 @@ import {LngLatBoundsLike} from '../geo/lng_lat_bounds';
13
13
  import {IControl} from './control/control';
14
14
  import EvaluationParameters from '../style/evaluation_parameters';
15
15
  import {fakeServer, FakeServer} from 'nise';
16
+ import {CameraOptions} from './camera';
17
+ import Terrain, {} from '../render/terrain';
18
+ import {mercatorZfromAltitude} from '../geo/mercator_coordinate';
16
19
 
17
20
  function createStyleSource() {
18
21
  return {
@@ -2132,6 +2135,108 @@ describe('Map', () => {
2132
2135
  map.fire(new Event('dataabort'));
2133
2136
  });
2134
2137
 
2138
+ describe('#calculateCameraOptionsFromTo', () => {
2139
+ // Choose initial zoom to avoid center being constrained by mercator latitude limits.
2140
+ test('pitch 90 with terrain', () => {
2141
+ const map = createMap();
2142
+
2143
+ const mockedGetElevation = jest.fn((_tileID: OverscaledTileID, _x: number, _y: number, _extent?: number) => 111200);
2144
+
2145
+ const terrainStub = {} as Terrain;
2146
+ terrainStub.getElevation = mockedGetElevation;
2147
+ map.style.terrain = terrainStub;
2148
+
2149
+ // distance between lng x and lng x+1 is 111.2km at same lat
2150
+ // altitude same as center elevation => 90° pitch
2151
+ const cameraOptions: CameraOptions = map.calculateCameraOptionsFromTo(new LngLat(1, 0), 111200, new LngLat(0, 0));
2152
+ expect(cameraOptions).toBeDefined();
2153
+ expect(cameraOptions.pitch).toBeCloseTo(90);
2154
+ expect(mockedGetElevation.mock.calls).toHaveLength(1);
2155
+ });
2156
+
2157
+ test('pitch 153.435 with terrain', () => {
2158
+ const map = createMap();
2159
+
2160
+ const mockedGetElevation = jest.fn((_tileID: OverscaledTileID, _x: number, _y: number, _extent?: number) => 111200 * 3);
2161
+
2162
+ const terrainStub = {} as Terrain;
2163
+ terrainStub.getElevation = mockedGetElevation;
2164
+ map.style.terrain = terrainStub;
2165
+ // distance between lng x and lng x+1 is 111.2km at same lat
2166
+ // (elevation difference of cam and center) / 2 = grounddistance =>
2167
+ // acos(111.2 / sqrt(111.2² + (111.2 * 2)²)) = acos(1/sqrt(5)) => 63.435 + 90 = 153.435
2168
+ const cameraOptions: CameraOptions = map.calculateCameraOptionsFromTo(new LngLat(1, 0), 111200, new LngLat(0, 0));
2169
+ expect(cameraOptions).toBeDefined();
2170
+ expect(cameraOptions.pitch).toBeCloseTo(153.435);
2171
+ expect(mockedGetElevation.mock.calls).toHaveLength(1);
2172
+ });
2173
+
2174
+ test('pitch 63 with terrain', () => {
2175
+ const map = createMap();
2176
+
2177
+ const mockedGetElevation = jest.fn((_tileID: OverscaledTileID, _x: number, _y: number, _extent?: number) => 111200 / 2);
2178
+
2179
+ const terrainStub = {} as Terrain;
2180
+ terrainStub.getElevation = mockedGetElevation;
2181
+ map.style.terrain = terrainStub;
2182
+
2183
+ // distance between lng x and lng x+1 is 111.2km at same lat
2184
+ // (elevation difference of cam and center) * 2 = grounddistance =>
2185
+ // acos(111.2 / sqrt(111.2² + (111.2 * 0.5)²)) = acos(1/sqrt(1.25)) => 90 (looking down) - 26.565 = 63.435
2186
+ const cameraOptions: CameraOptions = map.calculateCameraOptionsFromTo(new LngLat(0, 0), 111200, new LngLat(1, 0));
2187
+ expect(cameraOptions).toBeDefined();
2188
+ expect(cameraOptions.pitch).toBeCloseTo(63.435);
2189
+ expect(mockedGetElevation.mock.calls).toHaveLength(1);
2190
+ });
2191
+
2192
+ test('zoom distance 1000', () => {
2193
+ const map = createMap();
2194
+
2195
+ const mockedGetElevation = jest.fn((_tileID: OverscaledTileID, _x: number, _y: number, _extent?: number) => 1000);
2196
+
2197
+ const terrainStub = {} as Terrain;
2198
+ terrainStub.getElevation = mockedGetElevation;
2199
+ map.style.terrain = terrainStub;
2200
+
2201
+ const expectedZoom = Math.log2(map.transform.cameraToCenterDistance / mercatorZfromAltitude(1000, 0) / map.transform.tileSize);
2202
+ const cameraOptions = map.calculateCameraOptionsFromTo(new LngLat(0, 0), 0, new LngLat(0, 0));
2203
+
2204
+ expect(cameraOptions).toBeDefined();
2205
+ expect(cameraOptions.zoom).toBeCloseTo(expectedZoom);
2206
+ expect(mockedGetElevation.mock.calls).toHaveLength(1);
2207
+ });
2208
+
2209
+ test('don\'t call getElevation when altitude supplied', () => {
2210
+ const map = createMap();
2211
+
2212
+ const mockedGetElevation = jest.fn((_tileID: OverscaledTileID, _x: number, _y: number, _extent?: number) => 0);
2213
+
2214
+ const terrainStub = {} as Terrain;
2215
+ terrainStub.getElevation = mockedGetElevation;
2216
+ map.style.terrain = terrainStub;
2217
+
2218
+ const cameraOptions = map.calculateCameraOptionsFromTo(new LngLat(0, 0), 0, new LngLat(0, 0), 1000);
2219
+
2220
+ expect(cameraOptions).toBeDefined();
2221
+ expect(mockedGetElevation.mock.calls).toHaveLength(0);
2222
+ });
2223
+
2224
+ test('don\'t call getElevation when altitude 0 supplied', () => {
2225
+ const map = createMap();
2226
+
2227
+ const mockedGetElevation = jest.fn((_tileID: OverscaledTileID, _x: number, _y: number, _extent?: number) => 0);
2228
+
2229
+ const terrainStub = {} as Terrain;
2230
+ terrainStub.getElevation = mockedGetElevation;
2231
+ map.style.terrain = terrainStub;
2232
+
2233
+ const cameraOptions = map.calculateCameraOptionsFromTo(new LngLat(0, 0), 0, new LngLat(1, 0), 0);
2234
+
2235
+ expect(cameraOptions).toBeDefined();
2236
+ expect(mockedGetElevation.mock.calls).toHaveLength(0);
2237
+ });
2238
+ });
2239
+
2135
2240
  });
2136
2241
 
2137
2242
  function createStyle() {
package/src/ui/map.ts CHANGED
@@ -10,7 +10,7 @@ import Painter from '../render/painter';
10
10
  import Transform from '../geo/transform';
11
11
  import Hash from './hash';
12
12
  import HandlerManager from './handler_manager';
13
- import Camera from './camera';
13
+ import Camera, {CameraOptions} from './camera';
14
14
  import LngLat from '../geo/lng_lat';
15
15
  import LngLatBounds from '../geo/lng_lat_bounds';
16
16
  import Point from '@mapbox/point-geometry';
@@ -603,6 +603,13 @@ class Map extends Camera {
603
603
  return this._controls.indexOf(control) > -1;
604
604
  }
605
605
 
606
+ calculateCameraOptionsFromTo(from: LngLat, altitudeFrom: number, to: LngLat, altitudeTo?: number) : CameraOptions {
607
+ if (altitudeTo == null && this.style.terrain) {
608
+ altitudeTo = this.transform.getElevation(to, this.style.terrain);
609
+ }
610
+ return super.calculateCameraOptionsFromTo(from, altitudeFrom, to, altitudeTo);
611
+ }
612
+
606
613
  /**
607
614
  * Resizes the map according to the dimensions of its
608
615
  * `container` element.
package/src/util/ajax.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import {extend, warnOnce, isWorker} from './util';
2
2
  import config from './config';
3
- import assert from 'assert';
4
3
  import {cacheGet, cachePut} from './tile_request_cache';
5
4
  import webpSupported from './webp_supported';
6
5
 
@@ -390,7 +389,7 @@ export const getImage = function(
390
389
  if (advanced) return;
391
390
  advanced = true;
392
391
  numImageRequests--;
393
- assert(numImageRequests >= 0);
392
+
394
393
  while (imageQueue.length && numImageRequests < config.MAX_PARALLEL_IMAGE_REQUESTS) { // eslint-disable-line
395
394
  const request = imageQueue.shift();
396
395
  const {requestParameters, callback, cancelled} = request;
@@ -1,6 +1,5 @@
1
1
  import {RGBAImage} from './image';
2
2
  import {isPowerOfTwo} from './util';
3
- import assert from 'assert';
4
3
 
5
4
  import type {StylePropertyExpression} from '../style-spec/expression/index';
6
5
 
@@ -24,7 +23,7 @@ export function renderColorRamp(params: ColorRampParams): RGBAImage {
24
23
  const height = params.clips ? params.clips.length : 1;
25
24
  const image = params.image || new RGBAImage({width, height});
26
25
 
27
- assert(isPowerOfTwo(width));
26
+ if (!isPowerOfTwo(width)) throw new Error(`width is not a power of 2 - ${width}`);
28
27
 
29
28
  const renderPixel = (stride, index, progress) => {
30
29
  evaluationGlobals[params.evaluationKey] = progress;
@@ -1,4 +1,3 @@
1
- import assert from 'assert';
2
1
 
3
2
  class DictionaryCoder {
4
3
  _stringToNumber: {[_: string]: number};
@@ -15,12 +14,11 @@ class DictionaryCoder {
15
14
  }
16
15
 
17
16
  encode(string: string) {
18
- assert(string in this._stringToNumber);
19
17
  return this._stringToNumber[string];
20
18
  }
21
19
 
22
20
  decode(n: number) {
23
- assert(n < this._numberToString.length);
21
+ if (n >= this._numberToString.length) throw new Error(`Out of bounds. Index requested n=${n} can't be >= this._numberToString.length ${this._numberToString.length}`);
24
22
  return this._numberToString[n];
25
23
  }
26
24
  }
@@ -1,6 +1,5 @@
1
1
  import {uniqueId, asyncAll} from './util';
2
2
  import Actor from './actor';
3
- import assert from 'assert';
4
3
 
5
4
  import type WorkerPool from './worker_pool';
6
5
 
@@ -33,7 +32,7 @@ class Dispatcher {
33
32
  actor.name = `Worker ${i}`;
34
33
  this.actors.push(actor);
35
34
  }
36
- assert(this.actors.length);
35
+ if (!this.actors.length) throw new Error('No actors found');
37
36
  }
38
37
 
39
38
  /**
@@ -41,7 +40,6 @@ class Dispatcher {
41
40
  * @private
42
41
  */
43
42
  broadcast(type: string, data: unknown, cb?: (...args: any[]) => any) {
44
- assert(this.actors.length);
45
43
  cb = cb || function () {};
46
44
  asyncAll(this.actors, (actor, done) => {
47
45
  actor.send(type, data, done);
@@ -53,7 +51,6 @@ class Dispatcher {
53
51
  * @returns An actor object backed by a web worker for processing messages.
54
52
  */
55
53
  getActor(): Actor {
56
- assert(this.actors.length);
57
54
  this.currentActor = (this.currentActor + 1) % this.actors.length;
58
55
  return this.actors[this.currentActor];
59
56
  }
package/src/util/dom.ts CHANGED
@@ -1,7 +1,5 @@
1
1
  import Point from '@mapbox/point-geometry';
2
2
 
3
- import assert from 'assert';
4
-
5
3
  export default class DOM {
6
4
  private static readonly docStyle = typeof window !== 'undefined' && window.document && window.document.documentElement.style;
7
5
 
@@ -107,7 +105,6 @@ export default class DOM {
107
105
  }
108
106
 
109
107
  public static mouseButton(e: MouseEvent) {
110
- assert(e.type === 'mousedown' || e.type === 'mouseup');
111
108
  return e.button;
112
109
  }
113
110
 
package/src/util/image.ts CHANGED
@@ -1,5 +1,3 @@
1
- import assert from 'assert';
2
-
3
1
  import {register} from './web_worker_transfer';
4
2
 
5
3
  export type Size = {
@@ -71,7 +69,7 @@ function copyImage(srcImg: any, dstImg: any, srcPt: Point2D, dstPt: Point2D, siz
71
69
  const srcData = srcImg.data;
72
70
  const dstData = dstImg.data;
73
71
 
74
- assert(srcData !== dstData);
72
+ if (srcData === dstData) throw new Error('srcData equals dstData, so image is already copied');
75
73
 
76
74
  for (let y = 0; y < size.height; y++) {
77
75
  const srcOffset = ((srcPt.y + y) * srcImg.width + srcPt.x) * channels;
@@ -1,7 +1,5 @@
1
1
  // Note: all "sizes" are measured in bytes
2
2
 
3
- import assert from 'assert';
4
-
5
3
  import type {Transferable} from '../types/transferable';
6
4
 
7
5
  const viewTypes = {
@@ -111,7 +109,6 @@ abstract class StructArray {
111
109
  * @private
112
110
  */
113
111
  static serialize(array: StructArray, transferables?: Array<Transferable>): SerializedStructArray {
114
- assert(!array.isTransferred);
115
112
 
116
113
  array._trim();
117
114
 
@@ -160,7 +157,6 @@ abstract class StructArray {
160
157
  * @param {number} n The new size of the array.
161
158
  */
162
159
  resize(n: number) {
163
- assert(!this.isTransferred);
164
160
  this.reserve(n);
165
161
  this.length = n;
166
162
  }
@@ -209,7 +205,6 @@ function createLayout(
209
205
  let offset = 0;
210
206
  let maxSize = 0;
211
207
  const layoutMembers = members.map((member) => {
212
- assert(member.name.length);
213
208
  const typeSize = sizeOf(member.type);
214
209
  const memberOffset = offset = align(offset, Math.max(alignment, typeSize));
215
210
  const components = member.components || 1;
@@ -1,5 +1,3 @@
1
- import assert from 'assert';
2
-
3
1
  export type TaskID = number; // can't mark opaque due to https://github.com/flowtype/flow-remove-types/pull/61
4
2
 
5
3
  type Task = {
@@ -40,7 +38,7 @@ class TaskQueue {
40
38
  }
41
39
 
42
40
  run(timeStamp: number = 0) {
43
- assert(!this._currentlyRunning);
41
+ if (this._currentlyRunning) throw new Error('Attempting to run(), but is already running.');
44
42
  const queue = this._currentlyRunning = this._queue;
45
43
 
46
44
  // Tasks queued by callbacks in the current queue should be executed
@@ -1,5 +1,3 @@
1
- import assert from 'assert';
2
-
3
1
  import TransferableGridIndex from './transferable_grid_index';
4
2
  import Color from '../style-spec/util/color';
5
3
  import {StylePropertyFunction, StyleExpression, ZoomDependentExpression, ZoomConstantExpression} from '../style-spec/expression';
@@ -51,7 +49,7 @@ export function register<T extends any>(
51
49
  },
52
50
  options: RegisterOptions<T> = {}
53
51
  ) {
54
- assert(!registry[name], `${name} is already registered.`);
52
+ if (registry[name]) throw new Error(`${name} is already registered.`);
55
53
  ((Object.defineProperty as any))(klass, '_classRegistryKey', {
56
54
  value: name,
57
55
  writeable: false
@@ -159,7 +157,7 @@ export function serialize(input: unknown, transferables?: Array<Transferable> |
159
157
  if (!name) {
160
158
  throw new Error('can\'t serialize object of unregistered class');
161
159
  }
162
- assert(registry[name]);
160
+ if (!registry[name]) throw new Error(`${name} is not registered.`);
163
161
 
164
162
  const properties: SerializedObject = klass.serialize ?
165
163
  // (Temporary workaround) allow a class to provide static
@@ -185,8 +183,9 @@ export function serialize(input: unknown, transferables?: Array<Transferable> |
185
183
  properties.message = input.message;
186
184
  }
187
185
  } else {
188
- // make sure statically serialized object survives transfer of $name property
189
- assert(!transferables || properties as any !== transferables[transferables.length - 1]);
186
+ if (transferables && properties as any === transferables[transferables.length - 1]) {
187
+ throw new Error('statically serialized object won\'t survive transfer of $name property');
188
+ }
190
189
  }
191
190
 
192
191
  if (properties.$name) {