Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mapbox style multiple source #2128

Merged
merged 4 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Parser/GeoJsonParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ export default {

if (out.filteringExtent) {
if (typeof out.filteringExtent == 'boolean') {
out.filterExtent = json.extent.as(_in.crs);
out.filterExtent = options.extent.as(_in.crs);
} else if (out.filteringExtent.isExtent) {
out.filterExtent = out.filteringExtent;
}
Expand Down
10 changes: 5 additions & 5 deletions src/Parser/VectorTileParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,12 @@ function readPBF(file, options) {
}

// x,y,z tile coordinates
const x = file.extent.col;
const z = file.extent.zoom;
const x = options.extent.col;
const z = options.extent.zoom;
// We need to move from TMS to Google/Bing/OSM coordinates
// https://alastaira.wordpress.com/2011/07/06/converting-tms-tile-coordinates-to-googlebingosm-tile-coordinates/
// Only if the layer.origin is top
const y = options.in.isInverted ? file.extent.row : (1 << z) - file.extent.row - 1;
const y = options.in.isInverted ? options.extent.row : (1 << z) - options.extent.row - 1;

const collection = new FeatureCollection(options.out);

Expand All @@ -148,7 +148,7 @@ function readPBF(file, options) {

for (let i = sourceLayer.length - 1; i >= 0; i--) {
const vtFeature = sourceLayer.feature(i);
vtFeature.tileNumbers = { x, y: file.extent.row, z };
vtFeature.tileNumbers = { x, y: options.extent.row, z };
const layers = options.in.layers[layer_id].filter(l => l.filterExpression.filter({ zoom: z }, vtFeature) && z >= l.zoom.min && z < l.zoom.max);
let feature;

Expand All @@ -174,7 +174,7 @@ function readPBF(file, options) {
collection.features.sort((a, b) => a.order - b.order);
// TODO verify if is needed to updateExtent for previous features.
collection.updateExtent();
collection.extent = file.extent;
collection.extent = options.extent;
collection.isInverted = options.in.isInverted;
return Promise.resolve(collection);
}
Expand Down
31 changes: 31 additions & 0 deletions src/Provider/Fetcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,35 @@ export default {
return Promise.resolve(all);
});
},

get(format = '') {
const [type, subtype] = format.split('/');
switch (type) {
case 'application':
switch (subtype) {
case 'geo+json':
case 'json':
return this.json;
case 'kml':
case 'gpx':
return this.xml;
case 'x-protobuf;type=mapbox-vector':
case 'gtx':
return this.arrayBuffer;
case 'isg':
case 'gdf':
default:
return this.text;
}
case 'image':
switch (subtype) {
case 'x-bil;bits=32':
return this.textureFloat;
default:
return this.texture;
}
default:
return this.texture;
}
},
};
2 changes: 1 addition & 1 deletion src/Renderer/RasterTile.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class RasterTile extends THREE.EventDispatcher {
}

setTexture(index, texture, offsetScale) {
this.level = (texture && (index == 0)) ? texture.extent.zoom : this.level;
this.level = (texture && texture.extent && (index == 0)) ? texture.extent.zoom : this.level;
this.textures[index] = texture || null;
this.offsetScales[index] = offsetScale;
this.material.layersNeedUpdate = true;
Expand Down
1 change: 0 additions & 1 deletion src/Source/OrientedImageSource.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ class OrientedImageSource extends Source {
* to find the good texture for each camera for each panoramic.
*/
constructor(source) {
source.format = source.format || 'json';
super(source);
this.isOrientedImageSource = true;

Expand Down
35 changes: 9 additions & 26 deletions src/Source/Source.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,8 @@ import Fetcher from 'Provider/Fetcher';
import Cache from 'Core/Scheduler/Cache';
import CRS from 'Core/Geographic/Crs';

export const supportedFetchers = new Map([
['image/x-bil;bits=32', Fetcher.textureFloat],
['geojson', Fetcher.json],
['application/json', Fetcher.json],
['application/kml', Fetcher.xml],
['application/gpx', Fetcher.xml],
['application/x-protobuf;type=mapbox-vector', Fetcher.arrayBuffer],
['application/gtx', Fetcher.arrayBuffer],
['application/isg', Fetcher.text],
['application/gdf', Fetcher.text],
]);

export const supportedParsers = new Map([
['geojson', GeoJsonParser.parse],
['application/geo+json', GeoJsonParser.parse],
['application/json', GeoJsonParser.parse],
['application/kml', KMLParser.parse],
['application/gpx', GpxParser.parse],
Expand Down Expand Up @@ -66,15 +54,6 @@ class InformationsData {
// eslint-disable-next-line
class /* istanbul ignore next */ ParsingOptions {}

function fetchSourceData(source, extent) {
const url = source.urlFromExtent(extent);

return source.fetcher(url, source.networkOptions).then((f) => {
f.extent = extent;
return f;
}, err => source.handlingError(err));
}

let uid = 0;

/**
Expand Down Expand Up @@ -140,8 +119,8 @@ class Source extends InformationsData {

this.url = source.url;
this.format = source.format;
this.fetcher = source.fetcher || supportedFetchers.get(source.format) || Fetcher.texture;
this.parser = source.parser || supportedParsers.get(source.format) || (d => d);
this.fetcher = source.fetcher || Fetcher.get(source.format);
this.parser = source.parser || supportedParsers.get(source.format) || ((d, opt) => { d.extent = opt.extent; return d; });
this.isVectorSource = (source.parser || supportedParsers.get(source.format)) != undefined;
this.networkOptions = source.networkOptions || { crossOrigin: 'anonymous' };
this.attribution = source.attribution;
Expand Down Expand Up @@ -190,8 +169,12 @@ class Source extends InformationsData {
let features = cache.getByArray(key);
if (!features) {
// otherwise fetch/parse the data
features = cache.setByArray(fetchSourceData(this, extent).then(file => this.parser(file, { out, in: this }),
err => this.handlingError(err)), key);
features = cache.setByArray(
this.fetcher(this.urlFromExtent(extent), this.networkOptions)
.then(file => this.parser(file, { out, in: this, extent }))
.catch(err => this.handlingError(err)),
key);

/* istanbul ignore next */
if (this.onParsedFile) {
features.then((feat) => {
Expand Down
1 change: 0 additions & 1 deletion src/Source/TMSSource.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ class TMSSource extends Source {
this.zoom = source.zoom;

this.isInverted = source.isInverted || false;
this.url = source.url;
this.crs = CRS.formatToTms(source.crs);
this.tileMatrixSetLimits = source.tileMatrixSetLimits;
this.extentSetlimits = {};
Expand Down
74 changes: 61 additions & 13 deletions src/Source/VectorTilesSource.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
import { featureFilter } from '@mapbox/mapbox-gl-style-spec';
import Style from 'Core/Style';
import TMSSource from 'Source/TMSSource';
import URLBuilder from 'Provider/URLBuilder';
import Fetcher from 'Provider/Fetcher';
import urlParser from 'Parser/MapBoxUrlParser';

function toTMSUrl(url) {
return url.replace(/\{/g, '${');
}

function mergeCollections(collections) {
const collection = collections[0];
collections.forEach((col, index) => {
if (index === 0) { return; }
col.features.forEach((feature) => {
collection.features.push(feature);
});
});
return collection;
}

/**
* @classdesc
* VectorTilesSource are object containing informations on how to fetch vector
Expand Down Expand Up @@ -53,6 +65,7 @@ class VectorTilesSource extends TMSSource {
source.url = source.url || '.';
super(source);
const ffilter = source.filter || (() => true);
this.urls = [];
this.layers = {};
this.styles = {};
let promise;
Expand Down Expand Up @@ -86,9 +99,6 @@ class VectorTilesSource extends TMSSource {

return style;
}).then((style) => {
const s = Object.keys(style.sources)[0];
const os = style.sources[s];

style.layers.forEach((layer, order) => {
layer.sourceUid = this.uid;
if (layer.type === 'background') {
Expand All @@ -113,20 +123,31 @@ class VectorTilesSource extends TMSSource {
});

if (this.url == '.') {
if (os.url) {
const urlSource = urlParser.normalizeSourceURL(os.url, this.accessToken);
return Fetcher.json(urlSource, this.networkOptions).then((tileJSON) => {
if (tileJSON.tiles[0]) {
this.url = toTMSUrl(tileJSON.tiles[0]);
}
});
} else if (os.tiles[0]) {
this.url = toTMSUrl(os.tiles[0]);
}
const TMSUrlList = Object.values(style.sources).map((sourceVT) => {
if (sourceVT.url) {
const urlSource = urlParser.normalizeSourceURL(sourceVT.url, this.accessToken);
return Fetcher.json(urlSource, this.networkOptions).then((tileJSON) => {
if (tileJSON.tiles[0]) {
return toTMSUrl(tileJSON.tiles[0]);
}
});
} else if (sourceVT.tiles) {
return Promise.resolve(toTMSUrl(sourceVT.tiles[0]));
}
return Promise.reject();
});
return Promise.all(TMSUrlList);
}
return (Promise.resolve([this.url]));
}).then((TMSUrlList) => {
this.urls = Array.from(new Set(TMSUrlList));
});
}

urlFromExtent(extent, url) {
return URLBuilder.xyz(extent, { tileMatrixCallback: this.tileMatrixCallback, url });
}

onLayerAdded(options) {
super.onLayerAdded(options);
if (options.out.style) {
Expand All @@ -136,6 +157,33 @@ class VectorTilesSource extends TMSSource {
}
}
}

loadData(extent, out) {
const cache = this._featuresCaches[out.crs];
const key = this.requestToKey(extent);
// try to get parsed data from cache
let features = cache.getByArray(key);
if (!features) {
// otherwise fetch/parse the data
features = cache.setByArray(
Promise.all(this.urls.map(url =>
this.fetcher(this.urlFromExtent(extent, url), this.networkOptions)
.then(file => this.parser(file, { out, in: this, extent }))))
.then(collections => mergeCollections(collections))
.catch(err => this.handlingError(err)),
key);

/* istanbul ignore next */
if (this.onParsedFile) {
features.then((feat) => {
this.onParsedFile(feat);
console.warn('Source.onParsedFile was deprecated');
return feat;
});
}
}
return features;
}
}

export default VectorTilesSource;
Loading
Loading