Skip to content
This repository has been archived by the owner on Mar 8, 2023. It is now read-only.

Commit

Permalink
HARP-14678 Fix tile dependencies not working (#2186)
Browse files Browse the repository at this point in the history
* HARP-14678 Reproduce bug with two data sources & tile dependencies

Signed-off-by: Jonathan Stichbury <2533428+nzjony@users.noreply.github.com>

* HARP-14678 Fix issue with morton codes being stored as 32 bit

The tile dependency example wasn't working with two separate data sources because the morton code
was stored in a Float32Array, which doesn't have enough precision and caused issues. This change
stores the row, column and level separately and then in the decoder, the mortonCode is computed and
stored as a `number`, which has more accuracy that a 32 bit float.

Signed-off-by: Jonathan Stichbury <2533428+nzjony@users.noreply.github.com>

* HARP-14678 Fix prettier issue

Signed-off-by: Jonathan Stichbury <2533428+nzjony@users.noreply.github.com>
  • Loading branch information
nzjony committed May 6, 2021
1 parent b63d78e commit 2f10962
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 11 deletions.
15 changes: 12 additions & 3 deletions @here/harp-examples/decoder/custom_decoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,18 @@ class CustomDecoder extends ThemedTileDecoder {
const numberDependenciesIndex = numberPoints + 1;
// Add 1 because we need to skip the first element
const numberDependencies = data[numberDependenciesIndex];
for (let i = 0; i < numberDependencies; i++) {
// Add 1 to skip the number of dependencies
dependencies.push(data[numberDependenciesIndex + i + 1]);
// The format of each dependency is row, column, level, because we can't store the
// mortonCode in 32bits safely. I could have split into two 32 bit values, but that makes
// the code harder to read and debug, so this is fine, and the number of dependent tiles is
// generally not too big.

// Add 1 to skip the numberDependencies value
const offset = numberDependenciesIndex + 1;
for (let i = 0; i < numberDependencies; i += 3) {
const row = data[offset + i];
const column = data[offset + i + 1];
const level = data[offset + i + 2];
dependencies.push(TileKey.fromRowColumnLevel(row, column, level).mortonCode());
}
}
}
Expand Down
34 changes: 26 additions & 8 deletions @here/harp-examples/src/tile_dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ export namespace TileDependenciesExample {
`;
class CustomDataProvider extends DataProvider {
enableTileDependencies: boolean = false;

constructor(readonly mainTileKey: TileKey) {
super();
}

connect() {
// Here you could connect to the service.
return Promise.resolve();
Expand All @@ -85,18 +90,19 @@ export namespace TileDependenciesExample {
data.push(x, y);
}

const mainTileKey = new TileKey(16384, 16384, 15);
if (tileKey.mortonCode() === mainTileKey.mortonCode()) {
if (tileKey.mortonCode() === this.mainTileKey.mortonCode()) {
return Promise.resolve(new Float32Array([data.length, ...data, 0]));
} else {
// Simulate that the tile contents spread over multiple tiles
if (
this.enableTileDependencies &&
(tileKey.column >= mainTileKey.column - 3 ||
tileKey.column <= mainTileKey.column + 3)
(tileKey.column >= this.mainTileKey.column - 3 ||
tileKey.column <= this.mainTileKey.column + 3) &&
tileKey.row === this.mainTileKey.row
) {
//snippet:tile_dependencies.ts
return Promise.resolve(new Float32Array([0, 1, mainTileKey.mortonCode()]));
const { row, column, level } = this.mainTileKey;
return Promise.resolve(new Float32Array([0, 1, row, column, level]));
//end:tile_dependencies.ts
}
}
Expand Down Expand Up @@ -224,16 +230,27 @@ export namespace TileDependenciesExample {
map.resize(window.innerWidth, window.innerHeight);
});

const customDataProvider = new CustomDataProvider();
const customDP1 = new CustomDataProvider(new TileKey(16385, 16384, 15));
const customDP = new CustomDataProvider(new TileKey(16384, 16384, 15));

// snippet:tile_dependencies_create.ts
const customDatasource = new CustomDataSource({
name: "customDatasource",
styleSetName: "customStyleSet",
tilingScheme: webMercatorTilingScheme,
dataProvider: customDataProvider,
dataProvider: customDP,
concurrentDecoderServiceName: CUSTOM_DECODER_SERVICE_TYPE,
storageLevelOffset: -1
});
const customDatasource1 = new CustomDataSource({
name: "customDatasource1",
styleSetName: "customStyleSet",
tilingScheme: webMercatorTilingScheme,
dataProvider: customDP1,
concurrentDecoderServiceName: CUSTOM_DECODER_SERVICE_TYPE,
storageLevelOffset: -1
});
map.addDataSource(customDatasource1);
map.addDataSource(customDatasource);

// Also visualize the tile borders:
Expand All @@ -253,7 +270,8 @@ export namespace TileDependenciesExample {

const gui = new GUI({ width: 300 });
gui.add(guiOptions, "tileDependencies").onChange(val => {
customDataProvider.enableTileDependencies = !customDataProvider.enableTileDependencies;
customDP.enableTileDependencies = !customDP.enableTileDependencies;
customDP1.enableTileDependencies = !customDP1.enableTileDependencies;
map.clearTileCache();
map.update();
});
Expand Down
5 changes: 5 additions & 0 deletions @here/harp-mapview/lib/VisibleTileSet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -962,6 +962,11 @@ export class VisibleTileSet {
visibleTileKeys.find(
tileKeyEntry =>
tileKeyEntry.tileKey.mortonCode() === tileKey.mortonCode()
) === undefined &&
// Check that we haven't already added this TileKey
dependentTiles.find(
tileKeyEntry =>
tileKeyEntry.tileKey.mortonCode() === tileKey.mortonCode()
) === undefined
) {
dependentTiles.push(new TileKeyEntry(tileKey, 0));
Expand Down

0 comments on commit 2f10962

Please sign in to comment.