itowns 2.45.1-next.0 → 2.45.1-next.1

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 (185) hide show
  1. package/dist/455.js +2 -0
  2. package/dist/455.js.map +1 -0
  3. package/dist/debug.js +3 -0
  4. package/dist/debug.js.LICENSE.txt +13 -0
  5. package/dist/debug.js.map +1 -0
  6. package/dist/itowns.js +3 -0
  7. package/dist/itowns.js.LICENSE.txt +5 -0
  8. package/dist/itowns.js.map +1 -0
  9. package/dist/itowns_lasparser.js +2 -0
  10. package/dist/itowns_lasparser.js.map +1 -0
  11. package/dist/itowns_lasworker.js +2 -0
  12. package/dist/itowns_lasworker.js.map +1 -0
  13. package/dist/itowns_potree2worker.js +2 -0
  14. package/dist/itowns_potree2worker.js.map +1 -0
  15. package/dist/itowns_widgets.js +2 -0
  16. package/dist/itowns_widgets.js.map +1 -0
  17. package/lib/Controls/FirstPersonControls.js +308 -0
  18. package/lib/Controls/FlyControls.js +175 -0
  19. package/lib/Controls/GlobeControls.js +1178 -0
  20. package/lib/Controls/PlanarControls.js +1025 -0
  21. package/lib/Controls/StateControl.js +432 -0
  22. package/lib/Controls/StreetControls.js +392 -0
  23. package/lib/Converter/Feature2Mesh.js +612 -0
  24. package/lib/Converter/Feature2Texture.js +174 -0
  25. package/lib/Converter/convertToTile.js +70 -0
  26. package/lib/Converter/textureConverter.js +43 -0
  27. package/lib/Core/3DTiles/C3DTBatchTable.js +131 -0
  28. package/lib/Core/3DTiles/C3DTBatchTableHierarchyExtension.js +96 -0
  29. package/lib/Core/3DTiles/C3DTBoundingVolume.js +156 -0
  30. package/lib/Core/3DTiles/C3DTExtensions.js +97 -0
  31. package/lib/Core/3DTiles/C3DTFeature.js +110 -0
  32. package/lib/Core/3DTiles/C3DTilesEnums.js +20 -0
  33. package/lib/Core/3DTiles/C3DTileset.js +99 -0
  34. package/lib/Core/3DTiles/utils/BinaryPropertyAccessor.js +100 -0
  35. package/lib/Core/AnimationPlayer.js +142 -0
  36. package/lib/Core/CopcNode.js +174 -0
  37. package/lib/Core/Deprecated/Undeprecator.js +74 -0
  38. package/lib/Core/EntwinePointTileNode.js +126 -0
  39. package/lib/Core/Feature.js +488 -0
  40. package/lib/Core/Geographic/GeoidGrid.js +108 -0
  41. package/lib/Core/Label.js +222 -0
  42. package/lib/Core/MainLoop.js +209 -0
  43. package/lib/Core/Picking.js +255 -0
  44. package/lib/Core/PointCloudNode.js +42 -0
  45. package/lib/Core/Potree2Node.js +206 -0
  46. package/lib/Core/Potree2PointAttributes.js +139 -0
  47. package/lib/Core/PotreeNode.js +101 -0
  48. package/lib/Core/Prefab/Globe/Atmosphere.js +293 -0
  49. package/lib/Core/Prefab/Globe/GlobeLayer.js +152 -0
  50. package/lib/Core/Prefab/Globe/GlobeTileBuilder.js +110 -0
  51. package/lib/Core/Prefab/Globe/SkyShader.js +78 -0
  52. package/lib/Core/Prefab/GlobeView.js +155 -0
  53. package/lib/Core/Prefab/Planar/PlanarLayer.js +59 -0
  54. package/lib/Core/Prefab/Planar/PlanarTileBuilder.js +71 -0
  55. package/lib/Core/Prefab/PlanarView.js +62 -0
  56. package/lib/Core/Prefab/TileBuilder.js +82 -0
  57. package/lib/Core/Prefab/computeBufferTileGeometry.js +248 -0
  58. package/lib/Core/Scheduler/Cache.js +17 -0
  59. package/lib/Core/Scheduler/CancelledCommandException.js +15 -0
  60. package/lib/Core/Scheduler/Scheduler.js +294 -0
  61. package/lib/Core/Style.js +660 -0
  62. package/lib/Core/StyleOptions.js +486 -0
  63. package/lib/Core/System/Capabilities.js +63 -0
  64. package/lib/Core/Tile/Tile.js +205 -0
  65. package/lib/Core/Tile/TileGrid.js +49 -0
  66. package/lib/Core/TileGeometry.js +124 -0
  67. package/lib/Core/TileMesh.js +108 -0
  68. package/lib/Core/View.js +1115 -0
  69. package/lib/Layer/C3DTilesLayer.js +459 -0
  70. package/lib/Layer/ColorLayer.js +154 -0
  71. package/lib/Layer/CopcLayer.js +63 -0
  72. package/lib/Layer/ElevationLayer.js +139 -0
  73. package/lib/Layer/EntwinePointTileLayer.js +71 -0
  74. package/lib/Layer/FeatureGeometryLayer.js +77 -0
  75. package/lib/Layer/GeoidLayer.js +80 -0
  76. package/lib/Layer/GeometryLayer.js +233 -0
  77. package/lib/Layer/InfoLayer.js +64 -0
  78. package/lib/Layer/LabelLayer.js +469 -0
  79. package/lib/Layer/Layer.js +335 -0
  80. package/lib/Layer/LayerUpdateState.js +89 -0
  81. package/lib/Layer/LayerUpdateStrategy.js +80 -0
  82. package/lib/Layer/OGC3DTilesLayer.js +543 -0
  83. package/lib/Layer/OrientedImageLayer.js +227 -0
  84. package/lib/Layer/PointCloudLayer.js +405 -0
  85. package/lib/Layer/Potree2Layer.js +171 -0
  86. package/lib/Layer/PotreeLayer.js +72 -0
  87. package/lib/Layer/RasterLayer.js +37 -0
  88. package/lib/Layer/ReferencingLayerProperties.js +62 -0
  89. package/lib/Layer/TiledGeometryLayer.js +459 -0
  90. package/lib/Loader/LASLoader.js +193 -0
  91. package/lib/Loader/Potree2BrotliLoader.js +261 -0
  92. package/lib/Loader/Potree2Loader.js +207 -0
  93. package/lib/Main.js +113 -0
  94. package/lib/MainBundle.js +4 -0
  95. package/lib/Parser/B3dmParser.js +174 -0
  96. package/lib/Parser/CameraCalibrationParser.js +94 -0
  97. package/lib/Parser/GDFParser.js +72 -0
  98. package/lib/Parser/GTXParser.js +75 -0
  99. package/lib/Parser/GeoJsonParser.js +212 -0
  100. package/lib/Parser/GpxParser.js +25 -0
  101. package/lib/Parser/ISGParser.js +71 -0
  102. package/lib/Parser/KMLParser.js +25 -0
  103. package/lib/Parser/LASParser.js +137 -0
  104. package/lib/Parser/MapBoxUrlParser.js +83 -0
  105. package/lib/Parser/PntsParser.js +131 -0
  106. package/lib/Parser/Potree2BinParser.js +92 -0
  107. package/lib/Parser/PotreeBinParser.js +106 -0
  108. package/lib/Parser/PotreeCinParser.js +29 -0
  109. package/lib/Parser/ShapefileParser.js +78 -0
  110. package/lib/Parser/VectorTileParser.js +215 -0
  111. package/lib/Parser/XbilParser.js +120 -0
  112. package/lib/Parser/deprecated/LegacyGLTFLoader.js +1386 -0
  113. package/lib/Parser/iGLTFLoader.js +168 -0
  114. package/lib/Process/3dTilesProcessing.js +304 -0
  115. package/lib/Process/FeatureProcessing.js +76 -0
  116. package/lib/Process/LayeredMaterialNodeProcessing.js +229 -0
  117. package/lib/Process/ObjectRemovalHelper.js +97 -0
  118. package/lib/Process/handlerNodeError.js +23 -0
  119. package/lib/Provider/3dTilesProvider.js +149 -0
  120. package/lib/Provider/DataSourceProvider.js +24 -0
  121. package/lib/Provider/Fetcher.js +233 -0
  122. package/lib/Provider/PointCloudProvider.js +45 -0
  123. package/lib/Provider/TileProvider.js +16 -0
  124. package/lib/Provider/URLBuilder.js +116 -0
  125. package/lib/Renderer/Camera.js +281 -0
  126. package/lib/Renderer/Color.js +56 -0
  127. package/lib/Renderer/ColorLayersOrdering.js +115 -0
  128. package/lib/Renderer/CommonMaterial.js +31 -0
  129. package/lib/Renderer/Label2DRenderer.js +192 -0
  130. package/lib/Renderer/LayeredMaterial.js +243 -0
  131. package/lib/Renderer/OBB.js +150 -0
  132. package/lib/Renderer/OrientedImageCamera.js +118 -0
  133. package/lib/Renderer/OrientedImageMaterial.js +167 -0
  134. package/lib/Renderer/PointsMaterial.js +485 -0
  135. package/lib/Renderer/RasterTile.js +243 -0
  136. package/lib/Renderer/RenderMode.js +31 -0
  137. package/lib/Renderer/Shader/ShaderChunk.js +160 -0
  138. package/lib/Renderer/Shader/ShaderUtils.js +47 -0
  139. package/lib/Renderer/SphereHelper.js +17 -0
  140. package/lib/Renderer/WebXR.js +51 -0
  141. package/lib/Renderer/c3DEngine.js +214 -0
  142. package/lib/Source/C3DTilesGoogleSource.js +74 -0
  143. package/lib/Source/C3DTilesIonSource.js +54 -0
  144. package/lib/Source/C3DTilesSource.js +30 -0
  145. package/lib/Source/CopcSource.js +126 -0
  146. package/lib/Source/EntwinePointTileSource.js +72 -0
  147. package/lib/Source/FileSource.js +188 -0
  148. package/lib/Source/OGC3DTilesGoogleSource.js +29 -0
  149. package/lib/Source/OGC3DTilesIonSource.js +34 -0
  150. package/lib/Source/OGC3DTilesSource.js +21 -0
  151. package/lib/Source/OrientedImageSource.js +59 -0
  152. package/lib/Source/Potree2Source.js +167 -0
  153. package/lib/Source/PotreeSource.js +82 -0
  154. package/lib/Source/Source.js +202 -0
  155. package/lib/Source/TMSSource.js +144 -0
  156. package/lib/Source/VectorTilesSource.js +182 -0
  157. package/lib/Source/WFSSource.js +170 -0
  158. package/lib/Source/WMSSource.js +167 -0
  159. package/lib/Source/WMTSSource.js +92 -0
  160. package/lib/ThreeExtended/capabilities/WebGL.js +69 -0
  161. package/lib/ThreeExtended/libs/ktx-parse.module.js +506 -0
  162. package/lib/ThreeExtended/libs/zstddec.module.js +29 -0
  163. package/lib/ThreeExtended/loaders/DDSLoader.js +200 -0
  164. package/lib/ThreeExtended/loaders/DRACOLoader.js +400 -0
  165. package/lib/ThreeExtended/loaders/GLTFLoader.js +2879 -0
  166. package/lib/ThreeExtended/loaders/KTX2Loader.js +709 -0
  167. package/lib/ThreeExtended/math/ColorSpaces.js +59 -0
  168. package/lib/ThreeExtended/utils/BufferGeometryUtils.js +846 -0
  169. package/lib/ThreeExtended/utils/WorkerPool.js +70 -0
  170. package/lib/Utils/CameraUtils.js +554 -0
  171. package/lib/Utils/DEMUtils.js +350 -0
  172. package/lib/Utils/FeaturesUtils.js +156 -0
  173. package/lib/Utils/Gradients.js +16 -0
  174. package/lib/Utils/ThreeUtils.js +115 -0
  175. package/lib/Utils/gui/C3DTilesStyle.js +218 -0
  176. package/lib/Utils/gui/Main.js +7 -0
  177. package/lib/Utils/gui/Minimap.js +152 -0
  178. package/lib/Utils/gui/Navigation.js +245 -0
  179. package/lib/Utils/gui/Scale.js +104 -0
  180. package/lib/Utils/gui/Searchbar.js +234 -0
  181. package/lib/Utils/gui/Widget.js +80 -0
  182. package/lib/Utils/placeObjectOnGround.js +136 -0
  183. package/lib/Worker/LASLoaderWorker.js +19 -0
  184. package/lib/Worker/Potree2Worker.js +21 -0
  185. package/package.json +2 -2
