Fix drawing of temperature, precipitation, wind
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
import { Accessor, Component, createSignal } from 'solid-js'
|
||||
import { Accessor, Component, createSignal, Setter } from 'solid-js'
|
||||
|
||||
import styles from './harmonie.module.css'
|
||||
import { apiHost } from '../consts'
|
||||
import { GribMessage } from './interfaces'
|
||||
import { fetchBuffer } from '../helpers/fetch'
|
||||
import { drawGrib } from './draw/drawGrib'
|
||||
import { fetchWindData } from './draw/windDirection'
|
||||
|
||||
const CROP_BOUNDS = { x: 1906-1-400, y: 950, width: 400, height: 300 }
|
||||
|
||||
@@ -12,18 +13,25 @@ export const GribFile: Component<{
|
||||
name: string,
|
||||
isActive: Accessor<boolean>,
|
||||
getCanvas: Accessor<HTMLCanvasElement | undefined>,
|
||||
setIsLoading: Setter<boolean>,
|
||||
onClick: (name: string) => void,
|
||||
}> = ({ name, isActive, getCanvas, onClick }) => {
|
||||
const [getStructure, setStructure] = createSignal<GribMessage[]>([])
|
||||
}> = ({
|
||||
name,
|
||||
isActive,
|
||||
getCanvas,
|
||||
setIsLoading,
|
||||
onClick,
|
||||
}) => {
|
||||
const [getGribList, setGribList] = createSignal<GribMessage[]>([])
|
||||
const isCrop = createSignal(false)
|
||||
|
||||
function onFileClick() {
|
||||
onClick(name)
|
||||
|
||||
if (getStructure().length === 0) {
|
||||
if (getGribList().length === 0) {
|
||||
fetch(`${apiHost}/api/show/grib/${name}`)
|
||||
.then(re => re.json())
|
||||
.then(setStructure)
|
||||
.then(setGribList)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,12 +40,11 @@ export const GribFile: Component<{
|
||||
let cachedBitmasks: Uint8Array[] = []
|
||||
|
||||
function onParamClick(paramId: number) {
|
||||
const grib = getStructure()[paramId]
|
||||
console.log("onParamClick", grib)
|
||||
setIsLoading(true);
|
||||
const grib = getGribList()[paramId]
|
||||
const bitmaskSection = grib.sections.find(section => section.id === 6)
|
||||
const binarySection = grib.sections.find(section => section.id === 7)
|
||||
if (!bitmaskSection || !binarySection) return;
|
||||
console.log("sections 6,7")
|
||||
|
||||
const bitmaskOffset = bitmaskSection.offset + 6
|
||||
const bitmaskLength = bitmaskSection.size - 6
|
||||
@@ -47,9 +54,10 @@ export const GribFile: Component<{
|
||||
|
||||
const binaryOffset = binarySection.offset + 5
|
||||
const binaryLength = binarySection.size - 5
|
||||
const fetchPromise: Promise<[GribMessage[], ArrayBuffer[], ArrayBuffer[]]> =
|
||||
Promise.all([
|
||||
[grib],
|
||||
const fetchPromise: Promise<[GribMessage[], ArrayBuffer[], ArrayBuffer[]]> = grib.meteo.discipline === 0 && grib.meteo.category === 2 && grib.meteo.product === 192
|
||||
? fetchWindData(grib, getGribList())
|
||||
: Promise.all([
|
||||
Promise.resolve([grib]),
|
||||
fetchBuffer(`${apiHost}/api/grib/binary-chunk/${binaryOffset}/${binaryLength}/${name}`).then(b=>[b]),
|
||||
bitmaskPromise,
|
||||
])
|
||||
@@ -58,12 +66,11 @@ export const GribFile: Component<{
|
||||
cachedMessages = messages
|
||||
cachedBuffers = binaryBuffers.map(b => new Uint8Array(b))
|
||||
cachedBitmasks = bitmasks.map(b => new Uint8Array(b))
|
||||
const colors: [string, string] = ['#0000ff', '#ffff00']
|
||||
const cropBounds = isCrop[0]() ? CROP_BOUNDS : undefined
|
||||
drawGrib(getCanvas()!, cachedMessages, cachedBuffers, cachedBitmasks, colors, cropBounds)
|
||||
drawGrib(getCanvas()!, cachedMessages, cachedBuffers, cachedBitmasks, cropBounds)
|
||||
})
|
||||
.catch(err => console.warn(err.message))
|
||||
// .finally(() => setIsLoading(false))
|
||||
.finally(() => setIsLoading(false))
|
||||
}
|
||||
|
||||
return <li
|
||||
@@ -72,7 +79,7 @@ export const GribFile: Component<{
|
||||
>
|
||||
<div class={styles.name}>{ trimName(name) }</div>
|
||||
<ul class={styles.meteoParams}>
|
||||
{ getStructure()
|
||||
{ getGribList()
|
||||
.sort((a, b) => a.title > b.title ? 1 : -1)
|
||||
.map((grib, i) =>
|
||||
<li onClick={() => onParamClick(i)}>{ grib.title }</li>
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import { Component, createSignal } from 'solid-js'
|
||||
import { apiHost } from '../consts'
|
||||
|
||||
import { apiHost } from '../consts'
|
||||
import styles from './harmonie.module.css'
|
||||
import { GribFile } from './GribFile'
|
||||
import { LoadingSpinner } from '../components/LoadingSpinner'
|
||||
|
||||
export const Harmonie: Component<{}> = () => {
|
||||
const [getFileList, setFileList] = createSignal<string[]>([])
|
||||
const [getActiveGrib, setActiveGrib] = createSignal('')
|
||||
const [getCanvas, setCanvas] = createSignal<HTMLCanvasElement>()
|
||||
const [getIsLoading, setIsLoading] = createSignal(true)
|
||||
|
||||
fetch(`${apiHost}/api/show/grib-list`)
|
||||
.then(re => re.json())
|
||||
@@ -15,6 +17,7 @@ export const Harmonie: Component<{}> = () => {
|
||||
fileList.sort((a: string, b: string) => a < b ? 1 : -1)
|
||||
setFileList(fileList)
|
||||
})
|
||||
.finally(() => setIsLoading(false))
|
||||
|
||||
return <div class={styles.container}>
|
||||
<div class={styles.column}>
|
||||
@@ -24,13 +27,15 @@ export const Harmonie: Component<{}> = () => {
|
||||
name={fileName}
|
||||
isActive={() => getActiveGrib() === fileName}
|
||||
getCanvas={getCanvas}
|
||||
setIsLoading={setIsLoading}
|
||||
onClick={() => setActiveGrib(fileName)}
|
||||
/>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
<div class={styles.column}>
|
||||
<canvas ref={setCanvas} />
|
||||
{ getIsLoading() && <LoadingSpinner text='' />}
|
||||
<canvas ref={setCanvas} style={{ display: getIsLoading() ? 'none' : 'block' }} />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { GribMessage } from '../../interfaces/interfaces'
|
||||
import { GribMessage } from '../interfaces'
|
||||
import { CropBounds } from './drawGrib'
|
||||
|
||||
export function extractFromBounds(
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { interpolateColors } from '../../helpers/interpolateColors.ts'
|
||||
import { GribMessage, MeteoParam } from '../../interfaces/interfaces.ts'
|
||||
import { applyBitmask } from './bitmask.ts'
|
||||
import { extractFromBounds } from './bounds.ts'
|
||||
import { categoricalRainColors } from './categoricalRain.ts'
|
||||
import { precipitationColors } from './precipitation.ts'
|
||||
import { temperatureColors } from './temperature.ts'
|
||||
import { windDirectionArrows, windDirectionColors, windSpeedColors } from './windDirection.ts'
|
||||
import { interpolateColors } from '../../helpers/interpolateColors'
|
||||
import { GribMessage, MeteoParam } from '../interfaces'
|
||||
import { applyBitmask } from './bitmask'
|
||||
import { extractFromBounds } from './bounds'
|
||||
import { categoricalRainColors } from './categoricalRain'
|
||||
import { precipitationColors } from './precipitation'
|
||||
import { temperatureColors } from './temperature'
|
||||
import { windDirectionArrows, windDirectionColors, windSpeedColors } from './windDirection'
|
||||
|
||||
export type CropBounds = { x: number, y: number, width: number, height: number }
|
||||
|
||||
@@ -14,7 +14,6 @@ export function drawGrib(
|
||||
messages: GribMessage[],
|
||||
buffers: Uint8Array[],
|
||||
bitmasks: Uint8Array[],
|
||||
colors: [string, string],
|
||||
cropBounds: CropBounds | undefined,
|
||||
): void {
|
||||
// normally we have one message/buffer/bitmask?. special cases have multiple like wind direction
|
||||
@@ -41,7 +40,7 @@ export function drawGrib(
|
||||
const ctx = canvas.getContext('2d')!
|
||||
let imgData = ctx.createImageData(cols, rows)
|
||||
|
||||
fillImageData(imgData, messages, modifiedBuffers, colors)
|
||||
fillImageData(imgData, messages, modifiedBuffers)
|
||||
if (grib.meteo.discipline === 0 && grib.meteo.category === 2 && grib.meteo.product === 192) {
|
||||
imgData = windDirectionArrows(imgData, messages, modifiedBuffers)
|
||||
}
|
||||
@@ -71,10 +70,10 @@ function fillImageData(
|
||||
imgData: ImageData,
|
||||
messages: GribMessage[],
|
||||
buffers: Uint8Array[],
|
||||
colors: [string, string],
|
||||
) {
|
||||
const [grib] = messages
|
||||
const [buffer] = buffers
|
||||
const colors: [string, string] = ['#0000ff', '#ffff00']
|
||||
|
||||
const { meteo, conversion, bitsPerDataPoint } = grib
|
||||
const bytesPerPoint = grib.bitsPerDataPoint / 8
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { valueToColorInterpolated, valueToColorThreshold } from '../../helpers/interpolateColors'
|
||||
import { MeteoConversion } from '../../interfaces/interfaces'
|
||||
import { MeteoConversion } from '../interfaces'
|
||||
import { PRECIPITATION } from './constants'
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { valueToColorInterpolated, valueToColorThreshold } from '../../helpers/interpolateColors'
|
||||
import { MeteoConversion } from '../../interfaces/interfaces'
|
||||
import { MeteoConversion } from '../interfaces'
|
||||
import { TEMPERATURES } from './constants'
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user