diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..e966e83 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/rtwx.iml b/.idea/rtwx.iml new file mode 100644 index 0000000..bbe0211 --- /dev/null +++ b/.idea/rtwx.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nexrad-browser/commands.md b/nexrad-browser/commands.md new file mode 100644 index 0000000..e928857 --- /dev/null +++ b/nexrad-browser/commands.md @@ -0,0 +1,38 @@ +# `CLF ...` +Currently loaded file. + +| Command | Description | Example | +|-----------|-------------------------------------------------------------------------------------|-----------| +| `CLF OV` | Overwrite the currently loaded file with a new file from the file selection dialog. | `CLF OV` | +| `CLF LD` | Load the currently loaded file into the scope. | `CLF LD` | +| `CLF CLR` | Clear the currently loaded file. | `CLF CLR` | + +# `POS ...` +Position. + +| Command | Description | Example | +|----------------------------------|-------------------------------------------------------------|----------------------------| +| `POS SHOW` | Show the current position in latitude/longitude. | `POS SHOW` | +| `POS SLL [latitude] [longitude]` | Set the position to the desired latitude/longitude. | `POS SLL 38.8977 -77.0366` | +| `POS SITE [site]` | Set the position to the position of the desired radar site. | `POS SITE KRAX` | + +# `PREF` and `PREFSET` +Preferences. + +| Command | Description | Example | +|---------------------------|---------------------------------------------------|--------------------------------| +| `PREF SHOW [pref]` | Show the value of the preference. | `PREF SHOW RR` | +| `PREF SET [pref] [value]` | Set the value of the preference. | `PREF SET RR 5` | +| `PREF CLR [pref]` | Clear the prefernece (return to default value) | `PREF CLEAR RR` | +| `PREFSET SAVE [name]` | Save the current setup of the scope as a prefset. | `PREF SET SAVE krax_tornadoes` | +| `PREFSET RCL [name]` | Load the scope from the given prefset. | `PREF SET RCL krax_tornadoes` | +| `PREFSET CLR [name]` | Remove the saved prefset. | `PREF SET CLR krax_tornadoes` | +| `PREFSET CLRA` | Remove all saved prefsets. | `PREF SET CLRA` | + +## Available Preferences + +| Preference | Description | Value | +|------------|---------------------|----------------------------| +| RR | Range Rings | 1-100 (default 5) | +| RREN | Range Rings Enabled | true, false (default true) | +| FCS | Font Character Size | 1-100 (default 12) | \ No newline at end of file diff --git a/nexrad-browser/www/VT323-Regular.ttf b/nexrad-browser/www/VT323-Regular.ttf new file mode 100644 index 0000000..e69de29 diff --git a/nexrad-browser/www/index.html b/nexrad-browser/www/index.html index 89c6523..570b486 100644 --- a/nexrad-browser/www/index.html +++ b/nexrad-browser/www/index.html @@ -2,36 +2,27 @@ NEXRAD Browser -
-
- -
-
- - - -
-
-
+ + Something went wrong while loading the canvas. Sorry :/ + +

FONT TEST!

