@loaders.gl/mvt 4.3.0-alpha.1 → 4.3.0-alpha.3

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 (93) hide show
  1. package/dist/dist.dev.js +1289 -807
  2. package/dist/dist.min.js +1 -1
  3. package/dist/index.cjs +923 -773
  4. package/dist/index.cjs.map +4 -4
  5. package/dist/index.d.ts +7 -6
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +6 -2
  8. package/dist/lib/parse-mvt.d.ts +1 -1
  9. package/dist/lib/parse-mvt.js +2 -30
  10. package/dist/lib/parse-tilejson.d.ts +4 -4
  11. package/dist/lib/parse-tilejson.d.ts.map +1 -1
  12. package/dist/lib/parse-tilejson.js +1 -1
  13. package/dist/lib/utils/geometry-utils.d.ts +38 -1
  14. package/dist/lib/utils/geometry-utils.d.ts.map +1 -1
  15. package/dist/lib/utils/geometry-utils.js +65 -6
  16. package/dist/lib/vector-tile/vector-tile-feature.d.ts +28 -9
  17. package/dist/lib/vector-tile/vector-tile-feature.d.ts.map +1 -1
  18. package/dist/lib/vector-tile/vector-tile-feature.js +47 -50
  19. package/dist/lib/{geojsonvt/clip.d.ts → vector-tiler/features/clip-features.d.ts} +4 -4
  20. package/dist/lib/vector-tiler/features/clip-features.d.ts.map +1 -0
  21. package/dist/lib/{geojsonvt/clip.js → vector-tiler/features/clip-features.js} +4 -4
  22. package/dist/lib/vector-tiler/features/convert-feature.d.ts +18 -0
  23. package/dist/lib/vector-tiler/features/convert-feature.d.ts.map +1 -0
  24. package/dist/lib/vector-tiler/features/convert-feature.js +140 -0
  25. package/dist/lib/vector-tiler/features/proto-feature.d.ts +30 -0
  26. package/dist/lib/vector-tiler/features/proto-feature.d.ts.map +1 -0
  27. package/dist/lib/vector-tiler/features/proto-feature.js +52 -0
  28. package/dist/lib/{geojsonvt/simplify.d.ts → vector-tiler/features/simplify-path.d.ts} +2 -2
  29. package/dist/lib/vector-tiler/features/simplify-path.d.ts.map +1 -0
  30. package/dist/lib/{geojsonvt/simplify.js → vector-tiler/features/simplify-path.js} +3 -3
  31. package/dist/lib/{geojsonvt/wrap.d.ts → vector-tiler/features/wrap-features.d.ts} +5 -5
  32. package/dist/lib/vector-tiler/features/wrap-features.d.ts.map +1 -0
  33. package/dist/lib/{geojsonvt/wrap.js → vector-tiler/features/wrap-features.js} +33 -26
  34. package/dist/lib/vector-tiler/proto-tile.d.ts +40 -0
  35. package/dist/lib/vector-tiler/proto-tile.d.ts.map +1 -0
  36. package/dist/lib/vector-tiler/proto-tile.js +138 -0
  37. package/dist/lib/vector-tiler/tile-to-geojson.d.ts +12 -0
  38. package/dist/lib/vector-tiler/tile-to-geojson.d.ts.map +1 -0
  39. package/dist/lib/vector-tiler/tile-to-geojson.js +81 -0
  40. package/dist/lib/vector-tiler/transform-tile.d.ts +7 -0
  41. package/dist/lib/vector-tiler/transform-tile.d.ts.map +1 -0
  42. package/dist/lib/vector-tiler/transform-tile.js +41 -0
  43. package/dist/mvt-loader.d.ts +1 -1
  44. package/dist/mvt-loader.js +1 -1
  45. package/dist/mvt-source.d.ts +35 -18
  46. package/dist/mvt-source.d.ts.map +1 -1
  47. package/dist/mvt-source.js +30 -10
  48. package/dist/mvt-worker.js +101 -56
  49. package/dist/table-tile-source.d.ts +148 -0
  50. package/dist/table-tile-source.d.ts.map +1 -0
  51. package/dist/table-tile-source.js +420 -0
  52. package/dist/tilejson-loader.js +1 -1
  53. package/package.json +7 -6
  54. package/src/index.ts +14 -7
  55. package/src/lib/parse-mvt.ts +4 -33
  56. package/src/lib/parse-tilejson.ts +6 -6
  57. package/src/lib/utils/geometry-utils.ts +66 -1
  58. package/src/lib/vector-tile/vector-tile-feature.ts +65 -56
  59. package/src/lib/{geojsonvt/clip.ts → vector-tiler/features/clip-features.ts} +8 -8
  60. package/src/lib/vector-tiler/features/convert-feature.ts +191 -0
  61. package/src/lib/vector-tiler/features/proto-feature.ts +104 -0
  62. package/src/lib/{geojsonvt/simplify.ts → vector-tiler/features/simplify-path.ts} +8 -3
  63. package/src/lib/{geojsonvt/wrap.ts → vector-tiler/features/wrap-features.ts} +44 -29
  64. package/src/lib/vector-tiler/proto-tile.ts +217 -0
  65. package/src/lib/vector-tiler/tile-to-geojson.ts +105 -0
  66. package/src/lib/vector-tiler/transform-tile.ts +57 -0
  67. package/src/mvt-source.ts +47 -24
  68. package/src/table-tile-source.ts +553 -0
  69. package/src/tilejson-loader.ts +2 -2
  70. package/dist/geojson-tile-source.d.ts +0 -79
  71. package/dist/geojson-tile-source.d.ts.map +0 -1
  72. package/dist/geojson-tile-source.js +0 -319
  73. package/dist/lib/geojsonvt/clip.d.ts.map +0 -1
  74. package/dist/lib/geojsonvt/convert.d.ts +0 -10
  75. package/dist/lib/geojsonvt/convert.d.ts.map +0 -1
  76. package/dist/lib/geojsonvt/convert.js +0 -132
  77. package/dist/lib/geojsonvt/feature.d.ts +0 -3
  78. package/dist/lib/geojsonvt/feature.d.ts.map +0 -1
  79. package/dist/lib/geojsonvt/feature.js +0 -44
  80. package/dist/lib/geojsonvt/simplify.d.ts.map +0 -1
  81. package/dist/lib/geojsonvt/tile.d.ts +0 -38
  82. package/dist/lib/geojsonvt/tile.d.ts.map +0 -1
  83. package/dist/lib/geojsonvt/tile.js +0 -123
  84. package/dist/lib/geojsonvt/transform.d.ts +0 -7
  85. package/dist/lib/geojsonvt/transform.d.ts.map +0 -1
  86. package/dist/lib/geojsonvt/transform.js +0 -41
  87. package/dist/lib/geojsonvt/wrap.d.ts.map +0 -1
  88. package/src/geojson-tile-source.ts +0 -422
  89. package/src/lib/geojsonvt/convert.ts +0 -160
  90. package/src/lib/geojsonvt/feature.ts +0 -47
  91. package/src/lib/geojsonvt/tile.ts +0 -187
  92. package/src/lib/geojsonvt/transform.ts +0 -57
  93. /package/src/lib/{geojsonvt → vector-tiler}/LICENSE +0 -0
