Add checkbox for latvia contour

This commit is contained in:
Guntis Smaukstelis
2025-02-16 20:20:06 +02:00
parent 692594dcad
commit b78e8c20b6
4 changed files with 41 additions and 3 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

+5 -2
View File
@@ -17,6 +17,7 @@ export const GribFile: Component<{
getFileGribList: Accessor<GribMessage[]> // specific reference and forecast time (in one file) getFileGribList: Accessor<GribMessage[]> // specific reference and forecast time (in one file)
getAllGribLists: Accessor<GribMessage[]> getAllGribLists: Accessor<GribMessage[]>
getIsCrop: Accessor<boolean>, getIsCrop: Accessor<boolean>,
getIsContour: Accessor<boolean>,
onClick: (name: string) => void, onClick: (name: string) => void,
}> = ({ }> = ({
name, name,
@@ -25,6 +26,7 @@ export const GribFile: Component<{
getFileGribList, getFileGribList,
getAllGribLists, getAllGribLists,
getIsCrop, getIsCrop,
getIsContour,
onClick, onClick,
}) => { }) => {
let cachedMessages: GribMessage[] = [] let cachedMessages: GribMessage[] = []
@@ -36,10 +38,11 @@ export const GribFile: Component<{
createEffect(async () => { createEffect(async () => {
setIsLoading(true) setIsLoading(true)
const cropBounds = getIsCrop() ? CROP_BOUNDS : undefined const cropBounds = getIsCrop() ? CROP_BOUNDS : undefined
const contour = getIsContour()
// hack to show loading spinner // hack to show loading spinner
await new Promise(resolve => setTimeout(resolve, 100)) await new Promise(resolve => setTimeout(resolve, 100))
if (cachedMessages.length === 0) return; if (cachedMessages.length === 0) return;
drawGrib(getCanvas()!, cachedMessages, cachedBuffers, cachedBitmasks, cropBounds) drawGrib(getCanvas()!, cachedMessages, cachedBuffers, cachedBitmasks, cropBounds, contour)
setIsLoading(false) setIsLoading(false)
}) })
@@ -72,7 +75,7 @@ export const GribFile: Component<{
cachedBuffers = binaryBuffers.map(b => new Uint8Array(b)) cachedBuffers = binaryBuffers.map(b => new Uint8Array(b))
cachedBitmasks = bitmasks.map(b => new Uint8Array(b)) cachedBitmasks = bitmasks.map(b => new Uint8Array(b))
const cropBounds = getIsCrop() ? CROP_BOUNDS : undefined const cropBounds = getIsCrop() ? CROP_BOUNDS : undefined
drawGrib(getCanvas()!, cachedMessages, cachedBuffers, cachedBitmasks, cropBounds) drawGrib(getCanvas()!, cachedMessages, cachedBuffers, cachedBitmasks, cropBounds, getIsContour())
}) })
.catch(err => console.warn(err.message)) .catch(err => console.warn(err.message))
.finally(() => setIsLoading(false)) .finally(() => setIsLoading(false))
+7
View File
@@ -14,6 +14,7 @@ export const Harmonie: Component<{}> = () => {
const [getCanvas, setCanvas] = createSignal<HTMLCanvasElement>() const [getCanvas, setCanvas] = createSignal<HTMLCanvasElement>()
const [getIsLoading, setIsLoading] = createSignal(true) const [getIsLoading, setIsLoading] = createSignal(true)
const [getIsCrop, setIsCrop] = createSignal(true) const [getIsCrop, setIsCrop] = createSignal(true)
const [getIsContour, setIsContour] = createSignal(false)
const [getGribList, setGribList] = createSignal<GribMessage[]>([]) const [getGribList, setGribList] = createSignal<GribMessage[]>([])
fetchJson(`${apiHost}/api/show/grib-list`) fetchJson(`${apiHost}/api/show/grib-list`)
@@ -56,6 +57,11 @@ export const Harmonie: Component<{}> = () => {
Crop Latvia Crop Latvia
<input type='checkbox' checked={getIsCrop()} onChange={()=>setIsCrop(!getIsCrop())} /> <input type='checkbox' checked={getIsCrop()} onChange={()=>setIsCrop(!getIsCrop())} />
</label> </label>
&nbsp;
<label>
Contour
<input type='checkbox' checked={getIsContour()} onChange={()=>setIsContour(!getIsContour())} />
</label>
<ul class={styles.fileList}> <ul class={styles.fileList}>
{getFileList().map(fileName => {getFileList().map(fileName =>
<GribFile <GribFile
@@ -65,6 +71,7 @@ export const Harmonie: Component<{}> = () => {
getFileGribList={() => getCurrentGribList(fileName)} getFileGribList={() => getCurrentGribList(fileName)}
getAllGribLists={getGribList} getAllGribLists={getGribList}
getIsCrop={getIsCrop} getIsCrop={getIsCrop}
getIsContour={getIsContour}
onClick={() => onGribMessageClick(fileName)} onClick={() => onGribMessageClick(fileName)}
/> />
)} )}
+29 -1
View File
@@ -3,10 +3,15 @@ import { GribMessage, MeteoParam } from '../interfaces'
import { applyBitmask } from './bitmask' import { applyBitmask } from './bitmask'
import { extractFromBounds } from './bounds' import { extractFromBounds } from './bounds'
import { categoricalRainColors } from './categoricalRain' import { categoricalRainColors } from './categoricalRain'
import { hourPrecipitationColors, isCalculatedHourPrecipitation, precipitationColors } from './precipitation' import { hourPrecipitationColors, precipitationColors } from './precipitation'
import { temperatureColors } from './temperature' import { temperatureColors } from './temperature'
import { isCalculatedWindDirection, windDirectionArrows, windDirectionColors, windSpeedColors } from './windDirection' import { isCalculatedWindDirection, windDirectionArrows, windDirectionColors, windSpeedColors } from './windDirection'
import latvia_border from '../../assets/latvia_contour.webp'
const latviaBoderImg = new Image()
latviaBoderImg.onload = () => console.log('latvia_contour loaded')
latviaBoderImg.src = latvia_border
export type CropBounds = { x: number, y: number, width: number, height: number } export type CropBounds = { x: number, y: number, width: number, height: number }
export function drawGrib( export function drawGrib(
@@ -15,6 +20,7 @@ export function drawGrib(
buffers: Uint8Array[], buffers: Uint8Array[],
bitmasks: Uint8Array[], bitmasks: Uint8Array[],
cropBounds: CropBounds | undefined, cropBounds: CropBounds | undefined,
isContour: boolean,
): void { ): void {
// normally we have one message/buffer/bitmask?. special cases have multiple like wind direction // normally we have one message/buffer/bitmask?. special cases have multiple like wind direction
const [grib] = messages const [grib] = messages
@@ -56,6 +62,10 @@ export function drawGrib(
ctx.drawImage(tempCanvas, 0, -canvas.height) ctx.drawImage(tempCanvas, 0, -canvas.height)
// ctx.drawImage(tempCanvas, 0, 0) // ctx.drawImage(tempCanvas, 0, 0)
ctx.restore() ctx.restore()
if (isContour && !!cropBounds) {
drawContour(canvas, ctx) // draw latvia contour only on cropped image
}
} }
const CATEGORICAL_RAIN = [0, 1, 192] const CATEGORICAL_RAIN = [0, 1, 192]
@@ -137,6 +147,24 @@ function fillImageData(
} }
} }
function drawContour(
canvas: HTMLCanvasElement,
ctx: CanvasRenderingContext2D,
): void {
ctx.save()
ctx.translate(canvas.width/2 + 8, canvas.height/2 - 5)
const angle = -26
ctx.rotate(angle * Math.PI / 180)
const scale = 5.3
const scaledWidth = latviaBoderImg.width/scale
const scaledHeight = latviaBoderImg.height/scale
ctx.drawImage(latviaBoderImg,
-scaledWidth/2, -scaledHeight/2,
scaledWidth, scaledHeight
)
ctx.restore()
}
function rgbHexToU8(hex: string): RGBu8 { function rgbHexToU8(hex: string): RGBu8 {
return [ return [