itowns 2.43.2-next.0 → 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.
Files changed (67) hide show
  1. package/README.md +2 -0
  2. package/dist/debug.js +1 -1
  3. package/dist/debug.js.map +1 -1
  4. package/dist/itowns.js +1 -1
  5. package/dist/itowns.js.map +1 -1
  6. package/dist/itowns_widgets.js +1 -1
  7. package/dist/itowns_widgets.js.map +1 -1
  8. package/examples/3dtiles_25d.html +1 -1
  9. package/examples/3dtiles_basic.html +2 -2
  10. package/examples/3dtiles_batch_table.html +1 -3
  11. package/examples/3dtiles_pointcloud.html +9 -15
  12. package/examples/config.json +2 -1
  13. package/examples/copc_simple_loader.html +128 -0
  14. package/examples/entwine_3d_loader.html +1 -1
  15. package/examples/entwine_simple_loader.html +1 -1
  16. package/examples/js/plugins/COGParser.js +84 -50
  17. package/examples/js/plugins/COGSource.js +7 -4
  18. package/examples/layers/JSONLayers/OPENSM.json +1 -1
  19. package/examples/potree_25d_map.html +1 -1
  20. package/examples/potree_3d_map.html +1 -1
  21. package/examples/source_file_cog.html +22 -5
  22. package/lib/Controls/FirstPersonControls.js +0 -1
  23. package/lib/Controls/FlyControls.js +0 -1
  24. package/lib/Converter/Feature2Mesh.js +2 -4
  25. package/lib/Converter/textureConverter.js +1 -1
  26. package/lib/Core/3DTiles/C3DTBatchTable.js +1 -1
  27. package/lib/Core/3DTiles/C3DTFeature.js +0 -1
  28. package/lib/Core/CopcNode.js +174 -0
  29. package/lib/Core/Feature.js +1 -2
  30. package/lib/Core/Geographic/CoordStars.js +0 -1
  31. package/lib/Core/Label.js +0 -1
  32. package/lib/Core/MainLoop.js +0 -1
  33. package/lib/Core/Prefab/Globe/Atmosphere.js +0 -4
  34. package/lib/Core/Prefab/Globe/GlobeLayer.js +3 -3
  35. package/lib/Core/Style.js +2 -4
  36. package/lib/Core/View.js +2 -4
  37. package/lib/Layer/C3DTilesLayer.js +3 -1
  38. package/lib/Layer/CopcLayer.js +59 -0
  39. package/lib/Layer/ElevationLayer.js +2 -3
  40. package/lib/Layer/GeoidLayer.js +1 -2
  41. package/lib/Layer/LabelLayer.js +8 -17
  42. package/lib/Layer/Layer.js +4 -2
  43. package/lib/Layer/PointCloudLayer.js +4 -7
  44. package/lib/Layer/ReferencingLayerProperties.js +3 -3
  45. package/lib/Layer/TiledGeometryLayer.js +2 -3
  46. package/lib/Main.js +2 -0
  47. package/lib/Parser/GeoJsonParser.js +2 -3
  48. package/lib/Parser/LASLoader.js +45 -1
  49. package/lib/Parser/LASParser.js +57 -25
  50. package/lib/Parser/deprecated/LegacyGLTFLoader.js +1 -2
  51. package/lib/Process/FeatureProcessing.js +1 -2
  52. package/lib/Process/LayeredMaterialNodeProcessing.js +3 -9
  53. package/lib/Process/ObjectRemovalHelper.js +1 -2
  54. package/lib/Provider/3dTilesProvider.js +1 -0
  55. package/lib/Renderer/ColorLayersOrdering.js +1 -2
  56. package/lib/Renderer/Label2DRenderer.js +1 -4
  57. package/lib/Renderer/PointsMaterial.js +14 -9
  58. package/lib/Renderer/RenderMode.js +0 -1
  59. package/lib/Source/CopcSource.js +118 -0
  60. package/lib/Source/Source.js +3 -1
  61. package/lib/ThreeExtended/loaders/DDSLoader.js +11 -1
  62. package/lib/ThreeExtended/loaders/DRACOLoader.js +0 -1
  63. package/lib/ThreeExtended/loaders/GLTFLoader.js +1 -0
  64. package/lib/Utils/DEMUtils.js +2 -2
  65. package/lib/Utils/OrientationUtils.js +0 -1
  66. package/lib/Utils/gui/Searchbar.js +1 -2
  67. package/package.json +8 -7
