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

MVT Tile Layer #3935

Merged
merged 10 commits into from
Feb 28, 2020
5 changes: 4 additions & 1 deletion modules/geo-layers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@
"prepublishOnly": "npm run build-bundle && npm run build-bundle -- --env.dev"
},
"dependencies": {
"@loaders.gl/3d-tiles": "^2.1.0-alpha.4",
"@loaders.gl/3d-tiles": "2.1.0-alpha.4",
"@loaders.gl/terrain": "^2.1.0-alpha.4",
"@loaders.gl/mvt": "^2.1.0-alpha.5",
"@loaders.gl/core": "^2.0.4",
"math.gl": "^3.1.3",
"@math.gl/web-mercator": "^3.1.3",
"h3-js": "^3.6.0",
"long": "^3.2.0",
Expand Down
1 change: 1 addition & 0 deletions modules/geo-layers/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ export {default as H3ClusterLayer} from './h3-layers/h3-cluster-layer';
export {default as H3HexagonLayer} from './h3-layers/h3-hexagon-layer';
export {default as Tile3DLayer} from './tile-3d-layer/tile-3d-layer';
export {default as TerrainLayer} from './terrain-layer/terrain-layer';
export {default as MVTTileLayer} from './mvt-tile-layer/mvt-tile-layer';
66 changes: 66 additions & 0 deletions modules/geo-layers/src/mvt-tile-layer/mvt-tile-layer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import {Matrix4} from 'math.gl';
import {MVTLoader} from '@loaders.gl/mvt';
import {load} from '@loaders.gl/core';
import {COORDINATE_SYSTEM} from '@deck.gl/core';
import {GeoJsonLayer} from '@deck.gl/layers';

import TileLayer from '../tile-layer/tile-layer';

const defaultProps = Object.assign({}, TileLayer.defaultProps, {
renderSubLayers: {type: 'function', value: renderSubLayers, compare: false},
urlTemplates: []
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Start a documentation page in docs/layers?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point!

});

export default class MVTTileLayer extends TileLayer {
initializeState() {
super.initializeState();
const {urlTemplates} = this.props;

this.state = {
...this.state,
urlTemplates
};
}

async getTileData(tileProperties) {
const {urlTemplates} = this.state;

if (!urlTemplates || !urlTemplates.length) {
return Promise.reject();
}

const templateReplacer = (_, property) => tileProperties[property];
const tileURLIndex = getTileURLIndex(tileProperties, urlTemplates.length);
const tileURL = urlTemplates[tileURLIndex].replace(/\{ *([\w_-]+) *\}/g, templateReplacer);

return await load(tileURL, MVTLoader);
}
}

function renderSubLayers(tileProperties) {
return new GeoJsonLayer({
...tileProperties,
modelMatrix: getModelMatrix(tileProperties.tile),
coordinateSystem: COORDINATE_SYSTEM.CARTESIAN
});
}

function getModelMatrix(tile) {
const WORLD_SIZE = 512;
const worldScale = Math.pow(2, tile.z);

const xScale = WORLD_SIZE / worldScale;
const yScale = -xScale;

const xOffset = (WORLD_SIZE * tile.x) / worldScale;
const yOffset = WORLD_SIZE * (1 - tile.y / worldScale);

return new Matrix4().translate([xOffset, yOffset, 0]).scale([xScale, yScale, 1]);
}

function getTileURLIndex({x, y}, templatesLength) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a standard schema? If yes, can you add a link to its specs? Otherwise, should we allow users to customize this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's used to bypass Domain Sharding when HTTP 2 is not available. The user can provide N tiles endpoint and this function does the splitting to each one.

The tilejson spec defines a tiles attributes for that:

// REQUIRED. An array of tile endpoints. {z}, {x} and {y}, if present,
    // are replaced with the corresponding integers. If multiple endpoints are specified, clients
    // may use any combination of endpoints. All endpoints MUST return the same
    // content for the same URL. The array MUST contain at least one endpoint.
    "tiles": [
        "http://localhost:8888/admin/1.0.0/world-light,broadband/{z}/{x}/{y}.png"
    ]

return Math.abs(x + y) % templatesLength;
}

MVTTileLayer.layerName = 'MVTTileLayer';
MVTTileLayer.defaultProps = defaultProps;
16 changes: 14 additions & 2 deletions modules/geo-layers/src/tile-layer/tile-layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,17 @@ export default class TileLayer extends CompositeLayer {
(changeFlags.updateTriggersChanged.all || changeFlags.updateTriggersChanged.getTileData));

