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.
- package/dist/455.js +2 -0
- package/dist/455.js.map +1 -0
- package/dist/debug.js +3 -0
- package/dist/debug.js.LICENSE.txt +13 -0
- package/dist/debug.js.map +1 -0
- package/dist/itowns.js +3 -0
- package/dist/itowns.js.LICENSE.txt +5 -0
- package/dist/itowns.js.map +1 -0
- package/dist/itowns_lasparser.js +2 -0
- package/dist/itowns_lasparser.js.map +1 -0
- package/dist/itowns_lasworker.js +2 -0
- package/dist/itowns_lasworker.js.map +1 -0
- package/dist/itowns_potree2worker.js +2 -0
- package/dist/itowns_potree2worker.js.map +1 -0
- package/dist/itowns_widgets.js +2 -0
- package/dist/itowns_widgets.js.map +1 -0
- package/lib/Controls/FirstPersonControls.js +308 -0
- package/lib/Controls/FlyControls.js +175 -0
- package/lib/Controls/GlobeControls.js +1178 -0
- package/lib/Controls/PlanarControls.js +1025 -0
- package/lib/Controls/StateControl.js +432 -0
- package/lib/Controls/StreetControls.js +392 -0
- package/lib/Converter/Feature2Mesh.js +612 -0
- package/lib/Converter/Feature2Texture.js +174 -0
- package/lib/Converter/convertToTile.js +70 -0
- package/lib/Converter/textureConverter.js +43 -0
- package/lib/Core/3DTiles/C3DTBatchTable.js +131 -0
- package/lib/Core/3DTiles/C3DTBatchTableHierarchyExtension.js +96 -0
- package/lib/Core/3DTiles/C3DTBoundingVolume.js +156 -0
- package/lib/Core/3DTiles/C3DTExtensions.js +97 -0
- package/lib/Core/3DTiles/C3DTFeature.js +110 -0
- package/lib/Core/3DTiles/C3DTilesEnums.js +20 -0
- package/lib/Core/3DTiles/C3DTileset.js +99 -0
- package/lib/Core/3DTiles/utils/BinaryPropertyAccessor.js +100 -0
- package/lib/Core/AnimationPlayer.js +142 -0
- package/lib/Core/CopcNode.js +174 -0
- package/lib/Core/Deprecated/Undeprecator.js +74 -0
- package/lib/Core/EntwinePointTileNode.js +126 -0
- package/lib/Core/Feature.js +488 -0
- package/lib/Core/Geographic/GeoidGrid.js +108 -0
- package/lib/Core/Label.js +222 -0
- package/lib/Core/MainLoop.js +209 -0
- package/lib/Core/Picking.js +255 -0
- package/lib/Core/PointCloudNode.js +42 -0
- package/lib/Core/Potree2Node.js +206 -0
- package/lib/Core/Potree2PointAttributes.js +139 -0
- package/lib/Core/PotreeNode.js +101 -0
- package/lib/Core/Prefab/Globe/Atmosphere.js +293 -0
- package/lib/Core/Prefab/Globe/GlobeLayer.js +152 -0
- package/lib/Core/Prefab/Globe/GlobeTileBuilder.js +110 -0
- package/lib/Core/Prefab/Globe/SkyShader.js +78 -0
- package/lib/Core/Prefab/GlobeView.js +155 -0
- package/lib/Core/Prefab/Planar/PlanarLayer.js +59 -0
- package/lib/Core/Prefab/Planar/PlanarTileBuilder.js +71 -0
- package/lib/Core/Prefab/PlanarView.js +62 -0
- package/lib/Core/Prefab/TileBuilder.js +82 -0
- package/lib/Core/Prefab/computeBufferTileGeometry.js +248 -0
- package/lib/Core/Scheduler/Cache.js +17 -0
- package/lib/Core/Scheduler/CancelledCommandException.js +15 -0
- package/lib/Core/Scheduler/Scheduler.js +294 -0
- package/lib/Core/Style.js +660 -0
- package/lib/Core/StyleOptions.js +486 -0
- package/lib/Core/System/Capabilities.js +63 -0
- package/lib/Core/Tile/Tile.js +205 -0
- package/lib/Core/Tile/TileGrid.js +49 -0
- package/lib/Core/TileGeometry.js +124 -0
- package/lib/Core/TileMesh.js +108 -0
- package/lib/Core/View.js +1115 -0
- package/lib/Layer/C3DTilesLayer.js +459 -0
- package/lib/Layer/ColorLayer.js +154 -0
- package/lib/Layer/CopcLayer.js +63 -0
- package/lib/Layer/ElevationLayer.js +139 -0
- package/lib/Layer/EntwinePointTileLayer.js +71 -0
- package/lib/Layer/FeatureGeometryLayer.js +77 -0
- package/lib/Layer/GeoidLayer.js +80 -0
- package/lib/Layer/GeometryLayer.js +233 -0
- package/lib/Layer/InfoLayer.js +64 -0
- package/lib/Layer/LabelLayer.js +469 -0
- package/lib/Layer/Layer.js +335 -0
- package/lib/Layer/LayerUpdateState.js +89 -0
- package/lib/Layer/LayerUpdateStrategy.js +80 -0
- package/lib/Layer/OGC3DTilesLayer.js +543 -0
- package/lib/Layer/OrientedImageLayer.js +227 -0
- package/lib/Layer/PointCloudLayer.js +405 -0
- package/lib/Layer/Potree2Layer.js +171 -0
- package/lib/Layer/PotreeLayer.js +72 -0
- package/lib/Layer/RasterLayer.js +37 -0
- package/lib/Layer/ReferencingLayerProperties.js +62 -0
- package/lib/Layer/TiledGeometryLayer.js +459 -0
- package/lib/Loader/LASLoader.js +193 -0
- package/lib/Loader/Potree2BrotliLoader.js +261 -0
- package/lib/Loader/Potree2Loader.js +207 -0
- package/lib/Main.js +113 -0
- package/lib/MainBundle.js +4 -0
- package/lib/Parser/B3dmParser.js +174 -0
- package/lib/Parser/CameraCalibrationParser.js +94 -0
- package/lib/Parser/GDFParser.js +72 -0
- package/lib/Parser/GTXParser.js +75 -0
- package/lib/Parser/GeoJsonParser.js +212 -0
- package/lib/Parser/GpxParser.js +25 -0
- package/lib/Parser/ISGParser.js +71 -0
- package/lib/Parser/KMLParser.js +25 -0
- package/lib/Parser/LASParser.js +137 -0
- package/lib/Parser/MapBoxUrlParser.js +83 -0
- package/lib/Parser/PntsParser.js +131 -0
- package/lib/Parser/Potree2BinParser.js +92 -0
- package/lib/Parser/PotreeBinParser.js +106 -0
- package/lib/Parser/PotreeCinParser.js +29 -0
- package/lib/Parser/ShapefileParser.js +78 -0
- package/lib/Parser/VectorTileParser.js +215 -0
- package/lib/Parser/XbilParser.js +120 -0
- package/lib/Parser/deprecated/LegacyGLTFLoader.js +1386 -0
- package/lib/Parser/iGLTFLoader.js +168 -0
- package/lib/Process/3dTilesProcessing.js +304 -0
- package/lib/Process/FeatureProcessing.js +76 -0
- package/lib/Process/LayeredMaterialNodeProcessing.js +229 -0
- package/lib/Process/ObjectRemovalHelper.js +97 -0
- package/lib/Process/handlerNodeError.js +23 -0
- package/lib/Provider/3dTilesProvider.js +149 -0
- package/lib/Provider/DataSourceProvider.js +24 -0
- package/lib/Provider/Fetcher.js +233 -0
- package/lib/Provider/PointCloudProvider.js +45 -0
- package/lib/Provider/TileProvider.js +16 -0
- package/lib/Provider/URLBuilder.js +116 -0
- package/lib/Renderer/Camera.js +281 -0
- package/lib/Renderer/Color.js +56 -0
- package/lib/Renderer/ColorLayersOrdering.js +115 -0
- package/lib/Renderer/CommonMaterial.js +31 -0
- package/lib/Renderer/Label2DRenderer.js +192 -0
- package/lib/Renderer/LayeredMaterial.js +243 -0
- package/lib/Renderer/OBB.js +150 -0
- package/lib/Renderer/OrientedImageCamera.js +118 -0
- package/lib/Renderer/OrientedImageMaterial.js +167 -0
- package/lib/Renderer/PointsMaterial.js +485 -0
- package/lib/Renderer/RasterTile.js +243 -0
- package/lib/Renderer/RenderMode.js +31 -0
- package/lib/Renderer/Shader/ShaderChunk.js +160 -0
- package/lib/Renderer/Shader/ShaderUtils.js +47 -0
- package/lib/Renderer/SphereHelper.js +17 -0
- package/lib/Renderer/WebXR.js +51 -0
- package/lib/Renderer/c3DEngine.js +214 -0
- package/lib/Source/C3DTilesGoogleSource.js +74 -0
- package/lib/Source/C3DTilesIonSource.js +54 -0
- package/lib/Source/C3DTilesSource.js +30 -0
- package/lib/Source/CopcSource.js +126 -0
- package/lib/Source/EntwinePointTileSource.js +72 -0
- package/lib/Source/FileSource.js +188 -0
- package/lib/Source/OGC3DTilesGoogleSource.js +29 -0
- package/lib/Source/OGC3DTilesIonSource.js +34 -0
- package/lib/Source/OGC3DTilesSource.js +21 -0
- package/lib/Source/OrientedImageSource.js +59 -0
- package/lib/Source/Potree2Source.js +167 -0
- package/lib/Source/PotreeSource.js +82 -0
- package/lib/Source/Source.js +202 -0
- package/lib/Source/TMSSource.js +144 -0
- package/lib/Source/VectorTilesSource.js +182 -0
- package/lib/Source/WFSSource.js +170 -0
- package/lib/Source/WMSSource.js +167 -0
- package/lib/Source/WMTSSource.js +92 -0
- package/lib/ThreeExtended/capabilities/WebGL.js +69 -0
- package/lib/ThreeExtended/libs/ktx-parse.module.js +506 -0
- package/lib/ThreeExtended/libs/zstddec.module.js +29 -0
- package/lib/ThreeExtended/loaders/DDSLoader.js +200 -0
- package/lib/ThreeExtended/loaders/DRACOLoader.js +400 -0
- package/lib/ThreeExtended/loaders/GLTFLoader.js +2879 -0
- package/lib/ThreeExtended/loaders/KTX2Loader.js +709 -0
- package/lib/ThreeExtended/math/ColorSpaces.js +59 -0
- package/lib/ThreeExtended/utils/BufferGeometryUtils.js +846 -0
- package/lib/ThreeExtended/utils/WorkerPool.js +70 -0
- package/lib/Utils/CameraUtils.js +554 -0
- package/lib/Utils/DEMUtils.js +350 -0
- package/lib/Utils/FeaturesUtils.js +156 -0
- package/lib/Utils/Gradients.js +16 -0
- package/lib/Utils/ThreeUtils.js +115 -0
- package/lib/Utils/gui/C3DTilesStyle.js +218 -0
- package/lib/Utils/gui/Main.js +7 -0
- package/lib/Utils/gui/Minimap.js +152 -0
- package/lib/Utils/gui/Navigation.js +245 -0
- package/lib/Utils/gui/Scale.js +104 -0
- package/lib/Utils/gui/Searchbar.js +234 -0
- package/lib/Utils/gui/Widget.js +80 -0
- package/lib/Utils/placeObjectOnGround.js +136 -0
- package/lib/Worker/LASLoaderWorker.js +19 -0
- package/lib/Worker/Potree2Worker.js +21 -0
- 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;
|