@@ -0,0 +1,420 @@
1
+ // loaders.gl
2
+ // SPDX-License-Identifier: MIT AND ISC
3
+ // Copyright (c) vis.gl contributors
4
+ // Based on https://github.com/mapbox/geojson-vt under compatible ISC license
5
+ import { log } from '@loaders.gl/loader-utils';
6
+ import { deduceTableSchema } from '@loaders.gl/schema';
7
+ import { Stats, Stat } from '@probe.gl/stats';
8
+ import { createProtoTile } from "./lib/vector-tiler/proto-tile.js";
9
+ import { transformTile } from "./lib/vector-tiler/transform-tile.js"; // coordinate transformation
10
+ import { convertTileToGeoJSON } from "./lib/vector-tiler/tile-to-geojson.js"; // tile clipping and wrapping
11
+ import { convertFeaturesToProtoFeature } from "./lib/vector-tiler/features/convert-feature.js";
12
+ import { clipFeatures } from "./lib/vector-tiler/features/clip-features.js"; // stripe clipping algorithm
13
+ import { wrapFeatures } from "./lib/vector-tiler/features/wrap-features.js"; // date line processing
14
+ /** Options to configure tiling */
15
+ export const TableTileSource = {
16
+ name: 'TableTiler',
17
+ id: 'table-tiler',
18
+ version: '0.0.0',
19
+ extensions: ['mvt'],
20
+ mimeTypes: ['application/octet-stream'],
21
+ options: {
22
+ table: {
23
+ coordinates: 'local',
24
+ promoteId: undefined,
25
+ maxZoom: 14,
26
+ indexMaxZoom: 5,
27
+ maxPointsPerTile: 10000,
28
+ tolerance: 3,
29
+ extent: 4096,
30
+ buffer: 64,
31
+ generateId: undefined
32
+ }
33
+ },
34
+ type: 'table',
35
+ testURL: (url) => url.endsWith('.geojson'),
36
+ createDataSource(url, options) {
37
+ const needsLoading = typeof url === 'string' || url instanceof Blob;
38
+ const loader = options?.table?.loaders?.[0];
39
+ const tablePromise = needsLoading ? loadTable(url, loader) : url;
40
+ return new DynamicVectorTileSource(tablePromise, options);
41
+ }
42
+ // @ts-expect-error
43
+ };
44
+ async function loadTable(url, loader) {
45
+ if (typeof url === 'string') {
46
+ const response = await fetch(url);
47
+ const data = await response.arrayBuffer();
48
+ return (await loader.parse(data));
49
+ }
50
+ const data = await url.arrayBuffer();
51
+ return (await loader.parse(data)); // options.loaders, options.loadOptions)
52
+ }
53
+ /**
54
+ * Dynamically vector tiles a table (the table needs a geometry column)
55
+ * - Tiles are generated when requested.
56
+ * - Each tile contains a tables of clipped features.
57
+ *
58
+ * @note - Currently only accepts `GeoJSONTable` tables
59
+ * @note - Currently only outputs `GeoJSONTable`
60
+ * @note - (can be initialized with a promise that resolves to GeoJSONTable).
61
+ *
62
+ * @todo - metadata should scan all rows to determine schema
63
+ * @todo - metadata scan all rows to determine tilestats (field values[] etc).
64
+ * @todo - handle binary input tables
65
+ * @todo - generate binary output tables
66
+ * @todo - how does TileSourceLayer specify coordinates / decided which layer to render with
67
+ */
68
+ export class DynamicVectorTileSource {
69
+ /** Global stats for all DynamicVectorTileSources */
70
+ static stats = new Stats({
71
+ id: 'table-tile-source-all',
72
+ stats: [new Stat('count', 'tiles'), new Stat('count', 'features')]
73
+ });
74
+ /** Stats for this DynamicVectorTileSource */
75
+ stats = new Stats({
76
+ id: 'table-tile-source',
77
+ stats: [new Stat('tiles', 'count'), new Stat('features', 'count')]
78
+ });
79
+ /** MIME type of the tiles emitted by this tile source */
80
+ mimeType = 'application/vnd.mapbox-vector-tile';
81
+ localCoordinates = true;
82
+ /** The props that this tile source was created with */
83
+ // @ts-expect-error
84
+ props;
85
+ /* Schema of the data */
86
+ schema = null;
87
+ /** Map of generated tiles, indexed by stringified tile coordinates */
88
+ tiles = {};
89
+ /** Array of tile coordinates */
90
+ tileCoords = [];
91
+ /** Input data has loaded, initial top-level tiling is done, sync methods can now be called */
92
+ ready;
93
+ /** Metadata for the tile source (generated TileJSON/tilestats */
94
+ metadata;
95
+ constructor(table, props) {
96
+ // @ts-expect-error
97
+ this.props = { ...TableTileSource.options.table, ...props?.table };
98
+ this.getTileData = this.getTileData.bind(this);
99
+ this.ready = this.initializeTilesAsync(table);
100
+ this.metadata = this.getMetadata();
101
+ }
102
+ async initializeTilesAsync(tablePromise) {
103
+ const table = await tablePromise;
104
+ this.schema = deduceTableSchema(table);
105
+ this.createRootTiles(table);
106
+ }
107
+ async getMetadata() {
108
+ await this.ready;
109
+ return { schema: this.schema, minZoom: 0, maxZoom: this.props.maxZoom };
110
+ }
111
+ async getSchema() {
112
+ await this.ready;
113
+ return this.schema;
114
+ }
115
+ /**
116
+ * Get a tile at the specified index
117
+ * @param tileIndex z, x, y of tile
118
+ * @returns
119
+ */
120
+ async getVectorTile(tileIndex) {
121
+ await this.ready;
122
+ const table = this.getTileSync(tileIndex);
123
+ log.info(2, 'getVectorTile', tileIndex, table)();
124
+ return table;
125
+ }
126
+ async getTile(tileIndex) {
127
+ await this.ready;
128
+ return this.getTileSync(tileIndex);
129
+ }
130
+ async getTileData(tileParams) {
131
+ const { x, y, z } = tileParams.index;
132
+ const tile = await this.getVectorTile({ x, y, z });
133
+ return tile?.features || [];
134
+ }
135
+ // Implementation
136
+ /**
137
+ * Synchronously request a tile
138
+ * @note Application must await `source.ready` before calling sync methods.
139
+ */
140
+ getTileSync(tileIndex) {
141
+ const protoTile = this.getProtoTile(tileIndex);
142
+ if (!protoTile) {
143
+ return null;
144
+ }
145
+ return convertTileToGeoJSON(protoTile, {
146
+ coordinates: this.props.coordinates,
147
+ tileIndex,
148
+ extent: this.props.extent
149
+ });
150
+ }
151
+ /**
152
+ * Create the initial tiles
153
+ * @note the tiles stores all the features together with additional data
154
+ */
155
+ createRootTiles(table) {
156
+ if (this.props.maxZoom < 0 || this.props.maxZoom > 24) {
157
+ throw new Error('maxZoom should be in the 0-24 range');
158
+ }
159
+ if (this.props.promoteId && this.props.generateId) {
160
+ throw new Error('promoteId and generateId cannot be used together.');
161
+ }
162
+ log.log(1, 'DynamicVectorTileSource creating root tiles', this.props)();
163
+ // projects and adds simplification info
164
+ log.time(1, 'preprocess table')();
165
+ let features = convertFeaturesToProtoFeature(table, this.props);
166
+ log.timeEnd(1, 'preprocess table')();
167
+ // wraps features (ie extreme west and extreme east)
168
+ log.time(1, 'generate tiles')();
169
+ features = wrapFeatures(features, this.props);
170
+ // start slicing from the top tile down
171
+ if (features.length === 0) {
172
+ log.log(1, 'DynamicVectorTileSource: no features generated')();
173
+ return;
174
+ }
175
+ this.splitTile(features, 0, 0, 0);
176
+ const rootTile = this.tiles[0];
177
+ log.log(1, `root tile features: ${rootTile.numFeatures}, points: ${rootTile.numPoints}`)();
178
+ log.timeEnd(1, 'generate tiles')();
179
+ log.log(1, `DynamicVectorTileSource: tiles generated: ${this.stats.get('total').count}`, this.stats)();
180
+ }
181
+ /**
182
+ * Return geojsonvt-style "half formed" vector tile
183
+ * @note Application must await `source.ready` before calling sync methods.
184
+ */
185
+ // eslint-disable-next-line complexity, max-statements
186
+ getProtoTile(tileIndex) {
187
+ const { z, y } = tileIndex;
188
+ let { x } = tileIndex;
189
+ // z = +z;
190
+ // x = +x;
191
+ // y = +y;
192
+ const { extent } = this.props;
193
+ if (z < 0 || z > 24) {
194
+ return null;
195
+ }
196
+ const z2 = 1 << z;
197
+ x = (x + z2) & (z2 - 1); // wrapFeatures tile x coordinate
198
+ const id = toID(z, x, y);
199
+ if (this.tiles[id]) {
200
+ return transformTile(this.tiles[id], extent);
201
+ }
202
+ log.log(log, 'drilling down to z%d-%d-%d', z, x, y)();
203
+ let z0 = z;
204
+ let x0 = x;
205
+ let y0 = y;
206
+ let parent;
207
+ while (!parent && z0 > 0) {
208
+ z0--;
209
+ x0 = x0 >> 1;
210
+ y0 = y0 >> 1;
211
+ parent = this.tiles[toID(z0, x0, y0)];
212
+ }
213
+ if (!parent || !parent.sourceFeatures) {
214
+ return null;
215
+ }
216
+ // if we found a parent tile containing the original geometry, we can drill down from it
217
+ log.log(1, 'found parent tile z%d-%d-%d', z0, x0, y0)();
218
+ log.time(1, 'drilling down')();
219
+ this.splitTile(parent.sourceFeatures, z0, x0, y0, z, x, y);
220
+ log.timeEnd(1, 'drilling down')();
221
+ return this.tiles[id] ? transformTile(this.tiles[id], extent) : null;
222
+ }
223
+ /**
224
+ * splits features from a parent tile to sub-tiles.
225
+ * @param z, x, and y are the coordinates of the parent tile
226
+ * @param cz, cx, and cy are the coordinates of the target tile
227
+ *
228
+ * If no target tile is specified, splitting stops when we reach the maximum
229
+ * zoom or the number of points is low as specified in the props.
230
+ */
231
+ // eslint-disable-next-line max-params, max-statements, complexity
232
+ splitTile(features, z, x, y, cz, cx, cy) {
233
+ const stack = [features, z, x, y];
234
+ // avoid recursion by using a processing queue
235
+ while (stack.length) {
236
+ y = stack.pop();
237
+ x = stack.pop();
238
+ z = stack.pop();
239
+ features = stack.pop();
240
+ const z2 = 1 << z;
241
+ const id = toID(z, x, y);
242
+ let tile = this.tiles[id];
243
+ if (!tile) {
244
+ log.time(2, 'tile creation')();
245
+ tile = this.tiles[id] = createProtoTile(features, z, x, y, this.props);
246
+ this.tileCoords.push({ z, x, y });
247
+ const key = `z${z}`;
248
+ let stat = this.stats.get(key, 'count');
249
+ stat.incrementCount();
250
+ stat = this.stats.get('total');
251
+ stat.incrementCount();
252
+ stat = DynamicVectorTileSource.stats.get(key, 'count');
253
+ stat.incrementCount();
254
+ stat = DynamicVectorTileSource.stats.get('total');
255
+ stat.incrementCount();
256
+ log.log(2, 'tile z%d-%d-%d (features: %d, points: %d, simplified: %d)', z, x, y, tile.numFeatures, tile.numPoints, tile.numSimplified)();
257
+ log.timeEnd(2, 'tile creation')();
258
+ }
259
+ // save reference to original geometry in tile so that we can drill down later if we stop now
260
+ tile.sourceFeatures = features;
261
+ /* eslint-disable no-continue */
262
+ // if it's the first-pass tiling
263
+ if (cz === undefined) {
264
+ // stop tiling if we reached max zoom, or if the tile is too simple
265
+ if (z === this.props.indexMaxZoom || tile.numPoints <= this.props.maxPointsPerTile) {
266
+ continue;
267
+ }
268
+ // if a drilldown to a specific tile
269
+ }
270
+ else if (z === this.props.maxZoom || z === cz) {
271
+ // stop tiling if we reached base zoom or our target tile zoom
272
+ continue;
273
+ }
274
+ else if (cz !== undefined) {
275
+ // stop tiling if it's not an ancestor of the target tile
276
+ const zoomSteps = cz - z;
277
+ // @ts-expect-error TODO fix the types of cx cy
278
+ if (x !== cx >> zoomSteps || y !== cy >> zoomSteps) {
279
+ continue;
280
+ }
281
+ }
282
+ // if we slice further down, no need to keep source geometry
283
+ tile.sourceFeatures = null;
284
+ if (features.length === 0)
285
+ continue;
286
+ log.time(2, 'clipping tile')();
287
+ // values we'll use for clipping
288
+ const k1 = (0.5 * this.props.buffer) / this.props.extent;
289
+ const k2 = 0.5 - k1;
290
+ const k3 = 0.5 + k1;
291
+ const k4 = 1 + k1;
292
+ let tl = null;
293
+ let bl = null;
294
+ let tr = null;
295
+ let br = null;
296
+ let left = clipFeatures(features, z2, x - k1, x + k3, 0, tile.minX, tile.maxX, this.props);
297
+ let right = clipFeatures(features, z2, x + k2, x + k4, 0, tile.minX, tile.maxX, this.props);
298
+ // @ts-expect-error - unclear why this is needed?
299
+ features = null;
300
+ if (left) {
301
+ tl = clipFeatures(left, z2, y - k1, y + k3, 1, tile.minY, tile.maxY, this.props);
302
+ bl = clipFeatures(left, z2, y + k2, y + k4, 1, tile.minY, tile.maxY, this.props);
303
+ left = null;
304
+ }
305
+ if (right) {
306
+ tr = clipFeatures(right, z2, y - k1, y + k3, 1, tile.minY, tile.maxY, this.props);
307
+ br = clipFeatures(right, z2, y + k2, y + k4, 1, tile.minY, tile.maxY, this.props);
308
+ right = null;
309
+ }
310
+ log.timeEnd(2, 'clipping tile')();
311
+ stack.push(tl || [], z + 1, x * 2, y * 2);
312
+ stack.push(bl || [], z + 1, x * 2, y * 2 + 1);
313
+ stack.push(tr || [], z + 1, x * 2 + 1, y * 2);
314
+ stack.push(br || [], z + 1, x * 2 + 1, y * 2 + 1);
315
+ }
316
+ }
317
+ }
318
+ function toID(z, x, y) {
319
+ return ((1 << z) * y + x) * 32 + z;
320
+ }
321
+ /*
322
+
323
+ // eslint-disable-next-line max-statements, complexity
324
+ function convertToGeoJSONTable(
325
+ vtTile: ProtoTile,
326
+ props: {
327
+ coordinates: 'local' | 'wgs84' | 'EPSG:4326';
328
+ tileIndex: {x: number; y: number; z: number};
329
+ extent: number;
330
+ }
331
+ ): GeoJSONTable | null {
332
+ const features: Feature[] = [];
333
+ for (const rawFeature of vtTile.features) {
334
+ if (!rawFeature || !rawFeature.geometry) {
335
+ continue;
336
+ }
337
+
338
+ let type:
339
+ | 'Point'
340
+ | 'MultiPoint'
341
+ | 'LineString'
342
+ | 'MultiLineString'
343
+ | 'Polygon'
344
+ | 'MultiPolygon';
345
+
346
+ let coordinates: any;
347
+
348
+ // raw geometry
349
+ switch (rawFeature.type) {
350
+ case 1:
351
+ if (rawFeature.geometry.length === 1) {
352
+ type = 'Point';
353
+ coordinates = rawFeature.geometry[0];
354
+ } else {
355
+ type = 'MultiPoint';
356
+ coordinates = rawFeature.geometry;
357
+ }
358
+ break;
359
+ case 2:
360
+ if (rawFeature.geometry.length === 1) {
361
+ type = 'LineString';
362
+ coordinates = rawFeature.geometry[0];
363
+ } else {
364
+ type = 'MultiLineString';
365
+ coordinates = rawFeature.geometry;
366
+ }
367
+ break;
368
+ case 3:
369
+ if (rawFeature.geometry.length > 1) {
370
+ type = 'MultiPolygon';
371
+ coordinates = [rawFeature.geometry];
372
+ } else {
373
+ type = 'Polygon';
374
+ coordinates = rawFeature.geometry;
375
+ }
376
+ break;
377
+ default:
378
+ continue;
379
+ }
380
+
381
+ switch (props.coordinates) {
382
+ case 'EPSG:4326':
383
+ case 'wgs84':
384
+ projectToLngLat(coordinates, props.tileIndex, props.extent);
385
+ break;
386
+
387
+ case 'local':
388
+ convertToLocalCoordinates(coordinates, props.extent);
389
+ break;
390
+
391
+ default:
392
+ throw new Error(`Unsupported CRS ${props.coordinates}`);
393
+ }
394
+
395
+ const feature: Feature = {
396
+ type: 'Feature',
397
+ geometry: {
398
+ type,
399
+ coordinates
400
+ },
401
+ properties: rawFeature.tags || {},
402
+ id: rawFeature.id
403
+ };
404
+
405
+ features.push(feature);
406
+ }
407
+
408
+ if (features.length === 0) {
409
+ return null;
410
+ }
411
+
412
+ const table: GeoJSONTable = {
413
+ shape: 'geojson-table',
414
+ type: 'FeatureCollection',
415
+ features
416
+ };
417
+
418
+ return table;
419
+ }
420
+ */
@@ -4,7 +4,7 @@
4
4
  import { parseTileJSON } from "./lib/parse-tilejson.js";
