@loaders.gl/mvt 4.3.0-alpha.1 → 4.3.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 (77) hide show
  1. package/dist/dist.dev.js +568 -175
  2. package/dist/dist.min.js +1 -1
  3. package/dist/index.cjs +226 -163
  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 +1 -1
  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/utils/geometry-utils.d.ts +38 -1
  13. package/dist/lib/utils/geometry-utils.d.ts.map +1 -1
  14. package/dist/lib/utils/geometry-utils.js +65 -6
  15. package/dist/lib/vector-tile/vector-tile-feature.d.ts +28 -9
  16. package/dist/lib/vector-tile/vector-tile-feature.d.ts.map +1 -1
  17. package/dist/lib/vector-tile/vector-tile-feature.js +47 -50
  18. package/dist/lib/{geojsonvt → vector-tiler}/clip.d.ts +3 -3
  19. package/dist/lib/vector-tiler/clip.d.ts.map +1 -0
  20. package/dist/lib/vector-tiler/convert.d.ts +18 -0
  21. package/dist/lib/vector-tiler/convert.d.ts.map +1 -0
  22. package/dist/lib/{geojsonvt → vector-tiler}/convert.js +8 -1
  23. package/dist/lib/vector-tiler/feature.d.ts +3 -0
  24. package/dist/lib/vector-tiler/feature.d.ts.map +1 -0
  25. package/dist/lib/vector-tiler/simplify.d.ts.map +1 -0
  26. package/dist/lib/{geojsonvt → vector-tiler}/tile.d.ts +4 -4
  27. package/dist/lib/vector-tiler/tile.d.ts.map +1 -0
  28. package/dist/lib/vector-tiler/transform.d.ts +7 -0
  29. package/dist/lib/vector-tiler/transform.d.ts.map +1 -0
  30. package/dist/lib/{geojsonvt → vector-tiler}/wrap.d.ts +2 -2
  31. package/dist/lib/vector-tiler/wrap.d.ts.map +1 -0
  32. package/dist/mvt-loader.d.ts +1 -1
  33. package/dist/mvt-loader.js +1 -1
  34. package/dist/mvt-source.d.ts +4 -4
  35. package/dist/mvt-source.d.ts.map +1 -1
  36. package/dist/mvt-source.js +4 -4
  37. package/dist/mvt-worker.js +101 -56
  38. package/dist/table-tile-source.d.ts +118 -0
  39. package/dist/table-tile-source.d.ts.map +1 -0
  40. package/dist/{geojson-tile-source.js → table-tile-source.js} +154 -103
  41. package/dist/tilejson-loader.js +1 -1
  42. package/package.json +7 -6
  43. package/src/index.ts +3 -3
  44. package/src/lib/parse-mvt.ts +4 -33
  45. package/src/lib/parse-tilejson.ts +5 -5
  46. package/src/lib/utils/geometry-utils.ts +66 -1
  47. package/src/lib/vector-tile/vector-tile-feature.ts +65 -56
  48. package/src/lib/{geojsonvt → vector-tiler}/clip.ts +4 -4
  49. package/src/lib/{geojsonvt → vector-tiler}/convert.ts +18 -8
  50. package/src/lib/{geojsonvt → vector-tiler}/feature.ts +3 -3
  51. package/src/lib/{geojsonvt → vector-tiler}/tile.ts +8 -8
  52. package/src/lib/{geojsonvt → vector-tiler}/transform.ts +2 -2
  53. package/src/lib/{geojsonvt → vector-tiler}/wrap.ts +5 -5
  54. package/src/mvt-source.ts +6 -7
  55. package/src/table-tile-source.ts +508 -0
  56. package/dist/geojson-tile-source.d.ts +0 -79
  57. package/dist/geojson-tile-source.d.ts.map +0 -1
  58. package/dist/lib/geojsonvt/clip.d.ts.map +0 -1
  59. package/dist/lib/geojsonvt/convert.d.ts +0 -10
  60. package/dist/lib/geojsonvt/convert.d.ts.map +0 -1
  61. package/dist/lib/geojsonvt/feature.d.ts +0 -3
  62. package/dist/lib/geojsonvt/feature.d.ts.map +0 -1
  63. package/dist/lib/geojsonvt/simplify.d.ts.map +0 -1
  64. package/dist/lib/geojsonvt/tile.d.ts.map +0 -1
  65. package/dist/lib/geojsonvt/transform.d.ts +0 -7
  66. package/dist/lib/geojsonvt/transform.d.ts.map +0 -1
  67. package/dist/lib/geojsonvt/wrap.d.ts.map +0 -1
  68. package/src/geojson-tile-source.ts +0 -422
  69. /package/dist/lib/{geojsonvt → vector-tiler}/clip.js +0 -0
  70. /package/dist/lib/{geojsonvt → vector-tiler}/feature.js +0 -0
  71. /package/dist/lib/{geojsonvt → vector-tiler}/simplify.d.ts +0 -0
  72. /package/dist/lib/{geojsonvt → vector-tiler}/simplify.js +0 -0
  73. /package/dist/lib/{geojsonvt → vector-tiler}/tile.js +0 -0
  74. /package/dist/lib/{geojsonvt → vector-tiler}/transform.js +0 -0
  75. /package/dist/lib/{geojsonvt → vector-tiler}/wrap.js +0 -0
  76. /package/src/lib/{geojsonvt → vector-tiler}/LICENSE +0 -0
  77. /package/src/lib/{geojsonvt → vector-tiler}/simplify.ts +0 -0
