Skip to content

Commit

Permalink
feature(source): add VectorTileSource.
Browse files Browse the repository at this point in the history
  • Loading branch information
gchoqueux committed Nov 7, 2019
1 parent 02c7555 commit cd43854
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 110 deletions.
3 changes: 2 additions & 1 deletion docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@
"WFSSource",
"TMSSource",
"FileSource",
"OrientedImageSource"
"OrientedImageSource",
"VectorTilesSource"
],

"Provider": [
Expand Down
98 changes: 41 additions & 57 deletions examples/vector_tile_raster_2d.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,69 +54,53 @@
var count = 0;

// Add a vector tile layer
itowns.Fetcher.json('https://raw.githubusercontent.com/Oslandia/postile-openmaptiles/master/style.json').then(function (style) {
var supportedLayers = [];
var backgroundLayer;

style.layers.forEach(function(layer) {
if (layer.type === 'background') {
backgroundLayer = layer;
} else if (['fill', 'line'].includes(layer.type)) {
supportedLayers.push(layer);
}
});

function isValidData(data, extentDestination) {
// re-use the same vector tiles by interval 4
var z = extentDestination.zoom - 2;
return extentDestination.zoom, z - z % 4 == data.extent.zoom - 2;
}

var mvtSource = new itowns.TMSSource({
// eslint-disable-next-line no-template-curly-in-string
url: 'https://osm.oslandia.io/data/v3/${z}/${x}/${y}.pbf',
format: 'application/x-protobuf;type=mapbox-vector',
attribution: {
name: 'OpenStreetMap',
url: 'http://www.openstreetmap.org/',
},
zoom: {
min: 2,
max: 16,
},
tileMatrixSet: 'PM',
projection: 'EPSG:3857',
isInverted: true,
});
function isValidData(data, extentDestination) {
// re-use the same vector tiles by interval 4
// var z = extentDestination.zoom - 2;
return false;
}

var mvtLayer = new itowns.ColorLayer('MVT', {
isValidData: isValidData,
source: mvtSource,
filter: supportedLayers,
backgroundLayer,
projection: 'EPSG:3857',
});
var mvtSource = new itowns.VectorTilesSource({
style: 'https://raw.githubusercontent.com/Oslandia/postile-openmaptiles/master/style.json',
// eslint-disable-next-line no-template-curly-in-string
url: 'https://osm.oslandia.io/data/v3/${z}/${x}/${y}.pbf',
attribution: {
name: 'OpenStreetMap',
url: 'http://www.openstreetmap.org/',
},
filter: function (layer) { return ['fill', 'line'].includes(layer.type) },
zoom: {
min: 2,
max: 16,
},
});

view.addLayer(mvtLayer).then(function _(layer) {
FeatureToolTip.addLayer(layer, {
filterGeometries: function _(geometries) {
var uniqueClasses = [];
return geometries.filter(function _(g) {
if (g.geometry.properties.class && !uniqueClasses.includes(g.geometry.properties.class)) {
uniqueClasses.push(g.geometry.properties.class);
return true;
}
});
},
filterAllProperties: false,
format: function _(n, p) {
if (p !== undefined && n == 'class') return p;
}
});
return layer;
}).then(menuGlobe.addLayerGUI.bind(menuGlobe));
var mvtLayer = new itowns.ColorLayer('MVT', {
isValidData: isValidData,
source: mvtSource,
});

view.addLayer(mvtLayer).then(function _(layer) {
FeatureToolTip.addLayer(layer, {
filterGeometries: function _(geometries) {
var uniqueClasses = [];
return geometries.filter(function _(g) {
if (g.geometry.properties.class && !uniqueClasses.includes(g.geometry.properties.class)) {
uniqueClasses.push(g.geometry.properties.class);
return true;
}
});
},
filterAllProperties: false,
format: function _(n, p) {
if (p !== undefined && n == 'class') return p;
}
});
return layer;
}).then(menuGlobe.addLayerGUI.bind(menuGlobe));

// Request redraw
view.notifyChange(true);
debug.createTileDebugUI(menuGlobe.gui, view);
Expand Down
79 changes: 31 additions & 48 deletions examples/vector_tile_raster_3d.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,54 +44,37 @@
}));

// Add a vector tile layer
promises.push(itowns.Fetcher.json('https://raw.githubusercontent.com/Oslandia/postile-openmaptiles/master/style.json').then(function (style) {
var supportedLayers = [];
var backgroundLayer;

style.layers.forEach(function(layer) {
if (layer.type === 'background') {
backgroundLayer = layer;
} else if (['fill', 'line'].includes(layer.type)) {
supportedLayers.push(layer);
}
});

function inter(z) {
return z - (z % 5);
}

function isValidData(data, extentDestination) {
const isValid = inter(extentDestination.zoom) == inter(data.extent.zoom);
return isValid;
}

var mvtSource = new itowns.TMSSource({
// eslint-disable-next-line no-template-curly-in-string
url: 'https://osm.oslandia.io/data/v3/${z}/${x}/${y}.pbf',
format: 'application/x-protobuf;type=mapbox-vector',
attribution: {
name: 'OpenStreetMap',
url: 'http://www.openstreetmap.org/',
},
zoom: {
min: 0,
max: 13,
},
tileMatrixSet: 'PM',
projection: 'EPSG:3857',
isInverted: true,
});

var mvtLayer = new itowns.ColorLayer('MVT', {
isValidData: isValidData,
source: mvtSource,
filter: supportedLayers,
backgroundLayer,
fx: 2.5,
});

return view.addLayer(mvtLayer);
}));
function inter(z) {
return z - (z % 5);
}

