Skip to content

Commit

Permalink
Add zRange prop to TileLayer for use with TerrainLayer (#4397)
Browse files Browse the repository at this point in the history
  • Loading branch information
kylebarron authored Mar 26, 2020
1 parent 809ebea commit fa7da83
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 25 deletions.
23 changes: 22 additions & 1 deletion modules/geo-layers/src/terrain-layer/terrain-layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,25 @@ export default class TerrainLayer extends CompositeLayer {
});
}

// Update zRange of viewport
onViewportLoad(data) {
if (!data || data.length === 0 || data.every(x => !x)) {
return;
}

const {zRange} = this.state;
const ranges = data.map(arr => {
const bounds = arr[0].header.boundingBox;
return bounds.map(bound => bound[2]);
});
const minZ = Math.min(...ranges.map(x => x[0]));
const maxZ = Math.max(...ranges.map(x => x[1]));

if (!zRange || minZ < zRange[0] || maxZ > zRange[1]) {
this.setState({zRange: [minZ, maxZ]});
}
}

renderLayers() {
const {
color,
Expand Down Expand Up @@ -196,7 +215,9 @@ export default class TerrainLayer extends CompositeLayer {
meshMaxError,
elevationDecoder
}
}
},
onViewportLoad: this.onViewportLoad.bind(this),
zRange: this.state.zRange || null
}
);
}
Expand Down
7 changes: 4 additions & 3 deletions modules/geo-layers/src/tile-layer/tile-layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ const defaultProps = {
minZoom: 0,
maxCacheSize: null,
maxCacheByteSize: null,
refinementStrategy: STRATEGY_DEFAULT
refinementStrategy: STRATEGY_DEFAULT,
zRange: null
};

