@loaders.gl/mvt 4.3.2 → 4.4.0-alpha.2

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 (51) hide show
  1. package/dist/dist.dev.js +151 -93
  2. package/dist/dist.min.js +1 -1
  3. package/dist/index.cjs +74 -78
  4. package/dist/index.cjs.map +4 -4
  5. package/dist/index.d.ts +2 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +0 -1
  8. package/dist/lib/parse-mvt.d.ts.map +1 -1
  9. package/dist/lib/pojo-parser/mvt-constants.d.ts +116 -0
  10. package/dist/lib/pojo-parser/mvt-constants.d.ts.map +1 -0
  11. package/dist/lib/pojo-parser/mvt-constants.js +126 -0
  12. package/dist/lib/pojo-parser/mvt-types.d.ts +17 -0
  13. package/dist/lib/pojo-parser/mvt-types.d.ts.map +1 -0
  14. package/dist/lib/pojo-parser/mvt-types.js +4 -0
  15. package/dist/lib/pojo-parser/parse-geometry-from-pbf.d.ts +77 -0
  16. package/dist/lib/pojo-parser/parse-geometry-from-pbf.d.ts.map +1 -0
  17. package/dist/lib/pojo-parser/parse-geometry-from-pbf.js +234 -0
  18. package/dist/lib/pojo-parser/parse-mvt-from-pbf.d.ts +25 -0
  19. package/dist/lib/pojo-parser/parse-mvt-from-pbf.d.ts.map +1 -0
  20. package/dist/lib/pojo-parser/parse-mvt-from-pbf.js +262 -0
  21. package/dist/lib/vector-tile/vector-tile-feature.d.ts +2 -1
  22. package/dist/lib/vector-tile/vector-tile-feature.d.ts.map +1 -1
  23. package/dist/lib/vector-tile/vector-tile-layer.d.ts +1 -1
  24. package/dist/lib/vector-tile/vector-tile-layer.d.ts.map +1 -1
  25. package/dist/mvt-format.d.ts +12 -0
  26. package/dist/mvt-format.d.ts.map +1 -0
  27. package/dist/mvt-format.js +20 -0
  28. package/dist/mvt-loader.d.ts +12 -12
  29. package/dist/mvt-loader.d.ts.map +1 -1
  30. package/dist/mvt-loader.js +3 -13
  31. package/dist/mvt-source.d.ts +22 -24
  32. package/dist/mvt-source.d.ts.map +1 -1
  33. package/dist/mvt-source.js +14 -23
  34. package/dist/mvt-worker.js +20 -15
  35. package/dist/table-tile-source.d.ts +38 -38
  36. package/dist/table-tile-source.d.ts.map +1 -1
  37. package/dist/table-tile-source.js +54 -53
  38. package/dist/tilejson-loader.js +1 -1
  39. package/package.json +7 -7
  40. package/src/index.ts +2 -2
  41. package/src/lib/parse-mvt.ts +2 -8
  42. package/src/lib/pojo-parser/mvt-constants.ts +135 -0
  43. package/src/lib/pojo-parser/mvt-types.ts +22 -0
  44. package/src/lib/pojo-parser/parse-geometry-from-pbf.ts +285 -0
  45. package/src/lib/pojo-parser/parse-mvt-from-pbf.ts +310 -0
  46. package/src/lib/vector-tile/vector-tile-feature.ts +2 -6
  47. package/src/lib/vector-tile/vector-tile-layer.ts +1 -1
  48. package/src/mvt-format.ts +23 -0
  49. package/src/mvt-loader.ts +2 -13
  50. package/src/mvt-source.ts +33 -38
  51. package/src/table-tile-source.ts +116 -96
@@ -3,20 +3,18 @@
3
3
  // Copyright (c) vis.gl contributors
4
4
  // Based on https://github.com/mapbox/geojson-vt under compatible ISC license
5
5
 
