Skip to content

Commit

Permalink
fix: Fix overflow on massive maps, and tile measurements for great di…
Browse files Browse the repository at this point in the history
…stances.
  • Loading branch information
manticorp committed Mar 3, 2023
1 parent 7468dba commit 22be4a0
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 35 deletions.
64 changes: 49 additions & 15 deletions public/dist/js/main.js

Large diffs are not rendered by default.

28 changes: 25 additions & 3 deletions public/dist/js/processor.js

Large diffs are not rendered by default.

45 changes: 31 additions & 14 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ import {
LatLngZoom,
ConfigState,
TileLoadState,
NormaliseMode
NormaliseMode,
roll,
clamp
} from "./helpers";

type AppArgs = {
Expand Down Expand Up @@ -544,10 +546,12 @@ export default class App {
endy: 0,
bounds: [{latitude:0, longitude:0},{latitude:0, longitude:0}],
status: 'pending',
phys: {width: 0, height: 0}
phys: {width: 0, height: 0},
min: {x: 0, y: 0},
max: {x: 0, y: 0}
};
}
getCurrentState(scaleApprox : number = 1) {
getCurrentState(scaleApprox : number = 1) : ConfigState {
const state = this.newState();

const z = parseInt(this.inputs.outputzoom.val().toString());
Expand All @@ -563,12 +567,22 @@ export default class App {

state.exactPos = App.getTileCoordsFromLatLngExact(state.latitude, state.longitude, state.zoom);
state.widthInTiles = state.width/NextZen.tileWidth;
state.heightInTiles = state.height/NextZen.tileWidth;
state.heightInTiles = state.height/NextZen.tileHeight;

state.min = App.getTileCoordsFromLatLngExact( 85, -179.999, newZ);
state.min.x = Math.floor(state.min.x);
state.min.y = 0;
state.max = App.getTileCoordsFromLatLngExact(-85, 179.999, newZ);
state.max.x = Math.ceil(state.max.x);
state.max.y = Math.floor(state.max.y);

state.startx = Math.floor(state.exactPos.x - state.widthInTiles/2);
state.starty = Math.floor(state.exactPos.y - state.heightInTiles/2);
state.endx = Math.floor(state.exactPos.x + state.widthInTiles/2);
state.endy = Math.floor(state.exactPos.y + state.heightInTiles/2);
state.starty = clamp(Math.floor(state.exactPos.y - state.heightInTiles/2), state.min.y, state.max.y);
state.endy = clamp(Math.floor(state.exactPos.y + state.heightInTiles/2), state.min.y, state.max.y);

state.heightInTiles = clamp(state.exactPos.y + state.heightInTiles/2, state.min.y, state.max.y) - clamp(state.exactPos.y - state.heightInTiles/2, state.min.y, state.max.y);
state.height = state.heightInTiles * NextZen.tileHeight;

state.bounds = [
App.getLatLngFromTileCoords(
Expand All @@ -587,7 +601,7 @@ export default class App {
const lngWidth = Math.abs(state.bounds[1].longitude - state.bounds[0].longitude);
state.phys = {
height: (1000 * 110.574 * latWidth),
width: (1000 * 111.320 * Math.cos(App.toRad(latWidth)) * lngWidth)
width: (1000 * 110.574 * lngWidth),
};

return state;
Expand All @@ -605,15 +619,16 @@ export default class App {
for (let x = state.startx; x <= state.endx; x++) {
for (let y = state.starty; y <= state.endy; y++) {
imageFetches.push(new Promise((resolve, reject) => {
return App.getImageAt({...state, x, y}).then(buffer => {
const nx = roll(x, state.min.x, state.max.x);
return App.getImageAt({z: state.z, x: nx, y: y}).then(buffer => {
const png = PNG.fromBuffer(buffer);
resolve({...state, x, y, buffer, png, heights: png.terrariumToGrayscale()});
}).catch(e => {
if (e.type === 'abort') {
return;
}
console.error(e);
reject({...state, x, y});
reject({...state, x, y, nx});
});
}));
}
Expand All @@ -628,7 +643,6 @@ export default class App {
});
}).catch(e => {
console.error('Failed to load images', e);
this.displayError({text: 'Failed to load images'});
}).finally(() => {
this.els.generate.prop('disabled', false);
currentRequests = [];
Expand All @@ -645,7 +659,8 @@ export default class App {
for (let x = state.startx; x <= state.endx; x++) {
for (let y = state.starty; y <= state.endy; y++) {
imageFetches.push(new Promise((resolve, reject) => {
return App.getImageAt({...state, x, y}).then(buffer => {
const nx = roll(x, state.min.x, state.max.x);
return App.getImageAt({z: state.z, x: nx, y: y}).then(buffer => {
this.imageLoaded({...state, x, y});
const png = PNG.fromBuffer(buffer);
resolve({...state, x, y, buffer, png, heights: png.terrariumToGrayscale()});
Expand Down Expand Up @@ -698,19 +713,21 @@ export default class App {
async generateOutputUsingWorker(states : TileLoadState[]) {
//@ts-ignore
const output = await processor.combineImages(states, this.inputs.smartNormalisationControl.val()) as NormaliseResult<Float32Array>;
this.displayHeightData(output);
this.displayHeightData(output, states[0]);
return this.saveOutput(output.data, states);
}
displayHeightData(output : NormaliseResult<Float32Array>) {
displayHeightData(output : NormaliseResult<Float32Array>, state: TileLoadState) {
const fmt = this.meterFormatter;
const range = output.maxBefore - output.minBefore;
const unrealZscaleFactor = 0.001953125;
const zScale = unrealZscaleFactor * range * 100;
const xyScale = ((state.phys.width * 100) / state.width);
// Start by multiplying 4207 by 100 to convert the height into centimeters. This equals 420,700 cm.
// Next, multiply this new value by the ratio: 420,700 multiplied by 0.001953125 equals 821.6796875‬.
// This gives you a Z scale value of 821.6796875‬ and results in a heightmap that will go from -210,350 cm to 210,350 cm.
const txt = `<p>Height range: ${fmt.format(output.minBefore)} to ${fmt.format(output.maxBefore)}</p>
<p>In Unreal Engine, on import, a z scaling of <code>${zScale}</code> should be used for 1:1 height scaling using a normalised image.</p>`;
<p>In Unreal Engine, on import, a z scaling of <code>${zScale.toFixed(2)}</code> should be used for 1:1 height scaling using a normalised image.</p>
<p>x and y scales should be set to <code>${xyScale.toFixed(2)}</code></p>`;
this.els.outputText.html(txt);
}
async generateOutput(states : TileLoadState[]) {
Expand Down
10 changes: 8 additions & 2 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ export type ConfigState = TileCoords & LatLngZoom & {
endy: number,
status: string,
bounds: [LatLng, LatLng],
phys: {width: number, height: number}
phys: {width: number, height: number},
min: {y: number, x: number},
max: {y: number, x: number},
};

export type TileLoadState = ConfigState & {x: number, y: number, heights: Float32Array};
Expand All @@ -51,4 +53,8 @@ export enum NormaliseMode {
Regular = 1,
Smart = 2,
SmartWindow = 3,
}
}

export const roll = (num: number, min: number = 0, max: number = 1) => modWithNeg(num - min, max - min) + min;
export const modWithNeg = (x: number, mod: number) => ((x % mod) + mod) % mod;
export const clamp = (num : number, min: number = 0, max: number = 1) => Math.max(min, Math.min(max, num)));
8 changes: 7 additions & 1 deletion src/processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,13 @@ const processor = {
y: Math.floor((y%1)*tileWidth)
};
const idx = px.y*tileWidth + px.x;
output[i++] = map[tile.x][tile.y].heights[idx];
if (typeof map[tile.x] === 'undefined') {
throw new Error(`x value ${tile.x} was undefined`);
} else if (typeof map[tile.x][tile.y] === 'undefined') {
throw new Error(`y value ${tile.y} was undefined`);
} else {
output[i++] = map[tile.x][tile.y].heights[idx];
}
}
}
let result = {
Expand Down

0 comments on commit 22be4a0

Please sign in to comment.