itowns 2.43.2-next.2 → 2.43.2-next.20

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 (83) hide show
  1. package/dist/558.js +2 -0
  2. package/dist/558.js.map +1 -0
  3. package/dist/debug.js +1 -1
  4. package/dist/debug.js.map +1 -1
  5. package/dist/itowns.js +1 -1
  6. package/dist/itowns.js.map +1 -1
  7. package/dist/itowns_lasparser.js +2 -0
  8. package/dist/itowns_lasparser.js.map +1 -0
  9. package/dist/itowns_lasworker.js +2 -0
  10. package/dist/itowns_lasworker.js.map +1 -0
  11. package/dist/itowns_potree2worker.js +2 -0
  12. package/dist/itowns_potree2worker.js.map +1 -0
  13. package/dist/itowns_widgets.js +1 -1
  14. package/dist/itowns_widgets.js.map +1 -1
  15. package/examples/3dtiles_25d.html +1 -1
  16. package/examples/3dtiles_basic.html +2 -2
  17. package/examples/3dtiles_batch_table.html +1 -3
  18. package/examples/3dtiles_pointcloud.html +9 -15
  19. package/examples/config.json +1 -0
  20. package/examples/copc_simple_loader.html +1 -1
  21. package/examples/entwine_3d_loader.html +1 -1
  22. package/examples/entwine_simple_loader.html +1 -1
  23. package/examples/js/plugins/COGParser.js +84 -50
  24. package/examples/js/plugins/COGSource.js +7 -4
  25. package/examples/layers/JSONLayers/OPENSM.json +1 -1
  26. package/examples/potree2_25d_map.html +127 -0
  27. package/examples/potree_25d_map.html +1 -1
  28. package/examples/potree_3d_map.html +1 -1
  29. package/examples/source_file_cog.html +22 -5
  30. package/lib/Controls/FirstPersonControls.js +0 -1
  31. package/lib/Controls/FlyControls.js +0 -1
  32. package/lib/Converter/Feature2Mesh.js +2 -4
  33. package/lib/Converter/textureConverter.js +1 -1
  34. package/lib/Core/3DTiles/C3DTBatchTable.js +1 -1
  35. package/lib/Core/3DTiles/C3DTFeature.js +6 -7
  36. package/lib/Core/Feature.js +1 -2
  37. package/lib/Core/Geographic/CoordStars.js +0 -1
  38. package/lib/Core/Label.js +0 -1
  39. package/lib/Core/MainLoop.js +0 -1
  40. package/lib/Core/Potree2Node.js +206 -0
  41. package/lib/Core/Potree2PointAttributes.js +139 -0
  42. package/lib/Core/Prefab/Globe/Atmosphere.js +0 -4
  43. package/lib/Core/Prefab/Globe/GlobeLayer.js +3 -3
  44. package/lib/Core/Scheduler/Scheduler.js +1 -1
  45. package/lib/Core/Style.js +54 -53
  46. package/lib/Core/View.js +2 -4
  47. package/lib/Layer/C3DTilesLayer.js +8 -6
  48. package/lib/Layer/ElevationLayer.js +2 -3
  49. package/lib/Layer/GeoidLayer.js +1 -2
  50. package/lib/Layer/LabelLayer.js +8 -17
  51. package/lib/Layer/Layer.js +4 -2
  52. package/lib/Layer/PointCloudLayer.js +5 -8
  53. package/lib/Layer/Potree2Layer.js +165 -0
  54. package/lib/Layer/ReferencingLayerProperties.js +8 -3
  55. package/lib/Layer/TiledGeometryLayer.js +6 -4
  56. package/lib/Loader/Potree2BrotliLoader.js +261 -0
  57. package/lib/Loader/Potree2Loader.js +207 -0
  58. package/lib/Main.js +2 -0
  59. package/lib/Parser/GeoJsonParser.js +2 -3
  60. package/lib/Parser/LASParser.js +49 -18
  61. package/lib/Parser/Potree2BinParser.js +92 -0
  62. package/lib/Parser/deprecated/LegacyGLTFLoader.js +1 -2
  63. package/lib/Process/3dTilesProcessing.js +2 -1
  64. package/lib/Process/FeatureProcessing.js +1 -2
  65. package/lib/Process/LayeredMaterialNodeProcessing.js +3 -9
  66. package/lib/Process/ObjectRemovalHelper.js +1 -2
  67. package/lib/Provider/3dTilesProvider.js +3 -2
  68. package/lib/Renderer/ColorLayersOrdering.js +1 -2
  69. package/lib/Renderer/Label2DRenderer.js +1 -4
  70. package/lib/Renderer/PointsMaterial.js +135 -100
  71. package/lib/Renderer/RenderMode.js +0 -1
  72. package/lib/Source/FileSource.js +1 -1
  73. package/lib/Source/Potree2Source.js +172 -0
  74. package/lib/ThreeExtended/loaders/DDSLoader.js +11 -1
  75. package/lib/ThreeExtended/loaders/DRACOLoader.js +0 -1
  76. package/lib/ThreeExtended/loaders/GLTFLoader.js +1 -0
  77. package/lib/Utils/DEMUtils.js +2 -2
  78. package/lib/Utils/OrientationUtils.js +0 -1
  79. package/lib/Utils/gui/Searchbar.js +1 -2
  80. package/lib/Worker/LASLoaderWorker.js +19 -0
  81. package/lib/Worker/Potree2Worker.js +21 -0
  82. package/package.json +11 -8
  83. /package/lib/{Parser → Loader}/LASLoader.js +0 -0
