Skip to content

Commit

Permalink
Level details dialog added
Browse files Browse the repository at this point in the history
  • Loading branch information
kocatepedogu committed Sep 20, 2023
1 parent 3b7b12f commit d84606d
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 4 deletions.
8 changes: 8 additions & 0 deletions src/renderer/diagram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ interface PlotCurve extends PlotFeature {
}

export class SoundingPlot {
private observers: Array<(lev: number) => void> = [];
private sounding: data.Sounding;
private canvas: HTMLCanvasElement;
private ctx: CanvasRenderingContext2D;
Expand Down Expand Up @@ -133,6 +134,11 @@ export class SoundingPlot {
});
}

/** Adds a callback function that gets called when the active level is changed. */
addObserver(fncallback: (lev: number) => void) {
this.observers.push(fncallback);
}

/**
* Determines size of canvas based on the size of the div containing it.
*/
Expand Down Expand Up @@ -228,6 +234,8 @@ export class SoundingPlot {

const temp = this.tmin + (x - (this.plotHeight - y) * Math.sin(Math.PI * this.skew/180)) / this.rT;
informationBox.innerHTML += temp.toFixed(0) + '&deg;C';

this.observers.forEach(fn => fn(pres));
}
}

Expand Down
24 changes: 24 additions & 0 deletions src/renderer/dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
*/