5
5
  // __VERSION__ is injected by babel-plugin-version-inline
6
6
  // @ts-ignore TS2304: Cannot find name '__VERSION__'.
7
- const VERSION = typeof "4.2.0" !== 'undefined' ? "4.2.0" : 'latest';
7
+ const VERSION = typeof "4.3.0-alpha.2" !== 'undefined' ? "4.3.0-alpha.2" : 'latest';
8
8
  /**
9
9
  * Loader for TileJSON metadata
10
10
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@loaders.gl/mvt",
3
3
  "description": "Loader for Mapbox Vector Tiles",
4
- "version": "4.3.0-alpha.1",
4
+ "version": "4.3.0-alpha.3",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "publishConfig": {
@@ -41,11 +41,12 @@
41
41
  "build-worker": "esbuild src/workers/mvt-worker.ts --bundle --outfile=dist/mvt-worker.js --define:__VERSION__=\\\"$npm_package_version\\\""
42
42
  },
43
43
  "dependencies": {
44
- "@loaders.gl/gis": "4.3.0-alpha.1",
45
- "@loaders.gl/images": "4.3.0-alpha.1",
46
- "@loaders.gl/loader-utils": "4.3.0-alpha.1",
47
- "@loaders.gl/schema": "4.3.0-alpha.1",
44
+ "@loaders.gl/gis": "4.3.0-alpha.3",
45
+ "@loaders.gl/images": "4.3.0-alpha.3",
46
+ "@loaders.gl/loader-utils": "4.3.0-alpha.3",
47
+ "@loaders.gl/schema": "4.3.0-alpha.3",
48
48
  "@math.gl/polygon": "^4.0.0",
49
+ "@probe.gl/stats": "^4.0.0",
49
50
  "pbf": "^3.2.1"
50
51
  },
51
52
  "devDependencies": {
@@ -54,5 +55,5 @@
54
55
  "peerDependencies": {
55
56
  "@loaders.gl/core": "^4.0.0"
56
57
  },
57
- "gitHead": "568446ea69eb590f0c42d965459b636216cda74e"
58
+ "gitHead": "3213679d79e6ff2814d48fd3337acfa446c74099"
58
59
  }
package/src/index.ts CHANGED
@@ -2,16 +2,23 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- export type {MVTLoaderOptions} from './mvt-loader';
6
- export {MVTLoader, MVTWorkerLoader} from './mvt-loader';
5
+ // TileJSONLoader
7
6
 
8
- export type {TileJSON} from './lib/parse-tilejson';
9
- export type {TileJSONLoaderOptions} from './tilejson-loader';
10
7
  export {TileJSONLoader} from './tilejson-loader';
8
+ export type {TileJSONLoaderOptions} from './tilejson-loader';
9
+ export type {TileJSON} from './lib/parse-tilejson';
10
+
11
+ // MVTLoader
12
+
13
+ export {MVTLoader, MVTWorkerLoader} from './mvt-loader';
14
+ export type {MVTLoaderOptions} from './mvt-loader';
15
+
16
+ // MVTSource
11
17
 
12
18
  export {MVTSource} from './mvt-source';
19
+ export type {MVTTileSource, MVTTileSourceProps} from './mvt-source';
13
20
 
14
- // GeoJSONTileSource
21
+ // TableTileSource (dynamically tiles a table)
15
22
 
16
- export type {GeoJSONTileSourceOptions} from './geojson-tile-source';
17
- export {GeoJSONTileSource} from './geojson-tile-source';
23
+ export {TableTileSource} from './table-tile-source';
24
+ export type {DynamicVectorTileSource, DynamicVectorTileSourceProps} from './table-tile-source';
@@ -155,9 +155,9 @@ function getDecodedFeature(
155
155
  options: MVTOptions,
156
156
  layerName: string
157
157
  ): Feature {
158
- const decodedFeature = feature.toGeoJSON(
159
- // @ts-expect-error What is going on here?
160
- options.coordinates === 'wgs84' ? options.tileIndex : transformToLocalCoordinates
158
+ const decodedFeature = feature.toGeoJSONFeature(
159
+ options.coordinates || 'local',
160
+ options.tileIndex
161
161
  );
162
162
 
163
163
  // Add layer name to GeoJSON properties
@@ -179,10 +179,7 @@ function getDecodedFeatureBinary(
179
179
  options: MVTOptions,
180
180
  layerName: string
181
181
  ): FlatFeature {
182
- const decodedFeature = feature.toBinaryCoordinates(
183
- // @ts-expect-error
184
- options.coordinates === 'wgs84' ? options.tileIndex : transformToLocalCoordinatesBinary
185
- );
182
+ const decodedFeature = feature.toBinaryFeature(options.coordinates || 'local', options.tileIndex);
186
183
 
187
184
  // Add layer name to GeoJSON properties
188
185
  if (options.layerProperty && decodedFeature.properties) {
@@ -191,29 +188,3 @@ function getDecodedFeatureBinary(
191
188
 
192
189
  return decodedFeature;
193
190
  }
194
-
195
- /**
196
- * @param line
197
- * @param feature
198
- */
199
- function transformToLocalCoordinates(line: number[], feature: {extent: any}): void {
200
- // This function transforms local coordinates in a
201
- // [0 - bufferSize, this.extent + bufferSize] range to a
202
- // [0 - (bufferSize / this.extent), 1 + (bufferSize / this.extent)] range.
203
- // The resulting extent would be 1.
204
- const {extent} = feature;
205
- for (let i = 0; i < line.length; i++) {
206
- const p = line[i];
207
- p[0] /= extent;
208
- p[1] /= extent;
209
- }
210
- }
211
-
212
- function transformToLocalCoordinatesBinary(data: number[], feature: {extent: any}) {
213
- // For the binary code path, the feature data is just
214
- // one big flat array, so we just divide each value
215
- const {extent} = feature;
216
- for (let i = 0, il = data.length; i < il; ++i) {
217
- data[i] /= extent;
218
- }
219
- }
@@ -16,11 +16,6 @@ export type TileJSON = {
16
16
  tileFormat?: string;
17
17
  tilesetType?: string;
18
18
 
19
- /** Generating application. Tippecanoe adds this. */
20
- generator?: string;
21
- /** Generating application options. Tippecanoe adds this. */
22
- generatorOptions?: string;
23
-
24
19
  /** Tile indexing scheme */
25
20
  scheme?: 'xyz' | 'tms';
26
21
  /** Sharded URLs */
@@ -38,6 +33,11 @@ export type TileJSON = {
38
33
  // Combination of tilestats (if present) and tilejson layer information
39
34
  layers?: TileJSONLayer[];
40
35
 
36
+ /** Generating application. Tippecanoe adds this. */
37
+ generator?: string;
38
+ /** Generating application options. Tippecanoe adds this. */
39
+ generatorOptions?: string;
40
+
41
41
  /** Any nested JSON metadata */
42
42
  metaJson?: any | null;
43
43
  };
@@ -419,7 +419,7 @@ function attributeTypeToFieldType(aType: string): {type: string} {
419
419
  const type = aType.toLowerCase();
420
420
  if (!type || !attrTypeMap[type]) {
421
421
  // console.warn(
422
- // `cannot convert attribute type ${type} to loaders.gl data type, use string by default`
422
+ // `cannot convert feature type ${type} to loaders.gl data type, use string by default`
423
423
  // );
424
424
  }
425
425
  return attrTypeMap[type] || {type: 'string'};
@@ -20,16 +20,80 @@ export function signedArea(ring: number[][]) {
20
20
  return sum;
21
21
  }
22
22
 
23
+ /**
24
+ * This function projects local coordinates in a
25
+ * [0 - bufferSize, this.extent + bufferSize] range to a
26
+ * [0 - (bufferSize / this.extent), 1 + (bufferSize / this.extent)] range.
27
+ * The resulting extent would be 1.
28
+ * @param line
29
+ * @param feature
30
+ */
31
+ export function convertToLocalCoordinates(
32
+ coordinates: number[] | number[][] | number[][][] | number[][][][],
33
+ extent: number
34
+ ): void {
35
+ if (Array.isArray(coordinates[0])) {
36
+ for (const subcoords of coordinates) {
37
+ convertToLocalCoordinates(subcoords as number[] | number[][] | number[][][], extent);
38
+ }
39
+ return;
40
+ }
41
+
42
+ // Just a point
43
+ const p = coordinates as number[];
44
+ p[0] /= extent;
45
+ p[1] /= extent;
46
+ }
47
+
48
+ /**
49
+ * For the binary code path, the feature data is just
50
+ * one big flat array, so we just divide each value
51
+ * @param data
52
+ * @param feature
53
+ */
54
+ export function convertToLocalCoordinatesFlat(data: number[], extent: number): void {
55
+ for (let i = 0; i < data.length; ++i) {
56
+ data[i] /= extent;
57
+ }
58
+ }
59
+
23
60
  /**
24
61
  * Projects local tile coordinates to lngLat in place.
25
62
  * @param points
26
63
  * @param tileIndex
27
64
  */
65
+ export function projectToLngLat(
66
+ line: number[] | number[][] | number[][][],
67
+ tileIndex: {x: number; y: number; z: number},
68
+ extent: number
69
+ ): void {
70
+ if (typeof line[0][0] !== 'number') {
71
+ for (const point of line) {
72
+ // @ts-expect-error
73
+ projectToLngLat(point, tileIndex, extent);
74
+ }
75
+ return;
76
+ }
77
+ const size = extent * Math.pow(2, tileIndex.z);
78
+ const x0 = extent * tileIndex.x;
79
+ const y0 = extent * tileIndex.y;
80
+ for (let j = 0; j < line.length; j++) {
81
+ const p = line[j];
82
+ p[0] = ((p[0] + x0) * 360) / size - 180;
83
+ const y2 = 180 - ((p[1] + y0) * 360) / size;
84
+ p[1] = (360 / Math.PI) * Math.atan(Math.exp((y2 * Math.PI) / 180)) - 90;
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Projects local tile coordinates to lngLat in place.
90
+ * @param points
91
+ * @param tileIndex
28
92
  export function projectTileCoordinatesToLngLat(
29
93
  points: number[][],
30
94
  tileIndex: {x: number; y: number; z: number},
31
95
  extent: number
32
- ) {
96
+ ): void {
33
97
  const {x, y, z} = tileIndex;
34
98
  const size = extent * Math.pow(2, z);
35
99
  const x0 = extent * x;
@@ -41,6 +105,7 @@ export function projectTileCoordinatesToLngLat(
41
105
  p[1] = (360 / Math.PI) * Math.atan(Math.exp((y2 * Math.PI) / 180)) - 90;
42
106
  }
43
107
  }
108
+ */
44
109
 
45
110
  /**
46
111
  *