function isValidData(data, extentDestination) {
const isValid = inter(extentDestination.zoom) == inter(data.extent.zoom);
return isValid;
}

var mvtSource = new itowns.VectorTilesSource({
style: 'https://raw.githubusercontent.com/Oslandia/postile-openmaptiles/master/style.json',
// eslint-disable-next-line no-template-curly-in-string
url: 'https://osm.oslandia.io/data/v3/${z}/${x}/${y}.pbf',
attribution: {
name: 'OpenStreetMap',
url: 'http://www.openstreetmap.org/',
},
filter: function (layer) { return ['fill', 'line'].includes(layer.type) },
zoom: {
min: 2,
max: 16,
},
});

var mvtLayer = new itowns.ColorLayer('MVT', {
isValidData: isValidData,
source: mvtSource,
fx: 2.5,
});

view.addLayer(mvtLayer);

var menuGlobe = new GuiTools('menuDiv', view, 300);
// Listen for globe full initialisation event
Expand Down
5 changes: 3 additions & 2 deletions src/Converter/textureConverter.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ export default {
convert(data, extentDestination, layer) {
let texture;
if (data.isFeatureCollection) {
const backgroundColor = (layer.backgroundLayer && layer.backgroundLayer.paint) ?
new THREE.Color(layer.backgroundLayer.paint['background-color']) :
const backgroundLayer = layer.source.backgroundLayer;
const backgroundColor = (backgroundLayer && backgroundLayer.paint) ?
new THREE.Color(backgroundLayer.paint['background-color']) :
undefined;

extentDestination.as(CRS.formatToEPSG(layer.projection), extentTexture);
Expand Down
1 change: 1 addition & 0 deletions src/Main.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export { default as TMSSource } from 'Source/TMSSource';
export { default as WFSSource } from 'Source/WFSSource';
export { default as WMSSource } from 'Source/WMSSource';
export { default as WMTSSource } from 'Source/WMTSSource';
export { default as VectorTilesSource } from 'Source/VectorTilesSource';
export { default as OrientedImageSource } from 'Source/OrientedImageSource';

// Parsers provided by default in iTowns
Expand Down
4 changes: 2 additions & 2 deletions src/Provider/DataSourceProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ function parseSourceData(data, extDest, layer) {
buildExtent: source.isFileSource || !layer.isGeometryLayer,
crsIn: source.projection,
crsOut: layer.projection,
sprites: layer.sprites,
sprites: layer.sprites || source.sprites,
// TODO FIXME: error in filtering vector tile
// filteringExtent: extentDestination.as(layer.projection),
filteringExtent: !source.isFileSource && layer.isGeometryLayer ? extDest.as(source.projection) : undefined,
overrideAltitudeInToZero: layer.overrideAltitudeInToZero,
filter: layer.filter,
filter: layer.filter || source.filter,
isInverted: source.isInverted,
mergeFeatures: layer.mergeFeatures === undefined ? true : layer.mergeFeatures,
withNormal: layer.isGeometryLayer,
Expand Down
1 change: 1 addition & 0 deletions src/Source/Source.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ class Source {
this.networkOptions = source.networkOptions || { crossOrigin: 'anonymous' };
this.projection = source.projection;
this.attribution = source.attribution;
this.whenReady = Promise.resolve();
if (source.extent && !(source.extent.isExtent)) {
this.extent = new Extent(this.projection, source.extent);
} else {
Expand Down
74 changes: 74 additions & 0 deletions src/Source/VectorTilesSource.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import TMSSource from 'Source/TMSSource';
import Fetcher from 'Provider/Fetcher';

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

/**
* @classdesc
* VectorTilesSource are object containing informations on how to fetch vector tiles resources.
*
* @property {string} style - the url to json style.
* @property {string} sprite - the base url to sprites folder.
* @property {function} filter - function to filter vector tiles layers, the parameter function is a layer.
*
*/
class VectorTilesSource extends TMSSource {
/**
* @param {Object} source - An object that can contain all properties of a
* VectorTilesSource and {@link Source}.
*
* @constructor
*/
constructor(source) {
source.format = 'application/x-protobuf;type=mapbox-vector';
source.projection = 'EPSG:3857';
source.isInverted = true;
source.url = source.url || '.';
super(source);
const ffilter = source.filter || (() => true);
this.filter = [];
const promises = [];

if (source.style) {
promises.push(Fetcher.json(source.style).then((style) => {
const s = Object.keys(style.sources)[0];
const os = style.sources[s];

style.layers.forEach((layer) => {
if (layer.type === 'background') {
this.backgroundLayer = layer;
} else if (ffilter(layer)) {
this.filter.push(layer);
}
});
if (this.url == '.') {
if (os.url) {
return Fetcher.json(os.url).then((tileJSON) => {
if (tileJSON.tiles[0]) {
this.url = toTMSUrl(tileJSON.tiles[0]);
}
});
} else if (os.tiles[0]) {
this.url = toTMSUrl(os.tiles[0]);
}
}
}));
} else {
throw new Error('New VectorTilesSource: style is required');
}
if (source.sprite) {
promises.push(Fetcher.json(`${source.sprite}.json`).then((sprites) => {
this.sprites = sprites;
return Fetcher.texture(`${source.sprite}.png`, { crossOrigin: 'anonymous' }).then((texture) => {
this.sprites.img = texture.image;
});
}));
}

this.whenReady = Promise.all(promises);
}
}

export default VectorTilesSource;

0 comments on commit cd43854

Please sign in to comment.