if (createTileCache) {
const {maxZoom, minZoom, maxCacheSize, maxCacheByteSize, refinementStrategy} = props;
const {
maxZoom,
minZoom,
maxCacheSize,
maxCacheByteSize,
refinementStrategy,
tileToBoundingBox
} = props;
tileset = new Tileset2D({
getTileData: props.getTileData,
getTileData: this.getTileData.bind(this),
tileToBoundingBox,
maxCacheSize,
maxCacheByteSize,
maxZoom,
Expand Down Expand Up @@ -102,6 +110,10 @@ export default class TileLayer extends CompositeLayer {
layer._updateTileset();
}

getTileData(tilePosition) {
return this.props.getTileData(tilePosition);
}

getPickingInfo({info, sourceLayer}) {
info.sourceLayer = sourceLayer;
info.tile = sourceLayer.props.tile;
Expand Down
3 changes: 2 additions & 1 deletion modules/main/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ export {
TileLayer,
TripsLayer,
Tile3DLayer,
TerrainLayer
TerrainLayer,
MVTTileLayer
} from '@deck.gl/geo-layers';

export {SimpleMeshLayer, ScenegraphLayer} from '@deck.gl/mesh-layers';
Expand Down
1 change: 1 addition & 0 deletions test/modules/geo-layers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,4 @@ import './great-circle-layer.spec';
import './h3-layers.spec';
import './tile-3d-layer';
import './terrain-layer.spec';
import './mvt-tile-layer.spec';
18 changes: 18 additions & 0 deletions test/modules/geo-layers/mvt-tile-layer.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import test from 'tape-catch';
import {generateLayerTests, testLayer} from '@deck.gl/test-utils';
import {MVTTileLayer} from '@deck.gl/geo-layers';

test('MVTTileLayer', t => {
const testCases = generateLayerTests({
Layer: MVTTileLayer,
assert: t.ok,
sampleProps: {
urlTemplates: [
'https://a.basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}.png'
]
},
onBeforeUpdate: ({testCase}) => t.comment(testCase.title)
});
testLayer({Layer: MVTTileLayer, testCases, onError: t.notOk});
t.end();
});
24 changes: 22 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1558,7 +1558,7 @@
npmlog "^4.1.2"
write-file-atomic "^2.3.0"

"@loaders.gl/3d-tiles@^2.1.0-alpha.4":
"@loaders.gl/3d-tiles@2.1.0-alpha.4", "@loaders.gl/3d-tiles@^2.1.0-alpha.4":
version "2.1.0-alpha.4"
resolved "https://registry.yarnpkg.com/@loaders.gl/3d-tiles/-/3d-tiles-2.1.0-alpha.4.tgz#9a94aef87dea86b25ca8a104600214aacb5fa20b"
integrity sha512-9qqDj2QHO7KiPED77wdIQRhmW+avDy0KaQLcaIAdIk2/HQ0uy90Eb3X7di5Jf/ggRUOs4hFFm+0AQT0PLe6dEQ==
Expand All @@ -1580,6 +1580,14 @@
"@babel/runtime" "^7.3.1"
"@loaders.gl/loader-utils" "2.1.0-alpha.4"

"@loaders.gl/core@^2.0.4":
version "2.0.4"
resolved "https://registry.yarnpkg.com/@loaders.gl/core/-/core-2.0.4.tgz#10f647bf0e10af971a7d4e60031992f54c76a91b"
integrity sha512-rBj2QwZh5wUEYblI5tEf0uFRps23Hu/0OM4lA27y+9BUNrT1D4CVBktqsQ6EyMRFWoBGO6Q6G9SEg/49I6MM5w==
dependencies:
"@babel/runtime" "^7.3.1"
"@loaders.gl/loader-utils" "2.0.4"

"@loaders.gl/csv@^2.1.0-alpha.4":
version "2.1.0-alpha.4"
resolved "https://registry.yarnpkg.com/@loaders.gl/csv/-/csv-2.1.0-alpha.4.tgz#c570422229f4c783fd2347d75e17db35244c5b96"
Expand Down Expand Up @@ -1609,6 +1617,13 @@
resolved "https://registry.yarnpkg.com/@loaders.gl/images/-/images-2.0.2.tgz#546929146b38a428e55905e513b4b9ec7afc58e2"
integrity sha512-H6xhSvM24CI++P46TZRLX+95mn5B4HaP0jWGSIn2Lo0aBpcI9/T8z2EZhJyihjoR450fph1ER0j+Mnz+ovHEGg==

"@loaders.gl/loader-utils@2.0.4":
version "2.0.4"
resolved "https://registry.yarnpkg.com/@loaders.gl/loader-utils/-/loader-utils-2.0.4.tgz#de2494f85e6e36fc05ec43ee1d2ada65bcd7f3f6"
integrity sha512-e+Grafj+6pk+7WDClWW/OsuTg/wpaJ3+pLX7c+eG3KmcxiLEDoCNWSvQVbR8ALU4Y6m3S32+WlHptBnN1LL48A==
dependencies:
"@babel/runtime" "^7.3.1"

"@loaders.gl/loader-utils@2.1.0-alpha.4":
version "2.1.0-alpha.4"
resolved "https://registry.yarnpkg.com/@loaders.gl/loader-utils/-/loader-utils-2.1.0-alpha.4.tgz#92d623f2edf12084de48ae359958baac95ab8085"
Expand All @@ -1624,6 +1639,11 @@
"@loaders.gl/images" "2.1.0-alpha.4"
math.gl "^3.1.2"

"@loaders.gl/mvt@^2.1.0-alpha.5":
version "2.1.0-alpha.5"
resolved "https://registry.yarnpkg.com/@loaders.gl/mvt/-/mvt-2.1.0-alpha.5.tgz#46ace83d3a143c455f1a45133742f7100937d111"
integrity sha512-R5dFyxtyRuA6hJRWlWuo1KAFw/YJm3wMJ0u0H9ZL/v9GfSvgScepThj93uIbxeOAVXn6ZY0JwL3WwGgui2pSLA==

"@loaders.gl/polyfills@^2.1.0-alpha.4":
version "2.1.0-alpha.4"
resolved "https://registry.yarnpkg.com/@loaders.gl/polyfills/-/polyfills-2.1.0-alpha.4.tgz#4db9e7532785fb5f3317d016693ce15bd5b0b79c"
Expand Down Expand Up @@ -7024,7 +7044,7 @@ mapbox-gl@^1.0.0, mapbox-gl@^1.2.1:
tinyqueue "^2.0.0"
vt-pbf "^3.1.1"

math.gl@^3.1.2:
math.gl@^3.1.2, math.gl@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/math.gl/-/math.gl-3.1.3.tgz#1e702df8cba024cc229e18e3c57c60a27943cb95"
integrity sha512-3OYCtzTOW1wkZufjsxk8g1D77+z+x7QehOZcMFPGgw1QjVEFNcyy3ql6hdrZpUlkyE3pX4lYak7WOIE+n0obYg==
Expand Down