@@ -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 = cropped.planarDimensions();
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
- * Creates a texture from the pixel buffer(s).
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 | THREE.TypedArray[]} buffers The buffers (one buffer per band)
94
- * @param {number} buffers.width
95
- * @param {number} buffers.height
96
- * @param {number} buffers.byteLength
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, buffers) {
100
- const { width, height, byteLength } = buffers;
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
- let texture;
106
- let data;
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 (!data) {
116
- // We convert RGB buffer to RGBA
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
- texture = new THREE.DataTexture(data, width, height, format, THREE.UnsignedByteType);
121
- break;
158
+ return new THREE.DataTexture(tmpBuffer, width, height, format, THREE.UnsignedByteType);
122
159
  }
123
160
  case THREE.FloatType: {
124
- if (!data) {
125
- // We convert RGB buffer to RGBA
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
- texture = new THREE.DataTexture(data, width, height, format, THREE.FloatType);
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
- function convertToRGBA(buffers, newBuffers, defaultAlpha) {
140
- const { width, height } = buffers;
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
- newBuffers[index + 0] = buffers[oldIndex + 0]; // R
147
- newBuffers[index + 1] = buffers[oldIndex + 1]; // G
148
- newBuffers[index + 2] = buffers[oldIndex + 2]; // B
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
- newBuffers[index + 3] = defaultAlpha; // A
190
+ newBuffer[index + 3] = defaultAlpha; // A
151
191
  }
152
192
 
153
- return newBuffers;
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 nodeExtent = data.extent.as(source.crs);
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 texture = createTexture(source, buffers);
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 = data.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.tileWidth = this.firstImage.getTileWidth();
64
- this.tileHeight = this.firstImage.getTileHeight();
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.push(await Promise.all(promises));
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": "http://osm.oslandia.io/styles/klokantech-basic/${z}/${x}/${y}.png",
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/"
@@ -0,0 +1,127 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Point Cloud Viewer</title>
5
+
6
+ <style type="text/css">
7
+ #info {
8
+ color: #7ad7ff;
9
+ font-family: 'Open Sans', sans-serif;
10
+ position: absolute;
11
+ top: 0;
12
+ left: 0;
13
+ padding: 0.3rem;
14
+ background-color: #404040;
15
+ z-index: 1;
16
+ }
17
+ @media (max-width: 600px) {
18
+ #info,
19
+ .dg {
20
+ display: none;
21
+ }
22
+ }
23
+ </style>
24
+
25
+ <meta charset="UTF-8">
26
+ <link rel="stylesheet" type="text/css" href="css/example.css">
27
+ <link rel="stylesheet" type="text/css" href="css/LoadingScreen.css">
28
+
29
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
30
+ </head>
31
+ <body>
32
+ <div id="viewerDiv">
33
+ <div id="info"></div>
34
+ </div>
35
+
36
+ <div>
37
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script>
38
+ <script src="../dist/itowns.js"></script>
39
+ <script src="js/GUI/LoadingScreen.js"></script>
40
+ <script src="../dist/debug.js"></script>
41
+ <script type="text/javascript">
42
+ var potreeLayer;
43
+ var oldPostUpdate;
44
+ var viewerDiv;
45
+ var debugGui;
46
+ var view;
47
+ var controls;
48
+
49
+ // Define crs projection that we will use (taken from https://epsg.io/3946, Proj4js section)
50
+ itowns.proj4.defs('EPSG:3946', '+proj=lcc +lat_1=45.25 +lat_2=46.75 +lat_0=46 +lon_0=3 +x_0=1700000 +y_0=5200000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs');
51
+
52
+ viewerDiv = document.getElementById('viewerDiv');
53
+ viewerDiv.style.display = 'block';
54
+
55
+ debugGui = new dat.GUI();
56
+
57
+ // TODO: do we really need to disable logarithmicDepthBuffer ?
58
+ view = new itowns.View('EPSG:3946', viewerDiv);
59
+ setupLoadingScreen(viewerDiv, view);
60
+ view.mainLoop.gfxEngine.renderer.setClearColor(0xcccccc);
61
+
62
+ // Configure Point Cloud layer
63
+ potreeLayer = new itowns.Potree2Layer('Lion', {
64
+ source: new itowns.Potree2Source({
65
+ file: 'metadata.json',
66
+ url: 'https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/master/pointclouds/potree2.0/lion',
67
+ crs: view.referenceCrs,
68
+ }),
69
+ });
70
+
71
+ // point selection on double-click
72
+ function dblClickHandler(event) {
73
+ var pick = view.pickObjectsAt(event, 5, potreeLayer);
74
+
75
+ for (const p of pick) {
76
+ console.info('Selected point #' + p.index + ' in position (' +
77
+ p.object.position.x + ', ' +
78
+ p.object.position.y + ', ' +
79
+ p.object.position.z +
80
+ ') in Points ' + p.object.layer.id);
81
+ }
82
+ }
83
+ view.domElement.addEventListener('dblclick', dblClickHandler);
84
+
85
+ function placeCamera(position, lookAt) {
86
+ view.camera.camera3D.position.copy(position);
87
+ view.camera.camera3D.lookAt(lookAt);
88
+ // create controls
89
+ controls = new itowns.FirstPersonControls(view, { focusOnClick: true });
90
+ debugGui.add(controls.options, 'moveSpeed', 1, 100).name('Movement speed');
91
+
92
+ view.notifyChange(view.camera.camera3D);
93
+ }
94
+
95
+ // add potreeLayer to scene
96
+ function onLayerReady() {
97
+ var ratio;
98
+ var position;
99
+ var lookAt = new itowns.THREE.Vector3();
100
+ var size = new itowns.THREE.Vector3();
101
+
102
+ potreeLayer.root.bbox.getSize(size);
103
+ potreeLayer.root.bbox.getCenter(lookAt);
104
+
105
+ debug.PointCloudDebug.initTools(view, potreeLayer, debugGui);
106
+
107
+ view.camera.camera3D.far = 2.0 * size.length();
108
+
109
+ ratio = size.x / size.z;
110
+ position = potreeLayer.root.bbox.min.clone().add(
111
+ size.multiply({ x: 0, y: 0, z: ratio * 0.5 }));
112
+ lookAt.z = potreeLayer.root.bbox.min.z;
113
+ placeCamera(position, lookAt);
114
+ controls.moveSpeed = size.length() / 3;
115
+
116
+ // update stats window
117
+ var info = document.getElementById('info');
118
+ view.addFrameRequester(itowns.MAIN_LOOP_EVENTS.AFTER_RENDER, () => {
119
+ info.textContent = potreeLayer.displayedCount.toLocaleString() + ' points';
120
+ });
121
+ }
122
+ window.view = view;
123
+ view.addLayer(potreeLayer).then(onLayerReady);
124
+ </script>
125
+ </body>
126
+ </html>
127
+
@@ -102,7 +102,7 @@
102
102
  potreeLayer.root.bbox.getSize(size);
103
103
  potreeLayer.root.bbox.getCenter(lookAt);
104
104
 
105
- debug.PotreeDebug.initTools(view, potreeLayer, debugGui);
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.PotreeDebug.initTools(view, potreeLayer, debugGui);
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/bloc-in-bloc/iTowns2-sample-data@add-cog-sample/cog/orvault.tif';
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 loadCOG(url, crs) {
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
- var view = new itowns.PlanarView(viewerDiv, cogSource.extent, { disableSkirt: true, placement: { tilt: 90 } });
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
  });
@@ -49,7 +49,6 @@ const MOVEMENTS = {
49
49
  sign: -1
50
50
  } // DOWN: PageDown key
51
51
  };
