mirror of
https://github.com/netbymatt/ws4kp.git
synced 2026-04-14 15:49:31 -07:00
change to radar as a set of tiles for a smaller image download
This commit is contained in:
@@ -77,9 +77,9 @@ const removeDopplerRadarImageNoise = (RadarContext) => {
|
||||
|
||||
// is this pixel the old rgb?
|
||||
if ((R === 0 && G === 0 && B === 0)
|
||||
|| (R === 0 && G === 236 && B === 236)
|
||||
|| (R === 1 && G === 160 && B === 246)
|
||||
|| (R === 0 && G === 0 && B === 246)) {
|
||||
|| (R === 0 && G === 236 && B === 236)
|
||||
|| (R === 1 && G === 160 && B === 246)
|
||||
|| (R === 0 && G === 0 && B === 246)) {
|
||||
// change to your new rgb
|
||||
|
||||
// Transparent
|
||||
@@ -124,14 +124,14 @@ const removeDopplerRadarImageNoise = (RadarContext) => {
|
||||
B = 19;
|
||||
A = 255;
|
||||
} else if ((R === 214 && G === 0 && B === 0)
|
||||
|| (R === 255 && G === 0 && B === 0)) {
|
||||
|| (R === 255 && G === 0 && B === 0)) {
|
||||
// Red
|
||||
R = 171;
|
||||
G = 14;
|
||||
B = 14;
|
||||
A = 255;
|
||||
} else if ((R === 192 && G === 0 && B === 0)
|
||||
|| (R === 255 && G === 0 && B === 255)) {
|
||||
|| (R === 255 && G === 0 && B === 255)) {
|
||||
// Brown
|
||||
R = 115;
|
||||
G = 31;
|
||||
@@ -177,9 +177,44 @@ const mergeDopplerRadarImage = (mapContext, radarContext) => {
|
||||
mapContext.drawImage(radarContext.canvas, 0, 0);
|
||||
};
|
||||
|
||||
const tileSize = { x: 510, y: 320 };
|
||||
const radarFullSize = { width: 2550, height: 1600 };
|
||||
const radarFinalSize = { width: 640, height: 367 };
|
||||
const radarSourceSize = { width: 480, height: 276 };
|
||||
const scaling = {
|
||||
width: radarFinalSize.width / radarSourceSize.width,
|
||||
height: radarFinalSize.height / radarSourceSize.height,
|
||||
};
|
||||
|
||||
// convert a pixel location to a file/tile combination
|
||||
const pixelToFile = (xPixel, yPixel) => {
|
||||
const xTile = Math.floor(xPixel / tileSize.x);
|
||||
const yTile = Math.floor(yPixel / tileSize.y);
|
||||
if (xTile < 0 || xTile > 9 || yTile < 0 || yTile > 9) return false;
|
||||
return `${xTile.toFixed(0).padStart(2, '0')}-${yTile.toFixed(0).padStart(2, '0')}`;
|
||||
};
|
||||
|
||||
// convert a pixel location in the overall map to a pixel location on the tile
|
||||
const modTile = (xPixel, yPixel) => {
|
||||
const x = Math.round(xPixel) % tileSize.x;
|
||||
const y = Math.round(yPixel) % tileSize.y;
|
||||
return { x, y };
|
||||
};
|
||||
|
||||
const mapSizeToFinalSize = (x, y) => ({
|
||||
x: Math.round(x * scaling.height),
|
||||
y: Math.round(y * scaling.width),
|
||||
});
|
||||
|
||||
export {
|
||||
getXYFromLatitudeLongitudeDoppler,
|
||||
getXYFromLatitudeLongitudeMap,
|
||||
removeDopplerRadarImageNoise,
|
||||
mergeDopplerRadarImage,
|
||||
pixelToFile,
|
||||
modTile,
|
||||
mapSizeToFinalSize,
|
||||
tileSize,
|
||||
radarFinalSize,
|
||||
radarFullSize,
|
||||
};
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import * as utils from './radar-utils.mjs';
|
||||
|
||||
const radarFullSize = { width: 2550, height: 1600 };
|
||||
const radarFinalSize = { width: 640, height: 367 };
|
||||
import {
|
||||
radarFinalSize, radarFullSize, pixelToFile, modTile, tileSize, removeDopplerRadarImageNoise, mapSizeToFinalSize,
|
||||
} from './radar-utils.mjs';
|
||||
|
||||
const fetchAsBlob = async (url) => {
|
||||
const response = await fetch(url);
|
||||
return response.blob();
|
||||
};
|
||||
|
||||
const baseMapImages = new Promise((resolve) => {
|
||||
fetchAsBlob('/images/maps/radar.webp').then((blob) => {
|
||||
const baseMapImages = (tile) => new Promise((resolve) => {
|
||||
if (tile === false) resolve(false);
|
||||
fetchAsBlob(`/images/maps/radar-tiles/${tile}.webp`).then((blob) => {
|
||||
createImageBitmap(blob).then((imageBitmap) => {
|
||||
// extract the black pixels to overlay on to the final image (boundaries)
|
||||
const canvas = new OffscreenCanvas(imageBitmap.width, imageBitmap.height);
|
||||
@@ -28,13 +28,17 @@ const baseMapImages = new Promise((resolve) => {
|
||||
context.putImageData(imageData, 0, 0);
|
||||
|
||||
resolve({
|
||||
fullMap: imageBitmap,
|
||||
base: imageBitmap,
|
||||
overlay: canvas,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const drawOnBasemap = (baseContext, drawImage, positions) => {
|
||||
baseContext.drawImage(drawImage, positions.sx, positions.sy, positions.sw, positions.sh, positions.dx, positions.dy, positions.dw, positions.dh);
|
||||
};
|
||||
|
||||
onmessage = async (e) => {
|
||||
const {
|
||||
url, RADAR_HOST, OVERRIDES, radarSourceXY, sourceXY, offsetX, offsetY,
|
||||
@@ -63,9 +67,93 @@ onmessage = async (e) => {
|
||||
const radarContext = radarCanvas.getContext('2d');
|
||||
radarContext.imageSmoothingEnabled = false;
|
||||
|
||||
// get the base map
|
||||
const baseMaps = await baseMapImages;
|
||||
baseContext.drawImage(baseMaps.fullMap, sourceXY.x, sourceXY.y, offsetX * 2, offsetY * 2, 0, 0, radarFinalSize.width, radarFinalSize.height);
|
||||
// determine the basemap images needed
|
||||
const baseMapTiles = [
|
||||
pixelToFile(sourceXY.x, sourceXY.y),
|
||||
pixelToFile(sourceXY.x + offsetX * 2, sourceXY.y),
|
||||
pixelToFile(sourceXY.x, sourceXY.y + offsetY * 2),
|
||||
pixelToFile(sourceXY.x + offsetX * 2, sourceXY.y + offsetY * 2),
|
||||
];
|
||||
|
||||
// get the base maps
|
||||
const baseMapsPromise = Promise.allSettled(baseMapTiles.map(baseMapImages));
|
||||
|
||||
// do some more calculations for assembling the tiles
|
||||
// the tiles are arranged as follows, with the horizontal axis as x, and correlating with the second set of digits in the image file number
|
||||
// T[0] T[1]
|
||||
// T[2] T[3]
|
||||
// tile 0 gets special treatment, it's placement is the basis for all downstream calculations
|
||||
const t0Source = modTile(sourceXY.x, sourceXY.y);
|
||||
const t0Width = tileSize.x - t0Source.x;
|
||||
const t0Height = tileSize.y - t0Source.y;
|
||||
const t0FinalSize = mapSizeToFinalSize(t0Width, t0Height);
|
||||
|
||||
// these will all be used again for the overlay, calculate them once here
|
||||
const mapCoordinates = [];
|
||||
// t[0]
|
||||
mapCoordinates.push({
|
||||
sx: t0Source.x,
|
||||
sw: t0Width,
|
||||
dx: 0,
|
||||
dw: t0FinalSize.x,
|
||||
|
||||
sy: t0Source.y,
|
||||
sh: t0Height,
|
||||
dy: 0,
|
||||
dh: t0FinalSize.y,
|
||||
});
|
||||
// t[1]
|
||||
mapCoordinates.push({
|
||||
sx: 0,
|
||||
sw: tileSize.x - t0Width,
|
||||
dx: t0FinalSize.x,
|
||||
dw: mapSizeToFinalSize(tileSize.x - t0Width, 0).x,
|
||||
|
||||
sy: t0Source.y,
|
||||
sh: t0Height,
|
||||
dy: 0,
|
||||
dh: t0FinalSize.y,
|
||||
});
|
||||
// t[2]
|
||||
mapCoordinates.push({
|
||||
sx: t0Source.x,
|
||||
sw: t0Width,
|
||||
dx: 0,
|
||||
dw: t0FinalSize.x,
|
||||
|
||||
sy: 0,
|
||||
sh: tileSize.y - t0Height,
|
||||
dy: t0FinalSize.y,
|
||||
dh: mapSizeToFinalSize(0, tileSize.y - t0Height).y,
|
||||
});
|
||||
// t[3]
|
||||
mapCoordinates.push({
|
||||
sx: 0,
|
||||
sw: tileSize.x - t0Width,
|
||||
dx: t0FinalSize.x,
|
||||
dw: mapSizeToFinalSize(tileSize.x - t0Width, 0).x,
|
||||
|
||||
sy: 0,
|
||||
sh: tileSize.y - t0Height,
|
||||
dy: t0FinalSize.y,
|
||||
dh: mapSizeToFinalSize(0, tileSize.y - t0Height).y,
|
||||
});
|
||||
|
||||
// wait for the basemaps to arrive
|
||||
const baseMaps = (await baseMapsPromise).map((map) => map.value ?? false);
|
||||
|
||||
// draw each tile if needed
|
||||
drawOnBasemap(baseContext, baseMaps[0].base, mapCoordinates[0]);
|
||||
if (mapCoordinates[1].dx < radarFinalSize.width && baseMaps[1]) {
|
||||
drawOnBasemap(baseContext, baseMaps[1].base, mapCoordinates[1]);
|
||||
}
|
||||
if (mapCoordinates[2].dy < radarFinalSize.height && baseMaps[2]) {
|
||||
drawOnBasemap(baseContext, baseMaps[2].base, mapCoordinates[2]);
|
||||
if (mapCoordinates[1].dx < radarFinalSize.width && baseMaps[3]) {
|
||||
drawOnBasemap(baseContext, baseMaps[3].base, mapCoordinates[3]);
|
||||
}
|
||||
}
|
||||
// baseContext.drawImage(baseMaps.fullMap, sourceXY.x, sourceXY.y, offsetX * 2, offsetY * 2, 0, 0, radarFinalSize.width, radarFinalSize.height);
|
||||
|
||||
// test response
|
||||
const radarResponse = await radarResponsePromise;
|
||||
@@ -87,7 +175,7 @@ onmessage = async (e) => {
|
||||
croppedRadarContext.drawImage(radarCanvas, radarSource.x, radarSource.y, croppedRadarCanvas.width, croppedRadarCanvas.height, 0, 0, croppedRadarCanvas.width, croppedRadarCanvas.height);
|
||||
|
||||
// clean the image
|
||||
utils.removeDopplerRadarImageNoise(croppedRadarContext);
|
||||
removeDopplerRadarImageNoise(croppedRadarContext);
|
||||
|
||||
// stretch the radar image
|
||||
const stretchCanvas = new OffscreenCanvas(radarFinalSize.width, radarFinalSize.height);
|
||||
@@ -97,8 +185,17 @@ onmessage = async (e) => {
|
||||
|
||||
// put the radar on the base map
|
||||
baseContext.drawImage(stretchCanvas, 0, 0);
|
||||
// put the road/boundaries overlay on the map
|
||||
baseContext.drawImage(baseMaps.overlay, sourceXY.x, sourceXY.y, offsetX * 2, offsetY * 2, 0, 0, radarFinalSize.width, radarFinalSize.height);
|
||||
// put the road/boundaries overlay on the map as needed
|
||||
drawOnBasemap(baseContext, baseMaps[0].overlay, mapCoordinates[0]);
|
||||
if (mapCoordinates[1].dx < radarFinalSize.width && baseMaps[1]) {
|
||||
drawOnBasemap(baseContext, baseMaps[1].overlay, mapCoordinates[1]);
|
||||
}
|
||||
if (mapCoordinates[2].dy < radarFinalSize.height && baseMaps[2]) {
|
||||
drawOnBasemap(baseContext, baseMaps[2].overlay, mapCoordinates[2]);
|
||||
if (mapCoordinates[1].dx < radarFinalSize.width && baseMaps[3]) {
|
||||
drawOnBasemap(baseContext, baseMaps[3].overlay, mapCoordinates[3]);
|
||||
}
|
||||
}
|
||||
|
||||
const processedRadar = baseCanvas.transferToImageBitmap();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user