itowns 2.44.3-next.4 → 2.44.3-next.40
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/CODING.md +1 -1
- package/CONTRIBUTORS.md +1 -0
- package/dist/debug.js +1 -1
- package/dist/debug.js.map +1 -1
- package/dist/itowns.js +1 -1
- package/dist/itowns.js.LICENSE.txt +0 -2
- package/dist/itowns.js.map +1 -1
- package/dist/itowns_widgets.js +1 -1
- package/dist/itowns_widgets.js.map +1 -1
- package/examples/3dtiles_loader.html +123 -48
- package/examples/config.json +3 -10
- package/examples/copc_simple_loader.html +15 -5
- package/examples/effects_stereo.html +2 -2
- package/examples/entwine_3d_loader.html +3 -1
- package/examples/entwine_simple_loader.html +1 -1
- package/examples/images/itowns_logo.svg +123 -0
- package/examples/js/plugins/COGParser.js +1 -1
- package/examples/jsm/OGC3DTilesHelper.js +6 -1
- package/examples/layers/JSONLayers/GeoidMNT.json +3 -1
- package/examples/misc_collada.html +2 -2
- package/examples/source_file_geojson_3d.html +0 -1
- package/examples/source_file_kml_raster_usgs.html +0 -1
- package/examples/source_stream_wfs_raster.html +0 -7
- package/examples/vector_tile_mapbox_raster.html +91 -0
- package/examples/view_3d_map_webxr.html +3 -1
- package/examples/view_multi_25d.html +2 -2
- package/lib/Controls/GlobeControls.js +45 -28
- package/lib/Controls/StateControl.js +5 -2
- package/lib/Converter/Feature2Mesh.js +10 -4
- package/lib/Converter/Feature2Texture.js +6 -1
- package/lib/Converter/convertToTile.js +3 -8
- package/lib/Converter/textureConverter.js +4 -5
- package/lib/Core/Deprecated/Undeprecator.js +0 -1
- package/lib/Core/Feature.js +3 -4
- package/lib/Core/Geographic/Coordinates.js +143 -132
- package/lib/Core/Geographic/Crs.js +140 -145
- package/lib/Core/Geographic/Extent.js +221 -397
- package/lib/Core/Geographic/GeoidGrid.js +1 -1
- package/lib/Core/MainLoop.js +1 -3
- package/lib/Core/Math/Ellipsoid.js +62 -21
- package/lib/Core/Prefab/Globe/Atmosphere.js +4 -8
- package/lib/Core/Prefab/Globe/GlobeLayer.js +22 -15
- package/lib/Core/Prefab/Globe/GlobeTileBuilder.js +111 -0
- package/lib/Core/Prefab/GlobeView.js +2 -7
- package/lib/Core/Prefab/Planar/PlanarLayer.js +17 -11
- package/lib/Core/Prefab/Planar/PlanarTileBuilder.js +43 -43
- package/lib/Core/Prefab/TileBuilder.js +42 -40
- package/lib/Core/Prefab/computeBufferTileGeometry.js +195 -130
- package/lib/Core/Scheduler/Cache.js +1 -240
- package/lib/Core/Style.js +34 -495
- package/lib/Core/StyleOptions.js +486 -0
- package/lib/Core/Tile/Tile.js +207 -0
- package/lib/Core/Tile/TileGrid.js +49 -0
- package/lib/Core/TileGeometry.js +112 -28
- package/lib/Core/TileMesh.js +3 -3
- package/lib/Core/View.js +15 -8
- package/lib/Layer/C3DTilesLayer.js +20 -16
- package/lib/Layer/ColorLayer.js +35 -9
- package/lib/Layer/CopcLayer.js +7 -2
- package/lib/Layer/ElevationLayer.js +39 -7
- package/lib/Layer/EntwinePointTileLayer.js +14 -7
- package/lib/Layer/FeatureGeometryLayer.js +20 -6
- package/lib/Layer/GeometryLayer.js +42 -11
- package/lib/Layer/LabelLayer.js +45 -27
- package/lib/Layer/Layer.js +92 -61
- package/lib/Layer/OGC3DTilesLayer.js +212 -56
- package/lib/Layer/OrientedImageLayer.js +11 -5
- package/lib/Layer/PointCloudLayer.js +76 -30
- package/lib/Layer/Potree2Layer.js +9 -2
- package/lib/Layer/PotreeLayer.js +10 -3
- package/lib/Layer/RasterLayer.js +12 -2
- package/lib/Layer/TiledGeometryLayer.js +69 -13
- package/lib/Main.js +2 -2
- package/lib/Parser/GeoJsonParser.js +1 -1
- package/lib/Parser/VectorTileParser.js +42 -29
- package/lib/Parser/XbilParser.js +14 -2
- package/lib/Provider/Fetcher.js +5 -1
- package/lib/Provider/URLBuilder.js +22 -11
- package/lib/Renderer/Camera.js +1 -1
- package/lib/Renderer/Label2DRenderer.js +9 -7
- package/lib/Renderer/OBB.js +11 -13
- package/lib/Renderer/PointsMaterial.js +5 -5
- package/lib/Renderer/RasterTile.js +1 -2
- package/lib/Renderer/SphereHelper.js +0 -6
- package/lib/Source/CopcSource.js +13 -2
- package/lib/Source/EntwinePointTileSource.js +14 -4
- package/lib/Source/FileSource.js +9 -10
- package/lib/Source/OrientedImageSource.js +2 -2
- package/lib/Source/Source.js +26 -46
- package/lib/Source/TMSSource.js +10 -9
- package/lib/Source/VectorTilesSource.js +38 -34
- package/lib/Source/WFSSource.js +18 -13
- package/lib/Source/WMSSource.js +56 -18
- package/lib/Source/WMTSSource.js +13 -7
- package/lib/ThreeExtended/libs/ktx-parse.module.js +310 -274
- package/lib/ThreeExtended/loaders/DRACOLoader.js +3 -2
- package/lib/ThreeExtended/loaders/GLTFLoader.js +6 -3
- package/lib/ThreeExtended/loaders/KTX2Loader.js +144 -60
- package/lib/ThreeExtended/math/ColorSpaces.js +59 -0
- package/lib/Utils/CameraUtils.js +1 -1
- package/lib/Utils/gui/C3DTilesStyle.js +2 -3
- package/lib/Utils/placeObjectOnGround.js +0 -1
- package/package.json +10 -8
- package/examples/3dtiles_25d.html +0 -120
- package/examples/3dtiles_basic.html +0 -94
- package/examples/3dtiles_batch_table.html +0 -86
- package/examples/3dtiles_ion.html +0 -126
- package/examples/3dtiles_pointcloud.html +0 -95
- package/lib/Core/Prefab/Globe/BuilderEllipsoidTile.js +0 -110
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
|
+
import * as CRS from "./Crs.js";
|
|
2
3
|
import Coordinates from "./Coordinates.js";
|
|
3
|
-
import CRS from "./Crs.js";
|
|
4
4
|
const coord = new Coordinates('EPSG:4326');
|
|
5
5
|
const indexes = new THREE.Vector2();
|
|
6
6
|
function biLinearInterpolation(indexes, getData) {
|
package/lib/Core/MainLoop.js
CHANGED
|
@@ -42,7 +42,6 @@ function updateElements(context, geometryLayer, elements) {
|
|
|
42
42
|
for (const attachedLayer of geometryLayer.attachedLayers) {
|
|
43
43
|
if (attachedLayer.ready) {
|
|
44
44
|
attachedLayer.update(context, attachedLayer, sub.element, sub.parent);
|
|
45
|
-
attachedLayer.cache.flush();
|
|
46
45
|
}
|
|
47
46
|
}
|
|
48
47
|
} else if (sub.elements) {
|
|
@@ -56,7 +55,6 @@ function updateElements(context, geometryLayer, elements) {
|
|
|
56
55
|
for (const attachedLayer of geometryLayer.attachedLayers) {
|
|
57
56
|
if (attachedLayer.ready) {
|
|
58
57
|
attachedLayer.update(context, attachedLayer, sub.elements[i], sub.parent);
|
|
59
|
-
attachedLayer.cache.flush();
|
|
60
58
|
}
|
|
61
59
|
}
|
|
62
60
|
}
|
|
@@ -140,7 +138,7 @@ class MainLoop extends EventDispatcher {
|
|
|
140
138
|
}
|
|
141
139
|
|
|
142
140
|
// Clear the cache of expired resources
|
|
143
|
-
|
|
141
|
+
|
|
144
142
|
view.execFrameRequesters(MAIN_LOOP_EVENTS.AFTER_LAYER_UPDATE, dt, this.#updateLoopRestarted, geometryLayer);
|
|
145
143
|
}
|
|
146
144
|
}
|
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
2
|
import proj4 from 'proj4';
|
|
3
3
|
import Coordinates from "../Geographic/Coordinates.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Length of the semi-axes of the WGS84 ellipsoid.
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
4
9
|
export const ellipsoidSizes = new THREE.Vector3(proj4.WGS84.a, proj4.WGS84.a, proj4.WGS84.b);
|
|
5
10
|
const normal = new THREE.Vector3();
|
|
6
11
|
class Ellipsoid {
|
|
12
|
+
/**
|
|
13
|
+
* Length of the semi-axes of the ellipsoid.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Eccentricity of the ellipsoid.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param size - Length of the semi-axes of the ellipsoid. Defaults to those
|
|
22
|
+
* defined by the WGS84 ellipsoid.
|
|
23
|
+
*/
|
|
7
24
|
constructor() {
|
|
8
25
|
let size = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ellipsoidSizes;
|
|
9
26
|
this.size = new THREE.Vector3();
|
|
@@ -12,10 +29,28 @@ class Ellipsoid {
|
|
|
12
29
|
this.eccentricity = 0;
|
|
13
30
|
this.setSize(size);
|
|
14
31
|
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Computes the normal vector to an ellipsoid at the given cartesian
|
|
35
|
+
* coordinate `(x, y, z)`.
|
|
36
|
+
*
|
|
37
|
+
* @param cartesian - The given cartesian coordinate.
|
|
38
|
+
* @param target - An object to store this vector to. If this is not
|
|
39
|
+
* specified, a new vector will be created.
|
|
40
|
+
*/
|
|
15
41
|
geodeticSurfaceNormal(cartesian) {
|
|
16
42
|
let target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new THREE.Vector3();
|
|
17
43
|
return cartesian.toVector3(target).multiply(this._invRadiiSquared).normalize();
|
|
18
44
|
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Computes the normal vector to an ellipsoid at the given geographic
|
|
48
|
+
* coordinate `(longitude, latitude, altitude)`.
|
|
49
|
+
*
|
|
50
|
+
* @param coordCarto - The given geographic coordinate.
|
|
51
|
+
* @param target - An object to store this vector to. If this is not
|
|
52
|
+
* specified, a new vector will be created.
|
|
53
|
+
*/
|
|
19
54
|
geodeticSurfaceNormalCartographic(coordCarto) {
|
|
20
55
|
let target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new THREE.Vector3();
|
|
21
56
|
const longitude = THREE.MathUtils.degToRad(coordCarto.longitude);
|
|
@@ -23,13 +58,22 @@ class Ellipsoid {
|
|
|
23
58
|
const cosLatitude = Math.cos(latitude);
|
|
24
59
|
return target.set(cosLatitude * Math.cos(longitude), cosLatitude * Math.sin(longitude), Math.sin(latitude));
|
|
25
60
|
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Sets the length of the semi-axes of this ellipsoid from a 3-dimensional
|
|
64
|
+
* vector-like object. The object shall have both `x`, `y` and `z`
|
|
65
|
+
* properties.
|
|
66
|
+
*
|
|
67
|
+
* @param size - The source vector.
|
|
68
|
+
*/
|
|
26
69
|
setSize(size) {
|
|
27
70
|
this.size.set(size.x, size.y, size.z);
|
|
28
71
|
this._radiiSquared.multiplyVectors(size, size);
|
|
29
|
-
this._invRadiiSquared.x = size.x
|
|
30
|
-
this._invRadiiSquared.y = size.y
|
|
31
|
-
this._invRadiiSquared.z = size.z
|
|
72
|
+
this._invRadiiSquared.x = size.x === 0 ? 0 : 1 / this._radiiSquared.x;
|
|
73
|
+
this._invRadiiSquared.y = size.y === 0 ? 0 : 1 / this._radiiSquared.y;
|
|
74
|
+
this._invRadiiSquared.z = size.z === 0 ? 0 : 1 / this._radiiSquared.z;
|
|
32
75
|
this.eccentricity = Math.sqrt(this._radiiSquared.x - this._radiiSquared.z) / this.size.x;
|
|
76
|
+
return this;
|
|
33
77
|
}
|
|
34
78
|
cartographicToCartesian(coordCarto) {
|
|
35
79
|
let target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new THREE.Vector3();
|
|
@@ -42,18 +86,18 @@ class Ellipsoid {
|
|
|
42
86
|
}
|
|
43
87
|
|
|
44
88
|
/**
|
|
45
|
-
* Convert cartesian coordinates to geographic according to the current
|
|
46
|
-
*
|
|
47
|
-
* @param
|
|
48
|
-
* @param
|
|
49
|
-
* @
|
|
50
|
-
*
|
|
51
|
-
* @returns {Coordinate} an object describing the coordinates on the reference ellipsoid, angles are in degree
|
|
89
|
+
* Convert cartesian coordinates to geographic according to the current
|
|
90
|
+
* ellipsoid of revolution.
|
|
91
|
+
* @param position - The coordinate to convert
|
|
92
|
+
* @param target - coordinate to copy result
|
|
93
|
+
* @returns an object describing the coordinates on the reference ellipsoid,
|
|
94
|
+
* angles are in degree
|
|
52
95
|
*/
|
|
53
96
|
cartesianToCartographic(position) {
|
|
54
97
|
let target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Coordinates('EPSG:4326', 0, 0, 0);
|
|
55
98
|
// for details, see for example http://www.linz.govt.nz/data/geodetic-system/coordinate-conversion/geodetic-datum-conversions/equations-used-datum
|
|
56
|
-
// TODO the following is only valable for oblate ellipsoid of
|
|
99
|
+
// TODO the following is only valable for oblate ellipsoid of
|
|
100
|
+
// revolution. do we want to support triaxial ellipsoid?
|
|
57
101
|
const R = Math.sqrt(position.x * position.x + position.y * position.y + position.z * position.z);
|
|
58
102
|
const a = this.size.x; // x
|
|
59
103
|
const b = this.size.z; // z
|
|
@@ -92,9 +136,9 @@ class Ellipsoid {
|
|
|
92
136
|
const t1 = (-b + d) / (2 * a);
|
|
93
137
|
const t2 = (-b - d) / (2 * a);
|
|
94
138
|
if (t1 <= EPSILON && t2 <= EPSILON) {
|
|
139
|
+
// both intersections are behind the ray origin
|
|
95
140
|
return false;
|
|
96
|
-
}
|
|
97
|
-
// var back = (t1 <= EPSILON || t2 <= EPSILON); // If only one intersection (t>0) then we are inside the ellipsoid and the intersection is at the back of the ellipsoid
|
|
141
|
+
}
|
|
98
142
|
let t = 0;
|
|
99
143
|
if (t1 <= EPSILON) {
|
|
100
144
|
t = t2;
|
|
@@ -111,19 +155,16 @@ class Ellipsoid {
|
|
|
111
155
|
inter.addVectors(ray.origin, dir.clone().setLength(t));
|
|
112
156
|
return inter;
|
|
113
157
|
}
|
|
114
|
-
computeDistance(coordCarto1, coordCarto2) {
|
|
115
|
-
console.warn('computeDistance is renamed to geodesicDistance');
|
|
116
|
-
this.geodesicDistance(coordCarto1, coordCarto2);
|
|
117
|
-
}
|
|
118
158
|
|
|
119
159
|
/**
|
|
120
160
|
* Calculate the geodesic distance, between coordCarto1 and coordCarto2.
|
|
121
|
-
* It's most short distance on ellipsoid surface between coordCarto1 and
|
|
161
|
+
* It's most short distance on ellipsoid surface between coordCarto1 and
|
|
162
|
+
* coordCarto2.
|
|
122
163
|
* It's called orthodromy.
|
|
123
164
|
*
|
|
124
|
-
* @param
|
|
125
|
-
* @param
|
|
126
|
-
* @
|
|
165
|
+
* @param coordCarto1 - The coordinate carto 1
|
|
166
|
+
* @param coordCarto2 - The coordinate carto 2
|
|
167
|
+
* @returns The orthodromic distance between the two given coordinates.
|
|
127
168
|
*/
|
|
128
169
|
geodesicDistance(coordCarto1, coordCarto2) {
|
|
129
170
|
// The formula uses the distance on approximated sphere,
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* To change this license header, choose License Headers in Project Properties.
|
|
3
|
-
* To change this template file, choose Tools | Templates
|
|
4
|
-
* and open the template in the editor.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
1
|
import * as THREE from 'three';
|
|
8
2
|
import GeometryLayer from "../../../Layer/GeometryLayer.js";
|
|
9
3
|
import Coordinates from "../../Geographic/Coordinates.js";
|
|
@@ -31,6 +25,10 @@ const colorSky = new THREE.Color();
|
|
|
31
25
|
const spaceColor = new THREE.Color(0x030508);
|
|
32
26
|
const limitAlti = 600000;
|
|
33
27
|
const mfogDistance = ellipsoidSizes.x * 160.0;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @extends GeometryLayer
|
|
31
|
+
*/
|
|
34
32
|
class Atmosphere extends GeometryLayer {
|
|
35
33
|
/**
|
|
36
34
|
* It's layer to simulate Globe atmosphere.
|
|
@@ -40,8 +38,6 @@ class Atmosphere extends GeometryLayer {
|
|
|
40
38
|
* * [Atmosphere Shader From Space (Atmospheric scattering)](http://stainlessbeer.weebly.com/planets-9-atmospheric-scattering.html)
|
|
41
39
|
* * [Accurate Atmospheric Scattering (NVIDIA GPU Gems 2)](https://developer.nvidia.com/gpugems/gpugems2/part-ii-shading-lighting-and-shadows/chapter-16-accurate-atmospheric-scattering).
|
|
42
40
|
*
|
|
43
|
-
* @extends GeometryLayer
|
|
44
|
-
*
|
|
45
41
|
* @param {string} id - The id of the layer Atmosphere.
|
|
46
42
|
* @param {Object} [options] - options layer.
|
|
47
43
|
* @param {number} [options.Kr] - `Kr` is the rayleigh scattering constant.
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
2
|
import TiledGeometryLayer from "../../../Layer/TiledGeometryLayer.js";
|
|
3
3
|
import { ellipsoidSizes } from "../../Math/Ellipsoid.js";
|
|
4
|
-
import { globalExtentTMS, schemeTiles } from "../../
|
|
5
|
-
import
|
|
6
|
-
import CRS from "../../Geographic/Crs.js";
|
|
4
|
+
import { globalExtentTMS, schemeTiles } from "../../Tile/TileGrid.js";
|
|
5
|
+
import { GlobeTileBuilder } from "./GlobeTileBuilder.js";
|
|
7
6
|
|
|
8
7
|
// matrix to convert sphere to ellipsoid
|
|
9
8
|
const worldToScaledEllipsoid = new THREE.Matrix4();
|
|
@@ -18,18 +17,18 @@ const scaledHorizonCullingPoint = new THREE.Vector3();
|
|
|
18
17
|
* @property {boolean} isGlobeLayer - Used to checkout whether this layer is a
|
|
19
18
|
* GlobeLayer. Default is true. You should not change this, as it is used
|
|
20
19
|
* internally for optimisation.
|
|
20
|
+
*
|
|
21
|
+
* @extends TiledGeometryLayer
|
|
21
22
|
*/
|
|
22
23
|
class GlobeLayer extends TiledGeometryLayer {
|
|
23
24
|
/**
|
|
24
25
|
* A {@link TiledGeometryLayer} to use with a {@link GlobeView}. It has
|
|
25
26
|
* specific method for updating and subdivising its grid.
|
|
26
27
|
*
|
|
27
|
-
* @extends TiledGeometryLayer
|
|
28
|
-
*
|
|
29
28
|
* @param {string} id - The id of the layer, that should be unique. It is
|
|
30
29
|
* not mandatory, but an error will be emitted if this layer is added a
|
|
31
30
|
* {@link View} that already has a layer going by that id.
|
|
32
|
-
* @param {THREE.
|
|
31
|
+
* @param {THREE.Object3D} [object3d=THREE.Group] - The object3d used to
|
|
33
32
|
* contain the geometry of the TiledGeometryLayer. It is usually a
|
|
34
33
|
* `THREE.Group`, but it can be anything inheriting from a `THREE.Object3d`.
|
|
35
34
|
* @param {Object} [config] - Optional configuration, all elements in it
|
|
@@ -48,22 +47,30 @@ class GlobeLayer extends TiledGeometryLayer {
|
|
|
48
47
|
*/
|
|
49
48
|
constructor(id, object3d) {
|
|
50
49
|
let config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
50
|
+
const {
|
|
51
|
+
minSubdivisionLevel = 2,
|
|
52
|
+
maxSubdivisionLevel = 19,
|
|
53
|
+
...tiledConfig
|
|
54
|
+
} = config;
|
|
55
|
+
|
|
51
56
|
// Configure tiles
|
|
52
|
-
const scheme = schemeTiles.get(
|
|
57
|
+
const scheme = schemeTiles.get('EPSG:4326');
|
|
53
58
|
const schemeTile = globalExtentTMS.get('EPSG:4326').subdivisionByScheme(scheme);
|
|
54
59
|
|
|
55
60
|
// Supported tile matrix set for color/elevation layer
|
|
56
|
-
|
|
57
|
-
const uvCount =
|
|
58
|
-
const builder = new
|
|
59
|
-
crs: 'EPSG:4978',
|
|
61
|
+
const tileMatrixSets = ['EPSG:4326', 'EPSG:3857'];
|
|
62
|
+
const uvCount = tileMatrixSets.length;
|
|
63
|
+
const builder = new GlobeTileBuilder({
|
|
60
64
|
uvCount
|
|
61
65
|
});
|
|
62
|
-
super(id, object3d || new THREE.Group(), schemeTile, builder,
|
|
66
|
+
super(id, object3d || new THREE.Group(), schemeTile, builder, {
|
|
67
|
+
tileMatrixSets,
|
|
68
|
+
...tiledConfig
|
|
69
|
+
});
|
|
63
70
|
this.isGlobeLayer = true;
|
|
64
71
|
this.options.defaultPickingRadius = 5;
|
|
65
|
-
this.minSubdivisionLevel =
|
|
66
|
-
this.maxSubdivisionLevel =
|
|
72
|
+
this.minSubdivisionLevel = minSubdivisionLevel;
|
|
73
|
+
this.maxSubdivisionLevel = maxSubdivisionLevel;
|
|
67
74
|
this.extent = this.schemeTile[0].clone();
|
|
68
75
|
for (let i = 1; i < this.schemeTile.length; i++) {
|
|
69
76
|
this.extent.union(this.schemeTile[i]);
|
|
@@ -97,7 +104,7 @@ class GlobeLayer extends TiledGeometryLayer {
|
|
|
97
104
|
}
|
|
98
105
|
subdivision(context, layer, node) {
|
|
99
106
|
if (node.level == 5) {
|
|
100
|
-
const row = node.getExtentsByProjection(
|
|
107
|
+
const row = node.getExtentsByProjection('EPSG:4326')[0].row;
|
|
101
108
|
if (row == 31 || row == 0) {
|
|
102
109
|
// doesn't subdivise the pole
|
|
103
110
|
return false;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import Coordinates from "../../Geographic/Coordinates.js";
|
|
3
|
+
import Extent from "../../Geographic/Extent.js";
|
|
4
|
+
const PI_OV_FOUR = Math.PI / 4;
|
|
5
|
+
const INV_TWO_PI = 1.0 / (Math.PI * 2);
|
|
6
|
+
const axisZ = new THREE.Vector3(0, 0, 1);
|
|
7
|
+
const axisY = new THREE.Vector3(0, 1, 0);
|
|
8
|
+
const quatToAlignLongitude = new THREE.Quaternion();
|
|
9
|
+
const quatToAlignLatitude = new THREE.Quaternion();
|
|
10
|
+
const quatNormalToZ = new THREE.Quaternion();
|
|
11
|
+
|
|
12
|
+
/** Transforms a WGS84 latitude into a usable texture offset. */
|
|
13
|
+
function WGS84ToOneSubY(latitude) {
|
|
14
|
+
return 1.0 - (0.5 - Math.log(Math.tan(PI_OV_FOUR + THREE.MathUtils.degToRad(latitude) * 0.5)) * INV_TWO_PI);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Specialized parameters for the [GlobeTileBuilder]. */
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* TileBuilder implementation for the purpose of generating globe (or more
|
|
21
|
+
* precisely ellipsoidal) tile arrangements.
|
|
22
|
+
*/
|
|
23
|
+
export class GlobeTileBuilder {
|
|
24
|
+
static _crs = 'EPSG:4978';
|
|
25
|
+
static _computeExtraOffset(params) {
|
|
26
|
+
const t = WGS84ToOneSubY(params.coordinates.latitude) * params.nbRow;
|
|
27
|
+
return (!isFinite(t) ? 0 : t) - params.deltaUV1;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Buffer holding information about the tile/vertex currently being
|
|
32
|
+
* processed.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
get crs() {
|
|
36
|
+
return GlobeTileBuilder._crs;
|
|
37
|
+
}
|
|
38
|
+
constructor(options) {
|
|
39
|
+
this._transform = {
|
|
40
|
+
coords: [new Coordinates('EPSG:4326', 0, 0), new Coordinates('EPSG:4326', 0, 0)],
|
|
41
|
+
position: new THREE.Vector3(),
|
|
42
|
+
dimension: new THREE.Vector2()
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// UV: Normalized coordinates (from degree) on the entire tile
|
|
46
|
+
// EPSG:4326
|
|
47
|
+
// Offset: Float row coordinate from Pseudo mercator coordinates
|
|
48
|
+
// EPSG:3857
|
|
49
|
+
if (options.uvCount > 1) {
|
|
50
|
+
this.computeExtraOffset = GlobeTileBuilder._computeExtraOffset;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
prepare(params) {
|
|
54
|
+
const nbRow = 2 ** (params.level + 1.0);
|
|
55
|
+
let st1 = WGS84ToOneSubY(params.extent.south);
|
|
56
|
+
if (!isFinite(st1)) {
|
|
57
|
+
st1 = 0;
|
|
58
|
+
}
|
|
59
|
+
const start = st1 % (1.0 / nbRow);
|
|
60
|
+
const newParams = {
|
|
61
|
+
nbRow,
|
|
62
|
+
deltaUV1: (st1 - start) * nbRow,
|
|
63
|
+
// transformation to align tile's normal to z axis
|
|
64
|
+
quatNormalToZ: quatNormalToZ.setFromAxisAngle(axisY, -(Math.PI * 0.5 - THREE.MathUtils.degToRad(params.extent.center().latitude))),
|
|
65
|
+
// let's avoid building too much temp objects
|
|
66
|
+
coordinates: new Coordinates(this.crs)
|
|
67
|
+
};
|
|
68
|
+
params.extent.planarDimensions(this._transform.dimension);
|
|
69
|
+
return {
|
|
70
|
+
...params,
|
|
71
|
+
...newParams
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
center(extent) {
|
|
75
|
+
return extent.center(this._transform.coords[0]).as(this.crs, this._transform.coords[1]).toVector3();
|
|
76
|
+
}
|
|
77
|
+
vertexPosition(coordinates) {
|
|
78
|
+
return this._transform.coords[0].setFromValues(coordinates.x, coordinates.y).as(this.crs, this._transform.coords[1]).toVector3(this._transform.position);
|
|
79
|
+
}
|
|
80
|
+
vertexNormal() {
|
|
81
|
+
return this._transform.coords[1].geodesicNormal;
|
|
82
|
+
}
|
|
83
|
+
uProject(u, extent) {
|
|
84
|
+
return extent.west + u * this._transform.dimension.x;
|
|
85
|
+
}
|
|
86
|
+
vProject(v, extent) {
|
|
87
|
+
return extent.south + v * this._transform.dimension.y;
|
|
88
|
+
}
|
|
89
|
+
computeShareableExtent(extent) {
|
|
90
|
+
// NOTE: It should be possible to take advantage of equatorial plane
|
|
91
|
+
// symmetry, for which we'd have to reverse the tile's UVs.
|
|
92
|
+
// This would halve the memory requirement when viewing a full globe,
|
|
93
|
+
// but that case is not that relevant for iTowns' usual use cases and
|
|
94
|
+
// the globe mesh memory usage is already inconsequential.
|
|
95
|
+
const sizeLongitude = Math.abs(extent.west - extent.east) / 2;
|
|
96
|
+
const shareableExtent = new Extent(extent.crs, -sizeLongitude, sizeLongitude, extent.south, extent.north);
|
|
97
|
+
|
|
98
|
+
// Compute rotation to transform the tile to position on the ellispoid.
|
|
99
|
+
// This transformation takes the parents' transformation into account.
|
|
100
|
+
const rotLon = THREE.MathUtils.degToRad(extent.west - shareableExtent.west);
|
|
101
|
+
const rotLat = THREE.MathUtils.degToRad(90 - extent.center(this._transform.coords[0]).latitude);
|
|
102
|
+
quatToAlignLongitude.setFromAxisAngle(axisZ, rotLon);
|
|
103
|
+
quatToAlignLatitude.setFromAxisAngle(axisY, rotLat);
|
|
104
|
+
quatToAlignLongitude.multiply(quatToAlignLatitude);
|
|
105
|
+
return {
|
|
106
|
+
shareableExtent,
|
|
107
|
+
quaternion: quatToAlignLongitude.clone(),
|
|
108
|
+
position: this.center(extent)
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -5,7 +5,6 @@ import Coordinates from "../Geographic/Coordinates.js";
|
|
|
5
5
|
import GlobeLayer from "./Globe/GlobeLayer.js";
|
|
6
6
|
import Atmosphere from "./Globe/Atmosphere.js";
|
|
7
7
|
import CameraUtils from "../../Utils/CameraUtils.js";
|
|
8
|
-
import CRS from "../Geographic/Crs.js";
|
|
9
8
|
import { ellipsoidSizes } from "../Math/Ellipsoid.js";
|
|
10
9
|
|
|
11
10
|
/**
|
|
@@ -90,10 +89,6 @@ class GlobeView extends View {
|
|
|
90
89
|
this.camera3D.far = ellipsoidSizes.x * 10;
|
|
91
90
|
const tileLayer = new GlobeLayer('globe', options.object3d, options);
|
|
92
91
|
this.mainLoop.gfxEngine.label2dRenderer.infoTileLayer = tileLayer.info;
|
|
93
|
-
const sun = new THREE.DirectionalLight();
|
|
94
|
-
sun.position.set(-0.5, 0, 1);
|
|
95
|
-
sun.updateMatrixWorld(true);
|
|
96
|
-
this.scene.add(sun);
|
|
97
92
|
this.addLayer(tileLayer);
|
|
98
93
|
this.tileLayer = tileLayer;
|
|
99
94
|
if (!placement.isExtent) {
|
|
@@ -133,11 +128,11 @@ class GlobeView extends View {
|
|
|
133
128
|
return Promise.reject(new Error('Add Layer type object'));
|
|
134
129
|
}
|
|
135
130
|
if (layer.isColorLayer) {
|
|
136
|
-
if (!this.tileLayer.tileMatrixSets.includes(
|
|
131
|
+
if (!this.tileLayer.tileMatrixSets.includes(layer.source.crs)) {
|
|
137
132
|
return layer._reject(`Only ${this.tileLayer.tileMatrixSets} tileMatrixSet are currently supported for color layers`);
|
|
138
133
|
}
|
|
139
134
|
} else if (layer.isElevationLayer) {
|
|
140
|
-
if (
|
|
135
|
+
if (layer.source.crs !== this.tileLayer.tileMatrixSets[0]) {
|
|
141
136
|
return layer._reject(`Only ${this.tileLayer.tileMatrixSets[0]} tileMatrixSet is currently supported for elevation layers`);
|
|
142
137
|
}
|
|
143
138
|
}
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
2
|
import TiledGeometryLayer from "../../../Layer/TiledGeometryLayer.js";
|
|
3
|
-
import { globalExtentTMS } from "../../
|
|
4
|
-
import
|
|
5
|
-
import PlanarTileBuilder from "./PlanarTileBuilder.js";
|
|
3
|
+
import { globalExtentTMS } from "../../Tile/TileGrid.js";
|
|
4
|
+
import { PlanarTileBuilder } from "./PlanarTileBuilder.js";
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* @property {boolean} isPlanarLayer - Used to checkout whether this layer is a
|
|
9
8
|
* PlanarLayer. Default is true. You should not change this, as it is used
|
|
10
9
|
* internally for optimisation.
|
|
10
|
+
* @extends TiledGeometryLayer
|
|
11
11
|
*/
|
|
12
12
|
class PlanarLayer extends TiledGeometryLayer {
|
|
13
13
|
/**
|
|
14
14
|
* A {@link TiledGeometryLayer} to use with a {@link PlanarView}. It has
|
|
15
15
|
* specific method for updating and subdivising its grid.
|
|
16
16
|
*
|
|
17
|
-
* @extends TiledGeometryLayer
|
|
18
|
-
*
|
|
19
17
|
* @param {string} id - The id of the layer, that should be unique. It is
|
|
20
18
|
* not mandatory, but an error will be emitted if this layer is added a
|
|
21
19
|
* {@link View} that already has a layer going by that id.
|
|
@@ -35,19 +33,27 @@ class PlanarLayer extends TiledGeometryLayer {
|
|
|
35
33
|
*/
|
|
36
34
|
constructor(id, extent, object3d) {
|
|
37
35
|
let config = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
|
|
38
|
-
const
|
|
36
|
+
const {
|
|
37
|
+
minSubdivisionLevel = 0,
|
|
38
|
+
maxSubdivisionLevel = 5,
|
|
39
|
+
...tiledConfig
|
|
40
|
+
} = config;
|
|
41
|
+
const tileMatrixSets = [extent.crs];
|
|
39
42
|
if (!globalExtentTMS.get(extent.crs)) {
|
|
40
43
|
// Add new global extent for this new crs projection.
|
|
41
44
|
globalExtentTMS.set(extent.crs, extent);
|
|
42
45
|
}
|
|
43
|
-
|
|
44
|
-
super(id, object3d || new THREE.Group(), [extent], new PlanarTileBuilder({
|
|
46
|
+
const builder = new PlanarTileBuilder({
|
|
45
47
|
crs: extent.crs
|
|
46
|
-
})
|
|
48
|
+
});
|
|
49
|
+
super(id, object3d || new THREE.Group(), [extent], builder, {
|
|
50
|
+
tileMatrixSets,
|
|
51
|
+
...tiledConfig
|
|
52
|
+
});
|
|
47
53
|
this.isPlanarLayer = true;
|
|
48
54
|
this.extent = extent;
|
|
49
|
-
this.minSubdivisionLevel =
|
|
50
|
-
this.maxSubdivisionLevel =
|
|
55
|
+
this.minSubdivisionLevel = minSubdivisionLevel;
|
|
56
|
+
this.maxSubdivisionLevel = maxSubdivisionLevel;
|
|
51
57
|
}
|
|
52
58
|
}
|
|
53
59
|
export default PlanarLayer;
|
|
@@ -3,70 +3,70 @@ import Coordinates from "../../Geographic/Coordinates.js";
|
|
|
3
3
|
import Extent from "../../Geographic/Extent.js";
|
|
4
4
|
const quaternion = new THREE.Quaternion();
|
|
5
5
|
const center = new THREE.Vector3();
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
|
|
7
|
+
/** Specialized parameters for the [PlanarTileBuilder]. */
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* TileBuilder implementation for the purpose of generating planar
|
|
11
|
+
* tile arrangements.
|
|
12
|
+
*/
|
|
13
|
+
export class PlanarTileBuilder {
|
|
14
|
+
constructor(options) {
|
|
10
15
|
if (options.projection) {
|
|
11
|
-
console.warn('PlanarTileBuilder projection parameter is deprecated, use crs instead.');
|
|
12
|
-
options.crs
|
|
13
|
-
}
|
|
14
|
-
if (options.crs) {
|
|
15
|
-
this.crs = options.crs;
|
|
16
|
-
} else {
|
|
17
|
-
throw new Error('options.crs is mandatory for PlanarTileBuilder');
|
|
16
|
+
console.warn('PlanarTileBuilder projection parameter is deprecated,' + ' use crs instead.');
|
|
17
|
+
options.crs ??= options.projection;
|
|
18
18
|
}
|
|
19
|
-
this.
|
|
19
|
+
this._crs = options.crs;
|
|
20
|
+
this._transform = {
|
|
20
21
|
coords: new Coordinates('EPSG:4326', 0, 0),
|
|
21
22
|
position: new THREE.Vector3(),
|
|
22
23
|
normal: new THREE.Vector3(0, 0, 1)
|
|
23
24
|
};
|
|
24
|
-
this.
|
|
25
|
+
this._uvCount = options.uvCount ?? 1;
|
|
26
|
+
}
|
|
27
|
+
get uvCount() {
|
|
28
|
+
return this._uvCount;
|
|
29
|
+
}
|
|
30
|
+
get crs() {
|
|
31
|
+
return this._crs;
|
|
25
32
|
}
|
|
26
|
-
// prepare params
|
|
27
|
-
// init projected object -> params.projected
|
|
28
33
|
prepare(params) {
|
|
29
|
-
|
|
30
|
-
|
|
34
|
+
const newParams = params;
|
|
35
|
+
newParams.nbRow = 2 ** (params.level + 1.0);
|
|
36
|
+
newParams.coordinates = new Coordinates(this.crs);
|
|
37
|
+
return newParams;
|
|
31
38
|
}
|
|
32
|
-
|
|
33
|
-
// get center tile in cartesian 3D
|
|
34
39
|
center(extent) {
|
|
35
|
-
extent.center(this.
|
|
36
|
-
center.set(this.
|
|
40
|
+
extent.center(this._transform.coords);
|
|
41
|
+
center.set(this._transform.coords.x, this._transform.coords.y, 0);
|
|
37
42
|
return center;
|
|
38
43
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
this.tmp.position.set(params.projected.x, params.projected.y, 0);
|
|
43
|
-
return this.tmp.position;
|
|
44
|
+
vertexPosition(coordinates) {
|
|
45
|
+
this._transform.position.set(coordinates.x, coordinates.y, 0);
|
|
46
|
+
return this._transform.position;
|
|
44
47
|
}
|
|
45
|
-
|
|
46
|
-
// get normal for last vertex
|
|
47
48
|
vertexNormal() {
|
|
48
|
-
return this.
|
|
49
|
+
return this._transform.normal;
|
|
49
50
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
uProjecte(u, params) {
|
|
53
|
-
params.projected.x = params.extent.west + u * (params.extent.east - params.extent.west);
|
|
51
|
+
uProject(u, extent) {
|
|
52
|
+
return extent.west + u * (extent.east - extent.west);
|
|
54
53
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
vProjecte(v, params) {
|
|
58
|
-
params.projected.y = params.extent.south + v * (params.extent.north - params.extent.south);
|
|
54
|
+
vProject(v, extent) {
|
|
55
|
+
return extent.south + v * (extent.north - extent.south);
|
|
59
56
|
}
|
|
60
|
-
|
|
61
|
-
// compute
|
|
57
|
+
computeShareableExtent(extent) {
|
|
58
|
+
// compute shareable extent to pool the geometries
|
|
62
59
|
// the geometry in common extent is identical to the existing input
|
|
63
60
|
// with a translation
|
|
64
|
-
const sharableExtent = new Extent(extent.crs, 0, Math.abs(extent.west - extent.east), 0, Math.abs(extent.north - extent.south));
|
|
65
61
|
return {
|
|
66
|
-
|
|
62
|
+
shareableExtent: new Extent(extent.crs).setFromExtent({
|
|
63
|
+
west: 0,
|
|
64
|
+
east: Math.abs(extent.west - extent.east),
|
|
65
|
+
south: 0,
|
|
66
|
+
north: Math.abs(extent.north - extent.south)
|
|
67
|
+
}),
|
|
67
68
|
quaternion,
|
|
68
69
|
position: this.center(extent).clone()
|
|
69
70
|
};
|
|
70
71
|
}
|
|
71
|
-
}
|
|
72
|
-
export default PlanarTileBuilder;
|
|
72
|
+
}
|