@@ -2,16 +2,37 @@
2
2
  // SPDX-License-Identifier: MIT AND ISC
3
3
  // Copyright (c) vis.gl contributors
4
4
  // Based on https://github.com/mapbox/geojson-vt under compatible ISC license
5
- import { convert } from "./lib/geojsonvt/convert.js"; // GeoJSON conversion and preprocessing
6
- import { clip } from "./lib/geojsonvt/clip.js"; // stripe clipping algorithm
7
- import { wrap } from "./lib/geojsonvt/wrap.js"; // date line processing
8
- import { transformTile } from "./lib/geojsonvt/transform.js"; // coordinate transformation
9
- import { createTile } from "./lib/geojsonvt/tile.js"; // final simplified tile generation
10
- export class GeoJSONTileSource {
11
- static defaultOptions = {
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 { convert } from "./lib/vector-tiler/convert.js"; // GeoJSON conversion and preprocessing
9
+ import { clip } from "./lib/vector-tiler/clip.js"; // stripe clipping algorithm
10
+ import { wrap } from "./lib/vector-tiler/wrap.js"; // date line processing
11
+ import { transformTile } from "./lib/vector-tiler/transform.js"; // coordinate transformation
12
+ import { createTile } from "./lib/vector-tiler/tile.js"; // final simplified tile generation
13
+ import { projectToLngLat } from "./lib/utils/geometry-utils.js";
14
+ import { convertToLocalCoordinates } from "./lib/utils/geometry-utils.js";
15
+ /**
16
+ * Dynamically vector tiles a table (the table needs a geometry column)
17
+ * - Tiles are generated when requested.
18
+ * - Each tile contains a tables of clipped features.
19
+ *
20
+ * @note - Currently only accepts `GeoJSONTable` tables
21
+ * @note - Currently only outputs `GeoJSONTable`
22
+ * @note - (can be initialized with a promise that resolves to GeoJSONTable).
23
+ *
24
+ * @todo - metadata should scan all rows to determine schema
25
+ * @todo - metadata scan all rows to determine tilestats (field values[] etc).
26
+ * @todo - handle binary input tables
27
+ * @todo - generate binary output tables
28
+ * @todo - how does TileSourceLayer specify coordinates / decided which layer to render with
29
+ */
30
+ export class TableTileSource {
31
+ static defaultProps = {
32
+ coordinates: 'wgs84', // coordinates in tile coordinates or lng/lat
12
33
  maxZoom: 14, // max zoom to preserve detail on
13
34
  indexMaxZoom: 5, // max zoom in the tile index
14
- indexMaxPoints: 100000, // max number of points per tile in the tile index
35
+ maxPointsPerTile: 100000, // max number of points per tile in the tile index
15
36
  tolerance: 3, // simplification tolerance (higher means simpler)
16
37
  extent: 4096, // tile extent
17
38
  buffer: 64, // tile buffer on each side
@@ -21,58 +42,49 @@ export class GeoJSONTileSource {
21
42
  generateId: false, // whether to generate feature ids. Cannot be used with promoteId
22
43
  debug: 0 // logging level (0, 1 or 2)
23
44
  };
45
+ /** Global stats for all TableTileSources */
46
+ static stats = new Stats({
47
+ id: 'table-tile-source-all',
48
+ stats: [new Stat('count', 'tiles'), new Stat('count', 'features')]
49
+ });
50
+ /** Stats for this TableTileSource */
51
+ stats = new Stats({
52
+ id: 'table-tile-source',
53
+ stats: [new Stat('tiles', 'count'), new Stat('features', 'count')]
54
+ });
55
+ /** MIME type of the tiles emitted by this tile source */
24
56
  mimeType = 'application/vnd.mapbox-vector-tile';
25
- options;
26
- // tiles and tileCoords are part of the public API
57
+ localCoordinates = true;
58
+ /** The props that this tile source was created with */
59
+ props;
60
+ /* Schema of the data */
61
+ schema = null;
62
+ /** Map of generated tiles, indexed by stringified tile coordinates */
27
63
  tiles = {};
64
+ /** Array of tile coordinates */
28
65
  tileCoords = [];
29
- stats = {};
30
- total = 0;
31
- /** Sync methods can be called: the input data promise has been resolved and initial top-level tiling is done */
66
+ /** Input data has loaded, initial top-level tiling is done, sync methods can now be called */
32
67
  ready;
33
- constructor(data, options) {
34
- this.options = { ...GeoJSONTileSource.defaultOptions, ...options };
68
+ /** Metadata for the tile source (generated TileJSON/tilestats */
69
+ metadata;
70
+ constructor(table, props) {
71
+ this.props = { ...TableTileSource.defaultProps, ...props };
35
72
  this.getTileData = this.getTileData.bind(this);
36
- this.ready = this.initializeTilesAsync(data);
73
+ this.ready = this.initializeTilesAsync(table);
74
+ this.metadata = this.getMetadata();
37
75
  }
38
- async initializeTilesAsync(dataPromise) {
39
- const data = await dataPromise;
40
- this.initializeTilesSync(data);
41
- }
42
- initializeTilesSync(data) {
43
- const options = this.options;
44
- const debug = options.debug;
45
- if (debug)
46
- console.time('preprocess data');
47
- if (this.options.maxZoom < 0 || this.options.maxZoom > 24) {
48
- throw new Error('maxZoom should be in the 0-24 range');
49
- }
50
- if (options.promoteId && this.options.generateId) {
51
- throw new Error('promoteId and generateId cannot be used together.');
52
- }
53
- // projects and adds simplification info
54
- let features = convert(data, options);
55
- if (debug) {
56
- console.timeEnd('preprocess data');
57
- console.log('index: maxZoom: %d, maxPoints: %d', options.indexMaxZoom, options.indexMaxPoints);
58
- console.time('generate tiles');
59
- }
60
- // wraps features (ie extreme west and extreme east)
61
- features = wrap(features, this.options);
62
- // start slicing from the top tile down
63
- if (features.length) {
64
- this.splitTile(features, 0, 0, 0);
65
- }
66
- if (debug) {
67
- if (features.length) {
68
- console.log('features: %d, points: %d', this.tiles[0].numFeatures, this.tiles[0].numPoints);
69
- }
70
- console.timeEnd('generate tiles');
71
- console.log('tiles generated:', this.total, JSON.stringify(this.stats));
72
- }
76
+ async initializeTilesAsync(tablePromise) {
77
+ const table = await tablePromise;
78
+ this.schema = deduceTableSchema(table);
79
+ this.createRootTiles(table);
73
80
  }
74
81
  async getMetadata() {
75
- return {};
82
+ await this.ready;
83
+ return { schema: this.schema, minZoom: 0, maxZoom: this.props.maxZoom };
84
+ }
85
+ async getSchema() {
86
+ await this.ready;
87
+ return this.schema;
76
88
  }
77
89
  /**
78
90
  * Get a tile at the specified index
@@ -82,6 +94,7 @@ export class GeoJSONTileSource {
82
94
  async getVectorTile(tileIndex) {
83
95
  await this.ready;
84
96
  const table = this.getTileSync(tileIndex);
97
+ log.info(2, 'getVectorTile', tileIndex, table)();
85
98
  return table;
86
99
  }
87
100
  async getTile(tileIndex) {
@@ -90,7 +103,8 @@ export class GeoJSONTileSource {
90
103
  }
91
104
  async getTileData(tileParams) {
92
105
  const { x, y, z } = tileParams.index;
93
- return await this.getVectorTile({ x, y, z });
106
+ const tile = await this.getVectorTile({ x, y, z });
107
+ return tile?.features || [];
94
108
  }
95
109
  // Implementation
96
110
  /**
@@ -102,7 +116,41 @@ export class GeoJSONTileSource {
102
116
  if (!rawTile) {
103
117
  return null;
104
118
  }
105
- return convertToGeoJSONTable(rawTile, this.options.extent);
119
+ return convertToGeoJSONTable(rawTile, {
120
+ coordinates: this.props.coordinates,
121
+ tileIndex,
122
+ extent: this.props.extent
123
+ });
124
+ }
125
+ /**
126
+ * Create the initial tiles
127
+ * @note the tiles stores all the features together with additional data
128
+ */
129
+ createRootTiles(table) {
130
+ if (this.props.maxZoom < 0 || this.props.maxZoom > 24) {
131
+ throw new Error('maxZoom should be in the 0-24 range');
132
+ }
133
+ if (this.props.promoteId && this.props.generateId) {
134
+ throw new Error('promoteId and generateId cannot be used together.');
135
+ }
136
+ log.log(1, 'TableTileSource creating root tiles', this.props)();
137
+ // projects and adds simplification info
138
+ log.time(1, 'preprocess table')();
139
+ let features = convert(table, this.props);
140
+ log.timeEnd(1, 'preprocess table')();
141
+ // wraps features (ie extreme west and extreme east)
142
+ log.time(1, 'generate tiles')();
143
+ features = wrap(features, this.props);
144
+ // start slicing from the top tile down
145
+ if (features.length === 0) {
146
+ log.log(1, 'TableTileSource: no features generated')();
147
+ return;
148
+ }
149
+ this.splitTile(features, 0, 0, 0);
150
+ const rootTile = this.tiles[0];
151
+ log.log(1, `root tile features: ${rootTile.numFeatures}, points: ${rootTile.numPoints}`)();
152
+ log.timeEnd(1, 'generate tiles')();
153
+ log.log(1, `TableTileSource: tiles generated: ${this.stats.get('total').count}`, this.stats)();
106
154
  }
107
155
  /**
108
156
  * Return geojsonvt-style "half formed" vector tile
@@ -115,7 +163,7 @@ export class GeoJSONTileSource {
115
163
  // z = +z;
116
164
  // x = +x;
117
165
  // y = +y;
118
- const { extent, debug } = this.options;
166
+ const { extent } = this.props;
119
167
  if (z < 0 || z > 24) {
120
168
  return null;
121
169
  }
@@ -125,8 +173,7 @@ export class GeoJSONTileSource {
125
173
  if (this.tiles[id]) {
126
174
  return transformTile(this.tiles[id], extent);
127
175
  }
128
- if (debug > 1)
129
- console.log('drilling down to z%d-%d-%d', z, x, y);
176
+ log.log(log, 'drilling down to z%d-%d-%d', z, x, y)();
130
177
  let z0 = z;
131
178
  let x0 = x;
132
179
  let y0 = y;
@@ -141,14 +188,10 @@ export class GeoJSONTileSource {
141
188
  return null;
142
189
  }
143
190
  // if we found a parent tile containing the original geometry, we can drill down from it
144
- if (debug > 1) {
145
- console.log('found parent tile z%d-%d-%d', z0, x0, y0);
146
- console.time('drilling down');
147
- }
191
+ log.log(1, 'found parent tile z%d-%d-%d', z0, x0, y0)();
192
+ log.time(1, 'drilling down')();
148
193
  this.splitTile(parent.source, z0, x0, y0, z, x, y);
149
- if (debug > 1) {
150
- console.timeEnd('drilling down');
151
- }
194
+ log.timeEnd(1, 'drilling down')();
152
195
  return this.tiles[id] ? transformTile(this.tiles[id], extent) : null;
153
196
  }
154
197
  /**
@@ -157,13 +200,11 @@ export class GeoJSONTileSource {
157
200
  * @param cz, cx, and cy are the coordinates of the target tile
158
201
  *
159
202
  * If no target tile is specified, splitting stops when we reach the maximum
160
- * zoom or the number of points is low as specified in the options.
203
+ * zoom or the number of points is low as specified in the props.
161
204
  */
162
205
  // eslint-disable-next-line max-params, max-statements, complexity
163
206
  splitTile(features, z, x, y, cz, cx, cy) {
164
207
  const stack = [features, z, x, y];
165
- const options = this.options;
166
- const debug = options.debug;
167
208
  // avoid recursion by using a processing queue
168
209
  while (stack.length) {
169
210
  y = stack.pop();
@@ -174,31 +215,33 @@ export class GeoJSONTileSource {
174
215
  const id = toID(z, x, y);
175
216
  let tile = this.tiles[id];
176
217
  if (!tile) {
177
- if (debug > 1) {
178
- console.time('creation');
179
- }
180
- tile = this.tiles[id] = createTile(features, z, x, y, options);
218
+ log.time(2, 'tile creation')();
219
+ tile = this.tiles[id] = createTile(features, z, x, y, this.props);
181
220
  this.tileCoords.push({ z, x, y });
182
- if (debug) {
183
- if (debug > 1) {
184
- console.log('tile z%d-%d-%d (features: %d, points: %d, simplified: %d)', z, x, y, tile.numFeatures, tile.numPoints, tile.numSimplified);
185
- console.timeEnd('creation');
186
- }
187
- const key = `z${z}`;
188
- this.stats[key] = (this.stats[key] || 0) + 1;
189
- this.total++;
190
- }
221
+ const key = `z${z}`;
222
+ let stat = this.stats.get(key, 'count');
223
+ stat.incrementCount();
224
+ stat = this.stats.get('total');
225
+ stat.incrementCount();
226
+ stat = TableTileSource.stats.get(key, 'count');
227
+ stat.incrementCount();
228
+ stat = TableTileSource.stats.get('total');
229
+ stat.incrementCount();
230
+ log.log(2, 'tile z%d-%d-%d (features: %d, points: %d, simplified: %d)', z, x, y, tile.numFeatures, tile.numPoints, tile.numSimplified)();
231
+ log.timeEnd(2, 'tile creation')();
191
232
  }
192
233
  // save reference to original geometry in tile so that we can drill down later if we stop now
193
234
  tile.source = features;
235
+ /** eslint-disable no-continue */
194
236
  // if it's the first-pass tiling
195
237
  if (cz === undefined) {
196
238
  // stop tiling if we reached max zoom, or if the tile is too simple
197
- if (z === options.indexMaxZoom || tile.numPoints <= options.indexMaxPoints)
239
+ if (z === this.props.indexMaxZoom || tile.numPoints <= this.props.maxPointsPerTile) {
198
240
  continue;
241
+ }
199
242
  // if a drilldown to a specific tile
200
243
  }
201
- else if (z === options.maxZoom || z === cz) {
244
+ else if (z === this.props.maxZoom || z === cz) {
202
245
  // stop tiling if we reached base zoom or our target tile zoom
203
246
  continue;
204
247
  }
@@ -206,17 +249,17 @@ export class GeoJSONTileSource {
206
249
  // stop tiling if it's not an ancestor of the target tile
207
250
  const zoomSteps = cz - z;
208
251
  // @ts-expect-error TODO fix the types of cx cy
209
- if (x !== cx >> zoomSteps || y !== cy >> zoomSteps)
252
+ if (x !== cx >> zoomSteps || y !== cy >> zoomSteps) {
210
253
  continue;
254
+ }
211
255
  }
212
256
  // if we slice further down, no need to keep source geometry
213
257
  tile.source = null;
214
258
  if (features.length === 0)
215
259
  continue;
216
- if (debug > 1)
217
- console.time('clipping');
260
+ log.time(2, 'clipping tile')();
218
261
  // values we'll use for clipping
219
- const k1 = (0.5 * options.buffer) / options.extent;
262
+ const k1 = (0.5 * this.props.buffer) / this.props.extent;
220
263
  const k2 = 0.5 - k1;
221
264
  const k3 = 0.5 + k1;
222
265
  const k4 = 1 + k1;
@@ -224,22 +267,21 @@ export class GeoJSONTileSource {
224
267
  let bl = null;
225
268
  let tr = null;
226
269
  let br = null;
227
- let left = clip(features, z2, x - k1, x + k3, 0, tile.minX, tile.maxX, options);
228
- let right = clip(features, z2, x + k2, x + k4, 0, tile.minX, tile.maxX, options);
270
+ let left = clip(features, z2, x - k1, x + k3, 0, tile.minX, tile.maxX, this.props);
271
+ let right = clip(features, z2, x + k2, x + k4, 0, tile.minX, tile.maxX, this.props);
229
272
  // @ts-expect-error - unclear why this is needed?
230
273
  features = null;
231
274
  if (left) {
232
- tl = clip(left, z2, y - k1, y + k3, 1, tile.minY, tile.maxY, options);
233
- bl = clip(left, z2, y + k2, y + k4, 1, tile.minY, tile.maxY, options);
275
+ tl = clip(left, z2, y - k1, y + k3, 1, tile.minY, tile.maxY, this.props);
276
+ bl = clip(left, z2, y + k2, y + k4, 1, tile.minY, tile.maxY, this.props);
234
277
  left = null;
235
278
  }
236
279
  if (right) {
237
- tr = clip(right, z2, y - k1, y + k3, 1, tile.minY, tile.maxY, options);
238
- br = clip(right, z2, y + k2, y + k4, 1, tile.minY, tile.maxY, options);
280
+ tr = clip(right, z2, y - k1, y + k3, 1, tile.minY, tile.maxY, this.props);
281
+ br = clip(right, z2, y + k2, y + k4, 1, tile.minY, tile.maxY, this.props);
239
282
  right = null;
240
283
  }
241
- if (debug > 1)
242
- console.timeEnd('clipping');
284
+ log.timeEnd(2, 'clipping tile')();
243
285
  stack.push(tl || [], z + 1, x * 2, y * 2);
244
286
  stack.push(bl || [], z + 1, x * 2, y * 2 + 1);
245
287
  stack.push(tr || [], z + 1, x * 2 + 1, y * 2);
@@ -250,7 +292,8 @@ export class GeoJSONTileSource {
250
292
  function toID(z, x, y) {
251
293
  return ((1 << z) * y + x) * 32 + z;
252
294
  }
253
- function convertToGeoJSONTable(vtTile, extent) {
295
+ // eslint-disable-next-line max-statements, complexity
296
+ function convertToGeoJSONTable(vtTile, props) {
254
297
  const features = [];
255
298
  for (const rawFeature of vtTile.features) {
256
299
  if (!rawFeature || !rawFeature.geometry) {
@@ -293,17 +336,31 @@ function convertToGeoJSONTable(vtTile, extent) {
293
336
  default:
294
337
  continue;
295
338
  }
296
- coordinates = toLngLat(coordinates, extent);
339
+ switch (props.coordinates) {
340
+ case 'EPSG:4326':
341
+ case 'wgs84':
342
+ projectToLngLat(coordinates, props.tileIndex, props.extent);
343
+ break;
344
+ case 'local':
345
+ convertToLocalCoordinates(coordinates, props.extent);
346
+ break;
347
+ default:
348
+ throw new Error(`Unsupported CRS ${props.coordinates}`);
349
+ }
297
350
  const feature = {
298
351
  type: 'Feature',
299
352
  geometry: {
300
353
  type,
301
354
  coordinates
302
355
  },
303
- properties: rawFeature.tags || {}
356
+ properties: rawFeature.tags || {},
357
+ id: rawFeature.id
304
358
  };
305
359
  features.push(feature);
306
360
  }
361
+ if (features.length === 0) {
362
+ return null;
363
+ }
307
364
  const table = {
308
365
  shape: 'geojson-table',
309
366
  type: 'FeatureCollection',
@@ -311,9 +368,3 @@ function convertToGeoJSONTable(vtTile, extent) {
311
368
  };
312
369
  return table;
313
370
  }
314
- function toLngLat(coords, extent) {
315
- if (Array.isArray(coords[0])) {
316
- return coords.map((c) => toLngLat(c, extent));
317
- }
318
- return [coords[0] / extent, coords[1] / extent];
319
- }
@@ -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.1" !== 'undefined' ? "4.3.0-alpha.1" : '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.2",
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.2",
45
+ "@loaders.gl/images": "4.3.0-alpha.2",
46
+ "@loaders.gl/loader-utils": "4.3.0-alpha.2",
47
+ "@loaders.gl/schema": "4.3.0-alpha.2",
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": "77a3cb538ab7a1fbf74245f25590210451689f5c"
58
59
  }
package/src/index.ts CHANGED
@@ -11,7 +11,7 @@ export {TileJSONLoader} from './tilejson-loader';
11
11
 
12
12
  export {MVTSource} from './mvt-source';
13
13
 
14
- // GeoJSONTileSource
14
+ // TableTileSource
15
15
 
16
- export type {GeoJSONTileSourceOptions} from './geojson-tile-source';
17
- export {GeoJSONTileSource} from './geojson-tile-source';
16
+ export type {TableTileSourceProps} from './table-tile-source';
17
+ export {TableTileSource} 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
  };
@@ -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, il = data.length; i < il; ++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
  *