itowns 2.43.2-next.1 → 2.43.2-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/README.md +2 -0
- package/dist/debug.js +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_widgets.js +1 -1
- package/dist/itowns_widgets.js.map +1 -1
- package/examples/3dtiles_25d.html +1 -1
- package/examples/3dtiles_basic.html +2 -2
- package/examples/3dtiles_batch_table.html +1 -3
- package/examples/3dtiles_pointcloud.html +9 -15
- package/examples/copc_simple_loader.html +1 -1
- package/examples/entwine_3d_loader.html +1 -1
- package/examples/entwine_simple_loader.html +1 -1
- package/examples/js/plugins/COGParser.js +84 -50
- package/examples/js/plugins/COGSource.js +7 -4
- package/examples/layers/JSONLayers/OPENSM.json +1 -1
- package/examples/potree_25d_map.html +1 -1
- package/examples/potree_3d_map.html +1 -1
- package/examples/source_file_cog.html +22 -5
- package/lib/Controls/FirstPersonControls.js +0 -1
- package/lib/Controls/FlyControls.js +0 -1
- package/lib/Converter/Feature2Mesh.js +2 -4
- package/lib/Converter/textureConverter.js +1 -1
- package/lib/Core/3DTiles/C3DTBatchTable.js +1 -1
- package/lib/Core/3DTiles/C3DTFeature.js +0 -1
- package/lib/Core/Feature.js +1 -2
- package/lib/Core/Geographic/CoordStars.js +0 -1
- package/lib/Core/Label.js +0 -1
- package/lib/Core/MainLoop.js +0 -1
- package/lib/Core/Prefab/Globe/Atmosphere.js +0 -4
- package/lib/Core/Prefab/Globe/GlobeLayer.js +3 -3
- package/lib/Core/Style.js +2 -4
- package/lib/Core/View.js +2 -4
- package/lib/Layer/C3DTilesLayer.js +3 -1
- package/lib/Layer/ElevationLayer.js +2 -3
- package/lib/Layer/GeoidLayer.js +1 -2
- package/lib/Layer/LabelLayer.js +8 -17
- package/lib/Layer/Layer.js +4 -2
- package/lib/Layer/PointCloudLayer.js +4 -7
- package/lib/Layer/ReferencingLayerProperties.js +3 -3
- package/lib/Layer/TiledGeometryLayer.js +2 -3
- package/lib/Parser/GeoJsonParser.js +2 -3
- package/lib/Parser/LASParser.js +2 -3
- package/lib/Parser/deprecated/LegacyGLTFLoader.js +1 -2
- package/lib/Process/FeatureProcessing.js +1 -2
- package/lib/Process/LayeredMaterialNodeProcessing.js +3 -9
- package/lib/Process/ObjectRemovalHelper.js +1 -2
- package/lib/Provider/3dTilesProvider.js +1 -0
- package/lib/Renderer/ColorLayersOrdering.js +1 -2
- package/lib/Renderer/Label2DRenderer.js +1 -4
- package/lib/Renderer/PointsMaterial.js +14 -9
- package/lib/Renderer/RenderMode.js +0 -1
- package/lib/ThreeExtended/loaders/DDSLoader.js +11 -1
- package/lib/ThreeExtended/loaders/DRACOLoader.js +0 -1
- package/lib/ThreeExtended/loaders/GLTFLoader.js +1 -0
- package/lib/Utils/DEMUtils.js +2 -2
- package/lib/Utils/OrientationUtils.js +0 -1
- package/lib/Utils/gui/Searchbar.js +1 -2
- package/package.json +8 -7
|
@@ -22,10 +22,8 @@
|
|
|
22
22
|
* @returns {GeoTIFFLevel} The selected zoom level.
|
|
23
23
|
*/
|
|
24
24
|
function selectLevel(source, requestExtent, requestWidth, requestHeight) {
|
|
25
|
-
// Number of images = original + overviews if any
|
|
26
|
-
const cropped = requestExtent.clone().intersect(source.extent);
|
|
27
25
|
// Dimensions of the requested extent
|
|
28
|
-
const extentDimension =
|
|
26
|
+
const extentDimension = requestExtent.clone().planarDimensions();
|
|
29
27
|
|
|
30
28
|
const targetResolution = Math.min(
|
|
31
29
|
extentDimension.x / requestWidth,
|
|
@@ -87,70 +85,112 @@ function makeWindowFromExtent(source, extent, resolution) {
|
|
|
87
85
|
}
|
|
88
86
|
|
|
89
87
|
/**
|
|
90
|
-
*
|
|
88
|
+
* Reads raster data from the image as RGB.
|
|
89
|
+
* The result is always an interleaved typed array.
|
|
90
|
+
* Colorspaces other than RGB will be transformed to RGB, color maps expanded.
|
|
91
|
+
*
|
|
92
|
+
* @param {Source} source The COGSource.
|
|
93
|
+
* @param {GeoTIFFLevel} level The GeoTIFF level to read
|
|
94
|
+
* @param {number[]} viewport The image region to read.
|
|
95
|
+
* @returns {Promise<TypedArray[]>} The raster data
|
|
96
|
+
*/
|
|
97
|
+
async function readRGB(source, level, viewport) {
|
|
98
|
+
try {
|
|
99
|
+
// TODO possible optimization: instead of letting geotiff.js crop and resample
|
|
100
|
+
// the tiles into the desired region, we could use image.getTileOrStrip() to
|
|
101
|
+
// read individual tiles (aka blocks) and make a texture per block. This way,
|
|
102
|
+
// there would not be multiple concurrent reads for the same block, and we would not
|
|
103
|
+
// waste time resampling the blocks since resampling is already done in the composer.
|
|
104
|
+
// We would create more textures, but it could be worth it.
|
|
105
|
+
return await level.image.readRGB({
|
|
106
|
+
window: viewport,
|
|
107
|
+
pool: source.pool,
|
|
108
|
+
width: source.tileWidth,
|
|
109
|
+
height: source.tileHeight,
|
|
110
|
+
resampleMethod: source.resampleMethod,
|
|
111
|
+
enableAlpha: true,
|
|
112
|
+
interleave: true,
|
|
113
|
+
});
|
|
114
|
+
} catch (error) {
|
|
115
|
+
if (error.toString() === 'AggregateError: Request failed') {
|
|
116
|
+
// Problem with the source that is blocked by another fetch
|
|
117
|
+
// (request failed in readRasters). See the conversations in
|
|
118
|
+
// https://github.com/geotiffjs/geotiff.js/issues/218
|
|
119
|
+
// https://github.com/geotiffjs/geotiff.js/issues/221
|
|
120
|
+
// https://github.com/geotiffjs/geotiff.js/pull/224
|
|
121
|
+
// Retry until it is not blocked.
|
|
122
|
+
// TODO retry counter
|
|
123
|
+
await new Promise((resolve) => {
|
|
124
|
+
setTimeout(resolve, 100);
|
|
125
|
+
});
|
|
126
|
+
return readRGB(level, viewport, source);
|
|
127
|
+
}
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Creates a texture from the pixel buffer
|
|
91
134
|
*
|
|
92
135
|
* @param {Object} source The COGSource
|
|
93
|
-
* @param {THREE.TypedArray
|
|
94
|
-
* @param {number}
|
|
95
|
-
* @param {number}
|
|
96
|
-
* @param {number}
|
|
136
|
+
* @param {THREE.TypedArray[]} buffer The pixel buffer
|
|
137
|
+
* @param {number} buffer.width
|
|
138
|
+
* @param {number} buffer.height
|
|
139
|
+
* @param {number} buffer.byteLength
|
|
97
140
|
* @returns {THREE.DataTexture} The generated texture.
|
|
98
141
|
*/
|
|
99
|
-
function createTexture(source,
|
|
100
|
-
const {
|
|
142
|
+
function createTexture(source, buffer) {
|
|
143
|
+
const { byteLength } = buffer;
|
|
144
|
+
const width = source.tileWidth;
|
|
145
|
+
const height = source.tileHeight;
|
|
101
146
|
const pixelCount = width * height;
|
|
102
147
|
const targetDataType = source.dataType;
|
|
103
148
|
const format = THREE.RGBAFormat;
|
|
104
149
|
const channelCount = 4;
|
|
105
|
-
|
|
106
|
-
let
|
|
107
|
-
|
|
108
|
-
// Check if it's a RGBA buffer
|
|
109
|
-
if (pixelCount * channelCount === byteLength) {
|
|
110
|
-
data = buffers;
|
|
111
|
-
}
|
|
150
|
+
const isRGBA = pixelCount * channelCount === byteLength;
|
|
151
|
+
let tmpBuffer = buffer;
|
|
112
152
|
|
|
113
153
|
switch (targetDataType) {
|
|
114
154
|
case THREE.UnsignedByteType: {
|
|
115
|
-
if (!
|
|
116
|
-
|
|
117
|
-
const newBuffers = new Uint8ClampedArray(pixelCount * channelCount);
|
|
118
|
-
data = convertToRGBA(buffers, newBuffers, source.defaultAlpha);
|
|
155
|
+
if (!isRGBA) {
|
|
156
|
+
tmpBuffer = convertToRGBA(tmpBuffer, new Uint8ClampedArray(pixelCount * channelCount), source.defaultAlpha);
|
|
119
157
|
}
|
|
120
|
-
|
|
121
|
-
break;
|
|
158
|
+
return new THREE.DataTexture(tmpBuffer, width, height, format, THREE.UnsignedByteType);
|
|
122
159
|
}
|
|
123
160
|
case THREE.FloatType: {
|
|
124
|
-
if (!
|
|
125
|
-
|
|
126
|
-
const newBuffers = new Float32Array(pixelCount * channelCount);
|
|
127
|
-
data = convertToRGBA(buffers, newBuffers, source.defaultAlpha / 255);
|
|
161
|
+
if (!isRGBA) {
|
|
162
|
+
tmpBuffer = convertToRGBA(tmpBuffer, new Float32Array(pixelCount * channelCount), source.defaultAlpha / 255);
|
|
128
163
|
}
|
|
129
|
-
|
|
130
|
-
break;
|
|
164
|
+
return new THREE.DataTexture(tmpBuffer, width, height, format, THREE.FloatType);
|
|
131
165
|
}
|
|
132
166
|
default:
|
|
133
167
|
throw new Error('unsupported data type');
|
|
134
168
|
}
|
|
135
|
-
|
|
136
|
-
return texture;
|
|
137
169
|
}
|
|
138
170
|
|
|
139
|
-
|
|
140
|
-
|
|
171
|
+
/**
|
|
172
|
+
* Convert RGB pixel buffer to RGBA pixel buffer
|
|
173
|
+
*
|
|
174
|
+
* @param {THREE.TypedArray[]} buffer The RGB pixel buffer
|
|
175
|
+
* @param {THREE.TypedArray[]} newBuffer The empty RGBA pixel buffer
|
|
176
|
+
* @param {number} defaultAlpha Default alpha value
|
|
177
|
+
* @returns {THREE.DataTexture} The generated texture.
|
|
178
|
+
*/
|
|
179
|
+
function convertToRGBA(buffer, newBuffer, defaultAlpha) {
|
|
180
|
+
const { width, height } = buffer;
|
|
141
181
|
|
|
142
182
|
for (let i = 0; i < width * height; i++) {
|
|
143
183
|
const oldIndex = i * 3;
|
|
144
184
|
const index = i * 4;
|
|
145
185
|
// Copy RGB from original buffer
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
186
|
+
newBuffer[index + 0] = buffer[oldIndex + 0]; // R
|
|
187
|
+
newBuffer[index + 1] = buffer[oldIndex + 1]; // G
|
|
188
|
+
newBuffer[index + 2] = buffer[oldIndex + 2]; // B
|
|
149
189
|
// Add alpha to new buffer
|
|
150
|
-
|
|
190
|
+
newBuffer[index + 3] = defaultAlpha; // A
|
|
151
191
|
}
|
|
152
192
|
|
|
153
|
-
return
|
|
193
|
+
return newBuffer;
|
|
154
194
|
}
|
|
155
195
|
|
|
156
196
|
/**
|
|
@@ -195,20 +235,14 @@ const COGParser = (function _() {
|
|
|
195
235
|
*/
|
|
196
236
|
parse: async function _(data, options) {
|
|
197
237
|
const source = options.in;
|
|
198
|
-
const
|
|
199
|
-
const level = selectLevel(source, nodeExtent, source.tileWidth, source.tileHeight);
|
|
200
|
-
const viewport = makeWindowFromExtent(source, nodeExtent, level.resolution);
|
|
201
|
-
|
|
202
|
-
const buffers = await level.image.readRGB({
|
|
203
|
-
window: viewport,
|
|
204
|
-
pool: source.pool,
|
|
205
|
-
enableAlpha: true,
|
|
206
|
-
interleave: true,
|
|
207
|
-
});
|
|
238
|
+
const tileExtent = options.extent.as(source.crs);
|
|
208
239
|
|
|
209
|
-
const
|
|
240
|
+
const level = selectLevel(source, tileExtent, source.tileWidth, source.tileHeight);
|
|
241
|
+
const viewport = makeWindowFromExtent(source, tileExtent, level.resolution);
|
|
242
|
+
const rgbBuffer = await readRGB(source, level, viewport);
|
|
243
|
+
const texture = createTexture(source, rgbBuffer);
|
|
210
244
|
texture.flipY = true;
|
|
211
|
-
texture.extent =
|
|
245
|
+
texture.extent = options.extent;
|
|
212
246
|
texture.needsUpdate = true;
|
|
213
247
|
texture.magFilter = THREE.LinearFilter;
|
|
214
248
|
texture.minFilter = THREE.LinearFilter;
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
* @property {string} url - The URL of the COG.
|
|
16
16
|
* @property {GeoTIFF.Pool} pool - Pool use to decode GeoTiff.
|
|
17
17
|
* @property {number} defaultAlpha - Alpha byte value used if no alpha is present in COG. Default value is 255.
|
|
18
|
+
* @property {number} tileWidth - Tile width in pixels. Default value use 'geotiff.getTileWidth()'.
|
|
19
|
+
* @property {number} tileHeight - Tile height in pixels. Default value use 'geotiff.getTileHeight()'.
|
|
20
|
+
* @property {number} resampleMethod - The desired resampling method. Default is 'nearest'.
|
|
18
21
|
*
|
|
19
22
|
* @example
|
|
20
23
|
* // Create the source
|
|
@@ -59,9 +62,9 @@ class COGSource extends itowns.Source {
|
|
|
59
62
|
this.firstImage = await geotiff.getImage();
|
|
60
63
|
this.origin = this.firstImage.getOrigin();
|
|
61
64
|
this.dataType = this.selectDataType(this.firstImage.getSampleFormat(), this.firstImage.getBitsPerSample());
|
|
62
|
-
|
|
63
|
-
this.
|
|
64
|
-
this.
|
|
65
|
+
this.tileWidth = source.tileWidth || this.firstImage.getTileWidth();
|
|
66
|
+
this.tileHeight = source.tileHeight || this.firstImage.getTileHeight();
|
|
67
|
+
this.resampleMethod = source.resampleMethod || 'nearest';
|
|
65
68
|
|
|
66
69
|
// Compute extent
|
|
67
70
|
const [minX, minY, maxX, maxY] = this.firstImage.getBoundingBox();
|
|
@@ -80,7 +83,7 @@ class COGSource extends itowns.Source {
|
|
|
80
83
|
.then(image => this.makeLevel(image, image.getResolution(this.firstImage)));
|
|
81
84
|
promises.push(promise);
|
|
82
85
|
}
|
|
83
|
-
this.levels.
|
|
86
|
+
this.levels = this.levels.concat(await Promise.all(promises));
|
|
84
87
|
});
|
|
85
88
|
}
|
|
86
89
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"crs": "EPSG:3857",
|
|
5
5
|
"isInverted": true,
|
|
6
6
|
"format": "image/png",
|
|
7
|
-
"url": "
|
|
7
|
+
"url": "https://maps.pole-emploi.fr/styles/klokantech-basic/${z}/${x}/${y}.png",
|
|
8
8
|
"attribution": {
|
|
9
9
|
"name":"OpenStreetMap",
|
|
10
10
|
"url": "http://www.openstreetmap.org/"
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
potreeLayer.root.bbox.getSize(size);
|
|
103
103
|
potreeLayer.root.bbox.getCenter(lookAt);
|
|
104
104
|
|
|
105
|
-
debug.
|
|
105
|
+
debug.PointCloudDebug.initTools(view, potreeLayer, debugGui);
|
|
106
106
|
|
|
107
107
|
view.camera3D.far = 2.0 * size.length();
|
|
108
108
|
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
|
|
72
72
|
// add potreeLayer to scene
|
|
73
73
|
function onLayerReady() {
|
|
74
|
-
debug.
|
|
74
|
+
debug.PointCloudDebug.initTools(view, potreeLayer, debugGui);
|
|
75
75
|
|
|
76
76
|
// update stats window
|
|
77
77
|
var info = document.getElementById('info');
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
itowns.proj4.defs('EPSG:2154', '+proj=lcc +lat_1=49 +lat_2=44 +lat_0=46.5 +lon_0=3 +x_0=700000 +y_0=6600000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs');
|
|
37
37
|
|
|
38
38
|
var viewerDiv = document.getElementById('viewerDiv');
|
|
39
|
+
var view;
|
|
39
40
|
|
|
40
41
|
function readCOGURL() {
|
|
41
42
|
var url = document.getElementById('cog_url').value || new URLSearchParams(window.location.search).get('geotiff');
|
|
@@ -47,7 +48,7 @@
|
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
function loadRGBSample() {
|
|
50
|
-
document.getElementById('cog_url').value = 'https://cdn.jsdelivr.net/gh/
|
|
51
|
+
document.getElementById('cog_url').value = 'https://cdn.jsdelivr.net/gh/iTowns/iTowns2-sample-data/cog/nantes/nantes.tif';
|
|
51
52
|
readCOGURL();
|
|
52
53
|
}
|
|
53
54
|
|
|
@@ -56,17 +57,33 @@
|
|
|
56
57
|
readCOGURL();
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
function
|
|
60
|
+
function removeAllChildNodes(parent) {
|
|
61
|
+
while (parent.firstChild) {
|
|
62
|
+
parent.removeChild(parent.firstChild);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function loadCOG(url) {
|
|
60
67
|
// create a source from a Cloud Optimized GeoTiff
|
|
61
68
|
var cogSource = new COGSource({
|
|
62
69
|
url: url,
|
|
63
|
-
crs: "EPSG:2154"
|
|
70
|
+
crs: "EPSG:2154",
|
|
71
|
+
// Default resample method is 'nearest', 'bilinear' looks better when zoomed
|
|
72
|
+
resampleMethod: 'bilinear'
|
|
64
73
|
});
|
|
65
74
|
|
|
66
75
|
cogSource.whenReady.then(() => {
|
|
67
|
-
|
|
76
|
+
if (view !== undefined) {
|
|
77
|
+
view.dispose(true);
|
|
78
|
+
removeAllChildNodes(viewerDiv);
|
|
79
|
+
}
|
|
80
|
+
view = new itowns.PlanarView(viewerDiv, cogSource.extent, {
|
|
81
|
+
// Default maxSubdivisionLevel is 5, so with huge geotiff it's not enough to see details when zoomed
|
|
82
|
+
maxSubdivisionLevel: 10,
|
|
83
|
+
disableSkirt: true,
|
|
84
|
+
placement: { tilt: 90 }
|
|
85
|
+
});
|
|
68
86
|
setupLoadingScreen(viewerDiv, view);
|
|
69
|
-
new itowns.PlanarControls(view, {});
|
|
70
87
|
var cogLayer = new itowns.ColorLayer('cog', {
|
|
71
88
|
source: cogSource,
|
|
72
89
|
});
|
|
@@ -416,7 +416,6 @@ function featureToExtrudedPolygon(feature, options) {
|
|
|
416
416
|
meshColor.toArray(colors, t); // top
|
|
417
417
|
meshColor.multiplyScalar(0.5).toArray(colors, i); // base is half dark
|
|
418
418
|
}
|
|
419
|
-
|
|
420
419
|
featureId++;
|
|
421
420
|
const geomVertices = vertices.slice(startTop * 3, (end + totalVertices) * 3);
|
|
422
421
|
const holesOffsets = geometry.indices.map(i => i.offset - start).slice(1);
|
|
@@ -496,14 +495,13 @@ function pointsToInstancedMeshes(feature) {
|
|
|
496
495
|
* @return {THREE.Mesh} mesh or GROUP of THREE.InstancedMesh
|
|
497
496
|
*/
|
|
498
497
|
function featureToMesh(feature, options) {
|
|
499
|
-
var _style$point, _style$point$model;
|
|
500
498
|
if (!feature.vertices) {
|
|
501
499
|
return;
|
|
502
500
|
}
|
|
503
501
|
let mesh;
|
|
504
502
|
switch (feature.type) {
|
|
505
503
|
case FEATURE_TYPES.POINT:
|
|
506
|
-
if (
|
|
504
|
+
if (style.point?.model?.object) {
|
|
507
505
|
try {
|
|
508
506
|
mesh = pointsToInstancedMeshes(feature);
|
|
509
507
|
mesh.isInstancedMesh = true;
|
|
@@ -592,7 +590,7 @@ export default {
|
|
|
592
590
|
// style properties (@link StyleOptions) using options.style.
|
|
593
591
|
// This is usually done in some tests and if you want to use Feature2Mesh.convert()
|
|
594
592
|
// as in examples/source_file_gpx_3d.html.
|
|
595
|
-
style =
|
|
593
|
+
style = this?.style || (options.style ? new Style(options.style) : defaultStyle);
|
|
596
594
|
context.setCollection(collection);
|
|
597
595
|
const features = collection.features;
|
|
598
596
|
if (!features || features.length == 0) {
|
|
@@ -21,7 +21,7 @@ export default {
|
|
|
21
21
|
const backgroundLayer = layer.source.backgroundLayer;
|
|
22
22
|
const backgroundColor = backgroundLayer && backgroundLayer.paint ? new THREE.Color(backgroundLayer.paint['background-color']) : undefined;
|
|
23
23
|
extentDestination.as(CRS.formatToEPSG(layer.crs), extentTexture);
|
|
24
|
-
texture = Feature2Texture.createTextureFromFeature(data, extentTexture,
|
|
24
|
+
texture = Feature2Texture.createTextureFromFeature(data, extentTexture, layer.subdivisionThreshold, layer.style, backgroundColor);
|
|
25
25
|
texture.features = data;
|
|
26
26
|
texture.extent = extentDestination;
|
|
27
27
|
} else if (data.isTexture) {
|
|
@@ -52,7 +52,7 @@ class C3DTBatchTable {
|
|
|
52
52
|
if (Array.isArray(propVal)) {
|
|
53
53
|
continue;
|
|
54
54
|
}
|
|
55
|
-
if (typeof
|
|
55
|
+
if (typeof propVal?.byteOffset !== 'undefined' && typeof propVal?.componentType !== 'undefined' && typeof propVal?.type !== 'undefined') {
|
|
56
56
|
jsonContent[propKey] = binaryPropertyAccessor(binaryBuffer, this.batchLength, propVal.byteOffset, propVal.componentType, propVal.type);
|
|
57
57
|
} else {
|
|
58
58
|
console.error('Invalid 3D Tiles batch table property that is neither a JSON array nor a valid ' + 'accessor to a binary body');
|
package/lib/Core/Feature.js
CHANGED
|
@@ -338,10 +338,9 @@ export class FeatureCollection extends THREE.Object3D {
|
|
|
338
338
|
* @param {FeatureBuildingOptions|Layer} options The building options .
|
|
339
339
|
*/
|
|
340
340
|
constructor(options) {
|
|
341
|
-
var _options$source;
|
|
342
341
|
super();
|
|
343
342
|
this.isFeatureCollection = true;
|
|
344
|
-
this.crs = CRS.formatToEPSG(options.accurate || !
|
|
343
|
+
this.crs = CRS.formatToEPSG(options.accurate || !options.source?.crs ? options.crs : options.source.crs);
|
|
345
344
|
this.features = [];
|
|
346
345
|
this.mergeFeatures = options.mergeFeatures === undefined ? true : options.mergeFeatures;
|
|
347
346
|
this.size = options.structure == '3d' ? 3 : 2;
|
package/lib/Core/Label.js
CHANGED
package/lib/Core/MainLoop.js
CHANGED
|
@@ -72,7 +72,6 @@ class Atmosphere extends GeometryLayer {
|
|
|
72
72
|
value: new THREE.Vector2(window.innerWidth, window.innerHeight)
|
|
73
73
|
} // Should be updated on screen resize...
|
|
74
74
|
},
|
|
75
|
-
|
|
76
75
|
vertexShader: GlowVS,
|
|
77
76
|
fragmentShader: GlowFS,
|
|
78
77
|
side: THREE.BackSide,
|
|
@@ -100,7 +99,6 @@ class Atmosphere extends GeometryLayer {
|
|
|
100
99
|
value: new THREE.Vector2(window.innerWidth, window.innerHeight)
|
|
101
100
|
} // Should be updated on screen resize...
|
|
102
101
|
},
|
|
103
|
-
|
|
104
102
|
vertexShader: GlowVS,
|
|
105
103
|
fragmentShader: GlowFS,
|
|
106
104
|
side: THREE.FrontSide,
|
|
@@ -135,7 +133,6 @@ class Atmosphere extends GeometryLayer {
|
|
|
135
133
|
scaleDepth: 0.25
|
|
136
134
|
// mieScaleDepth: 0.1,
|
|
137
135
|
};
|
|
138
|
-
|
|
139
136
|
this.object3d.updateMatrixWorld();
|
|
140
137
|
}
|
|
141
138
|
update(context, layer, node) {
|
|
@@ -288,7 +285,6 @@ class Atmosphere extends GeometryLayer {
|
|
|
288
285
|
skyDome.material.uniforms.mieDirectionalG.value = effectController.mieDirectionalG;
|
|
289
286
|
skyDome.material.uniforms.up.value = new THREE.Vector3(); // no more necessary, estimate normal from cam..
|
|
290
287
|
}
|
|
291
|
-
|
|
292
288
|
setRealisticOn(bool) {
|
|
293
289
|
if (bool) {
|
|
294
290
|
if (!this.realisticAtmosphere.children.length) {
|
|
@@ -3,7 +3,6 @@ import TiledGeometryLayer from "../../../Layer/TiledGeometryLayer.js";
|
|
|
3
3
|
import { ellipsoidSizes } from "../../Math/Ellipsoid.js";
|
|
4
4
|
import { globalExtentTMS, schemeTiles } from "../../Geographic/Extent.js";
|
|
5
5
|
import BuilderEllipsoidTile from "./BuilderEllipsoidTile.js";
|
|
6
|
-
import { SIZE_DIAGONAL_TEXTURE } from "../../../Process/LayeredMaterialNodeProcessing.js";
|
|
7
6
|
import CRS from "../../Geographic/Crs.js";
|
|
8
7
|
|
|
9
8
|
// matrix to convert sphere to ellipsoid
|
|
@@ -129,7 +128,7 @@ class GlobeLayer extends TiledGeometryLayer {
|
|
|
129
128
|
return isOccluded;
|
|
130
129
|
}
|
|
131
130
|
computeTileZoomFromDistanceCamera(distance, camera) {
|
|
132
|
-
const preSinus =
|
|
131
|
+
const preSinus = this.sizeDiagonalTexture * (this.sseSubdivisionThreshold * 0.5) / camera._preSSE / ellipsoidSizes.x;
|
|
133
132
|
let sinus = distance * preSinus;
|
|
134
133
|
let zoom = Math.log(Math.PI / (2.0 * Math.asin(sinus))) / Math.log(2);
|
|
135
134
|
const delta = Math.PI / 2 ** zoom;
|
|
@@ -143,7 +142,8 @@ class GlobeLayer extends TiledGeometryLayer {
|
|
|
143
142
|
const delta = Math.PI / 2 ** zoom;
|
|
144
143
|
const circleChord = 2.0 * ellipsoidSizes.x * Math.sin(delta * 0.5);
|
|
145
144
|
const radius = circleChord * 0.5;
|
|
146
|
-
|
|
145
|
+
const error = radius / this.sizeDiagonalTexture;
|
|
146
|
+
return camera._preSSE * error / (this.sseSubdivisionThreshold * 0.5) + radius;
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
export default GlobeLayer;
|
package/lib/Core/Style.js
CHANGED
|
@@ -12,8 +12,7 @@ const matrix = document.createElementNS('http://www.w3.org/2000/svg', 'svg').cre
|
|
|
12
12
|
const canvas = document.createElement('canvas');
|
|
13
13
|
const inv255 = 1 / 255;
|
|
14
14
|
function baseAltitudeDefault(properties, ctx) {
|
|
15
|
-
|
|
16
|
-
return (ctx === null || ctx === void 0 ? void 0 : (_ctx$coordinates = ctx.coordinates) === null || _ctx$coordinates === void 0 ? void 0 : _ctx$coordinates.z) || 0;
|
|
15
|
+
return ctx?.coordinates?.z || 0;
|
|
17
16
|
}
|
|
18
17
|
export function readExpression(property, ctx) {
|
|
19
18
|
if (property != undefined) {
|
|
@@ -154,7 +153,6 @@ function defineStyleProperty(style, category, parameter, userValue, defaultValue
|
|
|
154
153
|
Object.defineProperty(style[category], parameter, {
|
|
155
154
|
enumerable: true,
|
|
156
155
|
get: () => {
|
|
157
|
-
var _style$context$featur, _style$context$featur2;
|
|
158
156
|
// != to check for 'undefined' and 'null' value)
|
|
159
157
|
if (property != undefined) {
|
|
160
158
|
return property;
|
|
@@ -162,7 +160,7 @@ function defineStyleProperty(style, category, parameter, userValue, defaultValue
|
|
|
162
160
|
if (userValue != undefined) {
|
|
163
161
|
return readExpression(userValue, style.context);
|
|
164
162
|
}
|
|
165
|
-
const dataValue =
|
|
163
|
+
const dataValue = style.context.featureStyle?.[category]?.[parameter];
|
|
166
164
|
if (dataValue != undefined) {
|
|
167
165
|
return readExpression(dataValue, style.context);
|
|
168
166
|
}
|
package/lib/Core/View.js
CHANGED
|
@@ -232,8 +232,7 @@ class View extends THREE.EventDispatcher {
|
|
|
232
232
|
* @returns {THREE.WebGLRenderer} the WebGLRenderer used to render this view.
|
|
233
233
|
*/
|
|
234
234
|
get renderer() {
|
|
235
|
-
|
|
236
|
-
return (_this$mainLoop = this.mainLoop) === null || _this$mainLoop === void 0 ? void 0 : (_this$mainLoop$gfxEng = _this$mainLoop.gfxEngine) === null || _this$mainLoop$gfxEng === void 0 ? void 0 : _this$mainLoop$gfxEng.getRenderer();
|
|
235
|
+
return this.mainLoop?.gfxEngine?.getRenderer();
|
|
237
236
|
}
|
|
238
237
|
|
|
239
238
|
/**
|
|
@@ -241,8 +240,7 @@ class View extends THREE.EventDispatcher {
|
|
|
241
240
|
* @returns {THREE.Camera} the threejs camera of this view
|
|
242
241
|
*/
|
|
243
242
|
get camera3D() {
|
|
244
|
-
|
|
245
|
-
return (_this$camera = this.camera) === null || _this$camera === void 0 ? void 0 : _this$camera.camera3D;
|
|
243
|
+
return this.camera?.camera3D;
|
|
246
244
|
}
|
|
247
245
|
|
|
248
246
|
/**
|
|
@@ -92,7 +92,9 @@ class C3DTilesLayer extends GeometryLayer {
|
|
|
92
92
|
* @param {Number} [config.cleanupDelay=1000] The time (in ms) after which a tile content (and its children) are
|
|
93
93
|
* removed from the scene.
|
|
94
94
|
* @param {C3DTExtensions} [config.registeredExtensions] 3D Tiles extensions managers registered for this tileset.
|
|
95
|
-
* @param {String} [config.pntsMode= PNTS_MODE.COLOR] {@link PointsMaterials} Point cloud coloring mode.
|
|
95
|
+
* @param {String} [config.pntsMode= PNTS_MODE.COLOR] {@link PointsMaterials} Point cloud coloring mode.
|
|
96
|
+
* Only 'COLOR' or 'CLASSIFICATION' are possible. COLOR uses RGB colors of the points,
|
|
97
|
+
* CLASSIFICATION uses a classification property of the batch table to color points.
|
|
96
98
|
* @param {String} [config.pntsShape= PNTS_SHAPE.CIRCLE] Point cloud point shape. Only 'CIRCLE' or 'SQUARE' are possible.
|
|
97
99
|
* @param {String} [config.pntsSizeMode= PNTS_SIZE_MODE.VALUE] {@link PointsMaterials} Point cloud size mode. Only 'VALUE' or 'ATTENUATED' are possible. VALUE use constant size, ATTENUATED compute size depending on distance from point to camera.
|
|
98
100
|
* @param {Number} [config.pntsMinAttenuatedSize=3] Minimum scale used by 'ATTENUATED' size mode
|
|
@@ -60,14 +60,13 @@ class ElevationLayer extends RasterLayer {
|
|
|
60
60
|
* view.addLayer(elevation);
|
|
61
61
|
*/
|
|
62
62
|
constructor(id) {
|
|
63
|
-
var _config$clampValues, _config$clampValues2;
|
|
64
63
|
let config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
65
64
|
super(id, config);
|
|
66
65
|
if (config.zmin || config.zmax) {
|
|
67
66
|
console.warn('Config using zmin and zmax are deprecated, use {clampValues: {min, max}} structure.');
|
|
68
67
|
}
|
|
69
|
-
this.zmin =
|
|
70
|
-
this.zmax =
|
|
68
|
+
this.zmin = config.clampValues?.min ?? config.zmin;
|
|
69
|
+
this.zmax = config.clampValues?.max ?? config.zmax;
|
|
71
70
|
this.isElevationLayer = true;
|
|
72
71
|
this.defineLayerProperty('scale', this.scale || 1.0);
|
|
73
72
|
}
|
package/lib/Layer/GeoidLayer.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import Layer from "./Layer.js";
|
|
2
2
|
import LayerUpdateState from "./LayerUpdateState.js";
|
|
3
3
|
export function geoidLayerIsVisible(tilelayer) {
|
|
4
|
-
|
|
5
|
-
return tilelayer === null || tilelayer === void 0 ? void 0 : (_tilelayer$attachedLa = tilelayer.attachedLayers.filter(l => l.isGeoidLayer)[0]) === null || _tilelayer$attachedLa === void 0 ? void 0 : _tilelayer$attachedLa.visible;
|
|
4
|
+
return tilelayer?.attachedLayers.filter(l => l.isGeoidLayer)[0]?.visible;
|
|
6
5
|
}
|
|
7
6
|
|
|
8
7
|
/**
|
package/lib/Layer/LabelLayer.js
CHANGED
|
@@ -195,11 +195,9 @@ class LabelLayer extends GeometryLayer {
|
|
|
195
195
|
set visible(value) {
|
|
196
196
|
super.visible = value;
|
|
197
197
|
if (value) {
|
|
198
|
-
|
|
199
|
-
(_this$domElement = this.domElement) === null || _this$domElement === void 0 ? void 0 : _this$domElement.show();
|
|
198
|
+
this.domElement?.show();
|
|
200
199
|
} else {
|
|
201
|
-
|
|
202
|
-
(_this$domElement2 = this.domElement) === null || _this$domElement2 === void 0 ? void 0 : _this$domElement2.hide();
|
|
200
|
+
this.domElement?.hide();
|
|
203
201
|
}
|
|
204
202
|
}
|
|
205
203
|
get submittedLabelNodes() {
|
|
@@ -231,16 +229,15 @@ class LabelLayer extends GeometryLayer {
|
|
|
231
229
|
coord.crs = data.crs;
|
|
232
230
|
context.setZoom(extent.zoom);
|
|
233
231
|
data.features.forEach(f => {
|
|
234
|
-
var _f$style, _f$style$text, _f$style2, _f$style2$point;
|
|
235
232
|
// TODO: add support for LINE and POLYGON
|
|
236
233
|
if (f.type !== FEATURE_TYPES.POINT) {
|
|
237
234
|
return;
|
|
238
235
|
}
|
|
239
236
|
context.setFeature(f);
|
|
240
|
-
const featureField =
|
|
237
|
+
const featureField = f.style?.text?.field;
|
|
241
238
|
|
|
242
239
|
// determine if altitude style is specified by the user
|
|
243
|
-
const altitudeStyle =
|
|
240
|
+
const altitudeStyle = f.style?.point?.base_altitude;
|
|
244
241
|
const isDefaultElevationStyle = altitudeStyle instanceof Function && altitudeStyle.name == 'baseAltitudeDefault';
|
|
245
242
|
|
|
246
243
|
// determine if the altitude needs update with ElevationLayer
|
|
@@ -292,19 +289,14 @@ class LabelLayer extends GeometryLayer {
|
|
|
292
289
|
this.toHide.add(labelsNode);
|
|
293
290
|
}
|
|
294
291
|
#findClosestDomElement(node) {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
var _node$parent$link$thi;
|
|
298
|
-
return ((_node$parent$link$thi = node.parent.link[this.id]) === null || _node$parent$link$thi === void 0 ? void 0 : _node$parent$link$thi.domElements) || this.#findClosestDomElement(node.parent);
|
|
292
|
+
if (node.parent?.isTileMesh) {
|
|
293
|
+
return node.parent.link[this.id]?.domElements || this.#findClosestDomElement(node.parent);
|
|
299
294
|
} else {
|
|
300
295
|
return this.domElement;
|
|
301
296
|
}
|
|
302
297
|
}
|
|
303
298
|
#hasLabelChildren(object) {
|
|
304
|
-
return object.children.every(c =>
|
|
305
|
-
var _c$layerUpdateState$t;
|
|
306
|
-
return c.layerUpdateState && ((_c$layerUpdateState$t = c.layerUpdateState[this.id]) === null || _c$layerUpdateState$t === void 0 ? void 0 : _c$layerUpdateState$t.hasFinished());
|
|
307
|
-
});
|
|
299
|
+
return object.children.every(c => c.layerUpdateState && c.layerUpdateState[this.id]?.hasFinished());
|
|
308
300
|
}
|
|
309
301
|
|
|
310
302
|
// Remove all labels invisible with pre-culling with screen grid
|
|
@@ -439,8 +431,7 @@ class LabelLayer extends GeometryLayer {
|
|
|
439
431
|
this.removeNodeDomElement(node);
|
|
440
432
|
}
|
|
441
433
|
removeNodeDomElement(node) {
|
|
442
|
-
|
|
443
|
-
if ((_node$link$this$id = node.link[this.id]) !== null && _node$link$this$id !== void 0 && _node$link$this$id.domElements) {
|
|
434
|
+
if (node.link[this.id]?.domElements) {
|
|
444
435
|
const child = node.link[this.id].domElements.dom;
|
|
445
436
|
child.parentElement.removeChild(child);
|
|
446
437
|
delete node.link[this.id].domElements;
|