@@ -0,0 +1,128 @@
1
+ <html>
2
+ <head>
3
+ <meta charset="UTF-8">
4
+
5
+ <title>Itowns - COPC loader</title>
6
+
7
+ <link rel="stylesheet" type="text/css" href="css/example.css">
8
+ <link rel="stylesheet" type="text/css" href="css/LoadingScreen.css">
9
+
10
+ <style>
11
+ #description {
12
+ z-index: 2;
13
+ left: 10px;
14
+ }
15
+ </style>
16
+
17
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
18
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script>
19
+ </head>
20
+ <body>
21
+ <div id="description">Specify the URL of a COPC file to load:
22
+ <input type="text" id="url" />
23
+ <button onclick="readURL()">Load</button>
24
+ <div>
25
+ <button onClick="loadAutzen()">Load Autzen Stadium (80mb)</button>
26
+ <button onClick="loadSofi()">Load SoFI Stadium (2.3gb)</button>
27
+ <button onClick="loadMillsite()">Load Millsite (1.9gb)</button>
28
+ <div id="share"></div>
29
+ </div>
30
+ </div>
31
+ <div id="viewerDiv"></div>
32
+
33
+ <script src="../dist/itowns.js"></script>
34
+ <script src="js/GUI/LoadingScreen.js"></script>
35
+ <script src="../dist/debug.js"></script>
36
+ <script type="text/javascript">
37
+ let layer; // COPCLayer
38
+
39
+ const uri = new URL(location);
40
+
41
+ const gui = new dat.GUI();
42
+
43
+ const viewerDiv = document.getElementById('viewerDiv');
44
+ const view = new itowns.View('EPSG:4326', viewerDiv);
45
+ const controls = new itowns.PlanarControls(view);
46
+ view.mainLoop.gfxEngine.renderer.setClearColor(0xdddddd);
47
+
48
+ setUrl(uri.searchParams.get('copc'));
49
+
50
+ function onLayerReady(layer) {
51
+ const camera = view.camera.camera3D;
52
+
53
+ const lookAt = new itowns.THREE.Vector3();
54
+ const size = new itowns.THREE.Vector3();
55
+ layer.root.bbox.getSize(size);
56
+ layer.root.bbox.getCenter(lookAt);
57
+
58
+ camera.far = 2.0 * size.length();
59
+
60
+ controls.groundLevel = layer.root.bbox.min.z;
61
+ const position = layer.root.bbox.min.clone().add(
62
+ size.multiply({ x: 1, y: 1, z: size.x / size.z }),
63
+ );
64
+
65
+ camera.position.copy(position);
66
+ camera.lookAt(lookAt);
67
+ camera.updateProjectionMatrix();
68
+
69
+ view.notifyChange(camera);
70
+ }
71
+
72
+
73
+ function readURL() {
74
+ const url = document.getElementById('url').value;
75
+
76
+ if (url) {
77
+ setUrl(url);
78
+ }
79
+ }
80
+
81
+ function setUrl(url) {
82
+ if (!url) return;
83
+
84
+ const input_url = document.getElementById('url');
85
+ if (!input_url) return;
86
+
87
+ uri.searchParams.set('copc', url);
88
+ history.replaceState(null, null, `?${uri.searchParams.toString()}`);
89
+
90
+ input_url.value = url;
91
+ load(url);
92
+ }
93
+
94
+
95
+ function load(url) {
96
+ const source = new itowns.CopcSource({ url });
97
+
98
+ if (layer) {
99
+ gui.removeFolder(layer.debugUI);
100
+ view.removeLayer('COPC');
101
+ view.notifyChange();
102
+ layer.delete();
103
+ }
104
+
105
+ layer = new itowns.CopcLayer('COPC', {
106
+ source,
107
+ crs: view.referenceCrs,
108
+ sseThreshold: 2,
109
+ pointBudget: 3000000,
110
+ });
111
+ view.addLayer(layer).then(onLayerReady);
112
+ debug.PointCloudDebug.initTools(view, layer, gui);
113
+ }
114
+
115
+ function loadAutzen() {
116
+ setUrl("https://s3.amazonaws.com/hobu-lidar/autzen-classified.copc.laz");
117
+ }
118
+
119
+ function loadSofi() {
120
+ setUrl("https://s3.amazonaws.com/hobu-lidar/sofi.copc.laz");
121
+ }
122
+
123
+ function loadMillsite() {
124
+ setUrl("https://s3.amazonaws.com/data.entwine.io/millsite.copc.laz");
125
+ }
126
+ </script>
127
+ </body>
128
+ </html>
@@ -98,7 +98,7 @@
98
98
 
99
99
  itowns.View.prototype.addLayer.call(view, eptLayer).then(onLayerReady);
100
100
 
101
- debug.PotreeDebug.initTools(view, eptLayer, debugGui);
101
+ debug.PointCloudDebug.initTools(view, eptLayer, debugGui);
102
102
  }
103
103
 
104
104
  readEPTURL();
@@ -104,7 +104,7 @@
104
104
  view.addLayer(eptLayer).then(onLayerReady);
105
105
 
106
106
  eptLayer.whenReady
107
- .then(() => debug.PotreeDebug.initTools(view, eptLayer, debugGui));
107
+ .then(() => debug.PointCloudDebug.initTools(view, eptLayer, debugGui));
108
108
 
109
109
  function dblClickHandler(event) {
110
110
  var pick = view.pickObjectsAt(event, 5, eptLayer);
@@ -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/"
@@ -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');
@@ -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
  }