- \ No newline at end of file diff --git a/nexrad-browser/www/index.js b/nexrad-browser/www/index.js index 0b0afa7..31c545f 100644 --- a/nexrad-browser/www/index.js +++ b/nexrad-browser/www/index.js @@ -4,14 +4,69 @@ wasm.__nxrd_browser_init(); console.log("[JS] setup event listeners"); -const fileSelector = document.getElementById('file'); +console.log("[JS] initializing the renderer"); -document.getElementById("go").addEventListener("click", (e) => { - const file = fileSelector.files[0]; - const reader = new FileReader(); - reader.addEventListener('load', (event) => { - let data = event.target.result; - wasm.load_ar2(data); - }); - reader.readAsArrayBuffer(file); -}); \ No newline at end of file + + +const DEFAULT_PREFERENCES = { + RR: 5, + RREN: true, + FCS: 16 +}; +let preferences = DEFAULT_PREFERENCES; + +function get_font_size() { return `${preferences.FCS}px `; } + +const canvas = document.getElementById("canvas"); +const ctx = canvas.getContext("2d"); + +const FIFTY_MILES = 0.0916; +let current_lat = 38.8977; +let current_long = -77.036560; + +function calcRenderbox() { + return [current_long - FIFTY_MILES, current_lat - FIFTY_MILES, current_long + FIFTY_MILES, current_lat + FIFTY_MILES]; +} + +function latlongXY(lat, long) { + let bbox = calcRenderbox(); + let pixelWidth = canvas.width; + let pixelHeight = canvas.height; + let bboxWidth = bbox[2] - bbox[0]; + let bboxHeight = bbox[3] - bbox[1]; + let widthPct = ( long - bbox[0] ) / bboxWidth; + let heightPct = ( lat - bbox[1] ) / bboxHeight; + let x = Math.floor( pixelWidth * widthPct ); + let y = Math.floor( pixelHeight * ( 1 - heightPct ) ); + return { x, y }; +} + +let x0 = 0; +let y0 = 0; +let xfull = canvas.width; +let yfull = canvas.height; + +function recalcBorderCoordinates() { + let xy = latlongXY(current_lat, current_long); + + x0 = xy.x - canvas.width; + y0 = xy.y - canvas.height; + xfull = xy.x + (canvas.width / 2); + yfull = xy.y + (canvas.height / 2); +} + +setInterval(() => { + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.font = get_font_size(); + ctx.resetTransform(); + + recalcBorderCoordinates(); + + let xy = latlongXY(current_lat, current_long); + + ctx.translate(xy.x, xy.y); + + // background (black, always) + ctx.fillStyle = "black"; + ctx.fillRect(x0, y0, xfull, yfull); +}) \ No newline at end of file diff --git a/nexrad2/Cargo.toml b/nexrad2/Cargo.toml index 43c7db2..f826e5e 100644 --- a/nexrad2/Cargo.toml +++ b/nexrad2/Cargo.toml @@ -6,6 +6,13 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -#bzip2-rs = "0.1" -bzip2 = "0.4" + +bzip2-rs = { version = "0.1", optional = true } +bzip2 = { version = "0.4", optional = true } + log = "0.4" + +[features] +default = ["bzip-impl-bzip2-rs"] +bzip-impl-libbzip2 = ["bzip2"] +bzip-impl-bzip2-rs = ["bzip2-rs"] \ No newline at end of file diff --git a/nexrad2/src/bzip.rs b/nexrad2/src/bzip.rs new file mode 100644 index 0000000..888130f --- /dev/null +++ b/nexrad2/src/bzip.rs @@ -0,0 +1,26 @@ +#[cfg(feature = "bzip-impl-libbzip2")] +pub mod _internal_ffi { + use bzip2::read::BzDecoder; + + pub type BzipImpl = BzDecoder; +} +#[cfg(feature = "bzip-impl-bzip2-rs")] +pub mod _internal_pure { + use bzip2_rs::DecoderReader; + + pub type BzipImpl = DecoderReader; +} + +#[cfg(all(feature = "bzip-impl-bzip2-rs", feature = "bzip-impl-libbzip2"))] +compile_error!("Only one bzip2 implementation can be used. Please select bzip-impl-bzip2-rs or bzip-impl-libbzip2, but not both."); + +#[cfg(not(any(feature = "bzip-impl-bzip2-rs", feature = "bzip-impl-libbzip2")))] +compile_error!("A bzip2 implementation is required. Please select either bzip-impl-bzip2-rs or bzip-impl-libbzip2."); + +#[cfg(all(target_arch = "wasm32", feature = "bzip-impl-libbzip2"))] +compile_error!("bzip-impl-libbzip2 is not compatible with WebAssembly targets. Please use bzip-impl-bzip2-rs instead."); + +#[cfg(feature = "bzip-impl-libbzip2")] +pub type BzipDecoder = _internal_ffi::BzipImpl; +#[cfg(feature = "bzip-impl-bzip2-rs")] +pub type BzipDecoder = _internal_pure::BzipImpl; \ No newline at end of file diff --git a/nexrad2/src/lib.rs b/nexrad2/src/lib.rs index 34f27d4..a0951fa 100644 --- a/nexrad2/src/lib.rs +++ b/nexrad2/src/lib.rs @@ -6,11 +6,12 @@ use std::fmt::{Display, Formatter}; use std::io; use std::io::{Cursor, Read, Seek, SeekFrom}; use std::str::Utf8Error; -use bzip2::read::BzDecoder; -//use bzip2_rs::DecoderReader; use log::{debug, trace}; +use crate::bzip::BzipDecoder; +use crate::message::{LEGACY_CTM_HEADER_LEN, MESSAGE_BODY_SIZE, MESSAGE_HEADER_SIZE, MessageHeader}; pub mod message; +pub mod bzip; #[derive(Debug)] pub struct Nexrad2Chunk { @@ -77,26 +78,6 @@ impl Error for NexradParseError {} pub const NEXRAD2_META_CHUNK_FIXED_LENGTH: usize = 325888; -pub const MESSAGE_HEADER_SIZE: usize = 2 + 1 + 1 + 2 + 2 + 4 + 2 + 2; - -#[derive(Debug)] -pub struct MessageHeader { - pub message_size: u16, - pub rda_redundant_channel: u8, - pub message_type: u8, - pub message_sequence_number: u16, - pub julian_date: u16, - pub millis_after_midnight: u32, - pub num_of_message_segments: u16, - pub message_segment_num: u16 - -} - -pub enum Message { - -} - -pub const LEGACY_TCM_HEADER_LENGTH: i64 = 12; pub fn parse_nx2_chunk(cursor: &mut (impl Read + Seek)) -> Result { let mut volume_header = [0u8; 24]; @@ -141,7 +122,7 @@ pub fn parse_nx2_chunk(cursor: &mut (impl Read + Seek)) -> Result Result (), + Err(e) if matches!(e.kind(), io::ErrorKind::UnexpectedEof) => { break; }, + Err(e) => return Err(NexradParseError::TcmChunkReadFailed(e)) + } let message_header = MessageHeader { message_size: u16::from_be_bytes(message_header[0..2].try_into().unwrap()), @@ -170,9 +157,15 @@ pub fn parse_nx2_chunk(cursor: &mut (impl Read + Seek)) -> Result