@deck.gl/geo-layers 8.9.15 → 8.9.17

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 (36) hide show
  1. package/LICENSE +19 -0
  2. package/dist/dist.dev.js +3259 -1138
  3. package/dist.min.js +57 -56
  4. package/package.json +11 -11
  5. package/typed/tile-3d-layer/utils.d.ts +3 -0
  6. package/typed/tile-3d-layer/utils.d.ts.map +1 -0
  7. package/typed/tile-layer/tileset-2d.d.ts.map +1 -1
  8. package/typed/tile-layer/utils.d.ts +1 -1
  9. package/typed/tile-layer/utils.d.ts.map +1 -1
  10. package/typed/geo-cell-layer/GeoCellLayer.js +0 -49
  11. package/typed/great-circle-layer/great-circle-layer.js +0 -29
  12. package/typed/h3-layers/h3-cluster-layer.js +0 -33
  13. package/typed/h3-layers/h3-hexagon-layer.js +0 -251
  14. package/typed/imagery-layer/imagery-layer.d.ts +0 -53
  15. package/typed/imagery-layer/imagery-layer.d.ts.map +0 -1
  16. package/typed/index.js +0 -33
  17. package/typed/mesh-layer/mesh-layer-fragment.glsl.js +0 -55
  18. package/typed/mesh-layer/mesh-layer-vertex.glsl.js +0 -80
  19. package/typed/mesh-layer/mesh-layer.js +0 -110
  20. package/typed/mvt-layer/coordinate-transform.js +0 -41
  21. package/typed/mvt-layer/find-index-binary.js +0 -96
  22. package/typed/mvt-layer/mvt-layer.js +0 -297
  23. package/typed/quadkey-layer/quadkey-layer.js +0 -18
  24. package/typed/quadkey-layer/quadkey-utils.js +0 -26
  25. package/typed/s2-layer/s2-geometry.js +0 -123
  26. package/typed/s2-layer/s2-layer.js +0 -37
  27. package/typed/s2-layer/s2-utils.js +0 -88
  28. package/typed/terrain-layer/terrain-layer.js +0 -226
  29. package/typed/tile-3d-layer/tile-3d-layer.js +0 -294
  30. package/typed/tile-layer/tile-2d-header.js +0 -113
  31. package/typed/tile-layer/tile-2d-traversal.js +0 -181
  32. package/typed/tile-layer/tile-layer.js +0 -192
  33. package/typed/tile-layer/tileset-2d.js +0 -399
  34. package/typed/tile-layer/types.js +0 -1
  35. package/typed/tile-layer/utils.js +0 -197
  36. package/typed/trips-layer/trips-layer.js +0 -92