export class Dialog {
private static windows: Dialog[] = [];

private zIndex: number;

private element: HTMLDivElement;
private titleElement: HTMLDivElement;
private closeBtn: HTMLDivElement;
Expand All @@ -34,6 +38,10 @@ export class Dialog {
this.titleElement = <HTMLDivElement>document.getElementById(id + '-title')!;
this.closeBtn = <HTMLDivElement>document.getElementById(id + '-close');

this.zIndex = Dialog.windows.length;
this.element.style.zIndex = this.zIndex.toString();
this.element.addEventListener('mousedown', () => {Dialog.raise(this)});

this.isBeingMoved = false;
this.pos1 = 0;
this.pos2 = 0;
Expand All @@ -45,6 +53,8 @@ export class Dialog {
document.addEventListener('mousemove', (e: MouseEvent) => {this.mouseMove(e)});
this.titleElement.addEventListener('mousedown', (e: MouseEvent) => {this.mouseDown(e)});
this.closeBtn.addEventListener('click', () => {this.close()});

Dialog.windows.push(this);
}

private mouseUp() {
Expand Down Expand Up @@ -123,4 +133,18 @@ export class Dialog {
private close() {
this.element.hidden = true;
}

private static raise(dialog: Dialog) {
const selfZ = dialog.zIndex;

for (const win of Dialog.windows) {
if (win.zIndex > selfZ) {
win.zIndex--;
win.element.style.zIndex = win.zIndex.toString();
}
}

dialog.zIndex = Dialog.windows.length;
dialog.element.style.zIndex = dialog.zIndex.toString();
}
}
77 changes: 77 additions & 0 deletions src/renderer/leveldetails.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// SPDX-License-Identifier: GPL-3.0-or-later

/*
* Copyright 2023 Doğu Kocatepe
* This file is part of Sounding Viewer.
* Sounding Viewer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* Sounding Viewer is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License along
* with Sounding Viewer. If not, see <https://www.gnu.org/licenses/>.
*/

import { Sounding } from "./sounding";
import * as numerical from "./numerical";

export class LevelDetails {
private snd: Sounding;
private pres: number;
private element: HTMLTextAreaElement;

constructor(snd: Sounding) {
this.element = <HTMLTextAreaElement>document.getElementById('sounding-level-details-text')!;
this.snd = snd;
this.pres = this.snd.first().pressure;
this.snd.addObserver(() => {this.update();});
this.update();
}

setLevel(pres: number) {
this.pres = pres;
this.update();
}

update() {
let result = '';

const pres = this.pres;
const height = this.snd.getValueAt(pres, 'height');
const temp = this.snd.getValueAt(pres, 'temp');
const dewpt = this.snd.getValueAt(pres, 'dewpt');
const e = numerical.vaporPressure(dewpt);
const es = numerical.saturatedVaporPressure(temp);
const w = numerical.mixingRatio(dewpt, pres);
const ws = numerical.saturatedMixingRatio(temp, pres);
const rh = numerical.relativeHumidity(temp, dewpt, pres);
const spec = numerical.specificHumidityFromMixingRatio(w);
const tv = numerical.virtualTemperature(temp, dewpt, pres);
const theta = numerical.potentialTemperature(temp, pres);
const thetae = numerical.equivalentPotentialTemperature(temp, dewpt, pres);
const twet = numerical.wetBulbTemperature(temp, dewpt, pres);

result += `Pressure: ${pres.toFixed(1)} mb\n`;
result += `Height: ${height.toFixed(1)} m\n`;
result += `Temperature: ${temp.toFixed(2)} degC\n`;
result += `Dewpoint Temperature: ${dewpt.toFixed(2)} degC\n`;
result += `Virtual Temperature: ${tv.toFixed(2)} degC\n`;
result += `Potential Temperature: ${theta.toFixed(2)} degC\n`;
result += `Equivalent Potential Temperature: ${thetae.toFixed(2)} degC\n`;
result += `Wet bulb Temperature: ${twet.toFixed(2)} degC\n`;
result += `Vapor Pressure: ${e.toFixed(1)} mb\n`;
result += `Saturated Vapor Pressure: ${es.toFixed(1)} mb\n`;
result += `Mixing Ratio: ${w.toFixed(1)} g/kg\n`;
result += `Saturated Mixing Ratio: ${ws.toFixed(1)} g/kg\n`;
result += `Relative Humidity: ${(rh * 100).toFixed(1)}%\n`;
result += `Specific Humidity: ${(spec).toFixed(1)} g/kg\n`;

this.element.value = result;
}
}
23 changes: 23 additions & 0 deletions src/renderer/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
import * as data from "./sounding"

export class SoundingTable {
private observers: Array<(lev: number) => void> = [];
private previousActiveLevel: number;

/* Level properties that will be displayed together with their titles */
private readonly levelProperties = ["pressure", "height", "temp", "dewpt", "windspd", "winddir"];
private readonly levelPropertyTitles = [
Expand Down Expand Up @@ -179,8 +182,22 @@ export class SoundingTable {
event.preventDefault();
}

private mouseMoveHandler(event: MouseEvent, sounding: data.Sounding) {
const targetElement = event.target as HTMLElement;
if (targetElement.className == 'sounding-table-data-cells') {
const id = parseInt(targetElement.id.split('-')[0]);
const level = sounding.find(id);
if (this.previousActiveLevel != level.pressure) {
this.observers.forEach(fn => fn(level.pressure));
this.previousActiveLevel = level.pressure;
}
}
}

/* Fills table with given data and sets event handlers */
constructor(sounding: data.Sounding) {
this.previousActiveLevel = sounding.first().pressure;

/* Get sounding table element */
const soundingTable = document.getElementById('sounding-table');
if (!soundingTable) {
Expand All @@ -207,5 +224,11 @@ export class SoundingTable {
/* Event handlers of table */
soundingTable.addEventListener('click', (event) => {this.tableLeftClickHandler(event, sounding);});
soundingTable.addEventListener('contextmenu', (event) => {this.tableRightClickHandler(event);});
soundingTable.addEventListener('mousemove', (event) => {this.mouseMoveHandler(event, sounding);});
}

/** Adds a callback function that gets called when the active level is changed */
addObserver(fncallback: (lev: number) => void) {
this.observers.push(fncallback);
}
}
15 changes: 13 additions & 2 deletions src/renderer/viewer.css
Original file line number Diff line number Diff line change
Expand Up @@ -184,14 +184,25 @@ html, body {
text-align: left;
}

#sounding-diagram-settings-title {
#sounding-level-details {
position: absolute;
top: 100px;
left: 100px;
background-color: rgb(233, 233, 233);
border: rgb(121, 121, 121);
border-width: 1px;
border-style:solid;
text-align: left;
}

.dialog-title {
width: 100%;
background-color: var(--dark);
color: white;
cursor: move;
}

#sounding-diagram-settings-close {
.dialog-close {
float:right;
background-color: #888888;
cursor: pointer;
Expand Down
12 changes: 11 additions & 1 deletion src/renderer/viewer.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
<div id="sounding-diagram-toolbar">
<button type="submit" id="load-new-btn" onclick="window.location.href='./index.html';">New</button>
<button type="button" id="settings-btn">Settings</button>
<button type="button" id="level-details-btn">Level details</button>
<button type="button" id="export-btn">Export</button>
</div>
<canvas id="sounding-diagram"></canvas>
Expand All @@ -56,8 +57,17 @@
</div>
</div>

<div id="sounding-level-details" hidden>
<div id="sounding-level-details-title" class="dialog-title">Level Details
<div id="sounding-level-details-close" class="dialog-close">X</div>
</div>
<textarea id="sounding-level-details-text" readonly></textarea>
</div>

<div id="sounding-diagram-settings" hidden>
<div id="sounding-diagram-settings-title">Diagram Settings <div id="sounding-diagram-settings-close">X</div></div>
<div id="sounding-diagram-settings-title" class="dialog-title">Diagram Settings
<div id="sounding-diagram-settings-close" class="dialog-close">X</div>
</div>
<div id="sounding-diagram-settings-body">
<br><label>Skew: <input id="skew-input" type="number"></label>
<br><label>Tstep: <input id="tstep-input" type="number" min="1"></label>
Expand Down
12 changes: 11 additions & 1 deletion src/renderer/viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import * as sounding from "./sounding"
import * as table from "./table"
import * as diagram from "./diagram"
import * as indices from "./indices"
import * as levelDetails from "./leveldetails"
import { Dialog } from "./dialog"

function getData(){
Expand Down Expand Up @@ -103,17 +104,26 @@ window.initializeSounding = async function() {
const snd = new sounding.Sounding(src);
const plt = new diagram.SoundingPlot(snd);
const ind = new indices.IndexTable(snd);
new table.SoundingTable(snd);
const tbl = new table.SoundingTable(snd);
const det = new levelDetails.LevelDetails(snd);

plt.addObserver((lev) => det.setLevel(lev));
tbl.addObserver((lev) => det.setLevel(lev));
plt.update();
ind.update();

document.getElementById('export-btn')?.addEventListener('click', () => {
exportData(snd);
});

document.getElementById('level-details-btn')?.addEventListener('click', () => {
const levelDetailsDialog = document.getElementById('sounding-level-details');
levelDetailsDialog!.hidden = false;
})

document.getElementById('main-div')!.style.visibility = "visible";
document.getElementById('loading-div')!.style.visibility = "hidden";

new Dialog("sounding-diagram-settings");
new Dialog("sounding-level-details");
}

0 comments on commit d84606d

Please sign in to comment.