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,350 @@
1
+ import * as THREE from 'three';
2
+ import { Coordinates } from '@itowns/geographic';
3
+ import placeObjectOnGround from "./placeObjectOnGround.js";
4
+ const FAST_READ_Z = 0;
5
+ const PRECISE_READ_Z = 1;
6
+
7
+ /**
8
+ * Utility module to retrieve elevation at a given coordinates. The returned
9
+ * value is read in the elevation textures used by the graphics card to render
10
+ * the tiles (globe or plane). This implies that the return value may change
11
+ * depending on the current tile resolution.
12
+ *
13
+ * @module DEMUtils
14
+ */
15
+ export default {
16
+ /**
17
+ * Gives the elevation value of a {@link TiledGeometryLayer}, at a specific
18
+ * {@link Coordinates}.
19
+ *
20
+ * @param {TiledGeometryLayer} layer - The tile layer owning the elevation
21
+ * textures we're going to query. This is typically a `GlobeLayer` or
22
+ * `PlanarLayer` (accessible through `view.tileLayer`).
23
+ * @param {Coordinates} coord - The coordinates that we're interested in.
24
+ * @param {number} [method=FAST_READ_Z] - There are two available methods:
25
+ * `FAST_READ_Z` (default) or `PRECISE_READ_Z`. The first one is faster,
26
+ * while the second one is slower but gives better precision.
27
+ * @param {TileMesh[]} [tileHint] - Optional array of tiles to speed up the
28
+ * process. You can give candidates tiles likely to contain `coord`.
29
+ * Otherwise the lookup process starts from the root of `layer`.
30
+ *
31
+ * @return {number} If found, a value in meters is returned; otherwise
32
+ * `undefined`.
33
+ */
34
+ getElevationValueAt(layer, coord) {
35
+ let method = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : FAST_READ_Z;
36
+ let tileHint = arguments.length > 3 ? arguments[3] : undefined;
37
+ const result = _readZ(layer, method, coord, tileHint || layer.level0Nodes);
38
+ if (result) {
39
+ return result.coord.z;
40
+ }
41
+ },
42
+ /**
43
+ * @typedef Terrain
44
+ * @type {Object}
45
+ *
46
+ * @property {Coordinates} coord - Pick coordinate with the elevation in coord.z.
47
+ * @property {THREE.Texture} texture - the picked elevation texture.
48
+ * The texture where the `z` value has been read from
49
+ * @property {TileMesh} tile - the picked tile and the tile containing the texture
50
+ */
51
+ /**
52
+ * Gives a {@link Terrain} object, at a specific {@link Coordinates}. The returned
53
+ * object is as follow:
54
+ * - `coord`, Coordinate, coord.z is the value in meters of the elevation at the coordinates
55
+ * - `texture`, the texture where the `z` value has been read from
56
+ * - `tile`, the tile containing the texture
57
+ * @example
58
+ * // place mesh on the ground
59
+ * const coord = new Coordinates('EPSG:4326', 6, 45);
60
+ * const result = DEMUtils.getTerrainObjectAt(view.tileLayer, coord)
61
+ * mesh.position.copy(result.coord.as(view.referenceCrs));
62
+ * view.scene.add(mesh);
63
+ * mesh.updateMatrixWorld();
64
+ *
65
+ *
66
+ * @param {TiledGeometryLayer} layer - The tile layer owning the elevation
67
+ * textures we're going to query. This is typically a `GlobeLayer` or
68
+ * `PlanarLayer` (accessible through `view.tileLayer`).
69
+ * @param {Coordinates} coord - The coordinates that we're interested in.
70
+ * @param {number} [method=FAST_READ_Z] - There are two available methods:
71
+ * `FAST_READ_Z` (default) or `PRECISE_READ_Z`. The first one is faster,
72
+ * while the second one is slower but gives better precision.
73
+ * @param {TileMesh[]} [tileHint] - Optional array of tiles to speed up the
74
+ * process. You can give candidates tiles likely to contain `coord`.
75
+ * Otherwise the lookup process starts from the root of `layer`.
76
+ * @param {Object} [cache] - Object to cache previous result and speed up the next `getTerrainObjectAt`` use.
77
+ *
78
+ * @return {Terrain} - The {@link Terrain} object.
79
+ */
80
+ getTerrainObjectAt(layer, coord) {
81
+ let method = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : FAST_READ_Z;
82
+ let tileHint = arguments.length > 3 ? arguments[3] : undefined;
83
+ let cache = arguments.length > 4 ? arguments[4] : undefined;
84
+ return _readZ(layer, method, coord, tileHint || layer.level0Nodes, cache);
85
+ },
86
+ FAST_READ_Z,
87
+ PRECISE_READ_Z,
88
+ placeObjectOnGround
89
+ };
90
+ function tileAt(pt, tile) {
91
+ if (tile.extent) {
92
+ if (!tile.extent.isPointInside(pt)) {
93
+ return undefined;
94
+ }
95
+ for (let i = 0; i < tile.children.length; i++) {
96
+ const t = tileAt(pt, tile.children[i]);
97
+ if (t) {
98
+ return t;
99
+ }
100
+ }
101
+ const tileLayer = tile.material.getElevationLayer();
102
+ if (tileLayer && tileLayer.level >= 0) {
103
+ return tile;
104
+ }
105
+ return undefined;
106
+ }
107
+ }
108
+ let _canvas;
109
+ function _readTextureValueAt(metadata, texture) {
110
+ for (var _len = arguments.length, uv = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
111
+ uv[_key - 2] = arguments[_key];
112
+ }
113
+ for (let i = 0; i < uv.length; i += 2) {
114
+ uv[i] = THREE.MathUtils.clamp(uv[i], 0, texture.image.width - 1);
115
+ uv[i + 1] = THREE.MathUtils.clamp(uv[i + 1], 0, texture.image.height - 1);
116
+ }
117
+ if (texture.image.data) {
118
+ // read a single value
119
+ if (uv.length === 2) {
120
+ const v = texture.image.data[uv[1] * texture.image.width + uv[0]];
121
+ return v != metadata.noDataValue ? v : undefined;
122
+ }
123
+ // or read multiple values
124
+ const result = [];
125
+ for (let i = 0; i < uv.length; i += 2) {
126
+ const v = texture.image.data[uv[i + 1] * texture.image.width + uv[i]];
127
+ result.push(v != metadata.noDataValue ? v : undefined);
128
+ }
129
+ return result;
130
+ } else {
131
+ if (!_canvas) {
132
+ _canvas = document.createElement('canvas');
133
+ _canvas.width = 2;
134
+ _canvas.height = 2;
135
+ }
136
+ let minx = Infinity;
137
+ let miny = Infinity;
138
+ let maxx = -Infinity;
139
+ let maxy = -Infinity;
140
+ for (let i = 0; i < uv.length; i += 2) {
141
+ minx = Math.min(uv[i], minx);
142
+ miny = Math.min(uv[i + 1], miny);
143
+ maxx = Math.max(uv[i], maxx);
144
+ maxy = Math.max(uv[i + 1], maxy);
145
+ }
146
+ const dw = maxx - minx + 1;
147
+ const dh = maxy - miny + 1;
148
+ _canvas.width = Math.max(_canvas.width, dw);
149
+ _canvas.height = Math.max(_canvas.height, dh);
150
+ const ctx = _canvas.getContext('2d', {
151
+ willReadFrequently: true
152
+ });
153
+ ctx.drawImage(texture.image, minx, miny, dw, dh, 0, 0, dw, dh);
154
+ const d = ctx.getImageData(0, 0, dw, dh);
155
+ const result = [];
156
+ for (let i = 0; i < uv.length; i += 2) {
157
+ const ox = uv[i] - minx;
158
+ const oy = uv[i + 1] - miny;
159
+
160
+ // d is 4 bytes per pixel
161
+ const v = THREE.MathUtils.lerp(metadata.colorTextureElevationMinZ, metadata.colorTextureElevationMaxZ, d.data[4 * oy * dw + 4 * ox] / 255);
162
+ result.push(v != metadata.noDataValue ? v : undefined);
163
+ }
164
+ if (uv.length === 2) {
165
+ return result[0];
166
+ } else {
167
+ return result;
168
+ }
169
+ }
170
+ }
171
+ function _convertUVtoTextureCoords(texture, u, v) {
172
+ const width = texture.image.width;
173
+ const height = texture.image.height;
174
+ const up = Math.max(0, u * width - 0.5);
175
+ const vp = Math.max(0, v * height - 0.5);
176
+ const u1 = Math.floor(up);
177
+ const u2 = Math.ceil(up);
178
+ const v1 = Math.floor(vp);
179
+ const v2 = Math.ceil(vp);
180
+ return {
181
+ u1,
182
+ u2,
183
+ v1,
184
+ v2,
185
+ wu: up - u1,
186
+ wv: vp - v1
187
+ };
188
+ }
189
+ function _readTextureValueNearestFiltering(metadata, texture, vertexU, vertexV) {
190
+ const coords = _convertUVtoTextureCoords(texture, vertexU, vertexV);
191
+ const u = coords.wu <= 0 ? coords.u1 : coords.u2;
192
+ const v = coords.wv <= 0 ? coords.v1 : coords.v2;
193
+ return _readTextureValueAt(metadata, texture, u, v);
194
+ }
195
+ function _lerpWithUndefinedCheck(x, y, t) {
196
+ if (x == undefined) {
197
+ return y;
198
+ } else if (y == undefined) {
199
+ return x;
200
+ } else {
201
+ return THREE.MathUtils.lerp(x, y, t);
202
+ }
203
+ }
204
+ export function readTextureValueWithBilinearFiltering(metadata, texture, vertexU, vertexV) {
205
+ const coords = _convertUVtoTextureCoords(texture, vertexU, vertexV);
206
+ const [z11, z21, z12, z22] = _readTextureValueAt(metadata, texture, coords.u1, coords.v1, coords.u2, coords.v1, coords.u1, coords.v2, coords.u2, coords.v2);
207
+
208
+ // horizontal filtering
209
+ const zu1 = _lerpWithUndefinedCheck(z11, z21, coords.wu);
210
+ const zu2 = _lerpWithUndefinedCheck(z12, z22, coords.wu);
211
+ // then vertical filtering
212
+ return _lerpWithUndefinedCheck(zu1, zu2, coords.wv);
213
+ }
214
+ function _readZFast(layer, texture, uv) {
215
+ const elevationLayer = layer.attachedLayers.filter(l => l.isElevationLayer)[0];
216
+ return _readTextureValueNearestFiltering(elevationLayer, texture, uv.x, uv.y);
217
+ }
218
+ const bary = new THREE.Vector3();
219
+ function _readZCorrect(layer, texture, uv, tileDimensions, tileOwnerDimensions) {
220
+ // We need to emulate the vertex shader code that does 2 thing:
221
+ // - interpolate (u, v) between triangle vertices: u,v will be multiple of 1/nsegments
222
+ // (for now assume nsegments == 16)
223
+ // - read elevation texture at (u, v) for
224
+
225
+ // Determine u,v based on the vertices count.
226
+ // 'modulo' is the gap (in [0, 1]) between 2 successive vertices in the geometry
227
+ // e.g if you have 5 vertices, the only possible values for u (or v) are: 0, 0.25, 0.5, 0.75, 1
228
+ // so modulo would be 0.25
229
+ // note: currently the number of segments is hard-coded to 16 (see TileProvider) => 17 vertices
230
+ const modulo = tileDimensions.x / tileOwnerDimensions.x / (17 - 1);
231
+ let u = Math.floor(uv.x / modulo) * modulo;
232
+ let v = Math.floor(uv.y / modulo) * modulo;
233
+ if (u == 1) {
234
+ u -= modulo;
235
+ }
236
+ if (v == 1) {
237
+ v -= modulo;
238
+ }
239
+
240
+ // Build 4 vertices, 3 of them will be our triangle:
241
+ // 11---21
242
+ // | / |
243
+ // | / |
244
+ // | / |
245
+ // 21---22
246
+ const u1 = u;
247
+ const u2 = u + modulo;
248
+ const v1 = v;
249
+ const v2 = v + modulo;
250
+
251
+ // Our multiple z-value will be weigh-blended, depending on the distance of the real point
252
+ // so lu (resp. lv) are the weight. When lu -> 0 (resp. 1) the final value -> z at u1 (resp. u2)
253
+ const lu = (uv.x - u) / modulo;
254
+ const lv = (uv.y - v) / modulo;
255
+
256
+ // Determine if we're going to read the vertices from the top-left or lower-right triangle
257
+ // (low-right = on the line 21-22 or under the diagonal lu = 1 - lv)
258
+
259
+ const tri = new THREE.Triangle(new THREE.Vector3(u1, v2), new THREE.Vector3(u2, v1), lv == 1 || lu / (1 - lv) >= 1 ? new THREE.Vector3(u2, v2) : new THREE.Vector3(u1, v1));
260
+
261
+ // bary holds the respective weight of each vertices of the triangles
262
+ tri.getBarycoord(new THREE.Vector3(uv.x, uv.y), bary);
263
+ const elevationLayer = layer.attachedLayers.filter(l => l.isElevationLayer)[0];
264
+
265
+ // read the 3 interesting values
266
+ const z1 = readTextureValueWithBilinearFiltering(elevationLayer, texture, tri.a.x, tri.a.y);
267
+ const z2 = readTextureValueWithBilinearFiltering(elevationLayer, texture, tri.b.x, tri.b.y);
268
+ const z3 = readTextureValueWithBilinearFiltering(elevationLayer, texture, tri.c.x, tri.c.y);
269
+
270
+ // Blend with bary
271
+ return z1 * bary.x + z2 * bary.y + z3 * bary.z;
272
+ }
273
+ const temp = {
274
+ v: new THREE.Vector3(),
275
+ coord1: new Coordinates('EPSG:4978'),
276
+ coord2: new Coordinates('EPSG:4978'),
277
+ offset: new THREE.Vector2()
278
+ };
279
+ const dimension = new THREE.Vector2();
280
+ function offsetInExtent(point, extent) {
281
+ let target = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : new THREE.Vector2();
282
+ if (point.crs != extent.crs) {
283
+ throw new Error(`Unsupported mix: ${point.crs} and ${extent.crs}`);
284
+ }
285
+ extent.planarDimensions(dimension);
286
+ const originX = (point.x - extent.west) / dimension.x;
287
+ const originY = (extent.north - point.y) / dimension.y;
288
+ return target.set(originX, originY);
289
+ }
290
+ function _readZ(layer, method, coord, nodes, cache) {
291
+ const pt = coord.as(layer.extent.crs, temp.coord1);
292
+ let tileWithValidElevationTexture = null;
293
+ // first check in cache
294
+ if (cache?.tile?.material) {
295
+ tileWithValidElevationTexture = tileAt(pt, cache.tile);
296
+ }
297
+ for (let i = 0; !tileWithValidElevationTexture && i < nodes.length; i++) {
298
+ tileWithValidElevationTexture = tileAt(pt, nodes[i]);
299
+ }
300
+ if (!tileWithValidElevationTexture) {
301
+ // failed to find a tile, abort
302
+ return;
303
+ }
304
+ const tile = tileWithValidElevationTexture;
305
+ const tileLayer = tile.material.getElevationLayer();
306
+ const src = tileLayer.textures[0];
307
+
308
+ // check cache value if existing
309
+ if (cache) {
310
+ if (cache.id === src.id && cache.version === src.version) {
311
+ return {
312
+ coord: pt,
313
+ texture: src,
314
+ tile
315
+ };
316
+ }
317
+ }
318
+
319
+ // Assuming that tiles are split in 4 children, we lookup the parent that
320
+ // really owns this texture
321
+ const stepsUpInHierarchy = Math.round(Math.log2(1.0 / tileLayer.offsetScales[0].z));
322
+ for (let i = 0; i < stepsUpInHierarchy; i++) {
323
+ tileWithValidElevationTexture = tileWithValidElevationTexture.parent;
324
+ }
325
+
326
+ // offset = offset from top-left
327
+ offsetInExtent(pt, tileWithValidElevationTexture.extent, temp.offset);
328
+
329
+ // At this point we have:
330
+ // - tileWithValidElevationTexture.texture.image which is the current image
331
+ // used for rendering
332
+ // - offset which is the offset in this texture for the coordinate we're
333
+ // interested in
334
+ // We now have 2 options:
335
+ // - the fast one: read the value of tileWithValidElevationTexture.texture.image
336
+ // at (offset.x, offset.y) and we're done
337
+ // - the correct one: emulate the vertex shader code
338
+ if (method == PRECISE_READ_Z) {
339
+ pt.z = _readZCorrect(layer, src, temp.offset, tile.extent.planarDimensions(), tileWithValidElevationTexture.extent.planarDimensions());
340
+ } else {
341
+ pt.z = _readZFast(layer, src, temp.offset);
342
+ }
343
+ if (pt.z != undefined) {
344
+ return {
345
+ coord: pt,
346
+ texture: src,
347
+ tile
348
+ };
349
+ }
350
+ }
@@ -0,0 +1,156 @@
1
+ import { FEATURE_TYPES } from "../Core/Feature.js";
2
+ import { Coordinates } from '@itowns/geographic';
3
+ function pointIsOverLine(point, linePoints, epsilon, offset, count, size) {
4
+ const x0 = point.x;
5
+ const y0 = point.y;
6
+ // for each segment of the line (j is i -1)
7
+ for (let i = offset + size, j = offset; i < offset + count; j = i, i += size) {
8
+ /* **********************************************************
9
+ norm : norm of vector P1P2
10
+ distance : distance point P0 to line P1P2
11
+ scalar : dot product of P1P0 and P1P2 divide by norm, it represents the projection of P0 on the line
12
+ Point is over segment P1P2 if :
13
+ * if the distance, , is inferior to epsilon
14
+ * and if : -epsilon ≤ scalar ≤ (||P1P2|| + epsilon)
15
+ + (P0) _
16
+ | |
17
+ | |
18
+ <---scalar---->| distance
19
+ | |
20
+ | v
21
+ +-------------------------------+
22
+ (P1) (P2)
23
+ *********************************************************** */
24
+
25
+ const x1 = linePoints[i];
26
+ const y1 = linePoints[i + 1];
27
+ const x2 = linePoints[j];
28
+ const y2 = linePoints[j + 1];
29
+ const x21 = x2 - x1;
30
+ const y21 = y2 - y1;
31
+ const norm = Math.sqrt(x21 * x21 + y21 * y21);
32
+ const scalar = ((x0 - x1) * x21 + (y0 - y1) * y21) / norm;
33
+ if (scalar >= -epsilon && scalar <= norm + epsilon) {
34
+ const distance = Math.abs(y21 * x0 - x21 * y0 + x2 * y1 - y2 * x1) / norm;
35
+ if (distance <= epsilon) {
36
+ return true;
37
+ }
38
+ }
39
+ }
40
+ return false;
41
+ }
42
+ function getClosestPoint(point, points, epsilon, offset, count, size) {
43
+ const x0 = point.x;
44
+ const y0 = point.y;
45
+ let squaredEpsilon = epsilon * epsilon;
46
+ let closestPoint;
47
+ for (let i = offset; i < offset + count; i += size) {
48
+ const x1 = points[i];
49
+ const y1 = points[i + 1];
50
+ const xP = x0 - x1;
51
+ const yP = y0 - y1;
52
+ const n = xP * xP + yP * yP;
53
+ if (n < squaredEpsilon) {
54
+ closestPoint = [points[i], points[i + 1]];
55
+ squaredEpsilon = n;
56
+ }
57
+ }
58
+ return closestPoint;
59
+ }
60
+ function pointIsInsidePolygon(point, polygonPoints, epsilon, offset, count, size) {
61
+ // ray-casting algorithm based on
62
+ // http://wrf.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
63
+
64
+ const x = point.x;
65
+ const y = point.y;
66
+ let inside = false;
67
+ // in first j is last point of polygon
68
+ // for each segment of the polygon (j is i -1)
69
+ for (let i = offset, j = offset + count - size; i < offset + count; j = i, i += size) {
70
+ const xi = polygonPoints[i];
71
+ const yi = polygonPoints[i + 1];
72
+ const xj = polygonPoints[j];
73
+ const yj = polygonPoints[j + 1];
74
+ if (pointIsOverLine(point, [xi, yi, xj, yj], epsilon, 0, 4, 2)) {
75
+ return true;
76
+ }
77
+
78
+ // isIntersect semi-infinite ray horizontally with polygon's edge
79
+
80
+ if (yi > y != yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi) {
81
+ inside = !inside;
82
+ }
83
+ }
84
+ return inside;
85
+ }
86
+ function isFeatureSingleGeometryUnderCoordinate(coordinate, type, coordinates, epsilon, offset, count, size) {
87
+ if (type == FEATURE_TYPES.LINE && pointIsOverLine(coordinate, coordinates, epsilon, offset, count, size)) {
88
+ return true;
89
+ } else if (type == FEATURE_TYPES.POLYGON && pointIsInsidePolygon(coordinate, coordinates, epsilon, offset, count, size)) {
90
+ return true;
91
+ } else if (type == FEATURE_TYPES.POINT) {
92
+ const closestPoint = getClosestPoint(coordinate, coordinates, epsilon, offset, count, size);
93
+ if (closestPoint) {
94
+ return {
95
+ coordinates: closestPoint
96
+ };
97
+ }
98
+ }
99
+ }
100
+ function isFeatureUnderCoordinate(coordinate, feature, epsilon, result) {
101
+ const featCoord = coordinate.as(feature.crs);
102
+ for (const geometry of feature.geometries) {
103
+ if (geometry.extent == undefined || geometry.extent.isPointInside(featCoord, epsilon)) {
104
+ const offset = geometry.indices[0].offset * feature.size;
105
+ const count = geometry.indices[0].count * feature.size;
106
+ const under = isFeatureSingleGeometryUnderCoordinate(featCoord, feature.type, feature.vertices, epsilon, offset, count, feature.size);
107
+ if (under) {
108
+ result.push({
109
+ type: feature.type,
110
+ geometry,
111
+ coordinates: under.coordinates /* || coordinates */,
112
+ style: feature.style
113
+ });
114
+ }
115
+ }
116
+ }
117
+ }
118
+ const coord = new Coordinates('EPSG:4326', 0, 0, 0);
119
+ export default {
120
+ /**
121
+ * Filter from a list of features, features that are under a coordinate.
122
+ *
123
+ * @param {Coordinates} coordinate - The coordinate for the filter
124
+ * condition.
125
+ * @param {Feature|FeatureCollection} collection - A single feature or a
126
+ * collection of them, to filter given the previous coordinate.
127
+ * @param {number} [epsilon=0.1] Tolerance around the coordinate (in
128
+ * coordinate's unit).
129
+ *
130
+ * @return {Feature[]} Array of filtered features.
131
+ */
132
+ filterFeaturesUnderCoordinate(coordinate, collection) {
133
+ let epsilon = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0.1;
134
+ const result = [];
135
+
136
+ // transform coordinates to collection system projection
137
+ coordinate.as(collection.crs, coord);
138
+
139
+ // transform coordinates to local system
140
+ coord.applyMatrix4(collection.matrixWorldInverse);
141
+ if (collection.extent.isPointInside(coord, epsilon)) {
142
+ if (collection.isFeatureCollection) {
143
+ epsilon *= Math.sqrt(collection.scale.x ** 2 + collection.scale.y ** 2);
144
+ for (const feature of collection.features) {
145
+ if (feature.extent && !feature.extent.isPointInside(coord, epsilon)) {
146
+ continue;
147
+ }
148
+ isFeatureUnderCoordinate(coord, feature, epsilon, result);
149
+ }
150
+ } else if (collection.geometries) {
151
+ isFeatureUnderCoordinate(coord, collection, epsilon, result);
152
+ }
153
+ }
154
+ return result;
155
+ }
156
+ };
@@ -0,0 +1,16 @@
1
+ import * as THREE from 'three';
2
+ export default {
3
+ // From chroma spectral http://gka.github.io/chroma.js/
4
+ SPECTRAL: [[0, new THREE.Color(0.3686, 0.3098, 0.6353)], [0.1, new THREE.Color(0.1961, 0.5333, 0.7412)], [0.2, new THREE.Color(0.4000, 0.7608, 0.6471)], [0.3, new THREE.Color(0.6706, 0.8667, 0.6431)], [0.4, new THREE.Color(0.9020, 0.9608, 0.5961)], [0.5, new THREE.Color(1.0000, 1.0000, 0.7490)], [0.6, new THREE.Color(0.9961, 0.8784, 0.5451)], [0.7, new THREE.Color(0.9922, 0.6824, 0.3804)], [0.8, new THREE.Color(0.9569, 0.4275, 0.2627)], [0.9, new THREE.Color(0.8353, 0.2431, 0.3098)], [1, new THREE.Color(0.6196, 0.0039, 0.2588)]],
5
+ PLASMA: [[0.0, new THREE.Color(0.241, 0.015, 0.610)], [0.1, new THREE.Color(0.387, 0.001, 0.654)], [0.2, new THREE.Color(0.524, 0.025, 0.653)], [0.3, new THREE.Color(0.651, 0.125, 0.596)], [0.4, new THREE.Color(0.752, 0.227, 0.513)], [0.5, new THREE.Color(0.837, 0.329, 0.431)], [0.6, new THREE.Color(0.907, 0.435, 0.353)], [0.7, new THREE.Color(0.963, 0.554, 0.272)], [0.8, new THREE.Color(0.992, 0.681, 0.195)], [0.9, new THREE.Color(0.987, 0.822, 0.144)], [1.0, new THREE.Color(0.940, 0.975, 0.131)]],
6
+ YELLOW_GREEN: [[0, new THREE.Color(0.1647, 0.2824, 0.3451)], [0.1, new THREE.Color(0.1338, 0.3555, 0.4227)], [0.2, new THREE.Color(0.0610, 0.4319, 0.4864)], [0.3, new THREE.Color(0.0000, 0.5099, 0.5319)], [0.4, new THREE.Color(0.0000, 0.5881, 0.5569)], [0.5, new THREE.Color(0.1370, 0.6650, 0.5614)], [0.6, new THREE.Color(0.2906, 0.7395, 0.5477)], [0.7, new THREE.Color(0.4453, 0.8099, 0.5201)], [0.8, new THREE.Color(0.6102, 0.8748, 0.4850)], [0.9, new THREE.Color(0.7883, 0.9323, 0.4514)], [1, new THREE.Color(0.9804, 0.9804, 0.4314)]],
7
+ VIRIDIS: [[0.0, new THREE.Color(0.267, 0.005, 0.329)], [0.1, new THREE.Color(0.283, 0.141, 0.458)], [0.2, new THREE.Color(0.254, 0.265, 0.530)], [0.3, new THREE.Color(0.207, 0.372, 0.553)], [0.4, new THREE.Color(0.164, 0.471, 0.558)], [0.5, new THREE.Color(0.128, 0.567, 0.551)], [0.6, new THREE.Color(0.135, 0.659, 0.518)], [0.7, new THREE.Color(0.267, 0.749, 0.441)], [0.8, new THREE.Color(0.478, 0.821, 0.318)], [0.9, new THREE.Color(0.741, 0.873, 0.150)], [1.0, new THREE.Color(0.993, 0.906, 0.144)]],
8
+ INFERNO: [[0.0, new THREE.Color(0.077, 0.042, 0.206)], [0.1, new THREE.Color(0.225, 0.036, 0.388)], [0.2, new THREE.Color(0.373, 0.074, 0.432)], [0.3, new THREE.Color(0.522, 0.128, 0.420)], [0.4, new THREE.Color(0.665, 0.182, 0.370)], [0.5, new THREE.Color(0.797, 0.255, 0.287)], [0.6, new THREE.Color(0.902, 0.364, 0.184)], [0.7, new THREE.Color(0.969, 0.516, 0.063)], [0.8, new THREE.Color(0.988, 0.683, 0.072)], [0.9, new THREE.Color(0.961, 0.859, 0.298)], [1.0, new THREE.Color(0.988, 0.998, 0.645)]],
9
+ GRAYSCALE: [[0, new THREE.Color(0, 0, 0)], [1, new THREE.Color(1, 1, 1)]],
10
+ // 16 samples of the TURBU color scheme
11
+ // values taken from: https://gist.github.com/mikhailov-work/ee72ba4191942acecc03fe6da94fc73f
12
+ // original file licensed under Apache-2.0
13
+ TURBO: [[0.00, new THREE.Color(0.18995, 0.07176, 0.23217)], [0.07, new THREE.Color(0.25107, 0.25237, 0.63374)], [0.13, new THREE.Color(0.27628, 0.42118, 0.89123)], [0.20, new THREE.Color(0.25862, 0.57958, 0.99876)], [0.27, new THREE.Color(0.15844, 0.73551, 0.92305)], [0.33, new THREE.Color(0.09267, 0.86554, 0.7623)], [0.40, new THREE.Color(0.19659, 0.94901, 0.59466)], [0.47, new THREE.Color(0.42778, 0.99419, 0.38575)], [0.53, new THREE.Color(0.64362, 0.98999, 0.23356)], [0.60, new THREE.Color(0.80473, 0.92452, 0.20459)], [0.67, new THREE.Color(0.93301, 0.81236, 0.22667)], [0.73, new THREE.Color(0.99314, 0.67408, 0.20348)], [0.80, new THREE.Color(0.9836, 0.49291, 0.12849)], [0.87, new THREE.Color(0.92105, 0.31489, 0.05475)], [0.93, new THREE.Color(0.81608, 0.18462, 0.01809)], [1.00, new THREE.Color(0.66449, 0.08436, 0.00424)]],
14
+ RAINBOW: [[0, new THREE.Color(0.278, 0, 0.714)], [1 / 6, new THREE.Color(0, 0, 1)], [2 / 6, new THREE.Color(0, 1, 1)], [3 / 6, new THREE.Color(0, 1, 0)], [4 / 6, new THREE.Color(1, 1, 0)], [5 / 6, new THREE.Color(1, 0.64, 0)], [1, new THREE.Color(1, 0, 0)]],
15
+ CONTOUR: [[0.00, new THREE.Color(0, 0, 0)], [0.03, new THREE.Color(0, 0, 0)], [0.04, new THREE.Color(1, 1, 1)], [1.00, new THREE.Color(1, 1, 1)]]
16
+ };
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Find threejs textures from a material
3
+ * @param {Material} material the threejs material holding textures
4
+ * @returns {Array} an array of textures in the material
5
+ */
6
+ function findTextures(material) {
7
+ const textures = [];
8
+ if (material.alphaMap) {
9
+ textures.push(material.map);
10
+ }
11
+ if (material.aoMap) {
12
+ textures.push(material.map);
13
+ }
14
+ if (material.bumpMap) {
15
+ textures.push(material.bumpMap);
16
+ }
17
+ if (material.displacementMap) {
18
+ textures.push(material.bumpMap);
19
+ }
20
+ if (material.emissiveMap) {
21
+ textures.push(material.emissiveMap);
22
+ }
23
+ if (material.envMap) {
24
+ textures.push(material.envMap);
25
+ }
26
+ if (material.lightMap) {
27
+ textures.push(material.envMap);
28
+ }
29
+ if (material.map) {
30
+ textures.push(material.map);
31
+ }
32
+ if (material.metalnessMap) {
33
+ textures.push(material.map);
34
+ }
35
+ if (material.normalMap) {
36
+ textures.push(material.map);
37
+ }
38
+ if (material.roughnessMap) {
39
+ textures.push(material.map);
40
+ }
41
+ if (material.specularMap) {
42
+ textures.push(material.specularMap);
43
+ }
44
+ return textures;
45
+ }
46
+
47
+ /**
48
+ * Removes a material and its textures, memory will be freed.
49
+ * IMPORTANT NOTE: the material and the texture must not be referenced by other threejs objects, otherwise the memory
50
+ * won't be freed.
51
+ * @param {Material} material the material to remove
52
+ */
53
+ export default function disposeThreeMaterial(material) {
54
+ const textures = findTextures(material);
55
+ // Remove material
56
+ if (Array.isArray(material)) {
57
+ for (const m of material) {
58
+ m.dispose();
59
+ }
60
+ } else {
61
+ material.dispose();
62
+ }
63
+ // Remove textures
64
+ for (let i = 0; i < textures.length; i++) {
65
+ textures[i].dispose();
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Merge groups of an object3D when it can to reduce number of them + remove unused materials
71
+ * Reduce draw call https://threejs.org/docs/index.html?q=geometry#api/en/core/BufferGeometry.groups
72
+ *
73
+ * @param {THREE.Object3D} object3D - object to get optimize
74
+ */
75
+ export function optimizeGeometryGroups(object3D) {
76
+ if (!object3D.geometry) {
77
+ return;
78
+ }
79
+ object3D.geometry.groups.sort((a, b) => (a.start - b.start) * -1); // [5,10,7] => [10,7,5]
80
+ const lastIndex = object3D.geometry.groups.length - 1;
81
+ let currentMaterialIndex = object3D.geometry.groups[lastIndex].materialIndex; // initialized with the lastest group
82
+ const usedIndexMaterials = [currentMaterialIndex]; // compute materials actually used by group
83
+ // for loop descendant to be able to splice in loop without modifying group index
84
+ for (let index = lastIndex - 1; index >= 0; index--) {
85
+ // begin at lastIndex - 1 because intialized with lastIndex
86
+ const group = object3D.geometry.groups[index];
87
+ if (group.materialIndex !== currentMaterialIndex) {
88
+ // this is another group (!= materialIndex) take its material as ref to continue
89
+ currentMaterialIndex = group.materialIndex;
90
+ usedIndexMaterials.push(currentMaterialIndex);
91
+ continue;
92
+ } else {
93
+ // indeed same group merge with previous group
94
+ const previousGroup = object3D.geometry.groups[index + 1];
95
+ previousGroup.count += group.count; // previous group wrap the current one
96
+ object3D.geometry.groups.splice(index, 1); // remove group
97
+ }
98
+ }
99
+
100
+ // clean unused material
101
+ for (let index = object3D.material.length - 1; index >= 0; index--) {
102
+ if (!usedIndexMaterials.includes(index)) {
103
+ // update all materialIndex in groups
104
+ object3D.geometry.groups.forEach(group => {
105
+ if (group.materialIndex > index) {
106
+ // only materialIndex > at index are modified
107
+ group.materialIndex -= 1;
108
+ }
109
+ });
110
+
111
+ // remove
112
+ object3D.material.splice(index, 1);
113
+ }
114
+ }
115
+ }