6
- import {Source, VectorTileSource, TileSourceMetadata, log} from '@loaders.gl/loader-utils';
7
6
  import type {
8
- VectorTileSourceProps,
7
+ Source,
8
+ DataSourceOptions,
9
+ VectorTileSource,
10
+ TileSourceMetadata,
9
11
  GetTileDataParameters,
10
12
  GetTileParameters,
11
13
  LoaderWithParser
12
14
  } from '@loaders.gl/loader-utils';
13
- import {
14
- Schema,
15
- GeoJSONTable,
16
- Feature,
17
- BinaryFeatureCollection,
18
- deduceTableSchema
19
- } from '@loaders.gl/schema';
15
+ import {DataSource, getRequiredOptions, log} from '@loaders.gl/loader-utils';
16
+ import type {Schema, GeoJSONTable, Feature, BinaryFeatureCollection} from '@loaders.gl/schema';
17
+ import {deduceTableSchema} from '@loaders.gl/schema-utils';
20
18
  import {Stats, Stat} from '@probe.gl/stats';
21
19
 
22
20
  import type {ProtoFeature} from './lib/vector-tiler/features/proto-feature';
@@ -28,14 +26,46 @@ import {convertFeaturesToProtoFeature} from './lib/vector-tiler/features/convert
28
26
  import {clipFeatures} from './lib/vector-tiler/features/clip-features'; // stripe clipping algorithm
29
27
  import {wrapFeatures} from './lib/vector-tiler/features/wrap-features'; // date line processing
30
28
 
29
+ /** Options to configure tiling */
30
+ export type TableTileSourceOptions = DataSourceOptions & {
31
+ table?: {
32
+ coordinates?: 'local' | 'wgs84' | 'EPSG:4326';
33
+ /** max zoom to preserve detail on */
34
+ maxZoom?: number;
35
+ /** max zoom in the tile index */
36
+ indexMaxZoom?: number;
37
+ /** max number of points per tile in the tile index */
38
+ maxPointsPerTile?: number;
39
+ /** simplification tolerance (higher means simpler) */
40
+ tolerance?: number;
41
+ /** tile extent */
42
+ extent?: number;
43
+ /** tile buffer on each side */
44
+ buffer?: number;
45
+ /** name of a feature property to be promoted to feature.id */
46
+ promoteId?: string;
47
+ /** whether to generate feature ids. Cannot be used with promoteId */
48
+ generateId?: boolean;
49
+ /** logging level (0, 1 or 2) */
50
+ debug?: number;
51
+ /** whether to calculate line metrics */
52
+ lineMetrics?: boolean;
53
+ };
54
+ };
55
+
31
56
  /** Options to configure tiling */
