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,174 @@
1
+ import * as THREE from 'three';
2
+ import { FEATURE_TYPES } from "../Core/Feature.js";
3
+ import { Extent, Coordinates } from '@itowns/geographic';
4
+ import Style, { StyleContext } from "../Core/Style.js";
5
+ const defaultStyle = new Style();
6
+ const context = new StyleContext();
7
+ let style;
8
+
9
+ /**
10
+ * Draw polygon (contour, line edge and fill) based on feature vertices into canvas
11
+ * using the given style(s). Several styles will re-draws the polygon each one with
12
+ * a different style.
13
+ * @param {CanvasRenderingContext2D} ctx - canvas' 2D rendering context.
14
+ * @param {Number[]} vertices - All the vertices of the Feature.
15
+ * @param {Object[]} indices - Contains the indices that define the geometry.
16
+ * Objects stored in this array have two properties, an `offset` and a `count`.
17
+ * The offset is related to the overall number of vertices in the Feature.
18
+ * @param {Number} size - The size of the feature.
19
+ * @param {Number} extent - The extent.
20
+ * @param {Number} invCtxScale - The ration to scale line width and radius circle.
21
+ * @param {Boolean} canBeFilled - true if feature.type == FEATURE_TYPES.POLYGON
22
+ */
23
+ function drawPolygon(ctx, vertices) {
24
+ let indices = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [{
25
+ offset: 0,
26
+ count: 1
27
+ }];
28
+ let size = arguments.length > 3 ? arguments[3] : undefined;
29
+ let extent = arguments.length > 4 ? arguments[4] : undefined;
30
+ let invCtxScale = arguments.length > 5 ? arguments[5] : undefined;
31
+ let canBeFilled = arguments.length > 6 ? arguments[6] : undefined;
32
+ if (vertices.length === 0) {
33
+ return;
34
+ }
35
+ // build contour
36
+ const path = new Path2D();
37
+ for (const indice of indices) {
38
+ if (indice.extent && Extent.intersectsExtent(indice.extent, extent)) {
39
+ const offset = indice.offset * size;
40
+ const count = offset + indice.count * size;
41
+ path.moveTo(vertices[offset], vertices[offset + 1]);
42
+ for (let j = offset + size; j < count; j += size) {
43
+ path.lineTo(vertices[j], vertices[j + 1]);
44
+ }
45
+ }
46
+ }
47
+ style.applyToCanvasPolygon(ctx, path, invCtxScale, canBeFilled);
48
+ }
49
+ function drawPoint(ctx, x, y, invCtxScale) {
50
+ ctx.beginPath();
51
+ const opacity = style.point.opacity == undefined ? 1.0 : style.point.opacity;
52
+ if (opacity !== ctx.globalAlpha) {
53
+ ctx.globalAlpha = opacity;
54
+ }
55
+ ctx.arc(x, y, (style.point.radius || 3.0) * invCtxScale, 0, 2 * Math.PI, false);
56
+ if (style.point.color) {
57
+ ctx.fillStyle = style.point.color;
58
+ ctx.fill();
59
+ }
60
+ if (style.point.line) {
61
+ ctx.lineWidth = (style.point.width || 1.0) * invCtxScale;
62
+ ctx.strokeStyle = style.point.line;
63
+ ctx.stroke();
64
+ }
65
+ }
66
+ const coord = new Coordinates('EPSG:4326', 0, 0, 0);
67
+ function drawFeature(ctx, feature, extent, invCtxScale) {
68
+ const extentDim = extent.planarDimensions();
69
+ const scaleRadius = extentDim.x / ctx.canvas.width;
70
+ for (const geometry of feature.geometries) {
71
+ if (Extent.intersectsExtent(geometry.extent, extent)) {
72
+ context.setGeometry(geometry);
73
+ if (style.zoom.min > style.context.zoom || style.zoom.max <= style.context.zoom) {
74
+ return;
75
+ }
76
+ if (feature.type === FEATURE_TYPES.POINT && style.point) {
77
+ // cross multiplication to know in the extent system the real size of
78
+ // the point
79
+ const px = (Math.round(style.point.radius * invCtxScale) || 3 * invCtxScale) * scaleRadius;
80
+ for (const indice of geometry.indices) {
81
+ const offset = indice.offset * feature.size;
82
+ const count = offset + indice.count * feature.size;
83
+ for (let j = offset; j < count; j += feature.size) {
84
+ coord.setFromArray(feature.vertices, j);
85
+ if (extent.isPointInside(coord, px)) {
86
+ drawPoint(ctx, feature.vertices[j], feature.vertices[j + 1], invCtxScale);
87
+ }
88
+ }
89
+ }
90
+ } else {
91
+ drawPolygon(ctx, feature.vertices, geometry.indices, feature.size, extent, invCtxScale, feature.type == FEATURE_TYPES.POLYGON);
92
+ }
93
+ }
94
+ }
95
+ }
96
+ const origin = new THREE.Vector3();
97
+ const dimension = new THREE.Vector3(0, 0, 1);
98
+ const scale = new THREE.Vector3();
99
+ const quaternion = new THREE.Quaternion();
100
+ const world2texture = new THREE.Matrix4();
101
+ const feature2texture = new THREE.Matrix4();
102
+ const worldTextureOrigin = new THREE.Vector3();
103
+ const featureExtent = new Extent('EPSG:4326', 0, 0, 0, 0);
104
+ export default {
105
+ // backgroundColor is a THREE.Color to specify a color to fill the texture
106
+ // with, given there is no feature passed in parameter
107
+ createTextureFromFeature(collection, extent, sizeTexture, layerStyle, backgroundColor) {
108
+ style = layerStyle || defaultStyle;
109
+ style.setContext(context);
110
+ let texture;
111
+ if (collection) {
112
+ // A texture is instancied drawn canvas
113
+ // origin and dimension are used to transform the feature's coordinates to canvas's space
114
+ extent.planarDimensions(dimension);
115
+ const c = document.createElement('canvas');
116
+ coord.crs = extent.crs;
117
+ c.width = sizeTexture;
118
+ c.height = sizeTexture;
119
+ const ctx = c.getContext('2d', {
120
+ willReadFrequently: true
121
+ });
122
+ if (backgroundColor) {
123
+ ctx.fillStyle = backgroundColor.getStyle();
124
+ ctx.fillRect(0, 0, sizeTexture, sizeTexture);
125
+ }
126
+
127
+ // Documentation needed !!
128
+ ctx.globalCompositeOperation = layerStyle.globalCompositeOperation || 'source-over';
129
+ ctx.imageSmoothingEnabled = false;
130
+ ctx.lineJoin = 'round';
131
+
132
+ // transform extent to feature projection
133
+ extent.as(collection.crs, featureExtent);
134
+ // transform extent to local system
135
+ featureExtent.applyMatrix4(collection.matrixWorldInverse);
136
+
137
+ // compute matrix transformation `world2texture` to convert coordinates to texture coordinates
138
+ if (collection.isInverted) {
139
+ worldTextureOrigin.set(extent.west, extent.north, 0);
140
+ scale.set(ctx.canvas.width, -ctx.canvas.height, 1.0).divide(dimension);
141
+ } else {
142
+ worldTextureOrigin.set(extent.west, extent.south, 0);
143
+ scale.set(ctx.canvas.width, ctx.canvas.height, 1.0).divide(dimension);
144
+ }
145
+ world2texture.compose(worldTextureOrigin.multiply(scale).negate(), quaternion, scale);
146
+
147
+ // compute matrix transformation `feature2texture` to convert features coordinates to texture coordinates
148
+ feature2texture.multiplyMatrices(world2texture, collection.matrixWorld);
149
+ feature2texture.decompose(origin, quaternion, scale);
150
+ ctx.setTransform(scale.x, 0, 0, scale.y, origin.x, origin.y);
151
+
152
+ // to scale line width and radius circle
153
+ const invCtxScale = Math.abs(1 / scale.x);
154
+ context.setZoom(extent.zoom);
155
+
156
+ // Draw the canvas
157
+ for (const feature of collection.features) {
158
+ context.setFeature(feature);
159
+ drawFeature(ctx, feature, featureExtent, invCtxScale);
160
+ }
161
+ texture = new THREE.CanvasTexture(c);
162
+ texture.flipY = collection.isInverted;
163
+ } else if (backgroundColor) {
164
+ const data = new Uint8Array(3);
165
+ data[0] = backgroundColor.r * 255;
166
+ data[1] = backgroundColor.g * 255;
167
+ data[2] = backgroundColor.b * 255;
168
+ texture = new THREE.DataTexture(data, 1, 1, THREE.RGBAFormat);
169
+ } else {
170
+ texture = new THREE.Texture();
171
+ }
172
+ return texture;
173
+ }
174
+ };
@@ -0,0 +1,70 @@
1
+ import * as THREE from 'three';
2
+ import TileMesh from "../Core/TileMesh.js";
3
+ import LayeredMaterial from "../Renderer/LayeredMaterial.js";
4
+ import { newTileGeometry } from "../Core/Prefab/TileBuilder.js";
5
+ import ReferLayerProperties from "../Layer/ReferencingLayerProperties.js";
6
+ import { geoidLayerIsVisible } from "../Layer/GeoidLayer.js";
7
+ const dimensions = new THREE.Vector2();
8
+ function setTileFromTiledLayer(tile, tileLayer) {
9
+ if (tileLayer.diffuse) {
10
+ tile.material.diffuse = tileLayer.diffuse;
11
+ }
12
+ if (tileLayer.isGlobeLayer) {
13
+ // Computes a point used for horizon culling.
14
+ // If the point is below the horizon,
15
+ // the tile is guaranteed to be below the horizon as well.
16
+ tile.horizonCullingPoint = tile.extent.center().as('EPSG:4978').toVector3();
17
+ tile.extent.planarDimensions(dimensions).multiplyScalar(THREE.MathUtils.DEG2RAD);
18
+
19
+ // alpha is maximum angle between two points of tile
20
+ const alpha = dimensions.length();
21
+ const h = Math.abs(1.0 / Math.cos(alpha * 0.5));
22
+ tile.horizonCullingPoint.setLength(h * tile.horizonCullingPoint.length());
23
+ tile.horizonCullingPointElevationScaled = tile.horizonCullingPoint.clone();
24
+ }
25
+ }
26
+ export default {
27
+ convert(requester, extent, layer) {
28
+ const builder = layer.builder;
29
+ const parent = requester;
30
+ const level = parent !== undefined ? parent.level + 1 : 0;
31
+ const paramsGeometry = {
32
+ extent,
33
+ level,
34
+ segments: layer.segments || 16,
35
+ disableSkirt: layer.disableSkirt,
36
+ hideSkirt: layer.hideSkirt
37
+ };
38
+ return newTileGeometry(builder, paramsGeometry).then(result => {
39
+ // build tile mesh
40
+ result.geometry.increaseRefCount();
41
+ const crsCount = layer.tileMatrixSets.length;
42
+ const material = new LayeredMaterial(layer.materialOptions, crsCount);
43
+ ReferLayerProperties(material, layer);
44
+ const tile = new TileMesh(result.geometry, material, layer, extent, level);
45
+ if (parent && parent.isTileMesh) {
46
+ // get parent extent transformation
47
+ const pTrans = builder.computeShareableExtent(parent.extent);
48
+ // place relative to his parent
49
+ result.position.sub(pTrans.position).applyQuaternion(pTrans.quaternion.invert());
50
+ result.quaternion.premultiply(pTrans.quaternion);
51
+ }
52
+ tile.position.copy(result.position);
53
+ tile.quaternion.copy(result.quaternion);
54
+ tile.visible = false;
55
+ tile.updateMatrix();
56
+ setTileFromTiledLayer(tile, layer);
57
+ if (parent) {
58
+ tile.geoidHeight = parent.geoidHeight;
59
+ const geoidHeight = geoidLayerIsVisible(layer) ? tile.geoidHeight : 0;
60
+ tile.setBBoxZ({
61
+ min: parent.obb.z.min,
62
+ max: parent.obb.z.max,
63
+ geoidHeight
64
+ });
65
+ tile.material.geoidHeight = geoidHeight;
66
+ }
67
+ return tile;
68
+ });
69
+ }
70
+ };
@@ -0,0 +1,43 @@
1
+ import * as THREE from 'three';
2
+ import Feature2Texture from "./Feature2Texture.js";
3
+ import { Extent } from '@itowns/geographic';
4
+ const extentTexture = new Extent('EPSG:4326');
5
+ const textureLayer = (texture, layer) => {
6
+ texture.generateMipmaps = false;
7
+ texture.magFilter = layer.magFilter || THREE.LinearFilter;
8
+ texture.minFilter = layer.minFilter || THREE.LinearFilter;
9
+ return texture;
10
+ };
11
+ function textureColorLayer(texture, layer) {
12
+ texture.anisotropy = 16;
13
+ texture.premultiplyAlpha = layer.transparent;
14
+ return textureLayer(texture, layer);
15
+ }
16
+ export default {
17
+ convert(data, destinationTile, layer) {
18
+ let texture;
19
+ if (data.isFeatureCollection) {
20
+ const backgroundLayer = layer.source.backgroundLayer;
21
+ const backgroundColor = backgroundLayer && backgroundLayer.paint ? new THREE.Color(backgroundLayer.paint['background-color']) : undefined;
22
+ destinationTile.toExtent(layer.crs, extentTexture);
23
+ texture = Feature2Texture.createTextureFromFeature(data, extentTexture, layer.subdivisionThreshold, layer.style, backgroundColor);
24
+ texture.features = data;
25
+ texture.extent = destinationTile;
26
+ } else if (data.isTexture) {
27
+ texture = data;
28
+ } else {
29
+ throw new Error('Data type is not supported to convert into texture');
30
+ }
31
+ if (layer.isColorLayer) {
32
+ return textureColorLayer(texture, layer);
33
+ } else if (layer.isElevationLayer) {
34
+ if (texture.flipY) {
35
+ // DataTexture default to false, so make sure other Texture types
36
+ // do the same (eg image texture)
37
+ // See UV construction for more details
38
+ texture.flipY = false;
39
+ }
40
+ return textureLayer(texture, layer);
41
+ }
42
+ }
43
+ };
@@ -0,0 +1,131 @@
1
+ import binaryPropertyAccessor from "./utils/BinaryPropertyAccessor.js";
2
+ import { C3DTilesTypes } from "./C3DTilesEnums.js";
3
+ const utf8Decoder = new TextDecoder();
4
+
5
+ /**
6
+ * A 3D Tiles
7
+ * [batch
8
+ * table](https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/specification/TileFormats/BatchTable).
9
+ * @property {C3DTilesTypes} type - Used by 3D Tiles extensions
10
+ * (e.g. {@link C3DTBatchTableHierarchyExtension}) to know in which context
11
+ * (i.e. for which 3D Tiles class) the parsing of the extension should be done.
12
+ * @property {number} batchLength - the length of the batch.
13
+ * @property {object} content - the content of the batch table in the form:
14
+ * {property1: values[], property2: values[], ...}.
15
+ * @property {object} extensions - 3D Tiles extensions of the batch table
16
+ * stored in the following format:
17
+ * {extensioName1: extensionObject1, extensioName2: extensionObject2, ...}
18
+ */
19
+ class C3DTBatchTable {
20
+ /**
21
+ * @param {ArrayBuffer} [buffer=new ArrayBuffer()] - batch table buffer to parse
22
+ * @param {number} [jsonLength=0] - batch table json part length
23
+ * @param {number} [binaryLength=0] - batch table binary part length
24
+ * @param {number} [batchLength=0] - the length of the batch.
25
+ * @param {Object} [registeredExtensions] - extensions registered to the layer
26
+ */
27
+ constructor() {
28
+ let buffer = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new ArrayBuffer();
29
+ let jsonLength = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
30
+ let binaryLength = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
31
+ let batchLength = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
32
+ let registeredExtensions = arguments.length > 4 ? arguments[4] : undefined;
33
+ if (arguments.length === 4 && typeof batchLength === 'object' && !Array.isArray(batchLength) && batchLength !== null) {
34
+ console.warn('You most likely used a deprecated constructor of C3DTBatchTable.');
35
+ }
36
+ if (jsonLength + binaryLength !== buffer.byteLength) {
37
+ console.error('3DTiles batch table json length and binary length are not consistent with total buffer' + ' length. The batch table may be wrong.');
38
+ }
39
+ this.type = C3DTilesTypes.batchtable;
40
+ this.batchLength = batchLength;
41
+ const jsonBuffer = buffer.slice(0, jsonLength);
42
+ const decodedJsonBuffer = utf8Decoder.decode(new Uint8Array(jsonBuffer));
43
+ const jsonContent = decodedJsonBuffer === '' ? null : JSON.parse(decodedJsonBuffer);
44
+ if (binaryLength > 0) {
45
+ const binaryBuffer = buffer.slice(jsonLength, jsonLength + binaryLength);
46
+ for (const propKey in jsonContent) {
47
+ if (!Object.prototype.hasOwnProperty.call(jsonContent, propKey)) {
48
+ continue;
49
+ }
50
+ const propVal = jsonContent[propKey];
51
+ // Batch table entries that have already been parsed from the JSON buffer have an array of values.
52
+ if (Array.isArray(propVal)) {
53
+ continue;
54
+ }
55
+ if (typeof propVal?.byteOffset !== 'undefined' && typeof propVal?.componentType !== 'undefined' && typeof propVal?.type !== 'undefined') {
56
+ jsonContent[propKey] = binaryPropertyAccessor(binaryBuffer, this.batchLength, propVal.byteOffset, propVal.componentType, propVal.type);
57
+ } else {
58
+ console.error('Invalid 3D Tiles batch table property that is neither a JSON array nor a valid ' + 'accessor to a binary body');
59
+ }
60
+ }
61
+ }
62
+
63
+ // Separate the content and the possible extensions
64
+ // When an extension is found, we call its parser and append the
65
+ // returned object to batchTable.extensions
66
+ // Extensions must be registered in the layer (see an example of this in
67
+ // 3dtiles_hierarchy.html)
68
+ if (jsonContent && jsonContent.extensions) {
69
+ this.extensions = registeredExtensions.parseExtensions(jsonContent.extensions, this.type);
70
+ delete jsonContent.extensions;
71
+ }
72
+
73
+ // Store batch table json content
74
+ this.content = jsonContent;
75
+ }
76
+
77
+ /**
78
+ * Creates and returns a javascript object holding the displayable
79
+ * information from the batch table and from extensions of the batch table,
80
+ * for a given feature (identified with its batchID).
81
+ * @param {integer} batchID - id of the feature
82
+ * @returns {Object} - displayable information relative to the batch
83
+ * table and its extensions. Object is formatted as follow:
84
+ * {batchTable:
85
+ * {property1: value1
86
+ * property2: value2
87
+ * ...}
88
+ * extensions:
89
+ * {extension1:
90
+ * {property1: value1
91
+ * ...}
92
+ * extension2: {...}
93
+ * ...}
94
+ * }
95
+ */
96
+ getInfoById(batchID) {
97
+ // Verify that the batch ID is valid
98
+ if (batchID < 0 && batchID < this.batchLength) {
99
+ throw new Error(`Batch Id (${batchID}) must be between 0 and
100
+ ${this.batchLength} to access feature properties from the batch
101
+ table.`);
102
+ }
103
+ const featureDisplayableInfo = {};
104
+ featureDisplayableInfo.batchTable = {};
105
+ // Get properties from batch table content
106
+ for (const property in this.content) {
107
+ // check that the property is not inherited from prototype chain
108
+ if (Object.prototype.hasOwnProperty.call(this.content, property)) {
109
+ const val = this.content[property][batchID];
110
+ // Property value may be a threejs vector (see 3D Tiles spec and BinaryPropertyAccessor.js)
111
+ if (val && (val.isVector2 || val.isVector3 || val.isVector4)) {
112
+ featureDisplayableInfo.batchTable[property] = val.toArray();
113
+ } else {
114
+ featureDisplayableInfo.batchTable[property] = val;
115
+ }
116
+ }
117
+ }
118
+
119
+ // Extensions
120
+ if (this.extensions) {
121
+ featureDisplayableInfo.extensions = {};
122
+ for (const extName in this.extensions) {
123
+ if (Object.prototype.hasOwnProperty.call(this.extensions, extName)) {
124
+ featureDisplayableInfo.extensions[extName] = this.extensions[extName].getInfoById(batchID);
125
+ }
126
+ }
127
+ }
128
+ return featureDisplayableInfo;
129
+ }
130
+ }
131
+ export default C3DTBatchTable;
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Batch Table part of the 3D Tiles
3
+ * [Batch Table Hierarchy Extension](https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/extensions/3DTILES_batch_table_hierarchy)
4
+ * @property {object} classes - The classes as defined in the specification.
5
+ * @property {object} inverseHierarchy - InverseHierarchy contains for each
6
+ * instance (i.e. georgraphic feature e.g. building, roof, etc.) an array of the
7
+ * indexes of its parents. For example, the parents of the instance 0 can be
8
+ * found using inverseHierarchy[0].
9
+ * @property {number[]} instancesIdxs - For each instance of the extension,
10
+ * contains a javascript object with classId and instanceIdx. classId is the id
11
+ * of the class (from this.classes) of the instance. instanceIdx is the index of
12
+ * the instance in this class. Goal: Ease the retrieval of the properties of an
13
+ * instance.
14
+ */
15
+ class C3DTBatchTableHierarchyExtension {
16
+ /**
17
+ * Constructor of the C3DTBatchTableHierarchyExtension class.
18
+ * @param {Object} json - The parsed json of the batch table part of the 3D
19
+ * Tiles [Batch Table Hierarchy Extension](https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/extensions/3DTILES_batch_table_hierarchy)
20
+ */
21
+ constructor(json) {
22
+ this.classes = json.classes;
23
+ this.inverseHierarchy = {};
24
+ this.instancesIdxs = [];
25
+
26
+ // Counts the number of instances of a class
27
+ const classCounter = {};
28
+ let parentIdsCounter = 0;
29
+
30
+ // if omitted, parentCounts is an array of length instancesLength,
31
+ // where all values are 1 (cf. spec)
32
+ let parentCounts = json.parentCounts;
33
+ if (parentCounts === undefined) {
34
+ parentCounts = new Array(json.instancesLength);
35
+ parentCounts.fill(1);
36
+ }
37
+
38
+ // for each instance
39
+ for (let i = 0; i < json.instancesLength; i++) {
40
+ // for each parent of the current instance
41
+ for (let j = 0; j < parentCounts[i]; j++) {
42
+ // When an instance's parentId points to itself, then it has no
43
+ // parent" (cf. spec)
44
+ if (i !== json.parentIds[parentIdsCounter]) {
45
+ if (this.inverseHierarchy[i] === undefined) {
46
+ this.inverseHierarchy[i] = [];
47
+ }
48
+ this.inverseHierarchy[i].push(json.parentIds[parentIdsCounter]);
49
+ parentIdsCounter++;
50
+ }
51
+ }
52
+ const classId = json.classIds[i];
53
+ if (classCounter[classId] === undefined) {
54
+ classCounter[classId] = 0;
55
+ }
56
+ this.instancesIdxs[i] = {
57
+ classId,
58
+ instanceIdx: classCounter[classId]
59
+ };
60
+ classCounter[classId]++;
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Creates and returns a javascript object holding the displayable
66
+ * information relative to this extension for a given feature.
67
+ * @param {integer} featureId - id of the feature
68
+ * @returns {Object} - displayable information relative to this
69
+ * extension, for the feature with id=featureId and for its parents
70
+ */
71
+ getInfoById(featureId) {
72
+ const instanceProperties = {};
73
+ // get feature class name
74
+ const instanceClassId = this.instancesIdxs[featureId].classId;
75
+ const featureClass = this.classes[instanceClassId].name;
76
+ // get feature properties and values
77
+ const instanceIdx = this.instancesIdxs[featureId].instanceIdx;
78
+ const instances = this.classes[instanceClassId].instances;
79
+ for (const key in instances) {
80
+ if (Object.prototype.hasOwnProperty.call(instances, key)) {
81
+ instanceProperties[key] = instances[key][instanceIdx];
82
+ }
83
+ }
84
+ // create return object: className: {featureProperties and values}
85
+ const pickingInfo = {};
86
+ pickingInfo[featureClass] = instanceProperties;
87
+ // If this feature has parent(s), recurse on them
88
+ if (this.inverseHierarchy && this.inverseHierarchy[featureId]) {
89
+ for (const parentID of this.inverseHierarchy[featureId]) {
90
+ Object.assign(pickingInfo, this.getInfoById(parentID));
91
+ }
92
+ }
93
+ return pickingInfo;
94
+ }
95
+ }
96
+ export default C3DTBatchTableHierarchyExtension;
@@ -0,0 +1,156 @@
1
+ import * as THREE from 'three';
2
+ import { Ellipsoid, Coordinates } from '@itowns/geographic';
3
+ import { C3DTilesTypes, C3DTilesBoundingVolumeTypes } from "./C3DTilesEnums.js";
4
+ const ellipsoid = new Ellipsoid();
5
+
6
+ // bounding box scratch variables
7
+ const boxSize = new THREE.Vector3();
8
+ const boxCenter = new THREE.Vector3();
9
+
10
+ // Bounding region scratch variables
11
+ const southEastUpCarto = new Coordinates('EPSG:4326');
12
+ const southEastUpVec3 = new THREE.Vector3();
13
+ const northWestBottomCarto = new Coordinates('EPSG:4326');
14
+ const northWestBottomVec3 = new THREE.Vector3();
15
+ const radiusScratch = new THREE.Vector3();
16
+
17
+ // Culling scratch value
18
+ const worldCoordinateCenter = new THREE.Vector3();
19
+
20
+ /**
21
+ * Bounding region is converted to a bounding sphere to simplify and speed computation and culling. This function
22
+ * computes a sphere enclosing the bounding region.
23
+ * @param {Object} region - the parsed json from the tile representing the region
24
+ * @param {THREE.Matrix4} tileMatrixInverse - the inverse transformation matrix of the tile to transform the produced
25
+ * sphere from a global to a reference local to the tile
26
+ * @return {THREE.Sphere} a sphere enclosing the given region
27
+ */
28
+ function initFromRegion(region, tileMatrixInverse) {
29
+ const east = region[2];
30
+ const west = region[0];
31
+ const south = region[1];
32
+ const north = region[3];
33
+ const minHeight = region[4];
34
+ const maxHeight = region[5];
35
+ const eastDeg = THREE.MathUtils.radToDeg(east);
36
+ const westDeg = THREE.MathUtils.radToDeg(west);
37
+ const southDeg = THREE.MathUtils.radToDeg(south);
38
+ const northDeg = THREE.MathUtils.radToDeg(north);
39
+ northWestBottomCarto.setFromValues(westDeg, northDeg, minHeight);
40
+ ellipsoid.cartographicToCartesian(northWestBottomCarto, northWestBottomVec3);
41
+ southEastUpCarto.setFromValues(eastDeg, southDeg, maxHeight);
42
+ ellipsoid.cartographicToCartesian(southEastUpCarto, southEastUpVec3);
43
+ const regionCenter = new THREE.Vector3();
44
+ regionCenter.lerpVectors(northWestBottomVec3, southEastUpVec3, 0.5);
45
+ const radius = radiusScratch.subVectors(northWestBottomVec3, southEastUpVec3).length() / 2;
46
+ const sphere = new THREE.Sphere(regionCenter, radius);
47
+ sphere.applyMatrix4(tileMatrixInverse);
48
+ return sphere;
49
+ }
50
+
51
+ /**
52
+ * Create a bounding box from a json describing a box in a 3D Tiles tile.
53
+ * @param {Object} box - the parsed json from the tile representing the box
54
+ * @return {THREE.Box3} the bounding box of the tile
55
+ */
56
+ function initFromBox(box) {
57
+ // box[0], box[1], box[2] = center of the box
58
+ // box[3], box[4], box[5] = x axis direction and half-length
59
+ // box[6], box[7], box[8] = y axis direction and half-length
60
+ // box[9], box[10], box[11] = z axis direction and half-length
61
+ boxCenter.set(box[0], box[1], box[2]);
62
+ boxSize.set(box[3], box[7], box[11]).multiplyScalar(2);
63
+ const box3 = new THREE.Box3();
64
+ box3.setFromCenterAndSize(boxCenter, boxSize);
65
+ return box3;
66
+ }
67
+
68
+ /**
69
+ * Creats a bounding sphere from a json describing a sphere in a 3D Tiles tile.
70
+ * @param {Object} sphere - the parsed json from the tile representing the sphere
71
+ * @returns {THREE.Sphere} the bounding sphere of the tile
72
+ */
73
+ function initFromSphere(sphere) {
74
+ const sphereCenter = new THREE.Vector3();
75
+ sphereCenter.set(sphere[0], sphere[1], sphere[2]);
76
+ return new THREE.Sphere(sphereCenter, sphere[3]);
77
+ }
78
+
79
+ /**
80
+ * [bounding volume](https://github.com/AnalyticalGraphicsInc/3d-tiles/blob/master/specification/schema/boundingVolume.schema.json)
81
+ * Used to represent bounding volumes and viewer request volumes. The input bounding volume (from the dataset) can be a
82
+ * box, a sphere or a region. Regions are transformed to spheres internally for simplification of parsing and to speed
83
+ * up computations such as culling.
84
+ * @property {C3DTilesTypes} type - Used by 3D Tiles extensions
85
+ * (e.g. {@link C3DTBatchTableHierarchyExtension}) to know in which context
86
+ * (i.e. for which 3D Tiles class) the parsing of the extension should be done.
87
+ * @property {String} initialVolumeType - the initial volume type to be able to dissociate spheres
88
+ * and regions if needed since both are converted to spheres (one of {@link C3DTilesBoundingVolumeTypes})
89
+ * @property {THREE.Box3|THREE.Sphere} volume - The 3D bounding volume created. Can be a THREE.Box3 for bounding volumes
90
+ * of types box or a THREE.Sphere for bounding volumes of type sphere or region.
91
+ * @property {object} extensions - 3D Tiles extensions of the bounding volume
92
+ * stored in the following format:
93
+ * {extensioName1: extensionObject1, extensioName2: extensionObject2, ...}
94
+ */
95
+ class C3DTBoundingVolume {
96
+ constructor(json, tileMatrixInverse, registeredExtensions) {
97
+ this.type = C3DTilesTypes.boundingVolume;
98
+ if (json.region) {
99
+ this.initialVolumeType = C3DTilesBoundingVolumeTypes.region;
100
+ this.volume = initFromRegion(json.region, tileMatrixInverse);
101
+ } else if (json.box) {
102
+ this.initialVolumeType = C3DTilesBoundingVolumeTypes.box;
103
+ this.volume = initFromBox(json.box);
104
+ } else if (json.sphere) {
105
+ this.initialVolumeType = C3DTilesBoundingVolumeTypes.sphere;
106
+ this.volume = initFromSphere(json.sphere);
107
+ } else {
108
+ throw new Error(`Unknown bounding volume type: ${json}. 3D Tiles nodes must have a bounding volume of type
109
+ region, box or sphere.`);
110
+ }
111
+ if (json.extensions) {
112
+ this.extensions = registeredExtensions.parseExtensions(json.extensions, this.type);
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Performs camera frustum culling on bounding volumes.
118
+ * @param {Camera} camera - the camera to perform culling for
119
+ * @param {THREE.Matrix4} tileMatrixWorld - the world matrix of the tile
120
+ * @returns {boolean} true if the tile should be culled out (bounding volume not in camera frustum), false otherwise.
121
+ */
122
+ boundingVolumeCulling(camera, tileMatrixWorld) {
123
+ if (this.initialVolumeType === C3DTilesBoundingVolumeTypes.box) {
124
+ return !camera.isBox3Visible(this.volume, tileMatrixWorld);
125
+ } else if (this.initialVolumeType === C3DTilesBoundingVolumeTypes.sphere || this.initialVolumeType === C3DTilesBoundingVolumeTypes.region) {
126
+ return !camera.isSphereVisible(this.volume, tileMatrixWorld);
127
+ } else {
128
+ throw new Error('Unknown bounding volume type.');
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Checks if the camera is inside the [viewer request volumes](https://github.com/CesiumGS/3d-tiles/tree/main/specification#viewer-request-volume).
134
+ * @param {Camera} camera - the camera to perform culling for
135
+ * @param {THREE.Matrix4} tileMatrixWorld - the world matrix of the tile
136
+ * @returns {boolean} true if the camera is outside the viewer request volume, false otherwise.
137
+ */
138
+ viewerRequestVolumeCulling(camera, tileMatrixWorld) {
139
+ if (this.initialVolumeType === C3DTilesBoundingVolumeTypes.region) {
140
+ console.warn('Region viewerRequestVolume not yet supported');
141
+ return true;
142
+ }
143
+ if (this.initialVolumeType === C3DTilesBoundingVolumeTypes.box) {
144
+ console.warn('Bounding box viewerRequestVolume not yet supported');
145
+ return true;
146
+ }
147
+ if (this.initialVolumeType === C3DTilesBoundingVolumeTypes.sphere) {
148
+ worldCoordinateCenter.copy(this.volume.center);
149
+ worldCoordinateCenter.applyMatrix4(tileMatrixWorld);
150
+ // To check the distance between the center sphere and the camera
151
+ return !(camera.camera3D.position.distanceTo(worldCoordinateCenter) <= this.volume.radius);
152
+ }
153
+ return false;
154
+ }
155
+ }
156
+ export default C3DTBoundingVolume;