@@ -1,294 +0,0 @@
1
- import GL from '@luma.gl/constants';
2
- import { Geometry } from '@luma.gl/core';
3
- import { COORDINATE_SYSTEM, CompositeLayer } from '@deck.gl/core';
4
- import { PointCloudLayer } from '@deck.gl/layers';
5
- import { ScenegraphLayer } from '@deck.gl/mesh-layers';
6
- import { default as _MeshLayer } from '../mesh-layer/mesh-layer';
7
- import { log } from '@deck.gl/core';
8
- import { load } from '@loaders.gl/core';
9
- import { Tileset3D, TILE_TYPE } from '@loaders.gl/tiles';
10
- import { Tiles3DLoader } from '@loaders.gl/3d-tiles';
11
- const SINGLE_DATA = [0];
12
- const defaultProps = {
13
- getPointColor: { type: 'accessor', value: [0, 0, 0, 255] },
14
- pointSize: 1.0,
15
- data: null,
16
- loader: Tiles3DLoader,
17
- onTilesetLoad: { type: 'function', value: tileset3d => { }, compare: false },
18
- onTileLoad: { type: 'function', value: tileHeader => { }, compare: false },
19
- onTileUnload: { type: 'function', value: tileHeader => { }, compare: false },
20
- onTileError: { type: 'function', value: (tile, message, url) => { }, compare: false },
21
- _getMeshColor: { type: 'function', value: tileHeader => [255, 255, 255], compare: false }
22
- };
23
- export default class Tile3DLayer extends CompositeLayer {
24
- initializeState() {
25
- if ('onTileLoadFail' in this.props) {
26
- log.removed('onTileLoadFail', 'onTileError')();
27
- }
28
- // prop verification
29
- this.state = {
30
- layerMap: {},
31
- tileset3d: null,
32
- activeViewports: {},
33
- lastUpdatedViewports: null
34
- };
35
- }
36
- get isLoaded() {
37
- const { tileset3d } = this.state;
38
- return tileset3d && tileset3d.isLoaded();
39
- }
40
- shouldUpdateState({ changeFlags }) {
41
- return changeFlags.somethingChanged;
42
- }
43
- updateState({ props, oldProps, changeFlags }) {
44
- if (props.data && props.data !== oldProps.data) {
45
- this._loadTileset(props.data);
46
- }
47
- if (changeFlags.viewportChanged) {
48
- const { activeViewports } = this.state;
49
- const viewportsNumber = Object.keys(activeViewports).length;
50
- if (viewportsNumber) {
51
- this._updateTileset(activeViewports);
52
- this.state.lastUpdatedViewports = activeViewports;
53
- this.state.activeViewports = {};
54
- }
55
- }
56
- if (changeFlags.propsChanged) {
57
- const { layerMap } = this.state;
58
- for (const key in layerMap) {
59
- layerMap[key].needsUpdate = true;
60
- }
61
- }
62
- }
63
- activateViewport(viewport) {
64
- const { activeViewports, lastUpdatedViewports } = this.state;
65
- this.internalState.viewport = viewport;
66
- activeViewports[viewport.id] = viewport;
67
- const lastViewport = lastUpdatedViewports?.[viewport.id];
68
- if (!lastViewport || !viewport.equals(lastViewport)) {
69
- this.setChangeFlags({ viewportChanged: true });
70
- this.setNeedsUpdate();
71
- }
72
- }
73
- getPickingInfo({ info, sourceLayer }) {
74
- const { layerMap } = this.state;
75
- const layerId = sourceLayer && sourceLayer.id;
76
- if (layerId) {
77
- // layerId: this.id-[scenegraph|pointcloud]-tileId
78
- const substr = layerId.substring(this.id.length + 1);
79
- const tileId = substr.substring(substr.indexOf('-') + 1);
80
- info.object = layerMap[tileId] && layerMap[tileId].tile;
81
- }
82
- return info;
83
- }
84
- filterSubLayer({ layer, viewport }) {
85
- const { tile } = layer.props;
86
- const { id: viewportId } = viewport;
87
- return tile.selected && tile.viewportIds.includes(viewportId);
88
- }
89
- _updateAutoHighlight(info) {
90
- if (info.sourceLayer) {
91
- info.sourceLayer.updateAutoHighlight(info);
92
- }
93
- }
94
- async _loadTileset(tilesetUrl) {
95
- const { loadOptions = {} } = this.props;
96
- // TODO: deprecate `loader` in v9.0
97
- let loader = this.props.loader || this.props.loaders;
98
- if (Array.isArray(loader)) {
99
- loader = loader[0];
100
- }
101
- const options = { loadOptions: { ...loadOptions } };
102
- if (loader.preload) {
103
- const preloadOptions = await loader.preload(tilesetUrl, loadOptions);
104
- if (preloadOptions.headers) {
105
- options.loadOptions.fetch = {
106
- ...options.loadOptions.fetch,
107
- headers: preloadOptions.headers
108
- };
109
- }
110
- Object.assign(options, preloadOptions);
111
- }
112
- const tilesetJson = await load(tilesetUrl, loader, options.loadOptions);
113
- const tileset3d = new Tileset3D(tilesetJson, {
114
- onTileLoad: this._onTileLoad.bind(this),
115
- onTileUnload: this._onTileUnload.bind(this),
116
- onTileLoadFail: this.props.onTileError,
117
- ...options
118
- });
119
- this.setState({
120
- tileset3d,
121
- layerMap: {}
122
- });
123
- this._updateTileset(this.state.activeViewports);
124
- this.props.onTilesetLoad(tileset3d);
125
- }
126
- _onTileLoad(tileHeader) {
127
- const { lastUpdatedViewports } = this.state;
128
- this.props.onTileLoad(tileHeader);
129
- this._updateTileset(lastUpdatedViewports);
130
- this.setNeedsUpdate();
131
- }
132
- _onTileUnload(tileHeader) {
133
- // Was cleaned up from tileset cache. We no longer need to track it.
134
- delete this.state.layerMap[tileHeader.id];
135
- this.props.onTileUnload(tileHeader);
136
- }
137
- _updateTileset(viewports) {
138
- const { tileset3d } = this.state;
139
- const { timeline } = this.context;
140
- const viewportsNumber = Object.keys(viewports).length;
141
- if (!timeline || !viewportsNumber || !tileset3d) {
142
- return;
143
- }
144
- tileset3d.selectTiles(Object.values(viewports)).then(frameNumber => {
145
- const tilesetChanged = this.state.frameNumber !== frameNumber;
146
- if (tilesetChanged) {
147
- this.setState({ frameNumber });
148
- }
149
- });
150
- }
151
- _getSubLayer(tileHeader, oldLayer) {
152
- if (!tileHeader.content) {
153
- return null;
154
- }
155
- switch (tileHeader.type) {
156
- case TILE_TYPE.POINTCLOUD:
157
- return this._makePointCloudLayer(tileHeader, oldLayer);
158
- case TILE_TYPE.SCENEGRAPH:
159
- return this._make3DModelLayer(tileHeader, oldLayer);
160
- case TILE_TYPE.MESH:
161
- return this._makeSimpleMeshLayer(tileHeader, oldLayer);
162
- default:
163
- throw new Error(`Tile3DLayer: Failed to render layer of type ${tileHeader.content.type}`);
164
- }
165
- }
166
- _makePointCloudLayer(tileHeader, oldLayer) {
167
- const { attributes, pointCount, constantRGBA, cartographicOrigin, modelMatrix } = tileHeader.content;
168
- const { positions, normals, colors } = attributes;
169
- if (!positions) {
170
- return null;
171
- }
172
- const data = (oldLayer && oldLayer.props.data) || {
173
- header: {
174
- vertexCount: pointCount
175
- },
176
- attributes: {
177
- POSITION: positions,
178
- NORMAL: normals,
179
- COLOR_0: colors
180
- }
181
- };
182
- const { pointSize, getPointColor } = this.props;
183
- const SubLayerClass = this.getSubLayerClass('pointcloud', PointCloudLayer);
184
- return new SubLayerClass({
185
- pointSize
186
- }, this.getSubLayerProps({
187
- id: 'pointcloud'
188
- }), {
189
- id: `${this.id}-pointcloud-${tileHeader.id}`,
190
- tile: tileHeader,
191
- data,
192
- coordinateSystem: COORDINATE_SYSTEM.METER_OFFSETS,
193
- coordinateOrigin: cartographicOrigin,
194
- modelMatrix,
195
- getColor: constantRGBA || getPointColor,
196
- _offset: 0
197
- });
198
- }
199
- _make3DModelLayer(tileHeader) {
200
- const { gltf, instances, cartographicOrigin, modelMatrix } = tileHeader.content;
201
- const SubLayerClass = this.getSubLayerClass('scenegraph', ScenegraphLayer);
202
- return new SubLayerClass({
203
- _lighting: 'pbr'
204
- }, this.getSubLayerProps({
205
- id: 'scenegraph'
206
- }), {
207
- id: `${this.id}-scenegraph-${tileHeader.id}`,
208
- tile: tileHeader,
209
- data: instances || SINGLE_DATA,
210
- scenegraph: gltf,
211
- coordinateSystem: COORDINATE_SYSTEM.METER_OFFSETS,
212
- coordinateOrigin: cartographicOrigin,
213
- modelMatrix,
214
- getTransformMatrix: instance => instance.modelMatrix,
215
- getPosition: [0, 0, 0],
216
- _offset: 0
217
- });
218
- }
219
- _makeSimpleMeshLayer(tileHeader, oldLayer) {
220
- const content = tileHeader.content;
221
- const { attributes, indices, modelMatrix, cartographicOrigin, coordinateSystem = COORDINATE_SYSTEM.METER_OFFSETS, material, featureIds } = content;
222
- const { _getMeshColor } = this.props;
223
- const geometry = (oldLayer && oldLayer.props.mesh) ||
224
- new Geometry({
225
- drawMode: GL.TRIANGLES,
226
- attributes: getMeshGeometry(attributes),
227
- indices
228
- });
229
- const SubLayerClass = this.getSubLayerClass('mesh', _MeshLayer);
230
- return new SubLayerClass(this.getSubLayerProps({
231
- id: 'mesh'
232
- }), {
233
- id: `${this.id}-mesh-${tileHeader.id}`,
234
- tile: tileHeader,
235
- mesh: geometry,
236
- data: SINGLE_DATA,
237
- getColor: _getMeshColor(tileHeader),
238
- pbrMaterial: material,
239
- modelMatrix,
240
- coordinateOrigin: cartographicOrigin,
241
- coordinateSystem,
242
- featureIds,
243
- _offset: 0
244
- });
245
- }
246
- renderLayers() {
247
- const { tileset3d, layerMap } = this.state;
248
- if (!tileset3d) {
249
- return null;
250
- }
251
- return tileset3d.tiles
252
- .map(tile => {
253
- const layerCache = (layerMap[tile.id] = layerMap[tile.id] || { tile });
254
- let { layer } = layerCache;
255
- if (tile.selected) {
256
- // render selected tiles
257
- if (!layer) {
258
- // create layer
259
- layer = this._getSubLayer(tile);
260
- }
261
- else if (layerCache.needsUpdate) {
262
- // props have changed, rerender layer
263
- layer = this._getSubLayer(tile, layer);
264
- layerCache.needsUpdate = false;
265
- }
266
- }
267
- layerCache.layer = layer;
268
- return layer;
269
- })
270
- .filter(Boolean);
271
- }
272
- }
273
- function getMeshGeometry(contentAttributes) {
274
- const attributes = {};
275
- attributes.positions = {
276
- ...contentAttributes.positions,
277
- value: new Float32Array(contentAttributes.positions.value)
278
- };
279
- if (contentAttributes.normals) {
280
- attributes.normals = contentAttributes.normals;
281
- }
282
- if (contentAttributes.texCoords) {
283
- attributes.texCoords = contentAttributes.texCoords;
284
- }
285
- if (contentAttributes.colors) {
286
- attributes.colors = contentAttributes.colors;
287
- }
288
- if (contentAttributes.uvRegions) {
289
- attributes.uvRegions = contentAttributes.uvRegions;
290
- }
291
- return attributes;
292
- }
293
- Tile3DLayer.layerName = 'Tile3DLayer';
294
- Tile3DLayer.defaultProps = defaultProps;
@@ -1,113 +0,0 @@
1
- /* eslint-env browser */
2
- import { log } from '@deck.gl/core';
3
- export default class Tile2DHeader {
4
- constructor(index) {
5
- this.index = index;
6
- this.isVisible = false;
7
- this.isSelected = false;
8
- this.parent = null;
9
- this.children = [];
10
- this.content = null;
11
- this._loader = undefined;
12
- this._abortController = null;
13
- this._loaderId = 0;
14
- this._isLoaded = false;
15
- this._isCancelled = false;
16
- this._needsReload = false;
17
- }
18
- get data() {
19
- return this.isLoading && this._loader ? this._loader.then(() => this.data) : this.content;
20
- }
21
- get isLoaded() {
22
- return this._isLoaded && !this._needsReload;
23
- }
24
- get isLoading() {
25
- return Boolean(this._loader) && !this._isCancelled;
26
- }
27
- get needsReload() {
28
- return this._needsReload || this._isCancelled;
29
- }
30
- get byteLength() {
31
- const result = this.content ? this.content.byteLength : 0;
32
- if (!Number.isFinite(result)) {
33
- log.error('byteLength not defined in tile data')();
34
- }
35
- return result;
36
- }
37
- /* eslint-disable max-statements */
38
- async _loadData({ getData, requestScheduler, onLoad, onError }) {
39
- const { index, id, bbox, userData, zoom } = this;
40
- const loaderId = this._loaderId;
41
- this._abortController = new AbortController();
42
- const { signal } = this._abortController;
43
- // @ts-expect-error (2345) Argument of type '(tile: any) => 1 | -1' is not assignable ...
44
- const requestToken = await requestScheduler.scheduleRequest(this, tile => {
45
- return tile.isSelected ? 1 : -1;
46
- });
47
- if (!requestToken) {
48
- this._isCancelled = true;
49
- return;
50
- }
51
- // A tile can be cancelled while being scheduled
52
- if (this._isCancelled) {
53
- requestToken.done();
54
- return;
55
- }
56
- let tileData = null;
57
- let error;
58
- try {
59
- tileData = await getData({ index, id, bbox, userData, zoom, signal });
60
- }
61
- catch (err) {
62
- error = err || true;
63
- }
64
- finally {
65
- requestToken.done();
66
- }
67
- // If loadData has been called with a newer version, discard the result from this operation
68
- if (loaderId !== this._loaderId) {
69
- return;
70
- }
71
- // Clear the `isLoading` flag
72
- this._loader = undefined;
73
- // Rewrite tile content with the result of getTileData if successful, or `null` in case of
74
- // error or cancellation
75
- this.content = tileData;
76
- // If cancelled, do not invoke the callbacks
77
- // Consider it loaded if we tried to cancel but `getTileData` still returned data
78
- if (this._isCancelled && !tileData) {
79
- this._isLoaded = false;
80
- return;
81
- }
82
- this._isLoaded = true;
83
- this._isCancelled = false;
84
- if (error) {
85
- onError(error, this);
86
- }
87
- else {
88
- onLoad(this);
89
- }
90
- }
91
- loadData(opts) {
92
- this._isLoaded = false;
93
- this._isCancelled = false;
94
- this._needsReload = false;
95
- this._loaderId++;
96
- this._loader = this._loadData(opts);
97
- return this._loader;
98
- }
99
- setNeedsReload() {
100
- if (this.isLoading) {
101
- this.abort();
102
- this._loader = undefined;
103
- }
104
- this._needsReload = true;
105
- }
106
- abort() {
107
- if (this.isLoaded) {
108
- return;
109
- }
110
- this._isCancelled = true;
111
- this._abortController?.abort();
112
- }
113
- }
@@ -1,181 +0,0 @@
1
- /* eslint-disable complexity */
2
- import { WebMercatorViewport, _GlobeViewport } from '@deck.gl/core';
3
- import { CullingVolume, Plane, AxisAlignedBoundingBox, makeOrientedBoundingBoxFromPoints } from '@math.gl/culling';
4
- import { lngLatToWorld } from '@math.gl/web-mercator';
5
- import { osmTile2lngLat } from './utils';
6
- const TILE_SIZE = 512;
7
- // number of world copies to check
8
- const MAX_MAPS = 3;
9
- // for calculating bounding volume of a tile in a non-web-mercator viewport
10
- const REF_POINTS_5 = [
11
- [0.5, 0.5],
12
- [0, 0],
13
- [0, 1],
14
- [1, 0],
15
- [1, 1]
16
- ]; // 4 corners and center
17
- const REF_POINTS_9 = REF_POINTS_5.concat([
18
- [0, 0.5],
19
- [0.5, 0],
20
- [1, 0.5],
21
- [0.5, 1]
22
- ]); // 4 corners, center and 4 mid points
23
- const REF_POINTS_11 = REF_POINTS_9.concat([
24
- [0.25, 0.5],
25
- [0.75, 0.5]
26
- ]); // 2 additional points on equator for top tile
27
- class OSMNode {
28
- constructor(x, y, z) {
29
- this.x = x;
30
- this.y = y;
31
- this.z = z;
32
- }
33
- get children() {
34
- if (!this._children) {
35
- const x = this.x * 2;
36
- const y = this.y * 2;
37
- const z = this.z + 1;
38
- this._children = [
39
- new OSMNode(x, y, z),
40
- new OSMNode(x, y + 1, z),
41
- new OSMNode(x + 1, y, z),
42
- new OSMNode(x + 1, y + 1, z)
43
- ];
44
- }
45
- return this._children;
46
- }
47
- update(params) {
48
- const { viewport, cullingVolume, elevationBounds, minZ, maxZ, bounds, offset, project } = params;
49
- const boundingVolume = this.getBoundingVolume(elevationBounds, offset, project);
50
- // First, check if this tile is visible
51
- if (bounds && !this.insideBounds(bounds)) {
52
- return false;
53
- }
54
- const isInside = cullingVolume.computeVisibility(boundingVolume);
55
- if (isInside < 0) {
56
- return false;
57
- }
58
- // Avoid loading overlapping tiles - if a descendant is requested, do not request the ancester
59
- if (!this.childVisible) {
60
- let { z } = this;
61
- if (z < maxZ && z >= minZ) {
62
- // Adjust LOD
63
- // If the tile is far enough from the camera, accept a lower zoom level
64
- const distance = (boundingVolume.distanceTo(viewport.cameraPosition) * viewport.scale) / viewport.height;
65
- z += Math.floor(Math.log2(distance));
66
- }
67
- if (z >= maxZ) {
68
- // LOD is acceptable
69
- this.selected = true;
70
- return true;
71
- }
72
- }
73
- // LOD is not enough, recursively test child tiles
74
- this.selected = false;
75
- this.childVisible = true;
76
- for (const child of this.children) {
77
- child.update(params);
78
- }
79
- return true;
80
- }
81
- getSelected(result = []) {
82
- if (this.selected) {
83
- result.push(this);
84
- }
85
- if (this._children) {
86
- for (const node of this._children) {
87
- node.getSelected(result);
88
- }
89
- }
90
- return result;
91
- }
92
- insideBounds([minX, minY, maxX, maxY]) {
93
- const scale = Math.pow(2, this.z);
94
- const extent = TILE_SIZE / scale;
95
- return (this.x * extent < maxX &&
96
- this.y * extent < maxY &&
97
- (this.x + 1) * extent > minX &&
98
- (this.y + 1) * extent > minY);
99
- }
100
- getBoundingVolume(zRange, worldOffset, project) {
101
- if (project) {
102
- // Custom projection
103
- // Estimate bounding box from sample points
104
- // At low zoom level we need more samples to calculate the bounding volume correctly
105
- const refPoints = this.z < 1 ? REF_POINTS_11 : this.z < 2 ? REF_POINTS_9 : REF_POINTS_5;
106
- // Convert from tile-relative coordinates to common space
107
- const refPointPositions = [];
108
- for (const p of refPoints) {
109
- const lngLat = osmTile2lngLat(this.x + p[0], this.y + p[1], this.z);
110
- lngLat[2] = zRange[0];
111
- refPointPositions.push(project(lngLat));
112
- if (zRange[0] !== zRange[1]) {
113
- // Account for the elevation volume
114
- lngLat[2] = zRange[1];
115
- refPointPositions.push(project(lngLat));
116
- }
117
- }
118
- return makeOrientedBoundingBoxFromPoints(refPointPositions);
119
- }
120
- // Use WebMercator projection
121
- const scale = Math.pow(2, this.z);
122
- const extent = TILE_SIZE / scale;
123
- const originX = this.x * extent + worldOffset * TILE_SIZE;
124
- // deck's common space is y-flipped
125
- const originY = TILE_SIZE - (this.y + 1) * extent;
126
- return new AxisAlignedBoundingBox([originX, originY, zRange[0]], [originX + extent, originY + extent, zRange[1]]);
127
- }
128
- }
129
- export function getOSMTileIndices(viewport, maxZ, zRange, bounds) {
130
- const project = viewport instanceof _GlobeViewport && viewport.resolution
131
- ? // eslint-disable-next-line @typescript-eslint/unbound-method
132
- viewport.projectPosition
133
- : null;
134
- // Get the culling volume of the current camera
135
- const planes = Object.values(viewport.getFrustumPlanes()).map(({ normal, distance }) => new Plane(normal.clone().negate(), distance));
136
- const cullingVolume = new CullingVolume(planes);
137
- // Project zRange from meters to common space
138
- const unitsPerMeter = viewport.distanceScales.unitsPerMeter[2];
139
- const elevationMin = (zRange && zRange[0] * unitsPerMeter) || 0;
140
- const elevationMax = (zRange && zRange[1] * unitsPerMeter) || 0;
141
- // Always load at the current zoom level if pitch is small
142
- const minZ = viewport instanceof WebMercatorViewport && viewport.pitch <= 60 ? maxZ : 0;
143
- // Map extent to OSM position
144
- if (bounds) {
145
- const [minLng, minLat, maxLng, maxLat] = bounds;
146
- const topLeft = lngLatToWorld([minLng, maxLat]);
147
- const bottomRight = lngLatToWorld([maxLng, minLat]);
148
- bounds = [topLeft[0], TILE_SIZE - topLeft[1], bottomRight[0], TILE_SIZE - bottomRight[1]];
149
- }
150
- const root = new OSMNode(0, 0, 0);
151
- const traversalParams = {
152
- viewport,
153
- project,
154
- cullingVolume,
155
- elevationBounds: [elevationMin, elevationMax],
156
- minZ,
157
- maxZ,
158
- bounds,
159
- // num. of worlds from the center. For repeated maps
160
- offset: 0
161
- };
162
- root.update(traversalParams);
163
- if (viewport instanceof WebMercatorViewport &&
164
- viewport.subViewports &&
165
- viewport.subViewports.length > 1) {
166
- // Check worlds in repeated maps
167
- traversalParams.offset = -1;
168
- while (root.update(traversalParams)) {
169
- if (--traversalParams.offset < -MAX_MAPS) {
170
- break;
171
- }
172
- }
173
- traversalParams.offset = 1;
174
- while (root.update(traversalParams)) {
175
- if (++traversalParams.offset > MAX_MAPS) {
176
- break;
177
- }
178
- }
179
- }
180
- return root.getSelected();
181
- }