52
-
53
52
  function moveCameraVerticalPlanar(value) {
54
53
  this.camera.position.z += value;
55
54
  }
@@ -45,7 +45,6 @@ const MOVEMENTS = {
45
45
  oneshot: true
46
46
  } // WHEEL down
47
47
  };
48
-
49
48
  function onDocumentMouseDown(event) {
50
49
  event.preventDefault();
51
50
  this._isMouseDown = true;
@@ -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 ((_style$point = style.point) !== null && _style$point !== void 0 && (_style$point$model = _style$point.model) !== null && _style$point$model !== void 0 && _style$point$model.object) {
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 = (this === null || this === void 0 ? void 0 : this.style) || (options.style ? new Style(options.style) : defaultStyle);
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, 256, layer.style, backgroundColor);
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 (propVal === null || propVal === void 0 ? void 0 : propVal.byteOffset) !== 'undefined' && typeof (propVal === null || propVal === void 0 ? void 0 : propVal.componentType) !== 'undefined' && typeof (propVal === null || propVal === void 0 ? void 0 : propVal.type) !== 'undefined') {
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');
@@ -72,12 +72,12 @@ class C3DTFeature {
72
72
  target.min.y = Infinity;
73
73
  target.min.z = Infinity;
74
74
  this.groups.forEach(group => {
75
- const positionIndexStart = group.start * 3;
76
- const positionIndexCount = (group.start + group.count) * 3;
77
- for (let index = positionIndexStart; index < positionIndexCount; index += 3) {
78
- const x = this.object3d.geometry.attributes.position.array[index];
79
- const y = this.object3d.geometry.attributes.position.array[index + 1];
80
- const z = this.object3d.geometry.attributes.position.array[index + 2];
75
+ const positionIndexStart = group.start * this.object3d.geometry.attributes.position.itemSize;
76
+ const positionIndexCount = (group.start + group.count) * this.object3d.geometry.attributes.position.itemSize;
77
+ for (let index = positionIndexStart; index < positionIndexCount; index++) {
78
+ const x = this.object3d.geometry.attributes.position.getX(index);
79
+ const y = this.object3d.geometry.attributes.position.getY(index);
80
+ const z = this.object3d.geometry.attributes.position.getZ(index);
81
81
  target.max.x = Math.max(x, target.max.x);
82
82
  target.max.y = Math.max(y, target.max.y);
83
83
  target.max.z = Math.max(z, target.max.z);
@@ -103,7 +103,6 @@ class C3DTFeature {
103
103
  console.warn(`[C3DTFeature]: No batch table found for tile ${this.tileId}.`);
104
104
  return null; // or return undefined;
105
105
  }
106
-
107
106
  this.#info = batchTable.getInfoById(this.batchId);
108
107
  return this.#info;
109
108
  }
@@ -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 || !((_options$source = options.source) !== null && _options$source !== void 0 && _options$source.crs) ? options.crs : options.source.crs);
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;
@@ -68,7 +68,6 @@ const CoordStars = {
68
68
  };
69
69
  };
70
70
  },
71
-
72
71
  // Return scene coordinate ({x,y,z}) of sun
73
72
  getSunPositionInScene(date, lat, lon) {
74
73
  const sun = CoordStars.getSunPosition()(date, lat, lon);
package/lib/Core/Label.js CHANGED
@@ -71,7 +71,6 @@ class Label extends THREE.Object3D {
71
71
  // TODO: add smooth transition for fade in/out
72
72
  }
73
73
  },
74
-
75
74
  get() {
76
75
  return _visible;
77
76
  }
@@ -88,7 +88,6 @@ class MainLoop extends EventDispatcher {
88
88
  this.scheduler = scheduler;
89
89
  this.gfxEngine = engine; // TODO: remove me
90
90
  }
91
-
92
91
  scheduleViewUpdate(view, forceRedraw) {
93
92
  this.#needsRedraw |= forceRedraw;
94
93
  if (this.renderingState !== RENDERING_SCHEDULED) {