getElevationData = async (
tiles,
tileSize,
outputWidth,
outputHeight,
fetchTerrainTileCb,
getElevationCb,
inputCanvas = new OffscreenCanvas(256, 256),
outputCanvas = new OffscreenCanvas(256, 256)
) => {
const [x0, y0] = tiles[0];
const [x1, y1] = tiles[tiles.length - 1];
const tilesWide = x1 - x0 + 1;
const tilesHigh = y1 - y0 + 1;
inputCanvas.width = tilesWide * tileSize;
inputCanvas.height = tilesHigh * tileSize;
const inputContext = inputCanvas.getContext("2d");
for (const [x, y, image] of await Promise.all(
tiles.map(([x, y, z]) =>
fetchTerrainTileCb(x, y, z).then((image) => [x, y, image])
)
)) {
inputContext.drawImage(
image,
(x - x0) * tileSize,
(y - y0) * tileSize,
tileSize,
tileSize
);
}
outputCanvas.width = outputWidth;
outputCanvas.height = outputHeight;
const outputContext = outputCanvas.getContext("2d");
outputContext.drawImage(
inputContext.canvas,
Math.round((x0 + tiles.translate[0]) * tiles.scale),
Math.round((y0 + tiles.translate[1]) * tiles.scale),
tilesWide * tiles.scale,
tilesHigh * tiles.scale
);
const demImageData = outputContext.getImageData(
0,
0,
outputWidth,
outputHeight
);
const demData = demImageData.data;
const values = new Float64Array(outputWidth * outputHeight);
for (let y = 0; y < outputHeight; y++) {
for (let x = 0; x < outputWidth; x++) {
let k = x + y * outputWidth;
let k4 = 4 * k;
values[k] = getElevationCb(demData[k4], demData[k4 + 1], demData[k4 + 2]);
}
}
return values;
}