Skip to content

Commit

Permalink
fix out of bounds map caches if too many tiles are loaded (around the…
Browse files Browse the repository at this point in the history
… poles)
  • Loading branch information
svengcz committed May 1, 2023
1 parent 38334fe commit f7f9db8
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 37 deletions.
80 changes: 73 additions & 7 deletions apps/server/src/terrain/mapdata/worldmap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ export interface TileData {
grid: ElevationGrid,
}

export interface GridLookupData {
southwest: { latitude: number; longitude: number },
northeast: { latitude: number; longitude: number },
grid: { row: number; column: number }[][],
minWidthPerTile: number,
minHeightPerTile: number,
}

export class Worldmap {
public GridData: GridDefinition = {
rows: 0,
Expand Down Expand Up @@ -52,10 +60,13 @@ export class Worldmap {
});
}

public createGridLookupTable(position: PositionData): { row: number; column: number }[][] {
const [southwestLat, southwestLong] = projectWgs84(position.latitude, position.longitude, 225, this.VisibilityRange * 1852);
public createGridLookupTable(position: PositionData, maxWidth: number, maxHeight: number, defaultTileSize: number): GridLookupData {
let southwestLat = projectWgs84(position.latitude, position.longitude, 180, this.VisibilityRange * 1852)[0];
let southwestLong = projectWgs84(position.latitude, position.longitude, 270, this.VisibilityRange * 1852)[1];
let northeastLat = projectWgs84(position.latitude, position.longitude, 0, this.VisibilityRange * 1852)[0];
let northeastLong = projectWgs84(position.latitude, position.longitude, 90, this.VisibilityRange * 1852)[1];

const southwestGrid = this.worldMapIndices(southwestLat, southwestLong);
const [northeastLat, northeastLong] = projectWgs84(position.latitude, position.longitude, 45, this.VisibilityRange * 1852);
const northeastGrid = this.worldMapIndices(northeastLat, northeastLong);

let rowCount = northeastGrid.row - southwestGrid.row;
Expand All @@ -78,21 +89,76 @@ export class Worldmap {
columnCount += 1;

// create the look up table and sort from north->south and west->east
const retval = new Array(rowCount);
const grid = new Array(rowCount);
for (let y = 0; y < rowCount; ++y) {
let row = southwestGrid.row + rowDirection * y;
// ensure that the row index is not outside of bounds
if (row < 0) row = Math.abs(row);
if (row >= this.TileManager.grid.length) row -= this.TileManager.grid.length;

retval[rowCount - 1 - y] = new Array(columnCount);
grid[rowCount - 1 - y] = new Array(columnCount);
for (let x = 0; x < columnCount; x++) {
const column = (southwestGrid.column + x) % this.TileManager.grid[0].length;
retval[rowCount - 1 - y][x] = { row, column };
grid[rowCount - 1 - y][x] = { row, column };
}
}

return retval;
// find the minimum dimensions per tile
let minWidthPerTile = 5000;
let minHeightPerTile = 5000;
grid.forEach((row) => {
row.forEach((cellIdx) => {
const cell = this.TileManager.grid[cellIdx.row][cellIdx.column];
if (cell.tileIndex !== -1 && cell.elevationmap && cell.elevationmap.Rows !== 0 && cell.elevationmap.Columns !== 0) {
minWidthPerTile = Math.min(cell.elevationmap.Columns, minWidthPerTile);
minHeightPerTile = Math.min(cell.elevationmap.Rows, minHeightPerTile);
}
});
});
if (minWidthPerTile === 5000) minWidthPerTile = defaultTileSize;
if (minHeightPerTile === 5000) minHeightPerTile = defaultTileSize;

// delete rows if necessary (shared clipping between top and bottom)
const mapHeight = minHeightPerTile * grid.length;
if (mapHeight > maxHeight) {
const clippingTileCount = Math.ceil((mapHeight - maxHeight) / minHeightPerTile);
const topClippingCount = Math.ceil(clippingTileCount / 2);
const bottomClippingCount = Math.floor(clippingTileCount / 2);

for (let i = 0; i < topClippingCount; ++i) grid.shift();
for (let i = 0; i < bottomClippingCount; ++i) grid.pop();

northeastLat -= this.terrainData.AngularSteps.latitude * topClippingCount;
southwestLat += this.terrainData.AngularSteps.latitude * bottomClippingCount;
}

// delete columns as necessary (shared clipping between left and right)
const mapWidth = minWidthPerTile * grid[0].length;
if (mapWidth > maxWidth) {
const clippingTileCount = Math.ceil((mapWidth - maxWidth) / minWidthPerTile);
const startTileClipping = Math.ceil(clippingTileCount / 2);
const endTileClipping = Math.floor(clippingTileCount / 2);

grid.forEach((row) => {
for (let i = 0; i < startTileClipping; ++i) row.shift();
for (let i = 0; i < endTileClipping; ++i) row.pop();
});

southwestLong += this.terrainData.AngularSteps.longitude * startTileClipping;
northeastLong -= this.terrainData.AngularSteps.longitude * endTileClipping;

// ensure correct updates at -180.0, 180.0 degree wrap around
if (southwestLong >= 180.0) southwestLong -= 360.0;
if (northeastLong < -180.0) northeastLong += 360.0;
}

return {
southwest: { latitude: southwestLat, longitude: southwestLong },
northeast: { latitude: northeastLat, longitude: northeastLong },
grid,
minWidthPerTile,
minHeightPerTile,
};
}

public updatePosition(relevantTiles: { row: number; column: number }[][]): boolean {
Expand Down
50 changes: 20 additions & 30 deletions apps/server/src/terrain/processing/maphandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { NavigationDisplayThresholdsDto } from '../dto/navigationdisplaythreshol

// execution parameters
const GpuProcessingActive = true;
const GpuMaxPixelSize = 16384;

// mathematical conversion constants
const FeetPerNauticalMile = 6076.12;
Expand Down Expand Up @@ -378,8 +379,8 @@ class MapHandler {
};
const startupStatus: AircraftStatus = {
adiruDataValid: true,
latitude: 47.26081085205078,
longitude: 11.349658966064453,
latitude: 76.840366,
longitude: 21.019548,
altitude: 1904,
heading: 260,
verticalSpeed: 0,
Expand All @@ -392,8 +393,8 @@ class MapHandler {
navigationDisplayRenderingMode: TerrainRenderingMode.ArcMode,
};
const startupPosition: PositionData = {
latitude: 47.26081085205078,
longitude: 11.349658966064453,
latitude: 76.840366,
longitude: 21.019548,
};

// run all process steps to precompile the kernels
Expand Down Expand Up @@ -449,37 +450,23 @@ class MapHandler {
private updateGroundTruthPositionAndCachedTiles(position: PositionData, startup: boolean): void {
if (!this.initialized && !startup) return;
this.currentGroundTruthPosition = position;
const grid = this.worldmap.createGridLookupTable(position);
const loadedTiles = this.worldmap.updatePosition(grid);
const relevantTileCount = grid.length * grid[0].length;
const lookup = this.worldmap.createGridLookupTable(position, GpuMaxPixelSize, GpuMaxPixelSize, DefaultTileSize);
const loadedTiles = this.worldmap.updatePosition(lookup.grid);
const relevantTileCount = lookup.grid.length * lookup.grid[0].length;

if (loadedTiles || this.cachedElevationData.cachedTiles !== relevantTileCount) {
const [southwestLat, southwestLong] = projectWgs84(position.latitude, position.longitude, 225, this.worldmap.VisibilityRange * 1852);
const southwestGrid = this.worldmap.worldMapIndices(southwestLat, southwestLong);
const [northeastLat, northeastLong] = projectWgs84(position.latitude, position.longitude, 45, this.worldmap.VisibilityRange * 1852);
const northeastGrid = this.worldmap.worldMapIndices(northeastLat, northeastLong);

this.worldMapMetadata.minWidthPerTile = 5000;
this.worldMapMetadata.minHeightPerTile = 5000;
grid.forEach((row) => {
row.forEach((cellIdx) => {
const cell = this.worldmap.TileManager.grid[cellIdx.row][cellIdx.column];
if (cell.tileIndex !== -1 && cell.elevationmap && cell.elevationmap.Rows !== 0 && cell.elevationmap.Columns !== 0) {
this.worldMapMetadata.minWidthPerTile = Math.min(cell.elevationmap.Columns, this.worldMapMetadata.minWidthPerTile);
this.worldMapMetadata.minHeightPerTile = Math.min(cell.elevationmap.Rows, this.worldMapMetadata.minHeightPerTile);
}
});
});
const southwestGrid = this.worldmap.worldMapIndices(lookup.southwest.latitude, lookup.southwest.longitude);
const northeastGrid = this.worldmap.worldMapIndices(lookup.northeast.latitude, lookup.northeast.longitude);

if (this.worldMapMetadata.minWidthPerTile === 5000) this.worldMapMetadata.minWidthPerTile = DefaultTileSize;
if (this.worldMapMetadata.minHeightPerTile === 5000) this.worldMapMetadata.minHeightPerTile = DefaultTileSize;
this.worldMapMetadata.minWidthPerTile = lookup.minWidthPerTile;
this.worldMapMetadata.minHeightPerTile = lookup.minHeightPerTile;

const worldWidth = this.worldMapMetadata.minWidthPerTile * grid[0].length;
const worldHeight = this.worldMapMetadata.minHeightPerTile * grid.length;
const worldWidth = this.worldMapMetadata.minWidthPerTile * lookup.grid[0].length;
const worldHeight = this.worldMapMetadata.minHeightPerTile * lookup.grid.length;
this.cachedElevationData.cpuData = new Float32Array(worldWidth * worldHeight);
let yOffset = 0;

grid.forEach((row) => {
lookup.grid.forEach((row) => {
for (let y = 0; y < this.worldMapMetadata.minHeightPerTile; y++) {
let xOffset = 0;

Expand Down Expand Up @@ -512,13 +499,16 @@ class MapHandler {
this.worldMapMetadata.northeast.longitude = this.worldmap.TileManager.grid[northeastGrid.row][northeastGrid.column].southwest.longitude + this.worldmap.GridData.longitudeStep;
this.worldMapMetadata.width = worldWidth;
this.worldMapMetadata.height = worldHeight;
console.log(this.worldMapMetadata.southwest.latitude, this.worldMapMetadata.southwest.longitude,
this.worldMapMetadata.northeast.latitude, this.worldMapMetadata.northeast.longitude,
worldWidth, worldHeight);

this.uploadWorldMapToGPU = this.uploadWorldMapToGPU.setOutput([worldWidth, worldHeight]);
this.cachedElevationData.gpuData = this.uploadWorldMapToGPU(this.cachedElevationData.cpuData, worldWidth) as Texture;
// some GPU drivers require the flush call to release internal memory
if (GpuProcessingActive) this.uploadWorldMapToGPU.context.flush();

this.worldmap.TileManager.cleanupElevationCache(grid);
this.worldmap.TileManager.cleanupElevationCache(lookup.grid);
this.cachedElevationData.cachedTiles = relevantTileCount;
}

Expand All @@ -536,7 +526,7 @@ class MapHandler {
this.currentGroundTruthPosition.latitude,
this.currentGroundTruthPosition.longitude,
);
grid.forEach((row, rowIdx) => {
lookup.grid.forEach((row, rowIdx) => {
if (row[0].row === egoIndex.row) {
row.forEach((cell, columnIdx) => {
if (cell.column === egoIndex.column) {
Expand Down

0 comments on commit f7f9db8

Please sign in to comment.