32
57
  export const TableTileSource = {
33
58
  name: 'TableTiler',
34
59
  id: 'table-tiler',
60
+ module: 'mvt',
35
61
  version: '0.0.0',
36
62
  extensions: ['mvt'],
37
63
  mimeTypes: ['application/octet-stream'],
38
- options: {
64
+ type: 'table',
65
+ fromUrl: false,
66
+ fromBlob: false,
67
+
68
+ defaultOptions: {
39
69
  table: {
40
70
  coordinates: 'local',
41
71
  promoteId: undefined!,
@@ -48,59 +78,18 @@ export const TableTileSource = {
48
78
  generateId: undefined
49
79
  }
50
80
  },
51
- type: 'table',
81
+
52
82
  testURL: (url: string): boolean => url.endsWith('.geojson'),
53
83
  createDataSource(
54
84
  url: string | Blob | GeoJSONTable | Promise<GeoJSONTable>,
55
- options: DynamicVectorTileSourceProps
56
- ): DynamicVectorTileSource {
85
+ options: TableTileSourceOptions
86
+ ): TableVectorTileSource {
57
87
  const needsLoading = typeof url === 'string' || url instanceof Blob;
58
- const loader = options?.table?.loaders?.[0]!;
88
+ const loader = options?.core?.loaders?.[0] as LoaderWithParser;
59
89
  const tablePromise = needsLoading ? loadTable(url, loader) : url;
60
- return new DynamicVectorTileSource(tablePromise, options);
61
- }
62
- // @ts-expect-error
63
- } as const satisfies Source<DynamicVectorTileSource, DynamicVectorTileSourceProps>;
64
-
65
- async function loadTable(url: string | Blob, loader: LoaderWithParser): Promise<GeoJSONTable> {
66
- if (typeof url === 'string') {
67
- const response = await fetch(url);
68
- const data = await response.arrayBuffer();
69
- return (await loader.parse(data)) as GeoJSONTable;
90
+ return new TableVectorTileSource(tablePromise, options);
70
91
  }
71
-
72
- const data = await url.arrayBuffer();
73
- return (await loader.parse(data)) as GeoJSONTable; // options.loaders, options.loadOptions)
74
- }
75
-
76
- /** Options to configure tiling */
77
- export type DynamicVectorTileSourceProps = VectorTileSourceProps & {
78
- table: {
79
- coordinates: 'local' | 'wgs84' | 'EPSG:4326';
80
- /** max zoom to preserve detail on */
81
- maxZoom?: number;
82
- /** max zoom in the tile index */
83
- indexMaxZoom?: number;
84
- /** max number of points per tile in the tile index */
85
- maxPointsPerTile?: number;
86
- /** simplification tolerance (higher means simpler) */
87
- tolerance?: number;
88
- /** tile extent */
89
- extent?: number;
90
- /** tile buffer on each side */
91
- buffer?: number;
92
- /** name of a feature property to be promoted to feature.id */
93
- promoteId?: string;
94
- /** whether to generate feature ids. Cannot be used with promoteId */
95
- generateId?: boolean;
96
- /** logging level (0, 1 or 2) */
97
- debug?: number;
98
- /** whether to calculate line metrics */
99
- lineMetrics?: boolean;
100
- /** table loders */
101
- loaders?: LoaderWithParser[];
102
- };
103
- };
92
+ } as const satisfies Source<TableVectorTileSource>;
104
93
 
105
94
  /**
106
95
  * Dynamically vector tiles a table (the table needs a geometry column)
@@ -117,8 +106,9 @@ export type DynamicVectorTileSourceProps = VectorTileSourceProps & {
117
106
  * @todo - generate binary output tables
118
107
  * @todo - how does TileSourceLayer specify coordinates / decided which layer to render with
119
108
  */
120
- export class DynamicVectorTileSource
121
- implements VectorTileSource<DynamicVectorTileSourceProps, TileSourceMetadata>
109
+ export class TableVectorTileSource
110
+ extends DataSource<GeoJSONTable | Promise<GeoJSONTable>, TableTileSourceOptions>
111
+ implements VectorTileSource
122
112
  {
123
113
  /** Global stats for all DynamicVectorTileSources */
124
114
  static stats = new Stats({
@@ -126,7 +116,7 @@ export class DynamicVectorTileSource
126
116
  stats: [new Stat('count', 'tiles'), new Stat('count', 'features')]
127
117
  });
128
118
 
129
- /** Stats for this DynamicVectorTileSource */
119
+ /** Stats for this TableVectorTileSource */
130
120
  stats = new Stats({
131
121
  id: 'table-tile-source',
132
122
  stats: [new Stat('tiles', 'count'), new Stat('features', 'count')]
@@ -135,10 +125,7 @@ export class DynamicVectorTileSource
135
125
  /** MIME type of the tiles emitted by this tile source */
136
126
  readonly mimeType = 'application/vnd.mapbox-vector-tile';
137
127
  readonly localCoordinates = true;
138
-
139
- /** The props that this tile source was created with */
140
- // @ts-expect-error
141
- props: Required<DynamicVectorTileSourceProps['table']>;
128
+ readonly tableOptions: Required<Required<TableTileSourceOptions>['table']>;
142
129
 
143
130
  /* Schema of the data */
144
131
  schema: Schema | null = null;
@@ -153,9 +140,9 @@ export class DynamicVectorTileSource
153
140
  /** Metadata for the tile source (generated TileJSON/tilestats */
154
141
  metadata: Promise<unknown>;
155
142
 
156
- constructor(table: GeoJSONTable | Promise<GeoJSONTable>, props?: DynamicVectorTileSourceProps) {
157
- // @ts-expect-error
158
- this.props = {...TableTileSource.options.table, ...props?.table};
143
+ constructor(table: GeoJSONTable | Promise<GeoJSONTable>, options: TableTileSourceOptions) {
144
+ super(table, options, TableTileSource.defaultOptions);
145
+ this.tableOptions = getRequiredOptions(this.options).table;
159
146
  this.getTileData = this.getTileData.bind(this);
160
147
  this.ready = this.initializeTilesAsync(table);
161
148
  this.metadata = this.getMetadata();
@@ -169,7 +156,7 @@ export class DynamicVectorTileSource
169
156
 
170
157
  async getMetadata(): Promise<TileSourceMetadata & {schema: Schema | null}> {
171
158
  await this.ready;
172
- return {schema: this.schema, minZoom: 0, maxZoom: this.props.maxZoom};
159
+ return {schema: this.schema, minZoom: 0, maxZoom: this.tableOptions.maxZoom};
173
160
  }
174
161
 
175
162
  async getSchema(): Promise<Schema> {
@@ -215,9 +202,9 @@ export class DynamicVectorTileSource
215
202
  }
216
203
 
217
204
  return convertTileToGeoJSON(protoTile, {
218
- coordinates: this.props.coordinates,
205
+ coordinates: this.tableOptions.coordinates,
219
206
  tileIndex,
220
- extent: this.props.extent
207
+ extent: this.tableOptions.extent
221
208
  });
222
209
  }
223
210
 
@@ -226,28 +213,28 @@ export class DynamicVectorTileSource
226
213
  * @note the tiles stores all the features together with additional data
227
214
  */
228
215
  createRootTiles(table: GeoJSONTable): void {
229
- if (this.props.maxZoom < 0 || this.props.maxZoom > 24) {
216
+ if (this.tableOptions.maxZoom < 0 || this.tableOptions.maxZoom > 24) {
230
217
  throw new Error('maxZoom should be in the 0-24 range');
231
218
  }
232
- if (this.props.promoteId && this.props.generateId) {
219
+ if (this.tableOptions.promoteId && this.tableOptions.generateId) {
233
220
  throw new Error('promoteId and generateId cannot be used together.');
234
221
  }
235
222
 
236
- log.log(1, 'DynamicVectorTileSource creating root tiles', this.props)();
223
+ log.log(1, 'TableVectorTileSource creating root tiles', this.tableOptions)();
237
224
 
238
225
  // projects and adds simplification info
239
226
  log.time(1, 'preprocess table')();
240
- let features = convertFeaturesToProtoFeature(table, this.props);
227
+ let features = convertFeaturesToProtoFeature(table, this.tableOptions);
241
228
  log.timeEnd(1, 'preprocess table')();
242
229
 
243
230
  // wraps features (ie extreme west and extreme east)
244
231
  log.time(1, 'generate tiles')();
245
232
 
246
- features = wrapFeatures(features, this.props);
233
+ features = wrapFeatures(features, this.tableOptions);
247
234
 
248
235
  // start slicing from the top tile down
249
236
  if (features.length === 0) {
250
- log.log(1, 'DynamicVectorTileSource: no features generated')();
237
+ log.log(1, 'TableVectorTileSource: no features generated')();
251
238
  return;
252
239
  }
253
240
 
@@ -259,7 +246,7 @@ export class DynamicVectorTileSource
259
246
  log.timeEnd(1, 'generate tiles')();
260
247
  log.log(
261
248
  1,
262
- `DynamicVectorTileSource: tiles generated: ${this.stats.get('total').count}`,
249
+ `TableVectorTileSource: tiles generated: ${this.stats.get('total').count}`,
263
250
  this.stats
264
251
  )();
265
252
  }
@@ -276,7 +263,7 @@ export class DynamicVectorTileSource
276
263
  // x = +x;
277
264
  // y = +y;
278
265
 
279
- const {extent} = this.props;
266
+ const {extent} = this.tableOptions;
280
267
 
281
268
  if (z < 0 || z > 24) {
282
269
  return null;
@@ -325,7 +312,7 @@ export class DynamicVectorTileSource
325
312
  * @param cz, cx, and cy are the coordinates of the target tile
326
313
  *
327
314
  * If no target tile is specified, splitting stops when we reach the maximum
328
- * zoom or the number of points is low as specified in the props.
315
+ * zoom or the number of points is low as specified in the options.
329
316
  */
330
317
  // eslint-disable-next-line max-params, max-statements, complexity
331
318
  splitTile(
@@ -353,7 +340,7 @@ export class DynamicVectorTileSource
353
340
  if (!tile) {
354
341
  log.time(2, 'tile creation')();
355
342
 
356
- tile = this.tiles[id] = createProtoTile(features, z, x, y, this.props);
343
+ tile = this.tiles[id] = createProtoTile(features, z, x, y, this.tableOptions);
357
344
  this.tileCoords.push({z, x, y});
358
345
 
359
346
  const key = `z${z}`;
@@ -363,10 +350,10 @@ export class DynamicVectorTileSource
363
350
  stat = this.stats.get('total');
364
351
  stat.incrementCount();
365
352
 
366
- stat = DynamicVectorTileSource.stats.get(key, 'count');
353
+ stat = TableVectorTileSource.stats.get(key, 'count');
367
354
  stat.incrementCount();
368
355
 
369
- stat = DynamicVectorTileSource.stats.get('total');
356
+ stat = TableVectorTileSource.stats.get('total');
370
357
  stat.incrementCount();
371
358
 
372
359
  log.log(
@@ -390,11 +377,14 @@ export class DynamicVectorTileSource
390
377
  // if it's the first-pass tiling
391
378
  if (cz === undefined) {
392
379
  // stop tiling if we reached max zoom, or if the tile is too simple
393
- if (z === this.props.indexMaxZoom || tile.numPoints <= this.props.maxPointsPerTile) {
380
+ if (
381
+ z === this.tableOptions.indexMaxZoom ||
382
+ tile.numPoints <= this.tableOptions.maxPointsPerTile
383
+ ) {
394
384
  continue;
395
385
  }
396
386
  // if a drilldown to a specific tile
397
- } else if (z === this.props.maxZoom || z === cz) {
387
+ } else if (z === this.tableOptions.maxZoom || z === cz) {
398
388
  // stop tiling if we reached base zoom or our target tile zoom
399
389
  continue;
400
390
  } else if (cz !== undefined) {
@@ -414,7 +404,7 @@ export class DynamicVectorTileSource
414
404
  log.time(2, 'clipping tile')();
415
405
 
416
406
  // values we'll use for clipping
417
- const k1 = (0.5 * this.props.buffer) / this.props.extent;
407
+ const k1 = (0.5 * this.tableOptions.buffer) / this.tableOptions.extent;
418
408
  const k2 = 0.5 - k1;
419
409
  const k3 = 0.5 + k1;
420
410
  const k4 = 1 + k1;
@@ -424,21 +414,39 @@ export class DynamicVectorTileSource
424
414
  let tr: ProtoFeature[] | null = null;
425
415
  let br: ProtoFeature[] | null = null;
426
416
 
427
- let left = clipFeatures(features, z2, x - k1, x + k3, 0, tile.minX, tile.maxX, this.props);
428
- let right = clipFeatures(features, z2, x + k2, x + k4, 0, tile.minX, tile.maxX, this.props);
417
+ let left = clipFeatures(
418
+ features,
419
+ z2,
420
+ x - k1,
421
+ x + k3,
422
+ 0,
423
+ tile.minX,
424
+ tile.maxX,
425
+ this.tableOptions
426
+ );
427
+ let right = clipFeatures(
428
+ features,
429
+ z2,
430
+ x + k2,
431
+ x + k4,
432
+ 0,
433
+ tile.minX,
434
+ tile.maxX,
435
+ this.tableOptions
436
+ );
429
437
 
430
438
  // @ts-expect-error - unclear why this is needed?
431
439
  features = null;
432
440
 
433
441
  if (left) {
434
- tl = clipFeatures(left, z2, y - k1, y + k3, 1, tile.minY, tile.maxY, this.props);
435
- bl = clipFeatures(left, z2, y + k2, y + k4, 1, tile.minY, tile.maxY, this.props);
442
+ tl = clipFeatures(left, z2, y - k1, y + k3, 1, tile.minY, tile.maxY, this.tableOptions);
443
+ bl = clipFeatures(left, z2, y + k2, y + k4, 1, tile.minY, tile.maxY, this.tableOptions);
436
444
  left = null;
437
445
  }
438
446
 
439
447
  if (right) {
440
- tr = clipFeatures(right, z2, y - k1, y + k3, 1, tile.minY, tile.maxY, this.props);
441
- br = clipFeatures(right, z2, y + k2, y + k4, 1, tile.minY, tile.maxY, this.props);
448
+ tr = clipFeatures(right, z2, y - k1, y + k3, 1, tile.minY, tile.maxY, this.tableOptions);
449
+ br = clipFeatures(right, z2, y + k2, y + k4, 1, tile.minY, tile.maxY, this.tableOptions);
442
450
  right = null;
443
451
  }
444
452
 
@@ -455,12 +463,24 @@ export class DynamicVectorTileSource
455
463
  function toID(z, x, y): number {
456
464
  return ((1 << z) * y + x) * 32 + z;
457
465
  }
466
+
467
+ async function loadTable(url: string | Blob, loader: LoaderWithParser): Promise<GeoJSONTable> {
468
+ if (typeof url === 'string') {
469
+ const response = await fetch(url);
470
+ const data = await response.arrayBuffer();
471
+ return (await loader.parse(data)) as GeoJSONTable;
472
+ }
473
+
474
+ const data = await url.arrayBuffer();
475
+ return (await loader.parse(data)) as GeoJSONTable; // options.loaders, options.loadOptions)
476
+ }
477
+
458
478
  /*
459
479
 
460
480
  // eslint-disable-next-line max-statements, complexity
461
481
  function convertToGeoJSONTable(
462
482
  vtTile: ProtoTile,
463
- props: {
483
+ options: {
464
484
  coordinates: 'local' | 'wgs84' | 'EPSG:4326';
465
485
  tileIndex: {x: number; y: number; z: number};
466
486
  extent: number;
@@ -515,18 +535,18 @@ function convertToGeoJSONTable(
515
535
  continue;
516
536
  }
517
537
 
518
- switch (props.coordinates) {
538
+ switch (options.coordinates) {
519
539
  case 'EPSG:4326':
520
540
  case 'wgs84':
521
- projectToLngLat(coordinates, props.tileIndex, props.extent);
541
+ projectToLngLat(coordinates, options.tileIndex, options.extent);
522
542
  break;
523
543
 
524
544
  case 'local':
525
- convertToLocalCoordinates(coordinates, props.extent);
545
+ convertToLocalCoordinates(coordinates, options.extent);
526
546
  break;
527
547
 
528
548
  default:
529
- throw new Error(`Unsupported CRS ${props.coordinates}`);
549
+ throw new Error(`Unsupported CRS ${options.coordinates}`);
530
550
  }
531
551
 
532
552
  const feature: Feature = {