itowns 2.44.3-next.1 → 2.44.3-next.11

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 (58) hide show
  1. package/CODING.md +1 -1
  2. package/dist/455.js +1 -1
  3. package/dist/455.js.map +1 -1
  4. package/dist/debug.js +1 -1
  5. package/dist/debug.js.LICENSE.txt +1 -1
  6. package/dist/debug.js.map +1 -1
  7. package/dist/itowns.js +1 -1
  8. package/dist/itowns.js.map +1 -1
  9. package/dist/itowns_lasworker.js +1 -1
  10. package/dist/itowns_lasworker.js.map +1 -1
  11. package/dist/itowns_widgets.js +1 -1
  12. package/dist/itowns_widgets.js.map +1 -1
  13. package/examples/3dtiles_loader.html +104 -43
  14. package/examples/config.json +2 -10
  15. package/examples/images/itowns_logo.svg +123 -0
  16. package/lib/Controls/GlobeControls.js +41 -22
  17. package/lib/Controls/StateControl.js +4 -1
  18. package/lib/Controls/StreetControls.js +5 -2
  19. package/lib/Converter/Feature2Mesh.js +11 -4
  20. package/lib/Converter/textureConverter.js +3 -3
  21. package/lib/Core/Feature.js +2 -2
  22. package/lib/Core/Geographic/Extent.js +74 -266
  23. package/lib/Core/Prefab/Globe/GlobeLayer.js +1 -1
  24. package/lib/Core/Prefab/Planar/PlanarLayer.js +1 -1
  25. package/lib/Core/Style.js +2 -2
  26. package/lib/Core/Tile/Tile.js +219 -0
  27. package/lib/Core/Tile/TileGrid.js +46 -0
  28. package/lib/Core/TileMesh.js +3 -2
  29. package/lib/Core/View.js +1 -1
  30. package/lib/Layer/C3DTilesLayer.js +15 -14
  31. package/lib/Layer/CopcLayer.js +1 -1
  32. package/lib/Layer/LabelLayer.js +9 -5
  33. package/lib/Layer/OGC3DTilesLayer.js +36 -9
  34. package/lib/Parser/GeoJsonParser.js +1 -1
  35. package/lib/Parser/LASParser.js +1 -1
  36. package/lib/Parser/Potree2BinParser.js +1 -1
  37. package/lib/Parser/VectorTileParser.js +1 -1
  38. package/lib/Parser/XbilParser.js +15 -4
  39. package/lib/Provider/URLBuilder.js +22 -11
  40. package/lib/Renderer/Camera.js +1 -1
  41. package/lib/Renderer/LayeredMaterial.js +1 -1
  42. package/lib/Renderer/PointsMaterial.js +1 -1
  43. package/lib/Source/CopcSource.js +1 -1
  44. package/lib/Source/TMSSource.js +9 -7
  45. package/lib/Source/VectorTilesSource.js +2 -2
  46. package/lib/Source/WFSSource.js +4 -1
  47. package/lib/Source/WMSSource.js +4 -1
  48. package/lib/ThreeExtended/capabilities/WebGL.js +16 -11
  49. package/lib/ThreeExtended/loaders/GLTFLoader.js +10 -6
  50. package/lib/ThreeExtended/loaders/KTX2Loader.js +14 -7
  51. package/lib/Utils/CameraUtils.js +5 -4
  52. package/lib/Utils/gui/C3DTilesStyle.js +2 -3
  53. package/package.json +33 -28
  54. package/examples/3dtiles_25d.html +0 -120
  55. package/examples/3dtiles_basic.html +0 -94
  56. package/examples/3dtiles_batch_table.html +0 -86
  57. package/examples/3dtiles_ion.html +0 -126
  58. package/examples/3dtiles_pointcloud.html +0 -95
