itowns 2.44.3-next.1 → 2.44.3-next.10
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.
- package/CODING.md +1 -1
- package/dist/455.js +1 -1
- package/dist/455.js.map +1 -1
- package/dist/debug.js +1 -1
- package/dist/debug.js.LICENSE.txt +1 -1
- package/dist/debug.js.map +1 -1
- package/dist/itowns.js +1 -1
- package/dist/itowns.js.map +1 -1
- package/dist/itowns_lasworker.js +1 -1
- package/dist/itowns_lasworker.js.map +1 -1
- package/dist/itowns_widgets.js +1 -1
- package/dist/itowns_widgets.js.map +1 -1
- package/examples/3dtiles_loader.html +104 -43
- package/examples/config.json +2 -10
- package/lib/Controls/GlobeControls.js +41 -22
- package/lib/Controls/StateControl.js +4 -1
- package/lib/Controls/StreetControls.js +5 -2
- package/lib/Converter/Feature2Mesh.js +11 -4
- package/lib/Converter/textureConverter.js +3 -3
- package/lib/Core/Feature.js +2 -2
- package/lib/Core/Geographic/Extent.js +74 -266
- package/lib/Core/Prefab/Globe/GlobeLayer.js +1 -1
- package/lib/Core/Prefab/Planar/PlanarLayer.js +1 -1
- package/lib/Core/Style.js +2 -2
- package/lib/Core/Tile/Tile.js +219 -0
- package/lib/Core/Tile/TileGrid.js +46 -0
- package/lib/Core/TileMesh.js +3 -2
- package/lib/Core/View.js +1 -1
- package/lib/Layer/C3DTilesLayer.js +15 -14
- package/lib/Layer/CopcLayer.js +1 -1
- package/lib/Layer/LabelLayer.js +9 -5
- package/lib/Layer/OGC3DTilesLayer.js +36 -9
- package/lib/Parser/GeoJsonParser.js +1 -1
- package/lib/Parser/LASParser.js +1 -1
- package/lib/Parser/Potree2BinParser.js +1 -1
- package/lib/Parser/VectorTileParser.js +1 -1
- package/lib/Parser/XbilParser.js +15 -4
- package/lib/Provider/URLBuilder.js +22 -11
- package/lib/Renderer/Camera.js +1 -1
- package/lib/Renderer/LayeredMaterial.js +1 -1
- package/lib/Renderer/PointsMaterial.js +1 -1
- package/lib/Source/CopcSource.js +1 -1
- package/lib/Source/TMSSource.js +9 -7
- package/lib/Source/VectorTilesSource.js +2 -2
- package/lib/Source/WFSSource.js +4 -1
- package/lib/Source/WMSSource.js +4 -1
- package/lib/ThreeExtended/capabilities/WebGL.js +16 -11
- package/lib/ThreeExtended/loaders/GLTFLoader.js +10 -6
- package/lib/ThreeExtended/loaders/KTX2Loader.js +14 -7
- package/lib/Utils/CameraUtils.js +5 -4
- package/lib/Utils/gui/C3DTilesStyle.js +2 -3
- package/package.json +33 -28
- package/examples/3dtiles_25d.html +0 -120
- package/examples/3dtiles_basic.html +0 -94
- package/examples/3dtiles_batch_table.html +0 -86
- package/examples/3dtiles_ion.html +0 -126
- 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
|
+
}
|
package/lib/Core/TileMesh.js
CHANGED
|
@@ -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
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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() {
|
package/lib/Layer/CopcLayer.js
CHANGED
|
@@ -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((
|
|
35
|
+
this.whenReady = this.source.whenReady.then((/** @type {CopcSource} */source) => {
|
|
36
36
|
const {
|
|
37
37
|
cube,
|
|
38
38
|
rootHierarchyPage
|
package/lib/Layer/LabelLayer.js
CHANGED
|
@@ -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}
|
|
219
|
+
* @param {Extent|Tile} extentOrTile
|
|
220
220
|
*
|
|
221
221
|
* @return {Label[]} An array containing all the created labels.
|
|
222
222
|
*/
|
|
223
|
-
convert(data,
|
|
223
|
+
convert(data, extentOrTile) {
|
|
224
224
|
const labels = [];
|
|
225
225
|
|
|
226
226
|
// Converting the extent now is faster for further operation
|
|
227
|
-
|
|
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(
|
|
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=
|
|
113
|
-
* @param {Number} [config.pntsMaxAttenuatedSize=
|
|
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 ||
|
|
171
|
-
this.pntsMaxAttenuatedSize = config.pntsMaxAttenuatedSize ||
|
|
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?.
|
|
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
|
|
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
|
}
|
package/lib/Parser/LASParser.js
CHANGED
|
@@ -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(
|
|
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(
|
|
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/
|
|
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";
|
package/lib/Parser/XbilParser.js
CHANGED
|
@@ -67,11 +67,22 @@ export function computeMinMaxElevation(texture, pitch, options) {
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
-
|
|
71
|
-
|
|
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
|
|
74
|
-
|
|
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 {
|
|
55
|
-
* @param {
|
|
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 {
|
|
83
|
-
* @param {
|
|
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.
|
|
97
|
-
const
|
|
98
|
-
const
|
|
99
|
-
const
|
|
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));
|
package/lib/Renderer/Camera.js
CHANGED
|
@@ -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 /
|
|
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=
|
|
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.
|
package/lib/Source/CopcSource.js
CHANGED
|
@@ -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 = (
|
|
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,
|