@@ -0,0 +1,233 @@
1
+ import { TextureLoader, DataTexture, RedFormat, FloatType } from 'three';
2
+ const TEXTURE_TILE_DIM = 256;
3
+ const TEXTURE_TILE_SIZE = TEXTURE_TILE_DIM * TEXTURE_TILE_DIM;
4
+ const textureLoader = new TextureLoader();
5
+ function checkResponse(response) {
6
+ if (!response.ok) {
7
+ const error = new Error(`Error loading ${response.url}: status ${response.status}`);
8
+ error.response = response;
9
+ throw error;
10
+ }
11
+ }
12
+ const arrayBuffer = function (url) {
13
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
14
+ return fetch(url, options).then(response => {
15
+ checkResponse(response);
16
+ return response.arrayBuffer();
17
+ });
18
+ };
19
+
20
+ /**
21
+ * Utilitary to fetch resources from a server using the [fetch API](
22
+ * https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch).
23
+ *
24
+ * @module Fetcher
25
+ */
26
+ export default {
27
+ /**
28
+ * Wrapper over fetch to get some text.
29
+ *
30
+ * @param {string} url - The URL of the resources to fetch.
31
+ * @param {Object} options - Fetch options (passed directly to `fetch()`),
32
+ * see [the syntax for more information](
33
+ * https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Syntax).
34
+ *
35
+ * @return {Promise<string>} Promise containing the text.
36
+ */
37
+ text(url) {
38
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
39
+ return fetch(url, options).then(response => {
40
+ checkResponse(response);
41
+ return response.text();
42
+ });
43
+ },
44
+ /**
45
+ * Little wrapper over fetch to get some JSON.
46
+ *
47
+ * @param {string} url - The URL of the resources to fetch.
48
+ * @param {Object} options - Fetch options (passed directly to `fetch()`),
49
+ * see [the syntax for more information](
50
+ * https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Syntax).
51
+ *
52
+ * @return {Promise<Object>} Promise containing the JSON object.
53
+ */
54
+ json(url) {
55
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
56
+ return fetch(url, options).then(response => {
57
+ checkResponse(response);
58
+ return response.json();
59
+ });
60
+ },
61
+ /**
62
+ * Wrapper over fetch to get some XML.
63
+ *
64
+ * @param {string} url - The URL of the resources to fetch.
65
+ * @param {Object} options - Fetch options (passed directly to `fetch()`),
66
+ * see [the syntax for more information](
67
+ * https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Syntax).
68
+ *
69
+ * @return {Promise<Document>} Promise containing the XML Document.
70
+ */
71
+ xml(url) {
72
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
73
+ return fetch(url, options).then(response => {
74
+ checkResponse(response);
75
+ return response.text();
76
+ }).then(text => new window.DOMParser().parseFromString(text, 'text/xml'));
77
+ },
78
+ /**
79
+ * Wrapper around [THREE.TextureLoader](https://threejs.org/docs/#api/en/loaders/TextureLoader).
80
+ *
81
+ * @param {string} url - The URL of the resources to fetch.
82
+ * @param {Object} options - Fetch options (passed directly to `fetch()`),
83
+ * see [the syntax for more information](
84
+ * https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Syntax).
85
+ * Note that THREE.js docs mentions `withCredentials`, but it is not
86
+ * actually used in [THREE.TextureLoader](https://threejs.org/docs/#api/en/loaders/TextureLoader).
87
+ *
88
+ * @return {Promise<THREE.Texture>} Promise containing the
89
+ * [THREE.Texture](https://threejs.org/docs/api/en/textures/Texture.html).
90
+ */
91
+ texture(url) {
92
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
93
+ let res;
94
+ let rej;
95
+ textureLoader.crossOrigin = options.crossOrigin;
96
+ const promise = new Promise((resolve, reject) => {
97
+ res = resolve;
98
+ rej = reject;
99
+ });
100
+ textureLoader.load(url, res, () => {}, event => {
101
+ const error = new Error(`Failed to load texture from URL: \`${url}\``);
102
+ error.originalEvent = event;
103
+ rej(error);
104
+ });
105
+ return promise;
106
+ },
107
+ /**
108
+ * Wrapper over fetch to get some ArrayBuffer.
109
+ *
110
+ * @param {string} url - The URL of the resources to fetch.
111
+ * @param {Object} options - Fetch options (passed directly to `fetch()`),
112
+ * see [the syntax for more information](
113
+ * https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Syntax).
114
+ *
115
+ * @return {Promise<ArrayBuffer>} Promise containing the ArrayBuffer.
116
+ */
117
+ arrayBuffer,
118
+ /**
119
+ * Wrapper over fetch to get some
120
+ * [THREE.DataTexture](https://threejs.org/docs/#api/en/textures/DataTexture).
121
+ *
122
+ * @param {string} url - The URL of the resources to fetch.
123
+ * @param {Object} options - Fetch options (passed directly to `fetch()`),
124
+ * see [the syntax for more information](
125
+ * https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Syntax).
126
+ *
127
+ * @return {Promise<THREE.DataTexture>} Promise containing the DataTexture.
128
+ */
129
+ textureFloat(url) {
130
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
131
+ return arrayBuffer(url, options).then(buffer => {
132
+ if (buffer.byteLength !== TEXTURE_TILE_SIZE * Float32Array.BYTES_PER_ELEMENT) {
133
+ throw new Error(`Invalid float data from URL: \`${url}\``);
134
+ }
135
+ const data = new Float32Array(buffer);
136
+ const texture = new DataTexture(data, TEXTURE_TILE_DIM, TEXTURE_TILE_DIM, RedFormat, FloatType);
137
+ texture.internalFormat = 'R32F';
138
+ texture.needsUpdate = true;
139
+ return texture;
140
+ });
141
+ },
142
+ /**
143
+ * Wrapper over fetch to get a bunch of files sharing the same name, but
144
+ * different extensions.
145
+ *
146
+ * @param {string} baseUrl - The shared URL of the resources to fetch.
147
+ * @param {Object} extensions - An object containing arrays. The keys of
148
+ * each of this array are available fetch type, such as `text`, `json` or
149
+ * even `arrayBuffer`. The arrays contains the extensions to append after
150
+ * the `baseUrl` (see example below).
151
+ * @param {Object} options - Fetch options (passed directly to `fetch()`),
152
+ * see [the syntax for more information](
153
+ * https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Syntax).
154
+ *
155
+ * @return {Promise[]} An array of promises, containing all the files,
156
+ * organized by their extensions (see the example below).
157
+ *
158
+ * @example
159
+ * itowns.Fetcher.multiple('http://geo.server/shapefile', {
160
+ * // will fetch:
161
+ * // - http://geo.server/shapefile.shp
162
+ * // - http://geo.server/shapefile.dbf
163
+ * // - http://geo.server/shapefile.shx
164
+ * // - http://geo.server/shapefile.prj
165
+ * arrayBuffer: ['shp', 'dbf', 'shx'],
166
+ * text: ['prj'],
167
+ * }).then(function _(result) {
168
+ * // result looks like:
169
+ * result = {
170
+ * shp: ArrayBuffer
171
+ * dbf: ArrayBuffer
172
+ * shx: ArrayBuffer
173
+ * prj: string
174
+ * };
175
+ * });
176
+ */
177
+ multiple(baseUrl, extensions) {
178
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
179
+ const promises = [];
180
+ let url;
181
+ for (const fetchType in extensions) {
182
+ if (!this[fetchType]) {
183
+ throw new Error(`${fetchType} is not a valid Fetcher method.`);
184
+ } else {
185
+ for (const extension of extensions[fetchType]) {
186
+ url = `${baseUrl}.${extension}`;
187
+ promises.push(this[fetchType](url, options).then(result => ({
188
+ type: extension,
189
+ result
190
+ })));
191
+ }
192
+ }
193
+ }
194
+ return Promise.all(promises).then(result => {
195
+ const all = {};
196
+ for (const res of result) {
197
+ all[res.type] = res.result;
198
+ }
199
+ return Promise.resolve(all);
200
+ });
201
+ },
202
+ get() {
203
+ let format = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
204
+ const [type, subtype] = format.split('/');
205
+ switch (type) {
206
+ case 'application':
207
+ switch (subtype) {
208
+ case 'geo+json':
209
+ case 'json':
210
+ return this.json;
211
+ case 'kml':
212
+ case 'gpx':
213
+ return this.xml;
214
+ case 'x-protobuf;type=mapbox-vector':
215
+ case 'gtx':
216
+ return this.arrayBuffer;
217
+ case 'isg':
218
+ case 'gdf':
219
+ default:
220
+ return this.text;
221
+ }
222
+ case 'image':
223
+ switch (subtype) {
224
+ case 'x-bil;bits=32':
225
+ return this.textureFloat;
226
+ default:
227
+ return this.texture;
228
+ }
229
+ default:
230
+ return this.texture;
231
+ }
232
+ }
233
+ };
@@ -0,0 +1,45 @@
1
+ import * as THREE from 'three';
2
+ import { Extent } from '@itowns/geographic';
3
+ let nextuuid = 1;
4
+ function addPickingAttribute(points) {
5
+ // generate unique id for picking
6
+ const numPoints = points.geometry.attributes.position.count;
7
+ const ids = new Uint8Array(4 * numPoints);
8
+ const baseId = nextuuid++;
9
+ if (numPoints > 0xffff || baseId > 0xffff) {
10
+ // TODO: fixme
11
+ console.warn('Currently picking is limited to Points with less than 65535 elements and less than 65535 Points instances');
12
+ return points;
13
+ }
14
+ for (let i = 0; i < numPoints; i++) {
15
+ // todo numpoints > 16bits
16
+ const v = baseId << 16 | i;
17
+ ids[4 * i + 0] = (v & 0xff000000) >> 24;
18
+ ids[4 * i + 1] = (v & 0x00ff0000) >> 16;
19
+ ids[4 * i + 2] = (v & 0x0000ff00) >> 8;
20
+ ids[4 * i + 3] = (v & 0x000000ff) >> 0;
21
+ }
22
+ points.baseId = baseId;
23
+ points.geometry.setAttribute('unique_id', new THREE.BufferAttribute(ids, 4, true));
24
+ return points;
25
+ }
26
+ export default {
27
+ executeCommand(command) {
28
+ const layer = command.layer;
29
+ const node = command.requester;
30
+ return node.load().then(geometry => {
31
+ const points = new THREE.Points(geometry, layer.material);
32
+ addPickingAttribute(points);
33
+ points.frustumCulled = false;
34
+ points.matrixAutoUpdate = false;
35
+ points.position.copy(geometry.userData.origin || node.bbox.min);
36
+ points.scale.copy(layer.scale);
37
+ points.updateMatrix();
38
+ points.tightbbox = geometry.boundingBox.applyMatrix4(points.matrix);
39
+ points.layer = layer;
40
+ points.extent = Extent.fromBox3(command.view.referenceCrs, node.bbox);
41
+ points.userData.node = node;
42
+ return points;
43
+ });
44
+ }
45
+ };
@@ -0,0 +1,16 @@
1
+ import CancelledCommandException from "../Core/Scheduler/CancelledCommandException.js";
2
+ export default {
3
+ executeCommand(command) {
4
+ const promises = [];
5
+ const layer = command.layer;
6
+ const requester = command.requester;
7
+ const extentsSource = command.extentsSource;
8
+ if (requester && !requester.material) {
9
+ return Promise.reject(new CancelledCommandException(command));
10
+ }
11
+ for (const extent of extentsSource) {
12
+ promises.push(layer.convert(requester, extent));
13
+ }
14
+ return Promise.all(promises);
15
+ }
16
+ };
@@ -0,0 +1,116 @@
1
+ let subDomainsCount = 0;
2
+
3
+ /**
4
+ * @param {string} url
5
+ * @returns {string}
6
+ */
7
+ function subDomains(url) {
8
+ const subDomainsPtrn = /\$\{u:([\w-_.|]+)\}/.exec(url);
9
+ if (!subDomainsPtrn) {
10
+ return url;
11
+ }
12
+ const subDomainsList = subDomainsPtrn[1].split('|');
13
+ return url.replace(subDomainsPtrn[0], subDomainsList[subDomainsCount++ % subDomainsList.length]);
14
+ }
15
+
16
+ /**
17
+ * This module performs basic operations around urls, to replace some elements
18
+ * in it by coordinates or other things.
19
+ *
20
+ * In an url, it is also possible to specify subdomains alternatives using the
21
+ * `${u:a|b|c}` pattern, by separating differents options using `|`. It will go
22
+ * through the following alternative each time (no random). For example
23
+ * `https://${u:xyz.org|yzx.org|zxy.org}/${z}/${x}/${y}.png` or
24
+ * `https://${u:a|b|c}.tile.openstreetmap.org/${z}/${x}/${y}.png`.
25
+ *
26
+ * @module URLBuilder
27
+ */
28
+ export default {
29
+ subDomains,
30
+ /**
31
+ * Builds an URL knowing the coordinates and the source to query.
32
+ * <br><br>
33
+ * The source object needs to have an url property, which should have some
34
+ * specific strings that will be replaced by coordinates.
35
+ * <ul>
36
+ * <li>`${x}` or `%COL` will be replaced by `coords.col`</li>
37
+ * <li>`${y}` or `%ROW` will be replaced by `coords.row`</li>
38
+ * <li>`${z}` or `%TILEMATRIX` will be replaced by `coords.zoom`</li>
39
+ * </ul>
40
+ *
41
+ * @example
42
+ * coords = new Extent(CRS.formatToTms('EPSG:4326'), 12, 1410, 2072);
43
+ * source.url = 'http://server.geo/wmts/SERVICE=WMTS&TILEMATRIX=%TILEMATRIX&TILEROW=%ROW&TILECOL=%COL';
44
+ * url = URLBuilder.xyz(coords, source);
45
+ *
46
+ * // The resulting url is:
47
+ * // http://server.geo/wmts/SERVICE=WMTS&TILEMATRIX=12&TILEROW=1410&TILECOL=2072;
48
+ *
49
+ * @example
50
+ * coords = new Extent('TMS', 15, 2142, 3412);
51
+ * source.url = 'http://server.geo/tms/${z}/${y}/${x}.jpg';
52
+ * url = URLBuilder.xyz(coords, source);
53
+ *
54
+ * // The resulting url is:
55
+ * // http://server.geo/tms/15/2142/3412.jpg;
56
+ *
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
64
+ *
65
+ * @return {string} the formed url
66
+ */
67
+ xyz: function (coords, source) {
68
+ return subDomains(source.url.replace(/(\$\{z\}|%TILEMATRIX)/, source.tileMatrixCallback(coords.zoom)).replace(/(\$\{y\}|%ROW)/, coords.row).replace(/(\$\{x\}|%COL)/, coords.col));
69
+ },
70
+ /**
71
+ * Builds an URL knowing the bounding box and the source to query.
72
+ * <br><br>
73
+ * The source object needs to have an url property, which should have the
74
+ * string `%bbox` in it. This string will be replaced by the four cardinal
75
+ * points composing the bounding box.
76
+ * <br><br>
77
+ * Order of the points can be specified in the `axisOrder` property in
78
+ * source, using the letters `w, s, e, n` respectively for `WEST, SOUTH,
79
+ * EAST, NORTH`. The default order is `wsen`.
80
+ *
81
+ * @example
82
+ * extent = new Extent('EPSG:4326', 12, 14, 35, 46);
83
+ * source.crs = 'EPSG:4326';
84
+ * source.url = 'http://server.geo/wms/BBOX=%bbox&FORMAT=jpg&SERVICE=WMS';
85
+ * url = URLBuilder.bbox(extent, source);
86
+ *
87
+ * // The resulting url is:
88
+ * // http://server.geo/wms/BBOX=12,35,14,46&FORMAT=jpg&SERVICE=WMS
89
+ *
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
96
+ * @param {string} source.crs
97
+ * @param {number} source.bboxDigits
98
+ * @param {string} source.url
99
+ * @param {string} source.axisOrder
100
+ *
101
+ * @return {string} the formed url
102
+ */
103
+ bbox: function (bbox, source) {
104
+ let precision = source.crs == 'EPSG:4326' ? 9 : 2;
105
+ if (source.bboxDigits !== undefined) {
106
+ precision = source.bboxDigits;
107
+ }
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);
112
+ let bboxInUnit = source.axisOrder || 'wsen';
113
+ bboxInUnit = bboxInUnit.replace('w', `${w},`).replace('s', `${s},`).replace('e', `${e},`).replace('n', `${n},`).slice(0, -1);
114
+ return subDomains(source.url.replace('%bbox', bboxInUnit));
115
+ }
116
+ };
@@ -0,0 +1,281 @@
1
+ import * as THREE from 'three';
2
+ import { Coordinates } from '@itowns/geographic';
3
+ import DEMUtils from "../Utils/DEMUtils.js";
4
+
5
+ /**
6
+ * @typedef {object} Camera~CAMERA_TYPE
7
+ * Stores the different types of camera usable in iTowns.
8
+ *
9
+ * @property {number} PERSPECTIVE Perspective type of camera
10
+ * @property {number} ORTHOGRAPHIC Orthographic type of camera
11
+ */
12
+ export const CAMERA_TYPE = {
13
+ PERSPECTIVE: 0,
14
+ ORTHOGRAPHIC: 1
15
+ };
16
+ const tmp = {
17
+ frustum: new THREE.Frustum(),
18
+ matrix: new THREE.Matrix4(),
19
+ box3: new THREE.Box3()
20
+ };
21
+ const ndcBox3 = new THREE.Box3(new THREE.Vector3(-1, -1, -1), new THREE.Vector3(1, 1, 1));
22
+ function updatePreSse(camera, height, fov) {
23
+ // sse = projected geometric error on screen plane from distance
24
+ // We're using an approximation, assuming that the geometric error of all
25
+ // objects is perpendicular to the camera view vector (= we always compute
26
+ // for worst case).
27
+ //
28
+ // screen plane object
29
+ // | __
30
+ // | / \
31
+ // | geometric{|
32
+ // < fov angle . } sse error {| |
33
+ // | \__/
34
+ // |
35
+ // |<--------------------->
36
+ // | distance
37
+ //
38
+ // geometric_error * screen_width (resp. screen_height)
39
+ // = ---------------------------------------
40
+ // 2 * distance * tan (horizontal_fov / 2) (resp. vertical_fov)
41
+ //
42
+ //
43
+ // We pre-compute the preSSE (= constant part of the screen space error formula) once here
44
+
45
+ // Note: the preSSE for the horizontal FOV is the same value
46
+ // focal = (this.height * 0.5) / Math.tan(verticalFOV * 0.5);
47
+ // horizontalFOV = 2 * Math.atan(this.width * 0.5 / focal);
48
+ // horizontalPreSSE = this.width / (2.0 * Math.tan(horizontalFOV * 0.5)); (1)
49
+ // => replacing horizontalFOV in Math.tan(horizontalFOV * 0.5)
50
+ // Math.tan(horizontalFOV * 0.5) = Math.tan(2 * Math.atan(this.width * 0.5 / focal) * 0.5)
51
+ // = Math.tan(Math.atan(this.width * 0.5 / focal))
52
+ // = this.width * 0.5 / focal
53
+ // => now replacing focal
54
+ // = this.width * 0.5 / (this.height * 0.5) / Math.tan(verticalFOV * 0.5)
55
+ // = Math.tan(verticalFOV * 0.5) * this.width / this.height
56
+ // => back to (1)
57
+ // horizontalPreSSE = this.width / (2.0 * Math.tan(verticalFOV * 0.5) * this.width / this.height)
58
+ // = this.height / 2.0 * Math.tan(verticalFOV * 0.5)
59
+ // = verticalPreSSE
60
+
61
+ if (camera.camera3D.isOrthographicCamera) {
62
+ camera._preSSE = height;
63
+ } else {
64
+ const verticalFOV = THREE.MathUtils.degToRad(fov);
65
+ camera._preSSE = height / (2.0 * Math.tan(verticalFOV * 0.5));
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Wrapper around Three.js camera to expose some geographic helpers.
71
+ *
72
+ * @property {string} crs The camera's coordinate projection system.
73
+ * @property {THREE.Camera} camera3D The Three.js camera that is wrapped around.
74
+ * @property {number} width The width of the camera.
75
+ * @property {number} height The height of the camera.
76
+ * @property {number} _preSSE The precomputed constant part of the screen space error.
77
+ */
78
+ class Camera {
79
+ #_viewMatrixNeedsUpdate = true;
80
+ #_viewMatrix = (() => new THREE.Matrix4())();
81
+
82
+ /**
83
+ * @param {string} crs The camera's coordinate projection system.
84
+ * @param {number} width The width (in pixels) of the view the
85
+ * camera is associated to.
86
+ * @param {number} height The height (in pixels) of the view the
87
+ * camera is associated to.
88
+ * @param {Object} [options] Options for the camera.
89
+ * @param {THREE.Camera} [options.cameraThree] A custom Three.js camera object to wrap
90
+ * around.
91
+ * @param {Camera~CAMERA_TYPE} [options.type=CAMERA_TYPE.PERSPECTIVE] The type of the camera. See {@link
92
+ * CAMERA_TYPE}.
93
+ * @constructor
94
+ */
95
+ constructor(crs, width, height) {
96
+ let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
97
+ this.crs = crs;
98
+ if (options.isCamera) {
99
+ console.warn('options.camera parameter is deprecated. Use options.camera.cameraThree to place a custom ' + 'camera as a parameter. See the documentation of Camera.');
100
+ this.camera3D = options;
101
+ } else if (options.cameraThree) {
102
+ this.camera3D = options.cameraThree;
103
+ } else {
104
+ switch (options.type) {
105
+ case CAMERA_TYPE.ORTHOGRAPHIC:
106
+ this.camera3D = new THREE.OrthographicCamera();
107
+ break;
108
+ case CAMERA_TYPE.PERSPECTIVE:
109
+ default:
110
+ this.camera3D = new THREE.PerspectiveCamera(30);
111
+ break;
112
+ }
113
+ }
114
+ this.camera3D.aspect = this.camera3D.aspect ?? 1;
115
+ this.width = width;
116
+ this.height = height;
117
+ this.resize(width, height);
118
+ this._preSSE = Infinity;
119
+ if (this.camera3D.isPerspectiveCamera) {
120
+ let fov = this.camera3D.fov;
121
+ Object.defineProperty(this.camera3D, 'fov', {
122
+ get: () => fov,
123
+ set: newFov => {
124
+ fov = newFov;
125
+ updatePreSse(this, this.height, fov);
126
+ }
127
+ });
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Resize the camera to a given width and height.
133
+ *
134
+ * @param {number} width The width to resize the camera to. Must be strictly positive, won't resize otherwise.
135
+ * @param {number} height The height to resize the camera to. Must be strictly positive, won't resize otherwise.
136
+ */
137
+ resize(width, height) {
138
+ if (!width || width <= 0 || !height || height <= 0) {
139
+ console.warn(`Trying to resize the Camera with invalid height (${height}) or width (${width}). Skipping resize.`);
140
+ return;
141
+ }
142
+ const ratio = width / height;
143
+ if (this.camera3D.aspect !== ratio) {
144
+ if (this.camera3D.isOrthographicCamera) {
145
+ this.camera3D.zoom *= this.width / width;
146
+ const halfH = this.camera3D.top * this.camera3D.aspect / ratio;
147
+ this.camera3D.bottom = -halfH;
148
+ this.camera3D.top = halfH;
149
+ } else if (this.camera3D.isPerspectiveCamera) {
150
+ this.camera3D.fov = 2 * THREE.MathUtils.radToDeg(Math.atan(height / this.height * Math.tan(THREE.MathUtils.degToRad(this.camera3D.fov) / 2)));
151
+ }
152
+ this.camera3D.aspect = ratio;
153
+ }
154
+ this.width = width;
155
+ this.height = height;
156
+ updatePreSse(this, this.height, this.camera3D.fov);
157
+ if (this.camera3D.updateProjectionMatrix) {
158
+ this.camera3D.updateProjectionMatrix();
159
+ this.#_viewMatrixNeedsUpdate = true;
160
+ }
161
+ }
162
+ update() {
163
+ // update matrix
164
+ this.camera3D.updateMatrixWorld();
165
+ this.#_viewMatrixNeedsUpdate = true;
166
+ }
167
+
168
+ /**
169
+ * Return the position in the requested CRS, or in camera's CRS if undefined.
170
+ *
171
+ * @param {string} [crs] If defined (e.g 'EPSG:4326'), the camera position will be returned in this CRS.
172
+ *
173
+ * @return {Coordinates} Coordinates object holding camera's position.
174
+ */
175
+ position(crs) {
176
+ return new Coordinates(this.crs).setFromVector3(this.camera3D.position).as(crs || this.crs);
177
+ }
178
+
179
+ /**
180
+ * Set the position of the camera using a Coordinates object.
181
+ * If you want to modify the position directly using x,y,z values then use `camera.camera3D.position.set(x, y, z)`
182
+ *
183
+ * @param {Coordinates} position The new position of the camera.
184
+ */
185
+ setPosition(position) {
186
+ this.camera3D.position.copy(position.as(this.crs));
187
+ }
188
+ isBox3Visible(box3, matrixWorld) {
189
+ return this.box3SizeOnScreen(box3, matrixWorld).intersectsBox(ndcBox3);
190
+ }
191
+ isSphereVisible(sphere, matrixWorld) {
192
+ if (this.#_viewMatrixNeedsUpdate) {
193
+ // update visibility testing matrix
194
+ this.#_viewMatrix.multiplyMatrices(this.camera3D.projectionMatrix, this.camera3D.matrixWorldInverse);
195
+ this.#_viewMatrixNeedsUpdate = false;
196
+ }
197
+ if (matrixWorld) {
198
+ tmp.matrix.multiplyMatrices(this.#_viewMatrix, matrixWorld);
199
+ tmp.frustum.setFromProjectionMatrix(tmp.matrix);
200
+ } else {
201
+ tmp.frustum.setFromProjectionMatrix(this.#_viewMatrix);
202
+ }
203
+ return tmp.frustum.intersectsSphere(sphere);
204
+ }
205
+ box3SizeOnScreen(box3, matrixWorld) {
206
+ const pts = projectBox3PointsInCameraSpace(this, box3, matrixWorld);
207
+
208
+ // All points are in front of the near plane -> box3 is invisible
209
+ if (!pts) {
210
+ return tmp.box3.makeEmpty();
211
+ }
212
+
213
+ // Project points on screen
214
+ for (let i = 0; i < 8; i++) {
215
+ pts[i].applyMatrix4(this.camera3D.projectionMatrix);
216
+ }
217
+ return tmp.box3.setFromPoints(pts);
218
+ }
219
+
220
+ /**
221
+ * Test for collision between camera and a geometry layer (DTM/DSM) to adjust camera position.
222
+ * It could be modified later to handle an array of geometry layers.
223
+ * TODO Improve Coordinates class to handle altitude for any coordinate system (even projected one)
224
+ *
225
+ * @param {View} view The view where we test the collision between geometry layers
226
+ * and the camera
227
+ * @param {ElevationLayer} elevationLayer The elevation layer (DTM/DSM) used to test the collision
228
+ * with the camera. Could be another geometry layer.
229
+ * @param {number} minDistanceCollision The minimum distance allowed between the camera and the
230
+ * surface.
231
+ */
232
+ adjustAltitudeToAvoidCollisionWithLayer(view, elevationLayer, minDistanceCollision) {
233
+ // We put the camera location in geographic by default to easily handle altitude.
234
+ // (Should be improved in Coordinates class for all ref)
235
+ const camLocation = view.camera.position().as('EPSG:4326');
236
+ if (elevationLayer !== undefined) {
237
+ const elevationUnderCamera = DEMUtils.getElevationValueAt(elevationLayer, camLocation);
238
+ if (elevationUnderCamera !== undefined) {
239
+ const difElevation = camLocation.altitude - (elevationUnderCamera + minDistanceCollision);
240
+ // We move the camera to avoid collision if too close to terrain
241
+ if (difElevation < 0) {
242
+ camLocation.altitude = elevationUnderCamera + minDistanceCollision;
243
+ view.camera3D.position.copy(camLocation.as(view.referenceCrs));
244
+ view.notifyChange(this.camera3D);
245
+ }
246
+ }
247
+ }
248
+ }
249
+ }
250
+ const points = [new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3()];
251
+ function projectBox3PointsInCameraSpace(camera, box3, matrixWorld) {
252
+ // Projects points in camera space
253
+ // We don't project directly on screen to avoid artifacts when projecting
254
+ // points behind the near plane.
255
+ let m = camera.camera3D.matrixWorldInverse;
256
+ if (matrixWorld) {
257
+ m = tmp.matrix.multiplyMatrices(camera.camera3D.matrixWorldInverse, matrixWorld);
258
+ }
259
+ points[0].set(box3.min.x, box3.min.y, box3.min.z).applyMatrix4(m);
260
+ points[1].set(box3.min.x, box3.min.y, box3.max.z).applyMatrix4(m);
261
+ points[2].set(box3.min.x, box3.max.y, box3.min.z).applyMatrix4(m);
262
+ points[3].set(box3.min.x, box3.max.y, box3.max.z).applyMatrix4(m);
263
+ points[4].set(box3.max.x, box3.min.y, box3.min.z).applyMatrix4(m);
264
+ points[5].set(box3.max.x, box3.min.y, box3.max.z).applyMatrix4(m);
265
+ points[6].set(box3.max.x, box3.max.y, box3.min.z).applyMatrix4(m);
266
+ points[7].set(box3.max.x, box3.max.y, box3.max.z).applyMatrix4(m);
267
+
268
+ // In camera space objects are along the -Z axis
269
+ // So if min.z is > -near, the object is invisible
270
+ let atLeastOneInFrontOfNearPlane = false;
271
+ for (let i = 0; i < 8; i++) {
272
+ if (points[i].z <= -camera.camera3D.near) {
273
+ atLeastOneInFrontOfNearPlane = true;
274
+ } else {
275
+ // Clamp to near plane
276
+ points[i].z = -camera.camera3D.near;
277
+ }
278
+ }
279
+ return atLeastOneInFrontOfNearPlane ? points : undefined;
280
+ }
281
+ export default Camera;