export default class TileLayer extends CompositeLayer {
Expand Down Expand Up @@ -85,8 +86,8 @@ export default class TileLayer extends CompositeLayer {

_updateTileset() {
const {tileset} = this.state;
const {onViewportLoad} = this.props;
const frameNumber = tileset.update(this.context.viewport);
const {onViewportLoad, zRange} = this.props;
const frameNumber = tileset.update(this.context.viewport, {zRange});
const {isLoaded} = tileset;

const loadingStateChanged = this.state.isLoaded !== isLoaded;
Expand Down
9 changes: 5 additions & 4 deletions modules/geo-layers/src/tile-layer/tileset-2d.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,14 @@ export default class Tileset2D {
* @param {*} viewport
* @param {*} onUpdate
*/
update(viewport) {
update(viewport, {zRange} = {}) {
if (viewport !== this._viewport) {
this._viewport = viewport;
const tileIndices = this.getTileIndices({
viewport,
maxZoom: this._maxZoom,
minZoom: this._minZoom
minZoom: this._minZoom,
zRange
});
this._selectedTiles = tileIndices.map(index => this._getTile(index, true));

Expand All @@ -130,8 +131,8 @@ export default class Tileset2D {
/* Public interface for subclassing */

// Returns array of {x, y, z}
getTileIndices({viewport, maxZoom, minZoom}) {
return getTileIndices(viewport, maxZoom, minZoom, this.opts.tileSize);
getTileIndices({viewport, maxZoom, minZoom, zRange}) {
return getTileIndices(viewport, maxZoom, minZoom, zRange, this.opts.tileSize);
}

// Add custom metadata to tiles
Expand Down
51 changes: 36 additions & 15 deletions modules/geo-layers/src/tile-layer/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,39 @@ export function getURLFromTemplate(template, properties) {
/**
* gets the bounding box of a viewport
*/
function getBoundingBox(viewport) {
const corners = [
viewport.unproject([0, 0]),
viewport.unproject([viewport.width, 0]),
viewport.unproject([0, viewport.height]),
viewport.unproject([viewport.width, viewport.height])
];
function getBoundingBox(viewport, zRange) {
let corners;
if (zRange && zRange.length === 2) {
const [minZ, maxZ] = zRange;
const minTargetZ = {targetZ: minZ};
const maxTargetZ = {targetZ: maxZ};
corners = [
// Lower zRange
viewport.unproject([0, 0], minTargetZ),
viewport.unproject([viewport.width, 0], minTargetZ),
viewport.unproject([0, viewport.height], minTargetZ),
viewport.unproject([viewport.width, viewport.height], minTargetZ),

// Upper zRange
viewport.unproject([0, 0], maxTargetZ),
viewport.unproject([viewport.width, 0], maxTargetZ),
viewport.unproject([0, viewport.height], maxTargetZ),
viewport.unproject([viewport.width, viewport.height], maxTargetZ)
];
} else {
corners = [
viewport.unproject([0, 0]),
viewport.unproject([viewport.width, 0]),
viewport.unproject([0, viewport.height]),
viewport.unproject([viewport.width, viewport.height])
];
}

return [
Math.min(corners[0][0], corners[1][0], corners[2][0], corners[3][0]),
Math.min(corners[0][1], corners[1][1], corners[2][1], corners[3][1]),
Math.max(corners[0][0], corners[1][0], corners[2][0], corners[3][0]),
Math.max(corners[0][1], corners[1][1], corners[2][1], corners[3][1])
Math.min(...corners.map(arr => arr[0])),
Math.min(...corners.map(arr => arr[1])),
Math.max(...corners.map(arr => arr[0])),
Math.max(...corners.map(arr => arr[1]))
];
}

Expand Down Expand Up @@ -122,8 +143,8 @@ function getIdentityTileIndices(viewport, z, tileSize) {
return indices;
}

function getOSMTileIndices(viewport, z) {
const bbox = getBoundingBox(viewport);
function getOSMTileIndices(viewport, z, zRange) {
const bbox = getBoundingBox(viewport, zRange);
const scale = getScale(z);
/*
minX, maxX could be out of bounds if longitude is near the 180 meridian or multiple worlds
Expand Down Expand Up @@ -160,7 +181,7 @@ function getOSMTileIndices(viewport, z) {
* than minZoom, return an empty array. If the current zoom level is greater than maxZoom,
* return tiles that are on maxZoom.
*/
export function getTileIndices(viewport, maxZoom, minZoom, tileSize = TILE_SIZE) {
export function getTileIndices(viewport, maxZoom, minZoom, zRange, tileSize = TILE_SIZE) {
let z = Math.ceil(viewport.zoom);
if (Number.isFinite(minZoom) && z < minZoom) {
return [];
Expand All @@ -170,6 +191,6 @@ export function getTileIndices(viewport, maxZoom, minZoom, tileSize = TILE_SIZE)
}

return viewport.isGeospatial
? getOSMTileIndices(viewport, z)
? getOSMTileIndices(viewport, z, zRange)
: getIdentityTileIndices(viewport, z, tileSize);
}
5 changes: 3 additions & 2 deletions test/modules/geo-layers/tile-layer/utils.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ test('getTileIndices', t => {
testCase.viewport,
testCase.maxZoom,
testCase.minZoom,
testCase.zRange,
testCase.tileSize
);
t.deepEqual(getTileIds(result), testCase.output, testCase.title);
Expand All @@ -185,8 +186,8 @@ test('getTileIndices', t => {
test('tileToBoundingBox', t => {
for (const testCase of TEST_CASES) {
if (testCase.output.length) {
const {viewport, minZoom, maxZoom, tileSize} = testCase;
const boundingBoxes = getTileIndices(viewport, maxZoom, minZoom, tileSize).map(tile =>
const {viewport, minZoom, maxZoom, tileSize, zRange} = testCase;
const boundingBoxes = getTileIndices(viewport, maxZoom, minZoom, zRange, tileSize).map(tile =>
tileToBoundingBox(viewport, tile.x, tile.y, tile.z, tileSize)
);
const result = mergeBoundingBox(boundingBoxes);
Expand Down

0 comments on commit fa7da83

Please sign in to comment.