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
package/lib/Source/Source.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as CRS from "../Core/Geographic/Crs.js";
|
|
1
2
|
import Extent from "../Core/Geographic/Extent.js";
|
|
2
3
|
import GeoJsonParser from "../Parser/GeoJsonParser.js";
|
|
3
4
|
import KMLParser from "../Parser/KMLParser.js";
|
|
@@ -7,40 +8,17 @@ import GTXParser from "../Parser/GTXParser.js";
|
|
|
7
8
|
import ISGParser from "../Parser/ISGParser.js";
|
|
8
9
|
import VectorTileParser from "../Parser/VectorTileParser.js";
|
|
9
10
|
import Fetcher from "../Provider/Fetcher.js";
|
|
10
|
-
import Cache from
|
|
11
|
-
import
|
|
11
|
+
// import Cache from 'Core/Scheduler/Cache';
|
|
12
|
+
import { LRUCache } from 'lru-cache';
|
|
12
13
|
|
|
13
14
|
/** @private */
|
|
14
15
|
export const supportedParsers = new Map([['application/geo+json', GeoJsonParser.parse], ['application/json', GeoJsonParser.parse], ['application/kml', KMLParser.parse], ['application/gpx', GpxParser.parse], ['application/x-protobuf;type=mapbox-vector', VectorTileParser.parse], ['application/gtx', GTXParser.parse], ['application/isg', ISGParser.parse], ['application/gdf', GDFParser.parse]]);
|
|
15
16
|
const noCache = {
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
get: () => {},
|
|
18
|
+
set: a => a,
|
|
18
19
|
clear: () => {}
|
|
19
20
|
};
|
|
20
21
|
|
|
21
|
-
/**
|
|
22
|
-
* @property {string} crs - data crs projection.
|
|
23
|
-
* @property {boolean} isInverted - This option is to be set to the
|
|
24
|
-
* correct value, true or false (default being false), if the computation of
|
|
25
|
-
* the coordinates needs to be inverted to same scheme as OSM, Google Maps
|
|
26
|
-
* or other system. See [this link](
|
|
27
|
-
* https://alastaira.wordpress.com/2011/07/06/converting-tms-tile-coordinates-to-googlebingosm-tile-coordinates)
|
|
28
|
-
* for more informations.
|
|
29
|
-
*
|
|
30
|
-
*/
|
|
31
|
-
class InformationsData {
|
|
32
|
-
constructor(options) {
|
|
33
|
-
/* istanbul ignore next */
|
|
34
|
-
if (options.projection) {
|
|
35
|
-
console.warn('Source projection parameter is deprecated, use crs instead.');
|
|
36
|
-
options.crs = options.crs || options.projection;
|
|
37
|
-
}
|
|
38
|
-
if (options.crs) {
|
|
39
|
-
CRS.isValid(options.crs);
|
|
40
|
-
}
|
|
41
|
-
this.crs = options.crs;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
22
|
/**
|
|
45
23
|
* This interface describes parsing options.
|
|
46
24
|
* @typedef {Object} ParsingOptions
|
|
@@ -94,13 +72,20 @@ let uid = 0;
|
|
|
94
72
|
* depending on the current fetched tile for example</li>
|
|
95
73
|
* </ul>
|
|
96
74
|
*/
|
|
97
|
-
class Source
|
|
75
|
+
class Source {
|
|
98
76
|
/**
|
|
99
77
|
* @param {Object} source - An object that can contain all properties of a
|
|
100
78
|
* Source. Only the `url` property is mandatory.
|
|
101
79
|
*/
|
|
102
80
|
constructor(source) {
|
|
103
|
-
|
|
81
|
+
if (source.projection) {
|
|
82
|
+
console.warn('Source projection parameter is deprecated, use crs instead.');
|
|
83
|
+
source.crs = source.crs || source.projection;
|
|
84
|
+
}
|
|
85
|
+
if (source.crs) {
|
|
86
|
+
CRS.isValid(source.crs);
|
|
87
|
+
}
|
|
88
|
+
this.crs = source.crs;
|
|
104
89
|
this.isSource = true;
|
|
105
90
|
if (!source.url) {
|
|
106
91
|
throw new Error('New Source: url is required');
|
|
@@ -122,7 +107,7 @@ class Source extends InformationsData {
|
|
|
122
107
|
this.whenReady = Promise.resolve();
|
|
123
108
|
this._featuresCaches = {};
|
|
124
109
|
if (source.extent && !source.extent.isExtent) {
|
|
125
|
-
this.extent = new Extent(this.crs
|
|
110
|
+
this.extent = new Extent(this.crs).setFromExtent(source.extent);
|
|
126
111
|
} else {
|
|
127
112
|
this.extent = source.extent;
|
|
128
113
|
}
|
|
@@ -142,8 +127,8 @@ class Source extends InformationsData {
|
|
|
142
127
|
urlFromExtent() {
|
|
143
128
|
throw new Error('In extended Source, you have to implement the method urlFromExtent!');
|
|
144
129
|
}
|
|
145
|
-
|
|
146
|
-
return
|
|
130
|
+
getDataKey(extent) {
|
|
131
|
+
return `z${extent.zoom}r${extent.row}c${extent.col}`;
|
|
147
132
|
}
|
|
148
133
|
|
|
149
134
|
/**
|
|
@@ -156,25 +141,18 @@ class Source extends InformationsData {
|
|
|
156
141
|
*/
|
|
157
142
|
loadData(extent, out) {
|
|
158
143
|
const cache = this._featuresCaches[out.crs];
|
|
159
|
-
const key = this.
|
|
144
|
+
const key = this.getDataKey(extent);
|
|
145
|
+
// console.log('Source.loadData', key);
|
|
160
146
|
// try to get parsed data from cache
|
|
161
|
-
let features = cache.
|
|
147
|
+
let features = cache.get(key);
|
|
162
148
|
if (!features) {
|
|
163
149
|
// otherwise fetch/parse the data
|
|
164
|
-
features =
|
|
150
|
+
features = this.fetcher(this.urlFromExtent(extent), this.networkOptions).then(file => this.parser(file, {
|
|
165
151
|
out,
|
|
166
152
|
in: this,
|
|
167
153
|
extent
|
|
168
|
-
})).catch(err => this.handlingError(err))
|
|
169
|
-
|
|
170
|
-
/* istanbul ignore next */
|
|
171
|
-
if (this.onParsedFile) {
|
|
172
|
-
features.then(feat => {
|
|
173
|
-
this.onParsedFile(feat);
|
|
174
|
-
console.warn('Source.onParsedFile was deprecated');
|
|
175
|
-
return feat;
|
|
176
|
-
});
|
|
177
|
-
}
|
|
154
|
+
})).catch(err => this.handlingError(err));
|
|
155
|
+
cache.set(key, features);
|
|
178
156
|
}
|
|
179
157
|
return features;
|
|
180
158
|
}
|
|
@@ -190,7 +168,9 @@ class Source extends InformationsData {
|
|
|
190
168
|
// Cache feature only if it's vector data, the feature are cached in source.
|
|
191
169
|
// It's not necessary to cache raster in Source,
|
|
192
170
|
// because it's already cached on layer.
|
|
193
|
-
this._featuresCaches[options.out.crs] = this.isVectorSource ? new
|
|
171
|
+
this._featuresCaches[options.out.crs] = this.isVectorSource ? new LRUCache({
|
|
172
|
+
max: 500
|
|
173
|
+
}) : noCache;
|
|
194
174
|
}
|
|
195
175
|
}
|
|
196
176
|
|
package/lib/Source/TMSSource.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import Source from "./Source.js";
|
|
2
2
|
import URLBuilder from "../Provider/URLBuilder.js";
|
|
3
|
-
import Extent
|
|
4
|
-
import
|
|
5
|
-
|
|
3
|
+
import Extent from "../Core/Geographic/Extent.js";
|
|
4
|
+
import Tile from "../Core/Tile/Tile.js";
|
|
5
|
+
import { globalExtentTMS } from "../Core/Tile/TileGrid.js";
|
|
6
|
+
const _tile = new Tile('EPSG:4326', 0, 0, 0);
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* An object defining the source of resources to get from a
|
|
@@ -86,7 +87,7 @@ class TMSSource extends Source {
|
|
|
86
87
|
}
|
|
87
88
|
this.zoom = source.zoom;
|
|
88
89
|
this.isInverted = source.isInverted || false;
|
|
89
|
-
this.crs =
|
|
90
|
+
this.crs = source.crs;
|
|
90
91
|
this.tileMatrixSetLimits = source.tileMatrixSetLimits;
|
|
91
92
|
this.extentSetlimits = {};
|
|
92
93
|
this.tileMatrixCallback = source.tileMatrixCallback || (zoomLevel => zoomLevel);
|
|
@@ -107,8 +108,8 @@ class TMSSource extends Source {
|
|
|
107
108
|
}
|
|
108
109
|
}
|
|
109
110
|
}
|
|
110
|
-
urlFromExtent(
|
|
111
|
-
return URLBuilder.xyz(
|
|
111
|
+
urlFromExtent(tile) {
|
|
112
|
+
return URLBuilder.xyz(tile, this);
|
|
112
113
|
}
|
|
113
114
|
onLayerAdded(options) {
|
|
114
115
|
super.onLayerAdded(options);
|
|
@@ -118,17 +119,17 @@ class TMSSource extends Source {
|
|
|
118
119
|
const crs = parent ? parent.extent.crs : options.out.crs;
|
|
119
120
|
if (this.tileMatrixSetLimits && !this.extentSetlimits[crs]) {
|
|
120
121
|
this.extentSetlimits[crs] = {};
|
|
121
|
-
|
|
122
|
+
_tile.crs = this.crs;
|
|
122
123
|
for (let i = this.zoom.max; i >= this.zoom.min; i--) {
|
|
123
124
|
const tmsl = this.tileMatrixSetLimits[i];
|
|
124
125
|
const {
|
|
125
126
|
west,
|
|
126
127
|
north
|
|
127
|
-
} =
|
|
128
|
+
} = _tile.set(i, tmsl.minTileRow, tmsl.minTileCol).toExtent(crs);
|
|
128
129
|
const {
|
|
129
130
|
east,
|
|
130
131
|
south
|
|
131
|
-
} =
|
|
132
|
+
} = _tile.set(i, tmsl.maxTileRow, tmsl.maxTileCol).toExtent(crs);
|
|
132
133
|
this.extentSetlimits[crs][i] = new Extent(crs, west, east, south, north);
|
|
133
134
|
}
|
|
134
135
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { featureFilter } from '@
|
|
2
|
-
import
|
|
1
|
+
import { featureFilter } from '@maplibre/maplibre-gl-style-spec';
|
|
2
|
+
import StyleOptions from "../Core/StyleOptions.js";
|
|
3
3
|
import TMSSource from "./TMSSource.js";
|
|
4
4
|
import URLBuilder from "../Provider/URLBuilder.js";
|
|
5
5
|
import Fetcher from "../Provider/Fetcher.js";
|
|
@@ -20,6 +20,15 @@ function mergeCollections(collections) {
|
|
|
20
20
|
return collection;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
// A deprecated (but still in use) Mapbox spec allows using 'ref' as a propertie to reference an other layer
|
|
24
|
+
// instead of duplicating the following properties: 'type', 'source', 'source-layer', 'minzoom', 'maxzoom', 'filter', 'layout'
|
|
25
|
+
function getPropertiesFromRefLayer(layers, layer) {
|
|
26
|
+
const refLayer = layers.filter(l => l.id === layer.ref)[0];
|
|
27
|
+
['type', 'source', 'source-layer', 'minzoom', 'maxzoom', 'filter', 'layout'].forEach(prop => {
|
|
28
|
+
layer[prop] = refLayer[prop];
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
23
32
|
/**
|
|
24
33
|
* VectorTilesSource are object containing informations on how to fetch vector
|
|
25
34
|
* tiles resources.
|
|
@@ -69,36 +78,41 @@ class VectorTilesSource extends TMSSource {
|
|
|
69
78
|
let promise;
|
|
70
79
|
this.isVectorTileSource = true;
|
|
71
80
|
this.accessToken = source.accessToken;
|
|
81
|
+
let mvtStyleUrl;
|
|
72
82
|
if (source.style) {
|
|
73
83
|
if (typeof source.style == 'string') {
|
|
74
|
-
|
|
75
|
-
promise = Fetcher.json(
|
|
84
|
+
mvtStyleUrl = urlParser.normalizeStyleURL(source.style, this.accessToken);
|
|
85
|
+
promise = Fetcher.json(mvtStyleUrl, this.networkOptions);
|
|
76
86
|
} else {
|
|
77
87
|
promise = Promise.resolve(source.style);
|
|
78
88
|
}
|
|
79
89
|
} else {
|
|
80
90
|
throw new Error('New VectorTilesSource: style is required');
|
|
81
91
|
}
|
|
82
|
-
this.whenReady = promise.then(
|
|
83
|
-
this.jsonStyle =
|
|
84
|
-
|
|
92
|
+
this.whenReady = promise.then(mvtStyle => {
|
|
93
|
+
this.jsonStyle = mvtStyle;
|
|
94
|
+
let baseurl = source.sprite || mvtStyle.sprite;
|
|
85
95
|
if (baseurl) {
|
|
96
|
+
baseurl = new URL(baseurl, mvtStyleUrl).toString();
|
|
86
97
|
const spriteUrl = urlParser.normalizeSpriteURL(baseurl, '', '.json', this.accessToken);
|
|
87
98
|
return Fetcher.json(spriteUrl, this.networkOptions).then(sprites => {
|
|
88
99
|
this.sprites = sprites;
|
|
89
100
|
const imgUrl = urlParser.normalizeSpriteURL(baseurl, '', '.png', this.accessToken);
|
|
90
101
|
this.sprites.source = imgUrl;
|
|
91
|
-
return
|
|
102
|
+
return mvtStyle;
|
|
92
103
|
});
|
|
93
104
|
}
|
|
94
|
-
return
|
|
95
|
-
}).then(
|
|
96
|
-
|
|
105
|
+
return mvtStyle;
|
|
106
|
+
}).then(mvtStyle => {
|
|
107
|
+
mvtStyle.layers.forEach((layer, order) => {
|
|
97
108
|
layer.sourceUid = this.uid;
|
|
98
109
|
if (layer.type === 'background') {
|
|
99
110
|
this.backgroundLayer = layer;
|
|
100
111
|
} else if (ffilter(layer)) {
|
|
101
|
-
|
|
112
|
+
if (layer['source-layer'] === undefined) {
|
|
113
|
+
getPropertiesFromRefLayer(mvtStyle.layers, layer);
|
|
114
|
+
}
|
|
115
|
+
const style = StyleOptions.setFromVectorTileLayer(layer, this.sprites, this.symbolToCircle);
|
|
102
116
|
this.styles[layer.id] = style;
|
|
103
117
|
if (!this.layers[layer['source-layer']]) {
|
|
104
118
|
this.layers[layer['source-layer']] = [];
|
|
@@ -106,20 +120,18 @@ class VectorTilesSource extends TMSSource {
|
|
|
106
120
|
this.layers[layer['source-layer']].push({
|
|
107
121
|
id: layer.id,
|
|
108
122
|
order,
|
|
109
|
-
filterExpression: featureFilter(layer.filter)
|
|
110
|
-
zoom: {
|
|
111
|
-
min: layer.minzoom || 0,
|
|
112
|
-
max: layer.maxzoom || 24
|
|
113
|
-
}
|
|
123
|
+
filterExpression: featureFilter(layer.filter)
|
|
114
124
|
});
|
|
115
125
|
}
|
|
116
126
|
});
|
|
117
127
|
if (this.url == '.') {
|
|
118
|
-
const TMSUrlList = Object.values(
|
|
128
|
+
const TMSUrlList = Object.values(mvtStyle.sources).map(sourceVT => {
|
|
119
129
|
if (sourceVT.url) {
|
|
130
|
+
sourceVT.url = new URL(sourceVT.url, mvtStyleUrl).toString();
|
|
120
131
|
const urlSource = urlParser.normalizeSourceURL(sourceVT.url, this.accessToken);
|
|
121
132
|
return Fetcher.json(urlSource, this.networkOptions).then(tileJSON => {
|
|
122
133
|
if (tileJSON.tiles[0]) {
|
|
134
|
+
tileJSON.tiles[0] = decodeURIComponent(new URL(tileJSON.tiles[0], urlSource).toString());
|
|
123
135
|
return toTMSUrl(tileJSON.tiles[0]);
|
|
124
136
|
}
|
|
125
137
|
});
|
|
@@ -130,13 +142,13 @@ class VectorTilesSource extends TMSSource {
|
|
|
130
142
|
});
|
|
131
143
|
return Promise.all(TMSUrlList);
|
|
132
144
|
}
|
|
133
|
-
return Promise.resolve([this.url]);
|
|
145
|
+
return Promise.resolve([toTMSUrl(this.url)]);
|
|
134
146
|
}).then(TMSUrlList => {
|
|
135
147
|
this.urls = Array.from(new Set(TMSUrlList));
|
|
136
148
|
});
|
|
137
149
|
}
|
|
138
|
-
urlFromExtent(
|
|
139
|
-
return URLBuilder.xyz(
|
|
150
|
+
urlFromExtent(tile, url) {
|
|
151
|
+
return URLBuilder.xyz(tile, {
|
|
140
152
|
tileMatrixCallback: this.tileMatrixCallback,
|
|
141
153
|
url
|
|
142
154
|
});
|
|
@@ -152,25 +164,17 @@ class VectorTilesSource extends TMSSource {
|
|
|
152
164
|
}
|
|
153
165
|
loadData(extent, out) {
|
|
154
166
|
const cache = this._featuresCaches[out.crs];
|
|
155
|
-
const key = this.
|
|
167
|
+
const key = this.getDataKey(extent);
|
|
156
168
|
// try to get parsed data from cache
|
|
157
|
-
let features = cache.
|
|
169
|
+
let features = cache.get(key);
|
|
158
170
|
if (!features) {
|
|
159
171
|
// otherwise fetch/parse the data
|
|
160
|
-
features =
|
|
172
|
+
features = Promise.all(this.urls.map(url => this.fetcher(this.urlFromExtent(extent, url), this.networkOptions).then(file => this.parser(file, {
|
|
161
173
|
out,
|
|
162
174
|
in: this,
|
|
163
175
|
extent
|
|
164
|
-
})))).then(collections => mergeCollections(collections)).catch(err => this.handlingError(err))
|
|
165
|
-
|
|
166
|
-
/* istanbul ignore next */
|
|
167
|
-
if (this.onParsedFile) {
|
|
168
|
-
features.then(feat => {
|
|
169
|
-
this.onParsedFile(feat);
|
|
170
|
-
console.warn('Source.onParsedFile was deprecated');
|
|
171
|
-
return feat;
|
|
172
|
-
});
|
|
173
|
-
}
|
|
176
|
+
})))).then(collections => mergeCollections(collections)).catch(err => this.handlingError(err));
|
|
177
|
+
cache.set(key, features);
|
|
174
178
|
}
|
|
175
179
|
return features;
|
|
176
180
|
}
|
package/lib/Source/WFSSource.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Source from "./Source.js";
|
|
2
2
|
import URLBuilder from "../Provider/URLBuilder.js";
|
|
3
|
-
import
|
|
3
|
+
import Extent from "../Core/Geographic/Extent.js";
|
|
4
|
+
const _extent = new Extent('EPSG:4326');
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* An object defining the source of resources to get from a
|
|
@@ -118,22 +119,25 @@ class WFSSource extends Source {
|
|
|
118
119
|
this.typeName = source.typeName;
|
|
119
120
|
this.version = source.version || '2.0.2';
|
|
120
121
|
this.bboxDigits = source.bboxDigits;
|
|
121
|
-
|
|
122
|
-
// Add ? at the end of the url if it is not already in the given URL
|
|
123
|
-
if (!this.url.endsWith('?')) {
|
|
124
|
-
this.url = `${this.url}?`;
|
|
125
|
-
}
|
|
126
|
-
this.url = `${source.url}SERVICE=WFS&REQUEST=GetFeature&typeName=${this.typeName}&VERSION=${this.version}&SRSNAME=${this.crs}&outputFormat=${this.format}&BBOX=%bbox,${this.crs}`;
|
|
127
122
|
this.zoom = {
|
|
128
123
|
min: 0,
|
|
129
124
|
max: Infinity
|
|
130
125
|
};
|
|
126
|
+
const urlObj = new URL(source.url);
|
|
127
|
+
urlObj.searchParams.set('SERVICE', 'WFS');
|
|
128
|
+
urlObj.searchParams.set('REQUEST', 'GetFeature');
|
|
129
|
+
urlObj.searchParams.set('typeName', this.typeName);
|
|
130
|
+
urlObj.searchParams.set('VERSION', this.version);
|
|
131
|
+
urlObj.searchParams.set('SRSNAME', this.crs);
|
|
132
|
+
urlObj.searchParams.set('outputFormat', this.format);
|
|
133
|
+
urlObj.searchParams.set('BBOX', `%bbox,${this.crs}`);
|
|
131
134
|
this.vendorSpecific = source.vendorSpecific;
|
|
132
135
|
for (const name in this.vendorSpecific) {
|
|
133
136
|
if (Object.prototype.hasOwnProperty.call(this.vendorSpecific, name)) {
|
|
134
|
-
|
|
137
|
+
urlObj.searchParams.set(name, this.vendorSpecific[name]);
|
|
135
138
|
}
|
|
136
139
|
}
|
|
140
|
+
this.url = decodeURIComponent(urlObj.toString());
|
|
137
141
|
}
|
|
138
142
|
handlingError(err) {
|
|
139
143
|
if (err.response && err.response.status == 400) {
|
|
@@ -148,14 +152,15 @@ class WFSSource extends Source {
|
|
|
148
152
|
}
|
|
149
153
|
return super.handlingError(err);
|
|
150
154
|
}
|
|
151
|
-
|
|
152
|
-
if (
|
|
153
|
-
return super.
|
|
155
|
+
getDataKey(extent) {
|
|
156
|
+
if (extent.isTile) {
|
|
157
|
+
return super.getDataKey(extent);
|
|
154
158
|
} else {
|
|
155
|
-
return
|
|
159
|
+
return `z${extent.zoom}s${extent.south}w${extent.west}`;
|
|
156
160
|
}
|
|
157
161
|
}
|
|
158
|
-
urlFromExtent(
|
|
162
|
+
urlFromExtent(extentOrTile) {
|
|
163
|
+
const extent = extentOrTile.isExtent ? extentOrTile.as(this.crs, _extent) : extentOrTile.toExtent(this.crs, _extent);
|
|
159
164
|
return URLBuilder.bbox(extent, this);
|
|
160
165
|
}
|
|
161
166
|
extentInsideLimit(extent) {
|
package/lib/Source/WMSSource.js
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
import Source from "./Source.js";
|
|
2
2
|
import URLBuilder from "../Provider/URLBuilder.js";
|
|
3
|
+
import Extent from "../Core/Geographic/Extent.js";
|
|
4
|
+
import * as CRS from "../Core/Geographic/Crs.js";
|
|
5
|
+
const _extent = new Extent('EPSG:4326');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Proj provides an optional param to define axis order and orientation for a
|
|
9
|
+
* given projection. 'enu' for instance stands for east, north, up.
|
|
10
|
+
* Elevation is not needed here. The two first characters are sufficient to map
|
|
11
|
+
* proj axis to iTowns bbox order formalism.
|
|
12
|
+
* 'enu' corresponds to 'wsen' because bbox starts by lower value coordinates
|
|
13
|
+
* and preserves axis ordering, here long/lat.
|
|
14
|
+
*/
|
|
15
|
+
const projAxisToBboxMappings = {
|
|
16
|
+
en: 'wsen',
|
|
17
|
+
es: 'wnes',
|
|
18
|
+
wn: 'eswn',
|
|
19
|
+
ws: 'enws',
|
|
20
|
+
ne: 'swne',
|
|
21
|
+
se: 'nwse',
|
|
22
|
+
nw: 'senw',
|
|
23
|
+
sw: 'nesw'
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Provides the bbox axis order matching provided proj4 axis
|
|
28
|
+
* @param {string} projAxis the CRS axis order as defined in proj4
|
|
29
|
+
* @returns {string} the corresponding bbox axis order to use for WMS 1.3.0
|
|
30
|
+
*/
|
|
31
|
+
function projAxisToWmsBbox(projAxis) {
|
|
32
|
+
return projAxis && projAxisToBboxMappings[projAxis.slice(0, 2)] || 'wsen';
|
|
33
|
+
}
|
|
3
34
|
|
|
4
35
|
/**
|
|
5
36
|
* An object defining the source of images to get from a
|
|
@@ -95,32 +126,39 @@ class WMSSource extends Source {
|
|
|
95
126
|
this.version = source.version || '1.3.0';
|
|
96
127
|
this.transparent = source.transparent || false;
|
|
97
128
|
this.bboxDigits = source.bboxDigits;
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
129
|
+
if (source.axisOrder) {
|
|
130
|
+
this.axisOrder = source.axisOrder;
|
|
131
|
+
} else if (this.version === '1.3.0') {
|
|
132
|
+
// If not set, axis order depends on WMS version
|
|
133
|
+
// Version 1.3.0 depends on CRS axis order as defined in epsg.org database
|
|
134
|
+
this.axisOrder = projAxisToWmsBbox(CRS.axisOrder(this.crs));
|
|
135
|
+
} else {
|
|
136
|
+
// Versions 1.X.X mandate long/lat order, east-north orientation
|
|
137
|
+
this.axisOrder = 'wsen';
|
|
108
138
|
}
|
|
109
139
|
const crsPropName = this.version === '1.3.0' ? 'CRS' : 'SRS';
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
140
|
+
const urlObj = new URL(this.url);
|
|
141
|
+
urlObj.searchParams.set('SERVICE', 'WMS');
|
|
142
|
+
urlObj.searchParams.set('REQUEST', 'GetMap');
|
|
143
|
+
urlObj.searchParams.set('LAYERS', this.name);
|
|
144
|
+
urlObj.searchParams.set('VERSION', this.version);
|
|
145
|
+
urlObj.searchParams.set('STYLES', this.style);
|
|
146
|
+
urlObj.searchParams.set('FORMAT', this.format);
|
|
147
|
+
urlObj.searchParams.set('TRANSPARENT', this.transparent);
|
|
148
|
+
urlObj.searchParams.set('BBOX', '%bbox');
|
|
149
|
+
urlObj.searchParams.set(crsPropName, this.crs);
|
|
150
|
+
urlObj.searchParams.set('WIDTH', this.width);
|
|
151
|
+
urlObj.searchParams.set('HEIGHT', this.height);
|
|
116
152
|
this.vendorSpecific = source.vendorSpecific;
|
|
117
153
|
for (const name in this.vendorSpecific) {
|
|
118
154
|
if (Object.prototype.hasOwnProperty.call(this.vendorSpecific, name)) {
|
|
119
|
-
|
|
155
|
+
urlObj.searchParams.set(name, this.vendorSpecific[name]);
|
|
120
156
|
}
|
|
121
157
|
}
|
|
158
|
+
this.url = decodeURIComponent(urlObj.toString());
|
|
122
159
|
}
|
|
123
|
-
urlFromExtent(
|
|
160
|
+
urlFromExtent(extentOrTile) {
|
|
161
|
+
const extent = extentOrTile.isExtent ? extentOrTile.as(this.crs, _extent) : extentOrTile.toExtent(this.crs, _extent);
|
|
124
162
|
return URLBuilder.bbox(extent, this);
|
|
125
163
|
}
|
|
126
164
|
extentInsideLimit(extent) {
|
package/lib/Source/WMTSSource.js
CHANGED
|
@@ -69,18 +69,24 @@ class WMTSSource extends TMSSource {
|
|
|
69
69
|
}
|
|
70
70
|
super(source);
|
|
71
71
|
this.isWMTSSource = true;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
const urlObj = new URL(this.url);
|
|
73
|
+
urlObj.searchParams.set('LAYER', source.name);
|
|
74
|
+
urlObj.searchParams.set('FORMAT', this.format);
|
|
75
|
+
urlObj.searchParams.set('SERVICE', 'WMTS');
|
|
76
|
+
urlObj.searchParams.set('VERSION', source.version || '1.0.0');
|
|
77
|
+
urlObj.searchParams.set('REQUEST', 'GetTile');
|
|
78
|
+
urlObj.searchParams.set('STYLE', source.style || 'normal');
|
|
79
|
+
urlObj.searchParams.set('TILEMATRIXSET', source.tileMatrixSet);
|
|
80
|
+
urlObj.searchParams.set('TILEMATRIX', '%TILEMATRIX');
|
|
81
|
+
urlObj.searchParams.set('TILEROW', '%ROW');
|
|
82
|
+
urlObj.searchParams.set('TILECOL', '%COL');
|
|
78
83
|
this.vendorSpecific = source.vendorSpecific;
|
|
79
84
|
for (const name in this.vendorSpecific) {
|
|
80
85
|
if (Object.prototype.hasOwnProperty.call(this.vendorSpecific, name)) {
|
|
81
|
-
|
|
86
|
+
urlObj.searchParams.set(name, this.vendorSpecific[name]);
|
|
82
87
|
}
|
|
83
88
|
}
|
|
89
|
+
this.url = decodeURIComponent(urlObj.toString());
|
|
84
90
|
}
|
|
85
91
|
}
|
|
86
92
|
export default WMTSSource;
|