@@ -0,0 +1,219 @@
1
+ import * as THREE from 'three';
2
+ import Coordinates from "../Geographic/Coordinates.js";
3
+ import CRS from "../Geographic/Crs.js";
4
+ import Extent from "../Geographic/Extent.js";
5
+ import { getInfoTms, getCountTiles } from "./TileGrid.js";
6
+ const _tmsCoord = new THREE.Vector2();
7
+ const _dimensionTile = new THREE.Vector2();
8
+ const r = {
9
+ row: 0,
10
+ col: 0,
11
+ invDiff: 0
12
+ };
13
+ function _rowColfromParent(/** @type {Tile} */tile, /** @type {number} */zoom) {
14
+ const diffLevel = tile.zoom - zoom;
15
+ const diff = 2 ** diffLevel;
16
+ r.invDiff = 1 / diff;
17
+ r.row = (tile.row - tile.row % diff) * r.invDiff;
18
+ r.col = (tile.col - tile.col % diff) * r.invDiff;
19
+ return r;
20
+ }
21
+ const _extent = new Extent('EPSG:4326', [0, 0, 0, 0]);
22
+ const _extent2 = new Extent('EPSG:4326', [0, 0, 0, 0]);
23
+ const _c = new Coordinates('EPSG:4326', 0, 0);
24
+ class Tile {
25
+ /**
26
+ * Tile is a geographical bounding rectangle defined by zoom, row and column.
27
+ *
28
+ * @param {String} crs projection of limit values.
29
+ * @param {number} [zoom=0] zoom value
30
+ * @param {number} [row=0] row value
31
+ * @param {number} [col=0] column value
32
+ */
33
+ constructor(crs) {
34
+ let zoom = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
35
+ let row = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
36
+ let col = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
37
+ this.isTile = true;
38
+ this.crs = crs;
39
+ this.zoom = zoom;
40
+ this.row = row;
41
+ this.col = col;
42
+ }
43
+
44
+ /**
45
+ * Clone this tile
46
+ * @return {Tile} cloned tile
47
+ */
48
+ clone() {
49
+ return new Tile(this.crs, this.zoom, this.row, this.col);
50
+ }
51
+
52
+ /**
53
+ * Convert tile to the specified extent.
54
+ * @param {string} crs the projection of destination.
55
+ * @param {Extent} target copy the destination to target.
56
+ * @return {Extent}
57
+ */
58
+ toExtent(crs, target) {
59
+ CRS.isValid(crs);
60
+ target = target || new Extent('EPSG:4326', [0, 0, 0, 0]);
61
+ const {
62
+ epsg,
63
+ globalExtent,
64
+ globalDimension
65
+ } = getInfoTms(this.crs);
66
+ const countTiles = getCountTiles(this.crs, this.zoom);
67
+ _dimensionTile.set(1, 1).divide(countTiles).multiply(globalDimension);
68
+ target.west = globalExtent.west + (globalDimension.x - _dimensionTile.x * (countTiles.x - this.col));
69
+ target.east = target.west + _dimensionTile.x;
70
+ target.south = globalExtent.south + _dimensionTile.y * (countTiles.y - this.row - 1);
71
+ target.north = target.south + _dimensionTile.y;
72
+ target.crs = epsg;
73
+ target.zoom = this.zoom;
74
+ return crs == epsg ? target : target.as(crs, target);
75
+ }
76
+
77
+ /**
78
+ * Return true if `tile` is inside this tile.
79
+ *
80
+ * @param {Tile} tile the tile to check
81
+ *
82
+ * @return {boolean}
83
+ */
84
+ isInside(tile) {
85
+ if (this.zoom == tile.zoom) {
86
+ return this.row == tile.row && this.col == tile.col;
87
+ } else if (this.zoom < tile.zoom) {
88
+ return false;
89
+ } else {
90
+ _rowColfromParent(this, tile.zoom);
91
+ return r.row == tile.row && r.col == tile.col;
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Return the translation and scale to transform this tile to input tile.
97
+ *
98
+ * @param {Tile} tile input tile
99
+ * @param {THREE.Vector4} target copy the result to target.
100
+ * @return {THREE.Vector4} {x: translation on west-east, y: translation on south-north, z: scale on west-east, w: scale on south-north}
101
+ */
102
+ offsetToParent(tile) {
103
+ let target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new THREE.Vector4();
104
+ if (this.crs != tile.crs) {
105
+ throw new Error('unsupported mix');
106
+ }
107
+ _rowColfromParent(this, tile.zoom);
108
+ return target.set(this.col * r.invDiff - r.col, this.row * r.invDiff - r.row, r.invDiff, r.invDiff);
109
+ }
110
+
111
+ /**
112
+ * Return parent tile with input level
113
+ *
114
+ * @param {number} levelParent level of parent.
115
+ * @return {Tile}
116
+ */
117
+ tiledExtentParent(levelParent) {
118
+ if (levelParent && levelParent < this.zoom) {
119
+ _rowColfromParent(this, levelParent);
120
+ return new Tile(this.crs, levelParent, r.row, r.col);
121
+ } else {
122
+ return this;
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Set zoom, row and column values
128
+ *
129
+ * @param {number} [zoom=0] zoom value
130
+ * @param {number} [row=0] row value
131
+ * @param {number} [col=0] column value
132
+ *
133
+ * @return {Tile}
134
+ */
135
+ set() {
136
+ let zoom = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
137
+ let row = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
138
+ let col = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
139
+ this.zoom = zoom;
140
+ this.row = row;
141
+ this.col = col;
142
+ return this;
143
+ }
144
+
145
+ /**
146
+ * Copy to this tile to input tile.
147
+ * @param {Tile} tile
148
+ * @return {Tile} copied extent
149
+ */
150
+ copy(tile) {
151
+ this.crs = tile.crs;
152
+ return this.set(tile.zoom, tile.row, tile.col);
153
+ }
154
+
155
+ /**
156
+ * Return values of tile in string, separated by the separator input.
157
+ * @param {string} separator
158
+ * @return {string}
159
+ */
160
+ toString() {
161
+ let separator = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
162
+ return `${this.zoom}${separator}${this.row}${separator}${this.col}`;
163
+ }
164
+ }
165
+
166
+ /**
167
+ * @param {Extent} e
168
+ * @param {string} tms
169
+ * @returns {Tile[]}
170
+ */
171
+ export function tiledCovering(e, tms) {
172
+ if (e.crs == 'EPSG:4326' && tms == CRS.tms_3857) {
173
+ const WMTS_PM = [];
174
+ const extent = _extent.copy(e).as(CRS.formatToEPSG(tms), _extent2);
175
+ const {
176
+ globalExtent,
177
+ globalDimension,
178
+ sTs
179
+ } = getInfoTms(CRS.formatToEPSG(tms));
180
+ extent.clampByExtent(globalExtent);
181
+ extent.planarDimensions(_dimensionTile);
182
+ const zoom = e.zoom + 1 || Math.floor(Math.log2(Math.round(globalDimension.x / (_dimensionTile.x * sTs.x))));
183
+ const countTiles = getCountTiles(tms, zoom);
184
+ const center = extent.center(_c);
185
+ _tmsCoord.x = center.x - globalExtent.west;
186
+ _tmsCoord.y = globalExtent.north - extent.north;
187
+ _tmsCoord.divide(globalDimension).multiply(countTiles).floor();
188
+
189
+ // ]N; N+1] => N
190
+ const maxRow = Math.ceil((globalExtent.north - extent.south) / globalDimension.x * countTiles.y) - 1;
191
+ for (let r = maxRow; r >= _tmsCoord.y; r--) {
192
+ WMTS_PM.push(new Tile(tms, zoom, r, _tmsCoord.x));
193
+ }
194
+ return WMTS_PM;
195
+ } else {
196
+ const target = new Tile(tms, 0, 0, 0);
197
+ const {
198
+ globalExtent,
199
+ globalDimension,
200
+ sTs,
201
+ isInverted
202
+ } = getInfoTms(e.crs);
203
+ const center = e.center(_c);
204
+ e.planarDimensions(_dimensionTile);
205
+ // Each level has 2^n * 2^n tiles...
206
+ // ... so we count how many tiles of the same width as tile we can fit in the layer
207
+ // ... 2^zoom = tilecount => zoom = log2(tilecount)
208
+ const zoom = Math.floor(Math.log2(Math.round(globalDimension.x / (_dimensionTile.x * sTs.x))));
209
+ const countTiles = getCountTiles(tms, zoom);
210
+
211
+ // Now that we have computed zoom, we can deduce x and y (or row / column)
212
+ _tmsCoord.x = center.x - globalExtent.west;
213
+ _tmsCoord.y = isInverted ? globalExtent.north - center.y : center.y - globalExtent.south;
214
+ _tmsCoord.divide(globalDimension).multiply(countTiles).floor();
215
+ target.set(zoom, _tmsCoord.y, _tmsCoord.x);
216
+ return [target];
217
+ }
218
+ }
219
+ export default Tile;
@@ -0,0 +1,46 @@
1
+ import * as THREE from 'three';
2
+ import CRS from "../Geographic/Crs.js";
3
+ import Extent from "../Geographic/Extent.js";
4
+ const _countTiles = new THREE.Vector2();
5
+ const _dim = new THREE.Vector2();
6
+ export const globalExtentTMS = new Map();
7
+ export const schemeTiles = new Map();
8
+ const extent4326 = new Extent('EPSG:4326', -180, 180, -90, 90);
9
+ globalExtentTMS.set('EPSG:4326', extent4326);
10
+
11
+ // Compute global extent of TMS in EPSG:3857
12
+ // It's square whose a side is between -180° to 180°.
13
+ // So, west extent, it's 180 convert in EPSG:3857
14
+ const extent3857 = extent4326.as('EPSG:3857');
15
+ extent3857.clampSouthNorth(extent3857.west, extent3857.east);
16
+ globalExtentTMS.set('EPSG:3857', extent3857);
17
+ schemeTiles.set('default', new THREE.Vector2(1, 1));
18
+ schemeTiles.set(CRS.tms_3857, schemeTiles.get('default'));
19
+ schemeTiles.set(CRS.tms_4326, new THREE.Vector2(2, 1));
20
+ export function getInfoTms(/** @type {string} */crs) {
21
+ const epsg = CRS.formatToEPSG(crs);
22
+ const globalExtent = globalExtentTMS.get(epsg);
23
+ const globalDimension = globalExtent.planarDimensions(_dim);
24
+ const tms = CRS.formatToTms(crs);
25
+ const sTs = schemeTiles.get(tms) || schemeTiles.get('default');
26
+ // The isInverted parameter is to be set to the correct value, true or false
27
+ // (default being false) if the computation of the coordinates needs to be
28
+ // inverted to match the same scheme as OSM, Google Maps or other system.
29
+ // See link below for more information
30
+ // https://alastaira.wordpress.com/2011/07/06/converting-tms-tile-coordinates-to-googlebingosm-tile-coordinates/
31
+ // in crs includes ':NI' => tms isn't inverted (NOT INVERTED)
32
+ const isInverted = !tms.includes(':NI');
33
+ return {
34
+ epsg,
35
+ globalExtent,
36
+ globalDimension,
37
+ sTs,
38
+ isInverted
39
+ };
40
+ }
41
+ export function getCountTiles(/** @type {string} */crs, /** @type {number} */zoom) {
42
+ const sTs = schemeTiles.get(CRS.formatToTms(crs)) || schemeTiles.get('default');
43
+ const count = 2 ** zoom;
44
+ _countTiles.set(count, count).multiply(sTs);
45
+ return _countTiles;
46
+ }
@@ -1,6 +1,7 @@
1
1
  import * as THREE from 'three';
2
2
  import CRS from "./Geographic/Crs.js";
3
3
  import { geoidLayerIsVisible } from "../Layer/GeoidLayer.js";
4
+ import { tiledCovering } from "./Tile/Tile.js";
4
5
 
5
6
  /**
6
7
  * A TileMesh is a THREE.Mesh with a geometricError and an OBB
@@ -12,7 +13,7 @@ import { geoidLayerIsVisible } from "../Layer/GeoidLayer.js";
12
13
  * @param {?number} level - the tile level (default = 0)
13
14
  */
14
15
  class TileMesh extends THREE.Mesh {
15
- #_tms = new Map();
16
+ #_tms = (() => new Map())();
16
17
  #visible = true;
17
18
  constructor(geometry, material, layer, extent) {
18
19
  let level = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
@@ -29,7 +30,7 @@ class TileMesh extends THREE.Mesh {
29
30
  this.boundingSphere = new THREE.Sphere();
30
31
  this.obb.box3D.getBoundingSphere(this.boundingSphere);
31
32
  for (const tms of layer.tileMatrixSets) {
32
- this.#_tms.set(tms, this.extent.tiledCovering(tms));
33
+ this.#_tms.set(tms, tiledCovering(this.extent, tms));
33
34
  }
34
35
  this.frustumCulled = false;
35
36
  this.matrixAutoUpdate = false;
package/lib/Core/View.js CHANGED
@@ -121,7 +121,7 @@ let screenMeters;
121
121
  */
122
122
  class View extends THREE.EventDispatcher {
123
123
  #layers = [];
124
- #pixelDepthBuffer = new Uint8Array(4);
124
+ #pixelDepthBuffer = (() => new Uint8Array(4))();
125
125
  #fullSizeDepthBuffer;
126
126
  /**
127
127
  * Constructs an Itowns View instance
@@ -102,6 +102,7 @@ class C3DTilesLayer extends GeometryLayer {
102
102
  * @param {View} view The view
103
103
  */
104
104
  constructor(id, config, view) {
105
+ console.warn('C3DTilesLayer is deprecated and will be removed in iTowns 3.0 version. Use OGC3DTilesLayer instead.');
105
106
  super(id, new THREE.Group(), {
106
107
  source: config.source
107
108
  });
@@ -143,7 +144,7 @@ class C3DTilesLayer extends GeometryLayer {
143
144
  }
144
145
 
145
146
  /** @type {Style} */
146
- this._style = config.style || null;
147
+ this.style = config.style || null;
147
148
 
148
149
  /** @type {Map<string, THREE.MeshStandardMaterial>} */
149
150
  this.#fillColorMaterialsBuffer = new Map();
@@ -368,21 +369,15 @@ class C3DTilesLayer extends GeometryLayer {
368
369
  if (c3DTileFeature.object3d != object3d) {
369
370
  continue; // this feature do not belong to object3d
370
371
  }
372
+ this._style.context.setGeometry({
373
+ properties: c3DTileFeature
374
+ });
375
+
371
376
  /** @type {THREE.Color} */
372
- let color = null;
373
- if (typeof this._style.fill.color === 'function') {
374
- color = new THREE.Color(this._style.fill.color(c3DTileFeature));
375
- } else {
376
- color = new THREE.Color(this._style.fill.color);
377
- }
377
+ const color = new THREE.Color(this._style.fill.color);
378
378
 
379
379
  /** @type {number} */
380
- let opacity = null;
381
- if (typeof this._style.fill.opacity === 'function') {
382
- opacity = this._style.fill.opacity(c3DTileFeature);
383
- } else {
384
- opacity = this._style.fill.opacity;
385
- }
380
+ const opacity = this._style.fill.opacity;
386
381
  const materialId = color.getHexString() + opacity;
387
382
  let material = null;
388
383
  if (this.#fillColorMaterialsBuffer.has(materialId)) {
@@ -445,7 +440,13 @@ class C3DTilesLayer extends GeometryLayer {
445
440
  return this.#fillColorMaterialsBuffer.size;
446
441
  }
447
442
  set style(value) {
448
- this._style = value;
443
+ if (value instanceof Style) {
444
+ this._style = value;
445
+ } else if (!value) {
446
+ this._style = null;
447
+ } else {
448
+ this._style = new Style(value);
449
+ }
449
450
  this.updateStyle();
450
451
  }
451
452
  get style() {
@@ -32,7 +32,7 @@ class CopcLayer extends PointCloudLayer {
32
32
  super(id, config);
33
33
  this.isCopcLayer = true;
34
34
  const resolve = () => this;
35
- this.whenReady = this.source.whenReady.then(( /** @type {CopcSource} */source) => {
35
+ this.whenReady = this.source.whenReady.then((/** @type {CopcSource} */source) => {
36
36
  const {
37
37
  cube,
38
38
  rootHierarchyPage
@@ -139,7 +139,7 @@ class LabelsNode extends THREE.Group {
139
139
  * internally for optimisation.
140
140
  */
141
141
  class LabelLayer extends GeometryLayer {
142
- #filterGrid = new ScreenGrid();
142
+ #filterGrid = (() => new ScreenGrid())();
143
143
  /**
144
144
  * @extends Layer
145
145
  *
@@ -216,17 +216,21 @@ class LabelLayer extends GeometryLayer {
216
216
  *
217
217
  * @param {FeatureCollection} data - The FeatureCollection to read the
218
218
  * labels from.
219
- * @param {Extent} extent
219
+ * @param {Extent|Tile} extentOrTile
220
220
  *
221
221
  * @return {Label[]} An array containing all the created labels.
222
222
  */
223
- convert(data, extent) {
223
+ convert(data, extentOrTile) {
224
224
  const labels = [];
225
225
 
226
226
  // Converting the extent now is faster for further operation
227
- extent.as(data.crs, _extent);
227
+ if (extentOrTile.isExtent) {
228
+ extentOrTile.as(data.crs, _extent);
229
+ } else {
230
+ extentOrTile.toExtent(data.crs, _extent);
231
+ }
228
232
  coord.crs = data.crs;
229
- context.setZoom(extent.zoom);
233
+ context.setZoom(extentOrTile.zoom);
230
234
  data.features.forEach(f => {
231
235
  // TODO: add support for LINE and POLYGON
232
236
  if (f.type !== FEATURE_TYPES.POINT) {
@@ -52,7 +52,19 @@ export const OGC3DTILES_LAYER_EVENTS = {
52
52
  * @property {Object} tile - the tile metadata from the tileset
53
53
  * @property {boolean} visible - the tile visible state
54
54
  */
55
- TILE_VISIBILITY_CHANGE: 'tile-visibility-change'
55
+ TILE_VISIBILITY_CHANGE: 'tile-visibility-change',
56
+ /**
57
+ * Fired when a new batch of tiles start loading (can be fired multiple times, e.g. when the camera moves and new tiles
58
+ * start loading)
59
+ * @event OGC3DTilesLayer#tiles-load-start
60
+ */
61
+ TILES_LOAD_START: 'tiles-load-start',
62
+ /**
63
+ * Fired when all visible tiles are loaded (can be fired multiple times, e.g. when the camera moves and new tiles
64
+ * are loaded)
65
+ * @event OGC3DTilesLayer#tiles-load-end
66
+ */
67
+ TILES_LOAD_END: 'tiles-load-end'
56
68
  };
57
69
 
58
70
  /**
@@ -95,6 +107,13 @@ export function enableKtx2Loader(path, renderer) {
95
107
  class OGC3DTilesLayer extends GeometryLayer {
96
108
  /**
97
109
  * Layer for [3D Tiles](https://www.ogc.org/standard/3dtiles/) datasets.
110
+ *
111
+ * Advanced configuration note: 3D Tiles rendering is delegated to 3DTilesRendererJS that exposes several
112
+ * configuration options accessible through the tilesRenderer property of this class. see the
113
+ * [3DTilesRendererJS doc](https://github.com/NASA-AMMOS/3DTilesRendererJS/blob/master/README.md). Also note that
114
+ * the cache is shared amongst 3D tiles layers and can be configured through tilesRenderer.lruCache (see the
115
+ * [following documentation](https://github.com/NASA-AMMOS/3DTilesRendererJS/blob/master/README.md#lrucache-1).
116
+ *
98
117
  * @extends Layer
99
118
  *
100
119
  * @param {String} id - unique layer id.
@@ -109,8 +128,8 @@ class OGC3DTilesLayer extends GeometryLayer {
109
128
  * @param {String} [config.pntsSizeMode= PNTS_SIZE_MODE.VALUE] {@link PointsMaterial} Point cloud size mode (passed to {@link PointsMaterial}).
110
129
  * Only 'VALUE' or 'ATTENUATED' are possible. VALUE use constant size, ATTENUATED compute size depending on distance
111
130
  * from point to camera.
112
- * @param {Number} [config.pntsMinAttenuatedSize=1] Minimum scale used by 'ATTENUATED' size mode.
113
- * @param {Number} [config.pntsMaxAttenuatedSize=7] Maximum scale used by 'ATTENUATED' size mode.
131
+ * @param {Number} [config.pntsMinAttenuatedSize=3] Minimum scale used by 'ATTENUATED' size mode.
132
+ * @param {Number} [config.pntsMaxAttenuatedSize=10] Maximum scale used by 'ATTENUATED' size mode.
114
133
  */
115
134
  constructor(id, config) {
116
135
  super(id, new THREE.Group(), {
@@ -122,11 +141,13 @@ class OGC3DTilesLayer extends GeometryLayer {
122
141
  if (config.source.isOGC3DTilesIonSource) {
123
142
  this.tilesRenderer.registerPlugin(new CesiumIonAuthPlugin({
124
143
  apiToken: config.source.accessToken,
125
- assetId: config.source.assetId
144
+ assetId: config.source.assetId,
145
+ autoRefreshToken: true
126
146
  }));
127
147
  } else if (config.source.isOGC3DTilesGoogleSource) {
128
148
  this.tilesRenderer.registerPlugin(new GoogleCloudAuthPlugin({
129
- apiToken: config.source.key
149
+ apiToken: config.source.key,
150
+ autoRefreshToken: true
130
151
  }));
131
152
  }
132
153
  this.tilesRenderer.registerPlugin(new ImplicitTilingPlugin());
@@ -167,8 +188,8 @@ class OGC3DTilesLayer extends GeometryLayer {
167
188
  this.pntsShape = config.pntsShape ?? PNTS_SHAPE.CIRCLE;
168
189
  this.classification = config.classification ?? ClassificationScheme.DEFAULT;
169
190
  this.pntsSizeMode = config.pntsSizeMode ?? PNTS_SIZE_MODE.VALUE;
170
- this.pntsMinAttenuatedSize = config.pntsMinAttenuatedSize || 1;
171
- this.pntsMaxAttenuatedSize = config.pntsMaxAttenuatedSize || 7;
191
+ this.pntsMinAttenuatedSize = config.pntsMinAttenuatedSize || 3;
192
+ this.pntsMaxAttenuatedSize = config.pntsMaxAttenuatedSize || 10;
172
193
  }
173
194
 
174
195
  /**
@@ -274,7 +295,7 @@ class OGC3DTilesLayer extends GeometryLayer {
274
295
 
275
296
  // Setup classification bufferAttribute
276
297
  if (model.isPoints) {
277
- const classificationData = batchTable?.getData('Classification');
298
+ const classificationData = batchTable?.getPropertyArray('Classification');
278
299
  if (classificationData) {
279
300
  geometry.setAttribute('classification', new THREE.BufferAttribute(classificationData, 1));
280
301
  }
@@ -348,7 +369,13 @@ class OGC3DTilesLayer extends GeometryLayer {
348
369
  _raycaster.near = camera.near;
349
370
  _raycaster.far = camera.far;
350
371
  _raycaster.firstHitOnly = true;
351
- _raycaster.intersectObject(this.tilesRenderer.group, true, target);
372
+ const picked = _raycaster.intersectObject(this.tilesRenderer.group, true);
373
+ // Store the layer of the picked object to conform to the interface of what's returned by Picking.js (used for
374
+ // other GeometryLayers
375
+ picked.forEach(p => {
376
+ p.layer = this;
377
+ });
378
+ target.push(...picked);
352
379
  return target;
353
380
  }
354
381
 
@@ -195,7 +195,7 @@ export default {
195
195
  _in.crs = _in.crs || readCRS(json);
196
196
  if (out.filteringExtent) {
197
197
  if (typeof out.filteringExtent == 'boolean') {
198
- out.filterExtent = options.extent.as(_in.crs);
198
+ out.filterExtent = options.extent.isExtent ? options.extent.as(_in.crs) : options.extent.toExtent(_in.crs);
199
199
  } else if (out.filteringExtent.isExtent) {
200
200
  out.filterExtent = out.filteringExtent;
201
201
  }
@@ -3,7 +3,7 @@ import { spawn, Thread, Transfer } from 'threads';
3
3
  let _lazPerf;
4
4
  let _thread;
5
5
  function workerInstance() {
6
- return new Worker( /* webpackChunkName: "itowns_lasparser" */
6
+ return new Worker(/* webpackChunkName: "itowns_lasparser" */
7
7
  new URL('../Worker/LASLoaderWorker.js', import.meta.url), {
8
8
  type: 'module'
9
9
  });
@@ -2,7 +2,7 @@ import * as THREE from 'three';
2
2
  import { spawn, Thread, Transfer } from 'threads';
3
3
  let _thread;
4
4
  function workerInstance() {
5
- return new Worker( /* webpackChunkName: "itowns_potree2worker" */
5
+ return new Worker(/* webpackChunkName: "itowns_potree2worker" */
6
6
  new URL('../Worker/Potree2Worker.js', import.meta.url), {
7
7
  type: 'module'
8
8
  });
@@ -1,7 +1,7 @@
1
1
  import { Vector2, Vector3 } from 'three';
2
2
  import Protobuf from 'pbf';
3
3
  import { VectorTile } from '@mapbox/vector-tile';
4
- import { globalExtentTMS } from "../Core/Geographic/Extent.js";
4
+ import { globalExtentTMS } from "../Core/Tile/TileGrid.js";
5
5
  import { FeatureCollection, FEATURE_TYPES } from "../Core/Feature.js";
6
6
  import { deprecatedParsingOptionsToNewOne } from "../Core/Deprecated/Undeprecator.js";
7
7
  import Coordinates from "../Core/Geographic/Coordinates.js";
@@ -67,11 +67,22 @@ export function computeMinMaxElevation(texture, pitch, options) {
67
67
  }
68
68
  }
69
69
  }
70
- if (options.zmin > min) {
71
- min = options.zmin;
70
+ // Clamp values to zmin and zmax values configured in ElevationLayer
71
+ if (options.zmin != null) {
72
+ if (min < options.zmin) {
73
+ min = options.zmin;
74
+ }
75
+ if (max < options.zmin) {
76
+ max = options.zmin;
77
+ }
72
78
  }
73
- if (options.zmax < max) {
74
- max = options.zmax;
79
+ if (options.zmax != null) {
80
+ if (min > options.zmax) {
81
+ min = options.zmax;
82
+ }
83
+ if (max > options.zmax) {
84
+ max = options.zmax;
85
+ }
75
86
  }
76
87
  }
77
88
  if (max === -Infinity || min === Infinity) {
@@ -1,6 +1,9 @@
1
- import Extent from "../Core/Geographic/Extent.js";
2
- const extent = new Extent('EPSG:4326', [0, 0, 0, 0]);
3
1
  let subDomainsCount = 0;
2
+
3
+ /**
4
+ * @param {string} url
5
+ * @returns {string}
6
+ */
4
7
  function subDomains(url) {
5
8
  const subDomainsPtrn = /\$\{u:([\w-_.|]+)\}/.exec(url);
6
9
  if (!subDomainsPtrn) {
@@ -51,8 +54,13 @@ export default {
51
54
  * // The resulting url is:
52
55
  * // http://server.geo/tms/15/2142/3412.jpg;
53
56
  *
54
- * @param {Extent} coords - the coordinates
55
- * @param {Source} source
57
+ * @param {Object} coords - tile coordinates
58
+ * @param {number} coords.row - tile row
59
+ * @param {number} coords.col - tile column
60
+ * @param {number} coords.zoom - tile zoom
61
+ * @param {Object} source
62
+ * @param {string} source.url
63
+ * @param {Function} source.tileMatrixCallback
56
64
  *
57
65
  * @return {string} the formed url
58
66
  */
@@ -79,8 +87,12 @@ export default {
79
87
  * // The resulting url is:
80
88
  * // http://server.geo/wms/BBOX=12,35,14,46&FORMAT=jpg&SERVICE=WMS
81
89
  *
82
- * @param {Extent} bbox - the bounding box
83
- * @param {Object} source
90
+ * @param {Object} bbox - the bounding box
91
+ * @param {number} bbox.west
92
+ * @param {number} bbox.south
93
+ * @param {number} bbox.east
94
+ * @param {number} bbox.north
95
+ * @param {Object} source - the source of data
84
96
  * @param {string} source.crs
85
97
  * @param {number} source.bboxDigits
86
98
  * @param {string} source.url
@@ -93,11 +105,10 @@ export default {
93
105
  if (source.bboxDigits !== undefined) {
94
106
  precision = source.bboxDigits;
95
107
  }
96
- bbox.as(source.crs, extent);
97
- const w = extent.west.toFixed(precision);
98
- const s = extent.south.toFixed(precision);
99
- const e = extent.east.toFixed(precision);
100
- const n = extent.north.toFixed(precision);
108
+ const w = bbox.west.toFixed(precision);
109
+ const s = bbox.south.toFixed(precision);
110
+ const e = bbox.east.toFixed(precision);
111
+ const n = bbox.north.toFixed(precision);
101
112
  let bboxInUnit = source.axisOrder || 'wsen';
102
113
  bboxInUnit = bboxInUnit.replace('w', `${w},`).replace('s', `${s},`).replace('e', `${e},`).replace('n', `${n},`).slice(0, -1);
103
114
  return subDomains(source.url.replace('%bbox', bboxInUnit));
@@ -77,7 +77,7 @@ function updatePreSse(camera, height, fov) {
77
77
  */
78
78
  class Camera {
79
79
  #_viewMatrixNeedsUpdate = true;
80
- #_viewMatrix = new THREE.Matrix4();
80
+ #_viewMatrix = (() => new THREE.Matrix4())();
81
81
 
82
82
  /**
83
83
  * @param {string} crs The camera's coordinate projection system.
@@ -12,7 +12,7 @@ const defaultTex = new THREE.Texture();
12
12
 
13
13
  // from three.js packDepthToRGBA
14
14
  const UnpackDownscale = 255 / 256; // 0..1 -> fraction (excluding 1)
15
- const bitSh = new THREE.Vector4(UnpackDownscale / (256.0 * 256.0 * 256.0), UnpackDownscale / (256.0 * 256.0), UnpackDownscale / 256.0, UnpackDownscale);
15
+ const bitSh = new THREE.Vector4(UnpackDownscale, UnpackDownscale / 256.0, UnpackDownscale / (256.0 * 256.0), UnpackDownscale / (256.0 * 256.0 * 256.0));
16
16
  export function unpack1K(color, factor) {
17
17
  return factor ? bitSh.dot(color) * factor : bitSh.dot(color);
18
18
  }
@@ -258,7 +258,7 @@ class PointsMaterial extends THREE.ShaderMaterial {
258
258
  /**
259
259
  * @class PointsMaterial
260
260
  * @param {object} [options={}] The options
261
- * @param {number} [options.size=0] size point
261
+ * @param {number} [options.size=1] point size
262
262
  * @param {number} [options.mode=PNTS_MODE.COLOR] display mode.
263
263
  * @param {number} [options.shape=PNTS_SHAPE.CIRCLE] rendered points shape.
264
264
  * @param {THREE.Vector4} [options.overlayColor=new THREE.Vector4(0, 0, 0, 0)] overlay color.
@@ -91,7 +91,7 @@ class CopcSource extends Source {
91
91
  this.parser = LASParser.parseChunk;
92
92
  this.fetcher = Fetcher.arrayBuffer;
93
93
  this.colorDepth = config.colorDepth ?? 16;
94
- const get = ( /** @type {number} */begin, /** @type {number} */end) => this.fetcher(this.url, {
94
+ const get = (/** @type {number} */begin, /** @type {number} */end) => this.fetcher(this.url, {
95
95
  ...this.networkOptions,
96
96
  headers: {
97
97
  ...this.networkOptions.headers,