This commit is contained in:
Tsuki 2024-03-24 19:50:18 +08:00
parent 09b7e83669
commit cd4c46f9c6
55 changed files with 506 additions and 843 deletions

View File

@ -89,15 +89,24 @@ impl Plugin for ETWSLoader {
CoordType::Other CoordType::Other
}; };
let lat = b.info.dimension_values.get(0).unwrap();
let lon = b.info.dimension_values.get(1).unwrap();
lat_range = [lat[0], lat[lat.len() - 1]];
lon_range = [lon[0], lon[lon.len() - 1]];
let shape = match b.info.dimension_size.len() { let shape = match b.info.dimension_size.len() {
1 => radarg_plugin_interface::DataShape::Vector, 1 => radarg_plugin_interface::DataShape::Vector,
2 => radarg_plugin_interface::DataShape::Matrix, 2 => {
_ => radarg_plugin_interface::DataShape::Scalar, let lat = b.info.dimension_values.get(0).unwrap();
let lon = b.info.dimension_values.get(1).unwrap();
lat_range = [lat[0], lat[lat.len() - 1]];
lon_range = [lon[0], lon[lon.len() - 1]];
radarg_plugin_interface::DataShape::Matrix
},
_ => {
let lat = b.info.dimension_values.get(1).unwrap();
let lon = b.info.dimension_values.get(2).unwrap();
lat_range = [lat[0], lat[lat.len() - 1]];
lon_range = [lon[0], lon[lon.len() - 1]];
radarg_plugin_interface::DataShape::Cube
},
}; };
let data_type = match b.info.value_name.as_str() { let data_type = match b.info.value_name.as_str() {
@ -115,6 +124,7 @@ impl Plugin for ETWSLoader {
"HCA" => PluginResultType::HCA, "HCA" => PluginResultType::HCA,
"QPE" => PluginResultType::QPE, "QPE" => PluginResultType::QPE,
"QPF" => PluginResultType::QPF, "QPF" => PluginResultType::QPF,
"FR" => PluginResultType::DBZ,
_ => PluginResultType::Unknown, _ => PluginResultType::Unknown,
}; };
@ -187,7 +197,7 @@ mod tests {
fn test() { fn test() {
let result = let result =
Record::parse_from_path("/Volumes/data2/RadarArray/HangZhou/radarData/OutputProducts/RadarProducts/BasicProductsX/20230624/20230624000800/ZJHZAA_20230624000800_VIL.dat.gz") Record::parse_from_path("/Volumes/data2/RadarArray/HangZhou/radarData/OutputProducts/RadarProducts/FuseDataX/20220727/ZJHZAA_20220727200000_FR.dat.gz")
.unwrap(); .unwrap();
} }
} }

View File

@ -1 +1 @@
{"rustc_fingerprint":13002805757961277866,"outputs":{"4614504638168534921":{"success":true,"status":"","code":0,"stdout":"rustc 1.75.0 (82e1608df 2023-12-21)\nbinary: rustc\ncommit-hash: 82e1608dfa6e0b5569232559e3d385fea5a93112\ncommit-date: 2023-12-21\nhost: x86_64-pc-windows-msvc\nrelease: 1.75.0\nLLVM version: 17.0.6\n","stderr":""},"4287340858553847514":{"success":true,"status":"","code":0,"stdout":"___.exe\nlib___.rlib\n___.dll\n___.dll\n___.lib\n___.dll\nC:\\Users\\qwin7\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\npacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"msvc\"\ntarget_family=\"windows\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"windows\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"pc\"\nwindows\n","stderr":""}},"successes":{}} {"rustc_fingerprint":6534886339914138005,"outputs":{"4614504638168534921":{"success":true,"status":"","code":0,"stdout":"rustc 1.77.0-nightly (d78329b92 2024-01-13)\nbinary: rustc\ncommit-hash: d78329b92e8d141d19505e7c1527181c4ab87ed4\ncommit-date: 2024-01-13\nhost: aarch64-apple-darwin\nrelease: 1.77.0-nightly\nLLVM version: 17.0.6\n","stderr":""},"15729799797837862367":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/Users/tsuki/.rustup/toolchains/nightly-aarch64-apple-darwin\noff\npacked\nunpacked\n___\ndebug_assertions\noverflow_checks\npanic=\"unwind\"\nproc_macro\nrelocation_model=\"pic\"\ntarget_abi=\"\"\ntarget_arch=\"aarch64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_feature=\"aes\"\ntarget_feature=\"crc\"\ntarget_feature=\"dit\"\ntarget_feature=\"dotprod\"\ntarget_feature=\"dpb\"\ntarget_feature=\"dpb2\"\ntarget_feature=\"fcma\"\ntarget_feature=\"fhm\"\ntarget_feature=\"flagm\"\ntarget_feature=\"fp16\"\ntarget_feature=\"frintts\"\ntarget_feature=\"jsconv\"\ntarget_feature=\"lor\"\ntarget_feature=\"lse\"\ntarget_feature=\"neon\"\ntarget_feature=\"paca\"\ntarget_feature=\"pacg\"\ntarget_feature=\"pan\"\ntarget_feature=\"pmuv3\"\ntarget_feature=\"ras\"\ntarget_feature=\"rcpc\"\ntarget_feature=\"rcpc2\"\ntarget_feature=\"rdm\"\ntarget_feature=\"sb\"\ntarget_feature=\"sha2\"\ntarget_feature=\"sha3\"\ntarget_feature=\"ssbs\"\ntarget_feature=\"v8.1a\"\ntarget_feature=\"v8.2a\"\ntarget_feature=\"v8.3a\"\ntarget_feature=\"v8.4a\"\ntarget_feature=\"vh\"\ntarget_has_atomic\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_has_atomic_equal_alignment=\"128\"\ntarget_has_atomic_equal_alignment=\"16\"\ntarget_has_atomic_equal_alignment=\"32\"\ntarget_has_atomic_equal_alignment=\"64\"\ntarget_has_atomic_equal_alignment=\"8\"\ntarget_has_atomic_equal_alignment=\"ptr\"\ntarget_has_atomic_load_store\ntarget_has_atomic_load_store=\"128\"\ntarget_has_atomic_load_store=\"16\"\ntarget_has_atomic_load_store=\"32\"\ntarget_has_atomic_load_store=\"64\"\ntarget_has_atomic_load_store=\"8\"\ntarget_has_atomic_load_store=\"ptr\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_thread_local\ntarget_vendor=\"apple\"\nunix\n","stderr":""}},"successes":{}}

View File

@ -1 +1 @@
ee6a7bacac3da619 16f3840281ed1c0f

View File

@ -1 +1 @@
{"rustc":10493413842677104517,"features":"[]","target":8454914719411586997,"profile":14094339167972473758,"path":17523903030608720598,"deps":[[3470807962260834726,"serde",false,4400031724788451666],[6147374319788932929,"serde_json",false,16164065312130377423],[6644485573429891122,"thiserror",false,18258125545593472374],[6954241390595330609,"nom",false,598865438637657466],[8926101378076943148,"byteorder",false,15440310884809793591],[8944703748776155531,"chrono",false,8244302838404386295],[10043922549268360936,"radarg_plugin_interface",false,14403560275837773923],[11138931377059941435,"num_traits",false,2394100724493043844],[12701726091060201577,"abi_stable",false,15910410634281474657],[12732307821348191974,"anyhow",false,3836683591027896962],[12935855096716563853,"flate2",false,15712347804304961314],[16098302879908240583,"nom_derive",false,43989377100278263]],"local":[{"CheckDepInfo":{"dep_info":"release\\.fingerprint\\etws_loader-826e392dbec97b5d\\dep-lib-etws_loader"}}],"rustflags":["-C","link-args=/LIBPATH:C:\\gtk-build\\gtk\\x64\\release\\lib\\"],"metadata":41698518999418921,"config":2202906307356721367,"compile_kind":0} {"rustc":17942353898403517573,"features":"[]","declared_features":"","target":8454914719411586997,"profile":14094339167972473758,"path":17523903030608720598,"deps":[[3470807962260834726,"serde",false,3464438898850424389],[6147374319788932929,"serde_json",false,4018346002534341099],[6644485573429891122,"thiserror",false,15376366722783231122],[6954241390595330609,"nom",false,17004332135801955629],[8926101378076943148,"byteorder",false,6029042559770906212],[8944703748776155531,"chrono",false,14085117952510397354],[10043922549268360936,"radarg_plugin_interface",false,2929903515477199145],[11138931377059941435,"num_traits",false,16208028648554347177],[12701726091060201577,"abi_stable",false,46919867052192855],[12732307821348191974,"anyhow",false,13132421988549874417],[12935855096716563853,"flate2",false,9880693184163145737],[16098302879908240583,"nom_derive",false,9783335926581460414]],"local":[{"CheckDepInfo":{"dep_info":"release/.fingerprint/etws_loader-826e392dbec97b5d/dep-lib-etws_loader"}}],"rustflags":[],"metadata":41698518999418921,"config":2202906307356721367,"compile_kind":0}

View File

@ -1,6 +1,6 @@
{"message":"unused imports: `Write`, `self`","code":{"code":"unused_imports","explanation":null},"level":"warning","spans":[{"file_name":"src\\parser.rs","byte_start":335,"byte_end":339,"line_start":13,"line_end":13,"column_start":15,"column_end":19,"is_primary":true,"text":[{"text":"use std::io::{self, Read, Write};","highlight_start":15,"highlight_end":19}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"src\\parser.rs","byte_start":347,"byte_end":352,"line_start":13,"line_end":13,"column_start":27,"column_end":32,"is_primary":true,"text":[{"text":"use std::io::{self, Read, Write};","highlight_start":27,"highlight_end":32}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`#[warn(unused_imports)]` on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"remove the unused imports","code":null,"level":"help","spans":[{"file_name":"src\\parser.rs","byte_start":335,"byte_end":341,"line_start":13,"line_end":13,"column_start":15,"column_end":21,"is_primary":true,"text":[{"text":"use std::io::{self, Read, Write};","highlight_start":15,"highlight_end":21}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"src\\parser.rs","byte_start":345,"byte_end":352,"line_start":13,"line_end":13,"column_start":25,"column_end":32,"is_primary":true,"text":[{"text":"use std::io::{self, Read, Write};","highlight_start":25,"highlight_end":32}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;11mwarning\u001b[0m\u001b[0m\u001b[1m\u001b[38;5;15m: unused imports: `Write`, `self`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m--> \u001b[0m\u001b[0msrc\\parser.rs:13:15\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;14m13\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m|\u001b[0m\u001b[0m \u001b[0m\u001b[0muse std::io::{self, Read, Write};\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;11m^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;11m^^^^^\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m= \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;15mnote\u001b[0m\u001b[0m: `#[warn(unused_imports)]` on by default\u001b[0m\n\n"} {"$message_type":"diagnostic","message":"unused imports: `Write`, `self`","code":{"code":"unused_imports","explanation":null},"level":"warning","spans":[{"file_name":"src/parser.rs","byte_start":323,"byte_end":327,"line_start":13,"line_end":13,"column_start":15,"column_end":19,"is_primary":true,"text":[{"text":"use std::io::{self, Read, Write};","highlight_start":15,"highlight_end":19}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"src/parser.rs","byte_start":335,"byte_end":340,"line_start":13,"line_end":13,"column_start":27,"column_end":32,"is_primary":true,"text":[{"text":"use std::io::{self, Read, Write};","highlight_start":27,"highlight_end":32}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`#[warn(unused_imports)]` on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"remove the unused imports","code":null,"level":"help","spans":[{"file_name":"src/parser.rs","byte_start":323,"byte_end":329,"line_start":13,"line_end":13,"column_start":15,"column_end":21,"is_primary":true,"text":[{"text":"use std::io::{self, Read, Write};","highlight_start":15,"highlight_end":21}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"src/parser.rs","byte_start":333,"byte_end":340,"line_start":13,"line_end":13,"column_start":25,"column_end":32,"is_primary":true,"text":[{"text":"use std::io::{self, Read, Write};","highlight_start":25,"highlight_end":32}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: unused imports: `Write`, `self`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/parser.rs:13:15\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m13\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0muse std::io::{self, Read, Write};\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: `#[warn(unused_imports)]` on by default\u001b[0m\n\n"}
{"message":"unused variable: `hlen2`","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"src\\parser.rs","byte_start":6848,"byte_end":6853,"line_start":198,"line_end":198,"column_start":21,"column_end":26,"is_primary":true,"text":[{"text":" let (input, hlen2) = Self::_parse_u32(input, order)?;","highlight_start":21,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`#[warn(unused_variables)]` on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"if this is intentional, prefix it with an underscore","code":null,"level":"help","spans":[{"file_name":"src\\parser.rs","byte_start":6848,"byte_end":6853,"line_start":198,"line_end":198,"column_start":21,"column_end":26,"is_primary":true,"text":[{"text":" let (input, hlen2) = Self::_parse_u32(input, order)?;","highlight_start":21,"highlight_end":26}],"label":null,"suggested_replacement":"_hlen2","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;11mwarning\u001b[0m\u001b[0m\u001b[1m\u001b[38;5;15m: unused variable: `hlen2`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m--> \u001b[0m\u001b[0msrc\\parser.rs:198:21\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;14m198\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m let (input, hlen2) = Self::_parse_u32(input, order)?;\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;11m^^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;11mhelp: if this is intentional, prefix it with an underscore: `_hlen2`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m= \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;15mnote\u001b[0m\u001b[0m: `#[warn(unused_variables)]` on by default\u001b[0m\n\n"} {"$message_type":"diagnostic","message":"unused variable: `hlen2`","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"src/parser.rs","byte_start":6651,"byte_end":6656,"line_start":198,"line_end":198,"column_start":21,"column_end":26,"is_primary":true,"text":[{"text":" let (input, hlen2) = Self::_parse_u32(input, order)?;","highlight_start":21,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`#[warn(unused_variables)]` on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"if this is intentional, prefix it with an underscore","code":null,"level":"help","spans":[{"file_name":"src/parser.rs","byte_start":6651,"byte_end":6656,"line_start":198,"line_end":198,"column_start":21,"column_end":26,"is_primary":true,"text":[{"text":" let (input, hlen2) = Self::_parse_u32(input, order)?;","highlight_start":21,"highlight_end":26}],"label":null,"suggested_replacement":"_hlen2","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: unused variable: `hlen2`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/parser.rs:198:21\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m198\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m let (input, hlen2) = Self::_parse_u32(input, order)?;\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33mhelp: if this is intentional, prefix it with an underscore: `_hlen2`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: `#[warn(unused_variables)]` on by default\u001b[0m\n\n"}
{"message":"unused variable: `order`","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"src\\parser.rs","byte_start":9313,"byte_end":9318,"line_start":279,"line_end":279,"column_start":9,"column_end":14,"is_primary":true,"text":[{"text":" order: Order,","highlight_start":9,"highlight_end":14}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"if this is intentional, prefix it with an underscore","code":null,"level":"help","spans":[{"file_name":"src\\parser.rs","byte_start":9313,"byte_end":9318,"line_start":279,"line_end":279,"column_start":9,"column_end":14,"is_primary":true,"text":[{"text":" order: Order,","highlight_start":9,"highlight_end":14}],"label":null,"suggested_replacement":"_order","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;11mwarning\u001b[0m\u001b[0m\u001b[1m\u001b[38;5;15m: unused variable: `order`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m--> \u001b[0m\u001b[0msrc\\parser.rs:279:9\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;14m279\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m order: Order,\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;11m^^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;11mhelp: if this is intentional, prefix it with an underscore: `_order`\u001b[0m\n\n"} {"$message_type":"diagnostic","message":"unused variable: `order`","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"src/parser.rs","byte_start":9035,"byte_end":9040,"line_start":279,"line_end":279,"column_start":9,"column_end":14,"is_primary":true,"text":[{"text":" order: Order,","highlight_start":9,"highlight_end":14}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"if this is intentional, prefix it with an underscore","code":null,"level":"help","spans":[{"file_name":"src/parser.rs","byte_start":9035,"byte_end":9040,"line_start":279,"line_end":279,"column_start":9,"column_end":14,"is_primary":true,"text":[{"text":" order: Order,","highlight_start":9,"highlight_end":14}],"label":null,"suggested_replacement":"_order","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: unused variable: `order`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/parser.rs:279:9\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m279\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m order: Order,\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33mhelp: if this is intentional, prefix it with an underscore: `_order`\u001b[0m\n\n"}
{"message":"unused variable: `dimension_len`","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"src\\lib.rs","byte_start":1151,"byte_end":1164,"line_start":43,"line_end":43,"column_start":26,"column_end":39,"is_primary":true,"text":[{"text":" let (dimension_len, data) = match b.data {","highlight_start":26,"highlight_end":39}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"if this is intentional, prefix it with an underscore","code":null,"level":"help","spans":[{"file_name":"src\\lib.rs","byte_start":1151,"byte_end":1164,"line_start":43,"line_end":43,"column_start":26,"column_end":39,"is_primary":true,"text":[{"text":" let (dimension_len, data) = match b.data {","highlight_start":26,"highlight_end":39}],"label":null,"suggested_replacement":"_dimension_len","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;11mwarning\u001b[0m\u001b[0m\u001b[1m\u001b[38;5;15m: unused variable: `dimension_len`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m--> \u001b[0m\u001b[0msrc\\lib.rs:43:26\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;14m43\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m let (dimension_len, data) = match b.data {\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;11m^^^^^^^^^^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;11mhelp: if this is intentional, prefix it with an underscore: `_dimension_len`\u001b[0m\n\n"} {"$message_type":"diagnostic","message":"unused variable: `dimension_len`","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"src/lib.rs","byte_start":1109,"byte_end":1122,"line_start":43,"line_end":43,"column_start":26,"column_end":39,"is_primary":true,"text":[{"text":" let (dimension_len, data) = match b.data {","highlight_start":26,"highlight_end":39}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"if this is intentional, prefix it with an underscore","code":null,"level":"help","spans":[{"file_name":"src/lib.rs","byte_start":1109,"byte_end":1122,"line_start":43,"line_end":43,"column_start":26,"column_end":39,"is_primary":true,"text":[{"text":" let (dimension_len, data) = match b.data {","highlight_start":26,"highlight_end":39}],"label":null,"suggested_replacement":"_dimension_len","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: unused variable: `dimension_len`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/lib.rs:43:26\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m43\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m let (dimension_len, data) = match b.data {\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^^^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33mhelp: if this is intentional, prefix it with an underscore: `_dimension_len`\u001b[0m\n\n"}
{"message":"variants `I64` and `U64` are never constructed","code":{"code":"dead_code","explanation":null},"level":"warning","spans":[{"file_name":"src\\parser.rs","byte_start":590,"byte_end":600,"line_start":28,"line_end":28,"column_start":6,"column_end":16,"is_primary":false,"text":[{"text":"enum ValueTypes {","highlight_start":6,"highlight_end":16}],"label":"variants in this enum","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"src\\parser.rs","byte_start":608,"byte_end":611,"line_start":29,"line_end":29,"column_start":5,"column_end":8,"is_primary":true,"text":[{"text":" I64,","highlight_start":5,"highlight_end":8}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"src\\parser.rs","byte_start":648,"byte_end":651,"line_start":33,"line_end":33,"column_start":5,"column_end":8,"is_primary":true,"text":[{"text":" U64,","highlight_start":5,"highlight_end":8}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`#[warn(dead_code)]` on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;11mwarning\u001b[0m\u001b[0m\u001b[1m\u001b[38;5;15m: variants `I64` and `U64` are never constructed\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m--> \u001b[0m\u001b[0msrc\\parser.rs:29:5\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;14m28\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m|\u001b[0m\u001b[0m \u001b[0m\u001b[0menum ValueTypes {\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m----------\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14mvariants in this enum\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;14m29\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m I64,\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;11m^^^\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;14m...\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;14m33\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m U64,\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;11m^^^\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m= \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;15mnote\u001b[0m\u001b[0m: `#[warn(dead_code)]` on by default\u001b[0m\n\n"} {"$message_type":"diagnostic","message":"variants `I64` and `U64` are never constructed","code":{"code":"dead_code","explanation":null},"level":"warning","spans":[{"file_name":"src/parser.rs","byte_start":563,"byte_end":573,"line_start":28,"line_end":28,"column_start":6,"column_end":16,"is_primary":false,"text":[{"text":"enum ValueTypes {","highlight_start":6,"highlight_end":16}],"label":"variants in this enum","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"src/parser.rs","byte_start":580,"byte_end":583,"line_start":29,"line_end":29,"column_start":5,"column_end":8,"is_primary":true,"text":[{"text":" I64,","highlight_start":5,"highlight_end":8}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"src/parser.rs","byte_start":616,"byte_end":619,"line_start":33,"line_end":33,"column_start":5,"column_end":8,"is_primary":true,"text":[{"text":" U64,","highlight_start":5,"highlight_end":8}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`#[warn(dead_code)]` on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: variants `I64` and `U64` are never constructed\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/parser.rs:29:5\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m28\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0menum ValueTypes {\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m----------\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12mvariants in this enum\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m29\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m I64,\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m...\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m33\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m U64,\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: `#[warn(dead_code)]` on by default\u001b[0m\n\n"}
{"message":"5 warnings emitted","code":null,"level":"warning","spans":[],"children":[],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;11mwarning\u001b[0m\u001b[0m\u001b[1m\u001b[38;5;15m: 5 warnings emitted\u001b[0m\n\n"} {"$message_type":"diagnostic","message":"5 warnings emitted","code":null,"level":"warning","spans":[],"children":[],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: 5 warnings emitted\u001b[0m\n\n"}

View File

@ -1,9 +1,9 @@
C:\Users\qwin7\Desktop\radar-g\etws_loader\target\release\deps\etws_loader.dll: src\lib.rs src\error.rs src\parser.rs /Users/tsuki/projects/radar-g/etws_loader/target/release/deps/libetws_loader.dylib: src/lib.rs src/error.rs src/parser.rs
C:\Users\qwin7\Desktop\radar-g\etws_loader\target\release\deps\libetws_loader.rlib: src\lib.rs src\error.rs src\parser.rs /Users/tsuki/projects/radar-g/etws_loader/target/release/deps/libetws_loader.rlib: src/lib.rs src/error.rs src/parser.rs
C:\Users\qwin7\Desktop\radar-g\etws_loader\target\release\deps\etws_loader.d: src\lib.rs src\error.rs src\parser.rs /Users/tsuki/projects/radar-g/etws_loader/target/release/deps/etws_loader.d: src/lib.rs src/error.rs src/parser.rs
src\lib.rs: src/lib.rs:
src\error.rs: src/error.rs:
src\parser.rs: src/parser.rs:

View File

@ -1 +1 @@
C:\Users\qwin7\Desktop\radar-g\etws_loader\target\release\libetws_loader.rlib: C:\Users\qwin7\Desktop\radar-g\etws_loader\src\error.rs C:\Users\qwin7\Desktop\radar-g\etws_loader\src\lib.rs C:\Users\qwin7\Desktop\radar-g\etws_loader\src\parser.rs C:\Users\qwin7\Desktop\radar-g\radarg_plugin_interface\src\error.rs C:\Users\qwin7\Desktop\radar-g\radarg_plugin_interface\src\lib.rs /Users/tsuki/projects/radar-g/etws_loader/target/release/libetws_loader.dylib: /Users/tsuki/projects/radar-g/etws_loader/src/error.rs /Users/tsuki/projects/radar-g/etws_loader/src/lib.rs /Users/tsuki/projects/radar-g/etws_loader/src/parser.rs /Users/tsuki/projects/radar-g/radarg_plugin_interface/src/error.rs /Users/tsuki/projects/radar-g/radarg_plugin_interface/src/lib.rs

View File

@ -1,5 +1,5 @@
use abi_stable::{ use abi_stable::{
std_types::{ RBoxError, RVec}, std_types::{RBoxError, RVec},
StableAbi, StableAbi,
}; };
@ -18,7 +18,6 @@ pub enum Error {
Many(RVec<Error>), Many(RVec<Error>),
} }
impl Display for Error { impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
@ -33,15 +32,15 @@ impl Display for Error {
)?; )?;
Ok(()) Ok(())
}, }
Error::Custom(e) => Display::fmt(e, f), Error::Custom(e) => Display::fmt(e, f),
Error::Many(list) => { Error::Many(list) => {
for e in list { for e in list {
writeln!(f, "{}", e)?; writeln!(f, "{}", e)?;
} }
Ok(()) Ok(())
}, }
_ => { Ok(())} _ => Ok(()),
} }
} }
} }

View File

@ -50,9 +50,9 @@ pub enum VecResult {
#[derive(StableAbi, Clone, Copy, Debug)] #[derive(StableAbi, Clone, Copy, Debug)]
#[sabi(impl_InterfaceType(Sync, Send, Debug))] #[sabi(impl_InterfaceType(Sync, Send, Debug))]
pub enum DataShape { pub enum DataShape {
Scalar,
Vector, Vector,
Matrix, Matrix,
Cube,
} }
#[repr(C)] #[repr(C)]

View File

@ -6,8 +6,8 @@ use gtk::prelude::{BoxExt, ButtonExt, GtkWindowExt, OrientableExt};
use relm4::actions::{AccelsPlus, ActionablePlus, RelmAction, RelmActionGroup}; use relm4::actions::{AccelsPlus, ActionablePlus, RelmAction, RelmActionGroup};
use relm4::{ComponentParts, ComponentSender, RelmApp, RelmWidgetExt, SimpleComponent}; use relm4::{ComponentParts, ComponentSender, RelmApp, RelmWidgetExt, SimpleComponent};
use crate::components::app::{AppModel, AppMsg}; use crate::components::app::{AppModel, AppMsg, LayerMsg};
use crate::widgets::Layer; use crate::widgets::{AssoElement, Layer};
relm4::new_action_group!(pub LayerActionGroup, "layer"); relm4::new_action_group!(pub LayerActionGroup, "layer");
relm4::new_stateless_action!(pub AddLayerAction, LayerActionGroup, "add"); relm4::new_stateless_action!(pub AddLayerAction, LayerActionGroup, "add");
@ -17,12 +17,18 @@ relm4::new_stateless_action!(pub MoveLayerAction, LayerActionGroup, "move");
pub fn register_layer_actions<W: AsRef<gtk::Widget>>(widget: W, sender: ComponentSender<AppModel>) { pub fn register_layer_actions<W: AsRef<gtk::Widget>>(widget: W, sender: ComponentSender<AppModel>) {
let add_action: RelmAction<AddLayerAction> = { let add_action: RelmAction<AddLayerAction> = {
let sender = sender.clone(); let sender = sender.clone();
RelmAction::new_stateless(move |_| sender.input(AppMsg::AddLayer)) RelmAction::new_stateless(move |_| {
sender.input(AppMsg::LayerManager(LayerMsg::Add(Layer::new(
true,
"Test".to_string(),
AssoElement::Test,
))))
})
}; };
let remove_action: RelmAction<RemoveLayerAction> = { let remove_action: RelmAction<RemoveLayerAction> = {
let sender = sender.clone(); let sender = sender.clone();
RelmAction::new_stateless(move |_| sender.input(AppMsg::RemoveSelectedLayer)) RelmAction::new_stateless(move |_| sender.input(AppMsg::LayerManager(LayerMsg::Remove(0))))
}; };
let mut group: RelmActionGroup<LayerActionGroup> = RelmActionGroup::new(); let mut group: RelmActionGroup<LayerActionGroup> = RelmActionGroup::new();

View File

@ -1,3 +1,4 @@
use super::sidebar::SideBarOutputMsg;
use super::{ use super::{
control_panel::{ControlPanelInputMsg, ControlPanelModel}, control_panel::{ControlPanelInputMsg, ControlPanelModel},
messages::{MonitorInputMsg, MonitorOutputMsg}, messages::{MonitorInputMsg, MonitorOutputMsg},
@ -5,7 +6,9 @@ use super::{
setting::SettingModel, setting::SettingModel,
ControlPanelOutputMsg, TimelineMsg, ControlPanelOutputMsg, TimelineMsg,
}; };
use crate::components::sidebar::{SideBarInputMsg, SideBarModel};
use crate::pipeline::{GridElementImpl, OffscreenRenderer}; use crate::pipeline::{GridElementImpl, OffscreenRenderer};
use crate::predefined::widgets::ColorBar;
use crate::widgets::{AssoElement, DynamicCol}; use crate::widgets::{AssoElement, DynamicCol};
use crate::{ use crate::{
actions::register_layer_actions, actions::register_layer_actions,
@ -53,7 +56,6 @@ use std::{
use tokio::{sync::oneshot, task}; use tokio::{sync::oneshot, task};
use tracing::{debug, error, info, warn}; use tracing::{debug, error, info, warn};
use tracing_subscriber::fmt::layer; use tracing_subscriber::fmt::layer;
use crate::components::sidebar::{SideBarInputMsg, SideBarModel};
relm4::new_action_group!(FileActionGroup, "file"); relm4::new_action_group!(FileActionGroup, "file");
relm4::new_stateless_action!(OpenAction, FileActionGroup, "open"); relm4::new_stateless_action!(OpenAction, FileActionGroup, "open");
@ -61,17 +63,24 @@ pub static FILE_PATH_ROOT: Lazy<Mutex<PathBuf>> = Lazy::new(|| Mutex::new(PathBu
pub type ElementKey = String; pub type ElementKey = String;
#[derive(Debug)]
pub enum LayerMsg {
Add(Layer),
Remove(usize),
SwitchToTime(usize),
Select(Vec<usize>),
RemoveSelected,
}
#[derive(Debug)] #[derive(Debug)]
pub enum AppMsg { pub enum AppMsg {
CloseRequest, CloseRequest,
Close, Close,
OpenDialog, OpenDialog,
AddLayer, LayerManager(LayerMsg),
RemoveSelectedLayer, Layer,
SwitchToTime(usize),
NewElement(Element), NewElement(Element),
DeleteElement(ElementKey), DeleteElement(ElementKey),
NewLayer(Layer),
} }
pub type Buffer = Rc<RefCell<HashMap<String, BTreeMap<DateTime<Utc>, Option<RenderResult>>>>>; pub type Buffer = Rc<RefCell<HashMap<String, BTreeMap<DateTime<Utc>, Option<RenderResult>>>>>;
type RcDispatcher = Rc<Dispatcher>; type RcDispatcher = Rc<Dispatcher>;
@ -90,6 +99,7 @@ pub struct AppModel {
render: Controller<MonitorModel>, render: Controller<MonitorModel>,
#[do_not_track] #[do_not_track]
sidebar: Controller<SideBarModel>, sidebar: Controller<SideBarModel>,
selected_layer: Vec<usize>,
#[do_not_track] #[do_not_track]
layers: Rc<RefCell<Vec<Layer>>>, layers: Rc<RefCell<Vec<Layer>>>,
#[do_not_track] #[do_not_track]
@ -214,7 +224,7 @@ impl Component for AppModel {
) -> ComponentParts<Self> { ) -> ComponentParts<Self> {
let layers = Rc::new(RefCell::new(vec![ let layers = Rc::new(RefCell::new(vec![
Layer::new(true, "Layer 1".to_string(), AssoElement::Test), Layer::new(true, "Layer 1".to_string(), AssoElement::Test),
Layer::new(true, "Layer 2".to_string(), AssoElement::Test) Layer::new(true, "Layer 2".to_string(), AssoElement::Test),
])); ]));
let control = ControlPanelModel::builder().launch(layers.clone()).forward( let control = ControlPanelModel::builder().launch(layers.clone()).forward(
sender.input_sender(), sender.input_sender(),
@ -223,22 +233,28 @@ impl Component for AppModel {
}, },
); );
let sidebar = SideBarModel::builder() let sidebar =
.launch(layers.clone()) SideBarModel::builder()
.forward(sender.input_sender(), |msg| match msg { .launch(layers.clone())
_ => AppMsg::Close, .forward(sender.input_sender(), |msg| {
}); AppMsg::LayerManager(match msg {
SideBarOutputMsg::SelectLayer(idx) => LayerMsg::Select(idx),
SideBarOutputMsg::NewLayer(layer) => LayerMsg::Add(layer),
SideBarOutputMsg::SwitchToTimeSeries(idx) => LayerMsg::SwitchToTime(idx),
})
});
let render = let render =
MonitorModel::builder() MonitorModel::builder()
.launch(layers.clone()) .launch(layers.clone())
.forward(sender.input_sender(), |a| match a { .forward(sender.input_sender(), |a| match a {
MonitorOutputMsg::LayerRenderFinished => AppMsg::Close, MonitorOutputMsg::LayerRenderFinished => AppMsg::Close,
MonitorOutputMsg::LayerSwitchToTime(idx) => AppMsg::SwitchToTime(idx),
_ => AppMsg::Close, _ => AppMsg::Close,
}); });
let setting = SettingModel::builder() let setting = SettingModel::builder()
.launch(()) .launch(())
.forward(sender.input_sender(), |a| AppMsg::Close); .forward(sender.input_sender(), |a| AppMsg::Close);
let mut dispatcher = Rc::new(Dispatcher::new(5, 5, chrono::Duration::minutes(1))); let mut dispatcher = Rc::new(Dispatcher::new(5, 5, chrono::Duration::minutes(1)));
let cms = CMS::new(Mercator::default().into(), (3000.0, 3000.0)); let cms = CMS::new(Mercator::default().into(), (3000.0, 3000.0));
@ -247,44 +263,51 @@ impl Component for AppModel {
let dialog_sidebar_sender = sidebar.sender().clone(); let dialog_sidebar_sender = sidebar.sender().clone();
let dialog_render_sender = render.sender().clone(); let dialog_render_sender = render.sender().clone();
OpenDialog::builder() OpenDialog::builder()
.transient_for_native(&root) .transient_for_native(&root)
.launch(OpenDialogSettings::default()) .launch(OpenDialogSettings::default())
.forward(sender.input_sender(), move |response| match response { .forward(sender.input_sender(), move |response| match response {
OpenDialogResponse::Accept(path) => { OpenDialogResponse::Accept(path) => {
*FILE_PATH_ROOT.lock().unwrap() = path.clone(); *FILE_PATH_ROOT.lock().unwrap() = path.clone();
let data = Self::open_file_only(path); let data = Self::open_file_only(path);
let meta: MetaInfo = (&data.meta).clone().into(); let meta: MetaInfo = (&data.meta).clone().into();
let (lat_start, lat_end) = meta.lat_range.unwrap(); let (lat_start, lat_end) = meta.lat_range.unwrap();
let (lon_start, lon_end) = meta.lon_range.unwrap(); let (lon_start, lon_end) = meta.lon_range.unwrap();
let element_impl = plugin_result_impl(&data); let element_impl = plugin_result_impl(&data);
let mut renderer = OffscreenRenderer::new(3000, 3000).unwrap(); let mut renderer = OffscreenRenderer::new(3000, 3000).unwrap();
let mut canvas = renderer.create_canvas(); let mut canvas = renderer.create_canvas();
let mut dialog_cms = CMS::new(Mercator::default().into(), (3000.0, 3000.0)); let mut dialog_cms = CMS::new(Mercator::default().into(), (3000.0, 3000.0));
let data_target = element_impl.render(&data, &mut canvas, &mut dialog_cms); let data_target = element_impl.render(&data, &mut canvas, &mut dialog_cms);
let data_target = DataTarget::new(Some(data), data_target); let data_target = DataTarget::new(Some(data), data_target);
let element = Element::create_instant( let element = Element::create_instant(
InstantElementDrawerType::Prepared((data_target, element_impl)), InstantElementDrawerType::Prepared((data_target, element_impl)),
dialog_dispatcher.clone(), dialog_dispatcher.clone(),
"ET".to_string(), "ET".to_string(),
) )
.get_instance(); .get_instance();
let layer = let layer = Layer::new(
Layer::new(true, "New Layer".to_string(), AssoElement::Instant(element)); true,
dialog_sidebar_sender.emit(SideBarInputMsg::AddMetaItems(meta.to_map())); "New Layer".to_string(),
dialog_render_sender.emit(MonitorInputMsg::SetRenderRange(lon_start, lon_end, lat_start, lat_end)); AssoElement::Instant(element),
AppMsg::NewLayer(layer) );
} dialog_sidebar_sender.emit(SideBarInputMsg::AddMetaItems(meta.to_map()));
_ => AppMsg::Close, dialog_render_sender.emit(MonitorInputMsg::SetRenderRange(
})}; lon_start, lon_end, lat_start, lat_end,
));
AppMsg::LayerManager(LayerMsg::Add(layer))
}
_ => AppMsg::Close,
})
};
let buffer: Buffer = Rc::new(RefCell::new(HashMap::new())); let buffer: Buffer = Rc::new(RefCell::new(HashMap::new()));
let model = AppModel { let model = AppModel {
cms, cms,
dispatcher, dispatcher,
waiting_for: None, waiting_for: None,
elements: Vec::with_capacity(20), elements: Vec::with_capacity(20),
open_dialog: dialog, open_dialog: dialog,
selected_layer: vec![],
sidebar, sidebar,
control, control,
render, render,
@ -318,31 +341,56 @@ impl Component for AppModel {
) { ) {
self.reset(); self.reset();
match msg { match msg {
AppMsg::NewLayer(layer) => { AppMsg::LayerManager(msg) => match msg {
(*self.layers).borrow_mut().push(layer); LayerMsg::Add(layer) => {
self.sidebar.sender().send(SideBarInputMsg::RefreshList); (*self.layers).borrow_mut().push(layer);
} self.sidebar.sender().send(SideBarInputMsg::RefreshList);
}
LayerMsg::SwitchToTime(idx) => {
let mut layer = (*self.layers).borrow_mut();
let switched_layer = layer.get_mut(idx).unwrap();
let asso_element = switched_layer.pop_associated_element();
if let AssoElement::Instant(e) = asso_element {
let dispatcher = self.dispatcher.clone();
let cms = self.cms.clone();
let (mut series, start_time) = e.to_time_series(dispatcher, cms);
switched_layer.set_time(start_time);
series.register(start_time).unwrap();
let element = Arc::new(Mutex::new(series));
switched_layer
.set_associated_element(AssoElement::TimeSeries(element.clone()));
self.elements.push(element);
}
self.sidebar.sender().send(SideBarInputMsg::RefreshList);
}
LayerMsg::Select(idx) => {
self.set_selected_layer(idx);
}
LayerMsg::RemoveSelected => {
let mut layer = (*self.layers).borrow_mut();
let selected = self.selected_layer.clone();
for idx in selected {
layer.remove(idx);
}
self.sidebar.sender().send(SideBarInputMsg::RefreshList);
}
LayerMsg::Remove(idx) => {
let mut layers = (*self.layers).borrow_mut();
let mut layer = layers.remove(idx);
if let AssoElement::TimeSeries(e) = layer.pop_associated_element() {
let size = Arc::strong_count(&e);
}
self.sidebar.sender().send(SideBarInputMsg::RefreshList);
}
},
AppMsg::CloseRequest => { AppMsg::CloseRequest => {
relm4::main_application().quit(); relm4::main_application().quit();
} }
AppMsg::Close => {} AppMsg::Close => {}
AppMsg::SwitchToTime(idx) => {
let mut layer = (*self.layers).borrow_mut();
let switched_layer = layer.get_mut(idx).unwrap();
let asso_element = switched_layer.pop_associated_element();
if let AssoElement::Instant(e) = asso_element {
let dispatcher = self.dispatcher.clone();
let cms = self.cms.clone();
let (mut series, start_time) = e.to_time_series(dispatcher, cms);
switched_layer.set_time(start_time);
series.register(start_time).unwrap();
let element = Arc::new(Mutex::new(series));
switched_layer.set_associated_element(AssoElement::TimeSeries(element.clone()));
self.elements.push(element);
}
self.sidebar.sender().send(SideBarInputMsg::RefreshList);
}
AppMsg::OpenDialog => { AppMsg::OpenDialog => {
self.open_dialog.emit(OpenDialogMsg::Open); self.open_dialog.emit(OpenDialogMsg::Open);
} }

View File

@ -2,7 +2,7 @@ use super::messages::*;
use super::thumbnail::{ImgItem, TypedListView}; use super::thumbnail::{ImgItem, TypedListView};
use crate::data::{CoordType, Radar2d, RadarData2d}; use crate::data::{CoordType, Radar2d, RadarData2d};
use crate::plugin_system::init_plugin; use crate::plugin_system::init_plugin;
use crate::widgets::render::predefined::color_mapper::BoundaryNorm; use crate::predefined::color_mapper::BoundaryNorm;
use crate::widgets::render::Layer; use crate::widgets::render::Layer;
use crate::widgets::timeline::{Selection, TimeLine}; use crate::widgets::timeline::{Selection, TimeLine};
use abi_stable::std_types::RStr; use abi_stable::std_types::RStr;

View File

@ -1,9 +1,8 @@
pub mod app; pub mod app;
mod control_panel; mod control_panel;
mod monitor; pub mod monitor;
mod setting; mod setting;
pub mod sidebar; pub mod sidebar;
pub use control_panel::*; pub use control_panel::*;
pub use monitor::*; pub use monitor::*;

View File

@ -1,20 +1,12 @@
use std::{collections::HashMap, fmt::Debug}; use std::fmt::Debug;
use crate::{ use crate::components::monitor::widget::Widget;
components::app::ElementKey,
pipeline::element::ElementID,
widgets::{render::Layer, widget::Widget},
};
pub enum MonitorInputMsg { pub enum MonitorInputMsg {
RefreshRender, RefreshRender,
AddWidget(Box<dyn Widget>), AddWidget(Box<dyn Widget>),
RemoveWidget, RemoveWidget,
// AddMetaItem(HashMap<String, String>),
// ClearMetaItems,
// UpdateMetaItem(HashMap<String, String>),
RefreshTiles, RefreshTiles,
// RefreshLayerList,
SetRenderRange(f64, f64, f64, f64), SetRenderRange(f64, f64, f64, f64),
ChangeZoom(f64), ChangeZoom(f64),
None, None,
@ -38,10 +30,6 @@ impl Debug for MonitorInputMsg {
#[derive(Debug)] #[derive(Debug)]
pub enum MonitorOutputMsg { pub enum MonitorOutputMsg {
LayerAdded(usize),
LayerRemoved(usize),
LayerUpdated(usize),
LayerSwitchToTime(usize),
LayerRenderFinished, LayerRenderFinished,
} }

View File

@ -1,4 +1,6 @@
pub mod messages; pub mod messages;
pub mod monitor; pub mod monitor;
pub mod widget;
pub use monitor::*; pub use monitor::*;
pub use widget::*;

View File

@ -1,10 +1,9 @@
use super::messages::{MonitorInputMsg, MonitorOutputMsg}; use super::messages::{MonitorInputMsg, MonitorOutputMsg};
use crate::components::monitor::widget::{Widget, WidgetType};
use crate::coords::cms::CMS; use crate::coords::cms::CMS;
use crate::pipeline::offscreen_renderer::OffscreenRenderer; use crate::pipeline::offscreen_renderer::OffscreenRenderer;
use crate::widgets::predefined::color_mapper::BoundaryNorm; use crate::predefined::color_mapper::BoundaryNorm;
use crate::widgets::predefined::widgets::ColorBar;
use crate::widgets::render::RenderConfig; use crate::widgets::render::RenderConfig;
use crate::widgets::widget::{Widget, WidgetType};
use crate::widgets::WidgetFrame; use crate::widgets::WidgetFrame;
use crate::{ use crate::{
coords::{proj::Mercator, Mapper}, coords::{proj::Mercator, Mapper},

View File

@ -11,8 +11,8 @@ pub enum WidgetType {
} }
pub trait Widget: 'static + Send + Sync { pub trait Widget: 'static + Send + Sync {
fn opengl_render(&self, canvas: &mut Canvas<OpenGl>, cms: CMS) {} fn opengl_render(&self, layers: &Vec<Layer>, canvas: &mut Canvas<OpenGl>, cms: CMS) {}
fn cairo_render(&self, canvas: &gtk::cairo::Context, w: f32, h: f32) {} fn cairo_render(&self, layers: &Vec<Layer>, canvas: &gtk::cairo::Context, w: f32, h: f32) {}
fn widget_type(&self) -> WidgetType; fn widget_type(&self) -> WidgetType;
fn size(&self) -> (f32, f32); fn size(&self) -> (f32, f32);

View File

@ -2,7 +2,8 @@ use super::dispatcher_list::PathItem;
use crate::{ use crate::{
config::PATH_FORMATS, config::PATH_FORMATS,
data::{self, CoordType, Radar2d}, data::{self, CoordType, Radar2d},
widgets::render::{predefined::color_mapper::BoundaryNorm, Layer}, predefined::color_mapper::BoundaryNorm,
widgets::render::Layer,
CONFIG, PLUGIN_MANAGER, CONFIG, PLUGIN_MANAGER,
}; };
use adw::prelude::*; use adw::prelude::*;

View File

@ -1,9 +1,7 @@
use crate::actions::*;
use gtk::prelude::*; use gtk::prelude::*;
use relm4::{ use relm4::{
factory::FactoryView, actions::traits::ActionablePlus, factory::FactoryView, gtk, prelude::*, FactorySender,
gtk,
prelude::{DynamicIndex, FactoryComponent},
FactorySender,
}; };
use super::SideBarInputMsg; use super::SideBarInputMsg;
@ -40,10 +38,9 @@ impl FactoryComponent for BottomBarModel {
view! { view! {
#[root] #[root]
gtk::Box{ gtk::Button{
gtk::Button{ set_icon_name=self.icon.as_str(),
set_icon_name=self.icon.as_str(), ActionablePlus::set_stateless_action::<RemoveLayerAction>: &(),
}
} }
} }

View File

@ -21,11 +21,7 @@ use relm4::{
use std::{cell::RefCell, collections::HashMap, rc::Rc}; use std::{cell::RefCell, collections::HashMap, rc::Rc};
use crate::components::app::AppMsg; use crate::components::app::AppMsg;
use crate::{ use crate::{chart::Chart, predefined::color_mapper::BoundaryNorm, widgets::render::Layer};
chart::Chart,
data::Npz,
widgets::render::{predefined::color_mapper::BoundaryNorm, Layer},
};
use super::{ use super::{
bottom_bar::BottomBarModel, bottom_bar::BottomBarModel,
@ -51,7 +47,7 @@ pub enum SideBarInputMsg {
#[derive(Debug)] #[derive(Debug)]
pub enum SideBarOutputMsg { pub enum SideBarOutputMsg {
SelectLayer(usize), SelectLayer(Vec<usize>),
NewLayer(Layer), NewLayer(Layer),
SwitchToTimeSeries(usize), SwitchToTimeSeries(usize),
} }
@ -141,8 +137,11 @@ impl SimpleComponent for SideBarModel {
list_view_wrapper.selection_model.connect_selection_changed( list_view_wrapper.selection_model.connect_selection_changed(
clone!(@strong sender => move |s,_, _| { clone!(@strong sender => move |s,_, _| {
let selection = s.selection(); let selection = s.selection();
let (iter,_) = gtk::BitsetIter::init_first(&selection).unwrap();
let positions = iter.collect::<Vec<_>>(); let (iter, first) = gtk::BitsetIter::init_first(&selection).unwrap();
let mut result = vec![first as usize];
result.extend(iter.map(|v| v as usize));
sender.output(SideBarOutputMsg::SelectLayer(result));
}), }),
); );
// let mut bottom_bar_vec = FactoryVecDeque::new(gtk::Box::default(), sender.input_sender()); // let mut bottom_bar_vec = FactoryVecDeque::new(gtk::Box::default(), sender.input_sender());
@ -381,7 +380,7 @@ impl RelmListItem for LayerItem {
LayerStatus::BindToOtherLayer(idx) => format!("Bind To Layer: {}", idx), LayerStatus::BindToOtherLayer(idx) => format!("Bind To Layer: {}", idx),
}); });
status_icon.set_icon_name(Some(match self.status{ status_icon.set_icon_name(Some(match self.status {
LayerStatus::BindToTime(_) => "timer-filled", LayerStatus::BindToTime(_) => "timer-filled",
LayerStatus::Instance => "timer-filled", LayerStatus::Instance => "timer-filled",
LayerStatus::BindToOtherLayer(_) => "timer-filled", LayerStatus::BindToOtherLayer(_) => "timer-filled",

View File

@ -1,6 +1,6 @@
use std::ops::Range;
use geo_types::LineString;
use crate::coords::Mapper; use crate::coords::Mapper;
use geo_types::LineString;
use std::ops::Range;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct CMS { pub struct CMS {

View File

@ -1,9 +1,9 @@
use num_traits::AsPrimitive; use num_traits::AsPrimitive;
use num_traits::Num; use num_traits::Num;
pub mod cms;
pub mod mapper; pub mod mapper;
pub mod proj; pub mod proj;
pub mod wgs84; pub mod wgs84;
pub mod cms;
pub use mapper::Mapper; pub use mapper::Mapper;
// pub use wgs84::LatLonCoord; // pub use wgs84::LatLonCoord;

View File

@ -2,18 +2,27 @@ pub mod meta;
use crate::errors::DataError; use crate::errors::DataError;
use async_trait::async_trait; use async_trait::async_trait;
pub use meta::MetaInfo; pub use meta::MetaInfo;
use ndarray::iter::Indices;
use ndarray::{ use ndarray::{
s, Array1, Array2, Array3, ArrayBase, DataMut, Dimension, Ix1, Ix2, OwnedRepr, RawDataClone, s, Array, Array1, Array2, Array3, ArrayBase, Axis, DataMut, Dimension, Ix1, Ix2, Ix3,
OwnedRepr, RawDataClone, Slice, ViewRepr,
}; };
use npyz::{npz::NpzArchive, Deserialize}; use npyz::{npz::NpzArchive, Deserialize};
use num_traits::{AsPrimitive, FromPrimitive, Num}; use num_traits::{AsPrimitive, FromPrimitive, Num};
use std::io::{Cursor, Seek};
use std::{self, f64::consts::PI, fmt::Debug, io::BufReader, path::Path}; use std::{self, f64::consts::PI, fmt::Debug, io::BufReader, path::Path};
use tokio::fs::File;
use tokio::io::{self, AsyncReadExt};
pub type Radar2d<T> = RadarData2d<T, OwnedRepr<T>>; pub type Radar2d<T> = RadarData2d<T, OwnedRepr<T>, OwnedRepr<f64>, OwnedRepr<f64>>;
pub type Radar3d<T> = RadarData3d<T, OwnedRepr<T>, OwnedRepr<f64>, OwnedRepr<f64>, OwnedRepr<f64>>;
pub type Radar2dRef<'a, T> = RadarData2d<T, ViewRepr<&'a T>, ViewRepr<&'a f64>, ViewRepr<&'a f64>>;
pub type Radar3dRef<'a, T> =
RadarData3d<T, ViewRepr<&'a T>, ViewRepr<&'a f64>, ViewRepr<&'a f64>, ViewRepr<&'a f64>>;
#[derive(Clone, Copy, Debug)]
pub enum CoordType {
Polar,
LatLon,
}
pub trait MultiDimensionData<T> pub trait MultiDimensionData<T>
where where
T: Num + Clone + PartialEq + PartialOrd, T: Num + Clone + PartialEq + PartialOrd,
@ -24,248 +33,84 @@ where
} }
#[derive(Clone)] #[derive(Clone)]
pub struct RadarData2d<T, Raw, X = f64, Y = f64, I = Ix1> pub struct RadarData2d<T, Raw, X, Y, I = Ix1>
where where
T: Num + Clone + PartialEq + PartialOrd, T: Num + Clone + PartialEq + PartialOrd,
Raw: ndarray::Data<Elem = T> + Clone + ndarray::RawDataClone, Raw: ndarray::Data<Elem = T> + ndarray::RawDataClone,
X: Num, X: ndarray::Data<Elem = f64> + ndarray::RawDataClone,
Y: Num, Y: ndarray::Data<Elem = f64> + ndarray::RawDataClone,
{ {
pub dim1: ArrayBase<OwnedRepr<X>, I>, pub dim1: ArrayBase<X, I>,
pub dim2: ArrayBase<OwnedRepr<Y>, I>, pub dim2: ArrayBase<Y, I>,
pub data: ArrayBase<Raw, Ix2>, pub data: ArrayBase<Raw, Ix2>,
pub fill_value: T, pub fill_value: T,
pub coord_type: CoordType, pub coord_type: CoordType,
} }
impl<T, Raw, X, Y, I> Debug for RadarData2d<T, Raw, X, Y, I> impl<T> Radar2d<T>
where where
T: Num + Clone + PartialEq + PartialOrd + Debug, T: Num + Clone + PartialEq + PartialOrd,
Raw: ndarray::Data<Elem = T> + Clone + ndarray::RawDataClone,
X: Num + Debug,
Y: Num + Debug,
I: Dimension,
{ {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { pub fn as_ref<'a>(&'a self) -> Radar2dRef<'a, T> {
f.debug_struct("RadarData2d") RadarData2d {
.field("dim1", &self.dim1) dim1: self.dim1.view(),
.field("dim2", &self.dim2) dim2: self.dim2.view(),
.field("data", &self.data) data: self.data.view(),
.field("fill_value", &self.fill_value) fill_value: self.fill_value.clone(),
.field("coord_type", &self.coord_type) coord_type: self.coord_type.clone(),
.finish() }
} }
} }
impl<T: Num + Clone + PartialEq + PartialOrd> Radar2d<T> { #[derive(Clone)]
pub fn load(path: impl AsRef<Path>, meth: impl DataLoader<T, Self>) -> Result<Self, DataError> { pub struct RadarData3d<T, Raw, X, Y, Z, I = Ix1>
Ok(meth.load(path)?) where
} T: Num + Clone + PartialEq + PartialOrd,
Raw: ndarray::Data<Elem = T> + ndarray::RawDataClone,
X: ndarray::Data<Elem = f64> + ndarray::RawDataClone,
Y: ndarray::Data<Elem = f64> + ndarray::RawDataClone,
Z: ndarray::Data<Elem = f64> + ndarray::RawDataClone,
{
pub dim1: ArrayBase<X, I>,
pub dim2: ArrayBase<Y, I>,
pub dim3: ArrayBase<Z, I>,
pub data: ArrayBase<Raw, Ix3>,
pub fill_value: T,
pub coord_type: CoordType,
} }
pub struct RadarData3d<T, X = f64, Y = f64, Z = f64> impl<T, Raw, X, Y, Z> RadarData3d<T, Raw, X, Y, Z>
where where
T: Num, T: Num + Clone + PartialEq + PartialOrd,
X: Num, X: ndarray::Data<Elem = f64> + ndarray::RawDataClone,
Y: Num, Y: ndarray::Data<Elem = f64> + ndarray::RawDataClone,
Z: Num, Z: ndarray::Data<Elem = f64> + ndarray::RawDataClone,
Raw: ndarray::Data<Elem = T> + ndarray::RawDataClone,
{ {
pub dim1: Array1<X>, pub fn index_axis(&self, axis: Axis, slice: usize) -> Radar2dRef<T> {
pub dim2: Array1<Y>,
pub dim3: Array1<Z>,
pub data: Array3<T>,
}
impl<T, Raw> RadarData2d<T, Raw>
where
T: Num + AsPrimitive<f64> + FromPrimitive + Clone + Debug + PartialOrd + PartialEq,
Raw: ndarray::Data<Elem = T> + Clone + ndarray::RawDataClone,
{
pub fn downsample(&self, output_shape: (usize, usize), meth: DownSampleMeth) -> Radar2d<T> {
let shape = self.data.shape(); let shape = self.data.shape();
assert!(shape[0] > output_shape.0 && shape[1] > output_shape.1); println!("shape: {:?}", shape);
let dim1 = self.dim1.view();
if shape[0] == output_shape.0 && shape[1] == output_shape.1 { let dim2 = self.dim2.view();
return Radar2d { let view = self.data.index_axis(axis, slice);
dim1: self.dim1.to_owned(), RadarData2d {
dim2: self.dim2.to_owned(),
data: self.data.to_owned(),
fill_value: self.fill_value.clone(),
coord_type: self.coord_type.clone(),
};
}
let scale_x = shape[1] as f64 / output_shape.1 as f64;
let scale_y = shape[0] as f64 / output_shape.0 as f64;
let mut output: Array2<T> = Array2::zeros(output_shape);
let dim1 = Array1::linspace(
*self.dim1.first().unwrap(),
*self.dim1.last().unwrap(),
output_shape.1,
);
let dim2 = Array1::linspace(
*self.dim2.first().unwrap(),
*self.dim2.last().unwrap(),
output_shape.0,
);
output.iter_mut().enumerate().for_each(|(s, vv)| {
let ri = s / output_shape.1;
let ci = s % output_shape.1;
let src_yf0 = scale_y * ri as f64;
let src_yf1 = src_yf0 + scale_y;
let src_y0 = src_yf0.floor() as usize;
let src_y1 = src_yf1.floor() as usize;
let src_xf0 = scale_x * ci as f64;
let src_xf1 = src_xf0 + scale_x;
let src_x0 = src_xf0.floor() as usize;
let src_x1 = src_xf1.floor() as usize;
match meth {
DownSampleMeth::MEAN => {}
DownSampleMeth::VAR | DownSampleMeth::STD => self.var(
src_yf0, src_yf1, src_xf0, src_xf1, src_y0, src_y1, src_x0, src_x1, vv,
),
}
});
if let DownSampleMeth::STD = meth {
output = output.mapv(|x| T::from_f64(f64::sqrt(x.as_())).unwrap());
}
return Radar2d {
dim1, dim1,
dim2, dim2,
data: view,
fill_value: self.fill_value.clone(), fill_value: self.fill_value.clone(),
data: output,
coord_type: self.coord_type.clone(), coord_type: self.coord_type.clone(),
};
}
fn var(
&self,
src_yf0: f64,
src_yf1: f64,
src_xf0: f64,
src_xf1: f64,
src_y0: usize,
mut src_y1: usize,
src_x0: usize,
mut src_x1: usize,
row: &mut T,
) {
let wy0 = 1f64 - (src_yf0 - src_y0 as f64);
let mut wy1 = src_yf1 - src_y1 as f64;
let wx0 = 1f64 - (src_xf0 - src_x0 as f64);
let mut wx1 = src_xf1 - src_x1 as f64;
if wy1 < f64::EPSILON {
wy1 = 1f64;
if src_y1 > src_y0 {
src_y1 -= 1;
}
} }
if wx1 < f64::EPSILON {
wx1 = 1f64;
if src_x1 > src_x0 {
src_x1 -= 1;
}
}
let mut v_sum: f64 = 0.0;
let mut w_sum = 0f64;
let mut wv_sum = 0f64;
let mut wvv_sum = 0f64;
for src_y in src_y0..=src_y1 {
let wy = if src_y == src_y0 {
wy0
} else {
if src_y == src_y1 {
wy1
} else {
1.0
}
};
for src_x in src_x0..=src_x1 {
let wx = if src_x == src_x0 {
wx0
} else {
if src_x == src_x1 {
wx1
} else {
1.0
}
};
let v = self.data[[src_y, src_x]].as_();
let w = wx * wy;
v_sum += v;
w_sum += w;
wv_sum += w * v;
wvv_sum += w * v * v;
}
if w_sum < f64::EPSILON {
return;
}
let v = ((wvv_sum * w_sum - wv_sum * wv_sum) / w_sum / w_sum).clamp(-125f64, 124f64);
*row = T::from_f64(v).unwrap();
}
}
fn split(&self) -> [RadarData2d<T, ndarray::ViewRepr<&T>>; 4] {
let middle_dim1 = self.dim1.len() / 2;
let middle_dim2 = self.dim2.len() / 2;
let lt = self.data.slice(s![..middle_dim1, ..middle_dim2]);
let rt = self.data.slice(s![middle_dim1.., ..middle_dim2]);
let lb = self.data.slice(s![..middle_dim1, middle_dim2..]);
let rb = self.data.slice(s![middle_dim1.., middle_dim2..]);
return [
RadarData2d {
dim1: self.dim1.slice(s![..middle_dim1]).to_owned(),
dim2: self.dim2.slice(s![..middle_dim2]).to_owned(),
data: lt,
fill_value: self.fill_value.clone(),
coord_type: self.coord_type,
},
RadarData2d {
dim1: self.dim1.slice(s![middle_dim1..]).to_owned(),
dim2: self.dim2.slice(s![..middle_dim2]).to_owned(),
data: rt,
fill_value: self.fill_value.clone(),
coord_type: self.coord_type,
},
RadarData2d {
dim1: self.dim1.slice(s![..middle_dim1]).to_owned(),
dim2: self.dim2.slice(s![middle_dim2..]).to_owned(),
data: lb,
fill_value: self.fill_value.clone(),
coord_type: self.coord_type,
},
RadarData2d {
dim1: self.dim1.slice(s![middle_dim1..]).to_owned(),
dim2: self.dim2.slice(s![middle_dim2..]).to_owned(),
data: rb,
fill_value: self.fill_value.clone(),
coord_type: self.coord_type,
},
];
} }
} }
impl<T, Raw> MultiDimensionData<T> for RadarData2d<T, Raw> impl<T, Raw, X, Y, Z> MultiDimensionData<T> for RadarData3d<T, Raw, X, Y, Z>
where where
T: Num + Clone, T: Num + Clone,
T: PartialEq + PartialOrd, T: PartialEq + PartialOrd,
Raw: ndarray::Data<Elem = T> + Clone + RawDataClone + DataMut, X: ndarray::Data<Elem = f64> + ndarray::RawDataClone,
Y: ndarray::Data<Elem = f64> + ndarray::RawDataClone,
Z: ndarray::Data<Elem = f64> + ndarray::RawDataClone,
Raw: ndarray::Data<Elem = T> + RawDataClone + DataMut,
{ {
fn map_by_fn<F>(&mut self, f: F) fn map_by_fn<F>(&mut self, f: F)
where where
@ -275,285 +120,18 @@ where
} }
} }
pub trait DataLoader<V, T> impl<T, Raw, X, Y> MultiDimensionData<T> for RadarData2d<T, Raw, X, Y>
where where
V: Num + Clone + PartialEq + PartialOrd, T: Num + Clone,
T: MultiDimensionData<V>,
{
fn load<P: AsRef<Path>>(&self, path: P) -> Result<T, DataError>;
}
#[async_trait]
pub trait AsyncDataLoader<V, T>
where
V: Num + Clone + PartialEq + PartialOrd,
T: MultiDimensionData<V> + Send + Sync,
{
async fn load<P: AsRef<Path> + Send>(&self, path: P) -> Result<T, DataError>;
}
pub struct Npz;
impl Npz {
#[inline]
fn load_1d<T: Num + Deserialize, R: std::io::Read + Seek>(
&self,
data: &mut NpzArchive<R>,
name: &str,
) -> Result<Array1<T>, DataError> {
// let mut data = npyz::npz::NpzArchive::open(path)?;
let a = data.by_name(name)?.unwrap();
let b: Vec<T> = a.into_vec().unwrap();
Ok(Array1::from_shape_vec(b.len(), b).unwrap())
}
#[inline]
fn load_2d<T: Num + Deserialize, R: std::io::Read + Seek>(
&self,
// path: &Path,
data: &mut NpzArchive<R>,
name: &str,
) -> Result<Array2<T>, DataError> {
// let mut data = npyz::npz::NpzArchive::open(path)?;
let a = data.by_name(name)?.unwrap();
let shape = a.shape().to_vec();
let b: Vec<T> = a.into_vec().unwrap();
Ok(Array2::from_shape_vec((shape[0] as usize, shape[1] as usize), b).unwrap())
}
fn load_3d(&self, data: &mut NpzArchive<BufReader<std::fs::File>>) {}
}
impl<T> DataLoader<T, RadarData2d<T, OwnedRepr<T>>> for Npz
where
T: Num + Clone + Deserialize + FromPrimitive,
T: PartialEq + PartialOrd, T: PartialEq + PartialOrd,
X: ndarray::Data<Elem = f64> + ndarray::RawDataClone,
Y: ndarray::Data<Elem = f64> + ndarray::RawDataClone,
Raw: ndarray::Data<Elem = T> + RawDataClone + DataMut,
{ {
fn load<P: AsRef<Path>>(&self, path: P) -> Result<RadarData2d<T, OwnedRepr<T>>, DataError> { fn map_by_fn<F>(&mut self, f: F)
let mut data: NpzArchive<BufReader<std::fs::File>> = npyz::npz::NpzArchive::open(path)?;
let dim1 = self.load_1d::<f64, BufReader<std::fs::File>>(&mut data, "lon")?;
let dim2 = self.load_1d::<f64, BufReader<std::fs::File>>(&mut data, "lat")?;
let value = self.load_2d::<T, BufReader<std::fs::File>>(&mut data, "value")?;
Ok(RadarData2d {
dim1: dim1,
dim2: dim2,
fill_value: T::from_f64(-125.0).unwrap(),
data: value,
coord_type: CoordType::LatLon,
})
}
}
impl<T> AsyncDataLoader<T, RadarData2d<T, OwnedRepr<T>>> for Npz
where
T: Num + Clone + Deserialize + FromPrimitive,
T: PartialEq + PartialOrd + Send + Sync,
{
fn load<'life0, 'async_trait, P>(
&'life0 self,
path: P,
) -> core::pin::Pin<
Box<
dyn core::future::Future<Output = Result<RadarData2d<T, OwnedRepr<T>>, DataError>>
+ core::marker::Send
+ 'async_trait,
>,
>
where where
P: 'async_trait + AsRef<Path> + Send, F: FnMut(&mut T),
'life0: 'async_trait,
Self: 'async_trait,
{ {
Box::pin(async { self.data.map_inplace(f);
let mut f = File::open(path).await?;
let mut buffer = Vec::new();
f.read_to_end(&mut buffer).await?;
let mut data = npyz::npz::NpzArchive::new(Cursor::new(buffer))?;
let dim1 = self.load_1d::<f64, Cursor<Vec<u8>>>(&mut data, "lon")?;
let dim2 = self.load_1d::<f64, Cursor<Vec<u8>>>(&mut data, "lat")?;
let value = self.load_2d::<T, Cursor<Vec<u8>>>(&mut data, "value")?;
Ok(RadarData2d {
dim1: dim1,
dim2: dim2,
fill_value: T::from_f64(-125.0).unwrap(),
data: value,
coord_type: CoordType::LatLon,
})
})
} }
} }
// fn resample(
// &self,
// width_rate: f64,
// height_rate: f64,
// filter_len: f64,
// ) -> Result<RadarData2d<T, OwnedRepr<T>>, DataError> {
// let width_rate = width_rate.min(1.0);
// let height_rate = height_rate.min(1.0);
// match self.coord_type {
// CoordType::Polar => Err(DataError::FormatError),
// CoordType::LatLon => {
// let width_filtered: ArrayBase<ndarray::OwnedRepr<T>, Ix2> =
// Self::_resample(&self.data, width_rate, filter_len);
// let result: ArrayBase<OwnedRepr<T>, Ix2> =
// Self::_resample(&width_filtered.t(), height_rate, filter_len)
// .t()
// .to_owned();
// let new_dim1: ArrayBase<OwnedRepr<f64>, Ix1> = Self::_resample(
// &Array2::from_shape_vec((1, self.dim1.len()), self.dim1.to_vec()).unwrap(),
// width_rate,
// filter_len,
// )
// .slice(s![0, ..])
// .to_owned();
// let new_dim2: ArrayBase<OwnedRepr<f64>, Ix1> = Self::_resample(
// &Array2::from_shape_vec((1, self.dim2.len()), self.dim2.to_vec()).unwrap(),
// height_rate,
// filter_len,
// )
// .slice(s![0, ..])
// .to_owned();
// Ok(RadarData2d {
// dim1: new_dim1,
// dim2: new_dim2,
// data: result,
// coord_type: self.coord_type.to_owned(),
// })
// }
// }
// }
// fn _resample<'a, V, R: ndarray::Data<Elem = V>>(
// data: &'a ArrayBase<R, Ix2>,
// rate: f64,
// filter_len: f64,
// ) -> Array2<V>
// where
// V: Num + Clone + AsPrimitive<f64> + FromPrimitive,
// {
// let ori_width = data.ncols();
// let ori_height = data.nrows();
// let new_width = (ori_width as f64 * rate).ceil() as usize;
// let mut result: Array2<V> = Array2::zeros((ori_height, new_width));
// (0..ori_height).into_iter().for_each(|height| {
// for width in 0..new_width {
// let center_x = (width as f64 + 0.5) / new_width as f64 * ori_width as f64;
// let filter_start = center_x - filter_len / 2.0;
// let start_idx = (filter_start - 0.5).ceil() as usize;
// let mut value_sum = 0.0;
// let mut filter_sum = 0.0;
// for i in 0..filter_len as usize {
// let input_x = start_idx + i;
// let weight = windowed_sinc(
// (input_x as f64 + 0.5 - center_x) * rate,
// (input_x as f64 + 0.5 - filter_start) / filter_len,
// );
// value_sum += weight * data[[height, input_x.clamp(0, ori_width - 1)]].as_();
// filter_sum += weight;
// }
// result[[height, width]] = V::from_f64(value_sum / filter_sum).unwrap();
// }
// });
// result
// }
// pub struct LevelData<T: Num + Clone + PartialEq + PartialOrd>(
// pub Quadtree<i64, RadarData2d<T, OwnedRepr<T>>>,
// );
// impl<T> LevelData<T>
// where
// T: Num + Clone + AsPrimitive<f64> + FromPrimitive + Debug + PartialEq + PartialOrd,
// {
// fn value(
// level_data: Vec<RadarData2d<T, OwnedRepr<T>>>,
// level_num: usize,
// ) -> Vec<RadarData2d<T, OwnedRepr<T>>> {
// if level_num == 0 {
// return level_data;
// }
// let mut result: Vec<RadarData2d<T, OwnedRepr<T>>> =
// Vec::with_capacity(level_data.len() * 4);
// let results = level_data
// .iter()
// .flat_map(|v| v.split().into_iter().map(|x| x.value_to_owned()));
// result.extend(results);
// return Self::value(result, level_num - 1);
// }
// fn new(data: &RadarData2d<T, OwnedRepr<T>>, level: usize, rate: f64) -> Self {
// // let rate = 1.0 / level as f64;
// let resampled = data.resample(rate, rate, 2.0).unwrap();
// let blocks = Self::value(vec![resampled], level);
// let mut tree: Quadtree<i64, RadarData2d<T, OwnedRepr<T>>> =
// quadtree_rs::Quadtree::new(level);
// blocks.into_iter().for_each(|block| {
// tree.insert(
// AreaBuilder::default()
// .anchor(quadtree_rs::point::Point {
// x: *block.dim1.first().unwrap() as i64,
// y: *block.dim2.first().unwrap() as i64,
// })
// .dimensions((block.dim1.len() as i64, block.dim2.len() as i64))
// .build()
// .unwrap(),
// block,
// );
// });
// Self(tree)
// }
// }
// pub fn levels<T>(data: Radar2d<T>, levels: usize) -> Vec<LevelData<T>>
// where
// T: Num + Clone + AsPrimitive<f64> + FromPrimitive + Debug,
// T: PartialEq + PartialOrd,
// {
// let numerator = 1.0 / levels as f64;
// (0..levels)
// .into_iter()
// .map(|level| LevelData::new(&data, level + 1, 1.0 - level as f64 * numerator))
// .collect()
// }
#[inline]
fn windowed_sinc(x: f64, y: f64) -> f64 {
let x = x * PI;
let sinc = if x != 0.0 { f64::sin(x) / x } else { 1.0 };
let window = if 0f64 <= y && y <= 1.0 {
1.0 - (y - 0.5).abs() * 2.0
} else {
0f64
};
sinc * window
}
pub enum DownSampleMeth {
STD,
MEAN,
VAR,
}
#[derive(Clone, Copy, Debug)]
pub enum CoordType {
Polar,
LatLon,
}

View File

@ -1,7 +1,7 @@
use crate::pipeline::element::ElementImpl; use crate::pipeline::element::ElementImpl;
use crate::pipeline::GridElementImpl; use crate::pipeline::GridElementImpl;
use crate::utils::*; use crate::utils::*;
use radarg_plugin_interface::{CoordType, PluginResult, PluginResultType}; use radarg_plugin_interface::{CoordType, DataShape, PluginResult, PluginResultType};
use std::sync::Arc; use std::sync::Arc;
macro_rules! data_to_grid { macro_rules! data_to_grid {
($_type:ident,$(($branch:path ,$boundary_norm: expr)),+) => { ($_type:ident,$(($branch:path ,$boundary_norm: expr)),+) => {

View File

@ -17,7 +17,7 @@ pub enum PipelineError {
source: ProjError, source: ProjError,
}, },
#[error("data error")] #[error("data error")]
DataError(String) DataError(String),
} }
#[derive(Debug, Error)] #[derive(Debug, Error)]
@ -50,7 +50,6 @@ pub enum PluginError {
PluginError, PluginError,
} }
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum PoolError { pub enum PoolError {
#[error("")] #[error("")]
@ -61,7 +60,6 @@ pub enum PoolError {
PoolInitialized(&'static str), PoolInitialized(&'static str),
} }
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum RenderError { pub enum RenderError {
#[error("")] #[error("")]
@ -70,5 +68,4 @@ pub enum RenderError {
None, None,
#[error("Canceled")] #[error("Canceled")]
Canceled, Canceled,
} }

View File

@ -1,9 +1,8 @@
pub fn lat_lon_to_zoom(lat_range: (f64, f64), lon_range: (f64, f64), w: f32, h: f32) -> u8 {
pub fn lat_lon_to_zoom(lat_range: (f64, f64), lon_range: (f64, f64), w: f32, h:f32 ) -> u8 {
let lat_diff = lat_range.1 - lat_range.0; let lat_diff = lat_range.1 - lat_range.0;
let lon_diff = lon_range.1 - lon_range.0; let lon_diff = lon_range.1 - lon_range.0;
let z1 = ( (360.0 * w) as f64 / lon_diff / 256.0).log2(); let z1 = ((360.0 * w) as f64 / lon_diff / 256.0).log2();
let z2 = ( (180.0 * h) as f64 / lat_diff / 256.0).log2(); let z2 = ((180.0 * h) as f64 / lat_diff / 256.0).log2();
let z = z1.min(z2); let z = z1.min(z2);
z as u8 z as u8
} }

View File

@ -1,17 +1,16 @@
use super::{offscreen_renderer::CanvasWrapper, Dispatcher, Pipeline}; use super::{offscreen_renderer::CanvasWrapper, Dispatcher, Pipeline};
use crate::components::app::AppCommand; use crate::components::Widget;
use crate::components::ControlPanelInputMsg;
use crate::coords::cms::CMS; use crate::coords::cms::CMS;
use crate::coords::Range;
use crate::data::MetaInfo; use crate::data::MetaInfo;
use crate::errors::{PipelineError, RenderError}; use crate::errors::{PipelineError, RenderError};
use crate::predefined::color_mapper::ColorMapper;
use crate::widgets::Render; use crate::widgets::Render;
use crate::RUNTIME; use crate::RUNTIME;
use crate::{coords::Range, widgets::widget::Widget};
use chrono::{DateTime, TimeZone, Utc}; use chrono::{DateTime, TimeZone, Utc};
use core_extensions::SelfOps; use femtovg::{ImageFlags, ImageId};
use femtovg::rgb::alt::GRAY8;
use femtovg::{renderer::OpenGl, Canvas, ImageFlags, ImageId, ImageInfo, PixelFormat};
use futures::StreamExt; use futures::StreamExt;
use num_traits::{AsPrimitive, FromPrimitive, NumOps};
use radarg_plugin_interface::PluginResult; use radarg_plugin_interface::PluginResult;
use std::any::Any; use std::any::Any;
use std::borrow::Borrow; use std::borrow::Borrow;
@ -21,17 +20,13 @@ use std::ops::{Deref, DerefMut};
use std::rc::Rc; use std::rc::Rc;
use std::sync::atomic::AtomicUsize; use std::sync::atomic::AtomicUsize;
use std::{ use std::{
cell::{Ref, RefCell},
fmt::Debug, fmt::Debug,
future::Future,
pin::Pin,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use tokio::sync::{ use tokio::sync::{
oneshot::{channel, Receiver, Sender}, oneshot::{channel, Receiver},
Notify, Notify,
}; };
use tracing::Instrument;
pub type ElementID = usize; pub type ElementID = usize;
static ELEMENT_ID: AtomicUsize = AtomicUsize::new(0); static ELEMENT_ID: AtomicUsize = AtomicUsize::new(0);
@ -122,6 +117,11 @@ pub struct InstantElement {
dispatcher: Rc<Dispatcher>, dispatcher: Rc<Dispatcher>,
} }
pub enum ElementImplMap {
ColorMap,
None,
}
pub trait ElementImpl: Debug + Send + Sync + 'static { pub trait ElementImpl: Debug + Send + Sync + 'static {
fn render(&self, data: &PluginResult, canvas: &mut CanvasWrapper, cms: &mut CMS) -> Target; fn render(&self, data: &PluginResult, canvas: &mut CanvasWrapper, cms: &mut CMS) -> Target;
} }
@ -147,6 +147,10 @@ impl InstantElement {
} }
} }
pub fn imp(&self) -> &InstantElementDrawerType {
&self.draw_type
}
pub fn to_time_series( pub fn to_time_series(
self, self,
dispatcher: Rc<Dispatcher>, dispatcher: Rc<Dispatcher>,
@ -231,6 +235,10 @@ impl TimeSeriesElement {
self.cms = cms; self.cms = cms;
} }
pub fn imp(&self) -> &Arc<dyn ElementImpl> {
&self.imp
}
fn register_noti(&self, datetime: DateTime<Utc>, noti: Arc<Notify>) { fn register_noti(&self, datetime: DateTime<Utc>, noti: Arc<Notify>) {
self.registers self.registers
.lock() .lock()

View File

@ -1,14 +1,15 @@
use super::predefined::GridFieldRenderer; use super::predefined::GridFieldRenderer;
use super::renders::DataRenderer; use super::renders::DataRenderer;
use crate::data::Radar2d; use crate::components::Widget;
use crate::pipeline::element::{ElementImpl, Target}; use crate::data::{Radar2d, Radar3d};
use crate::pipeline::element::{ElementImpl, ElementImplMap, Target};
use crate::pipeline::offscreen_renderer::CanvasWrapper; use crate::pipeline::offscreen_renderer::CanvasWrapper;
use crate::widgets::predefined::color_mapper::ColorMapper; use crate::predefined::color_mapper::ColorMapper;
use crate::widgets::{LayerImpl}; use crate::widgets::LayerImpl;
use num_traits::{AsPrimitive, FromPrimitive, Num, NumOps}; use num_traits::{AsPrimitive, FromPrimitive, Num, NumOps};
use radarg_plugin_interface::{DataShape, PluginResult};
use std::any::Any; use std::any::Any;
use std::fmt::Debug; use std::fmt::Debug;
use radarg_plugin_interface::PluginResult;
#[derive(Debug)] #[derive(Debug)]
pub struct GridElementImpl<CMAP, T> pub struct GridElementImpl<CMAP, T>
@ -52,8 +53,22 @@ where
cms: &mut crate::coords::cms::CMS, cms: &mut crate::coords::cms::CMS,
) -> crate::pipeline::element::Target { ) -> crate::pipeline::element::Target {
let first_block = data.blocks.first().unwrap(); let first_block = data.blocks.first().unwrap();
let data = first_block.clone().into(); match first_block.shape {
let result = self.renderer.render(canvas, cms, &data, (3000.0, 3000.0)); DataShape::Vector => {
result panic!("Vector data is not supported")
}
DataShape::Matrix => {
let data:Radar2d<T> = first_block.clone().into();
let data = data.as_ref();
let result = self.renderer.render(canvas, cms, &data, (3000.0, 3000.0));
result
}
DataShape::Cube => {
let data: Radar3d<T> = first_block.clone().into();
let data = data.index_axis(ndarray::Axis(0), 0);
let result = self.renderer.render(canvas, cms, &data, (3000.0, 3000.0));
result
}
}
} }
} }

View File

@ -8,7 +8,7 @@ mod renders;
pub mod utils; pub mod utils;
pub use dispatcher::Dispatcher; pub use dispatcher::Dispatcher;
pub use element::RenderResult; pub use element::*;
pub use element_impl::*;
pub use new_pipeline::Pipeline; pub use new_pipeline::Pipeline;
pub use offscreen_renderer::OffscreenRenderer; pub use offscreen_renderer::OffscreenRenderer;
pub use element_impl::*;

View File

@ -1,7 +1,8 @@
use super::super::renders::DataRenderer; use super::super::renders::DataRenderer;
use crate::coords::cms::CMS; use crate::coords::cms::CMS;
use crate::data::{Radar2dRef, RadarData2d};
use crate::pipeline::element::{Target, TargetType}; use crate::pipeline::element::{Target, TargetType};
use crate::widgets::predefined::color_mapper::ColorMapper; use crate::predefined::color_mapper::ColorMapper;
use crate::{data::Radar2d, utils::meshgrid}; use crate::{data::Radar2d, utils::meshgrid};
use femtovg::ImageInfo; use femtovg::ImageInfo;
use femtovg::{ use femtovg::{
@ -22,7 +23,7 @@ where
T: NumOps + PartialOrd + FromPrimitive + AsPrimitive<f64>, T: NumOps + PartialOrd + FromPrimitive + AsPrimitive<f64>,
CMAP: ColorMapper<T>, CMAP: ColorMapper<T>,
{ {
cmap: CMAP, pub cmap: CMAP,
value_phantom: PhantomData<T>, value_phantom: PhantomData<T>,
} }
@ -61,15 +62,6 @@ impl<T: NumOps + PartialOrd + Copy + FromPrimitive + AsPrimitive<f64>, CMAP: Col
let rt_lat = dim2[[r + 1, c + 1]]; let rt_lat = dim2[[r + 1, c + 1]];
let rt_lon = dim1[[r + 1, c + 1]]; let rt_lon = dim1[[r + 1, c + 1]];
// let cell: LineString = vec![
// (lb_lon, lb_lat),
// (rt_lon + 0.001, lb_lat),
// (rt_lon + 0.001, rt_lat),
// (lb_lon, rt_lat + 0.001),
// (lb_lon, lb_lat + 0.001),
// ]
// .into();
let v = &data[[r, c]]; let v = &data[[r, c]];
let mapped_color = self.cmap.map_value_to_color(*v, fill_value); let mapped_color = self.cmap.map_value_to_color(*v, fill_value);
@ -77,32 +69,23 @@ impl<T: NumOps + PartialOrd + Copy + FromPrimitive + AsPrimitive<f64>, CMAP: Col
continue; continue;
} }
// let mapped_ring = cms.ring_map(&cell).unwrap();
let (ox, oy) = cms.map((lb_lon, lb_lat)).unwrap(); let (ox, oy) = cms.map((lb_lon, lb_lat)).unwrap();
let (rx, ry) = cms.map((rt_lon, rt_lat)).unwrap(); let (rx, ry) = cms.map((rt_lon, rt_lat)).unwrap();
let mut path = Path::new(); let mut path = Path::new();
// let mut points = mapped_ring.points();
// let first_point = points.next().unwrap();
// path.move_to(first_point.x(), first_point.y());
//
// for point in points {
// path.line_to(point.x(), point.y());
// }
path.rect(ox, oy, (rx - ox) * 1.5, (ry - oy) * 1.5); path.rect(ox, oy, (rx - ox) * 1.5, (ry - oy) * 1.5);
// path.close();
canvas.fill_path(&path, &Paint::color(mapped_color.unwrap())); canvas.fill_path(&path, &Paint::color(mapped_color.unwrap()));
} }
} }
} }
} }
impl<T, CMAP> DataRenderer for GridFieldRenderer<CMAP, T> impl<'a, T, CMAP> DataRenderer<'a> for GridFieldRenderer<CMAP, T>
where where
T: Num + NumOps + PartialOrd + Copy + Clone + FromPrimitive + AsPrimitive<f64>, T: Num + NumOps + PartialOrd + Copy + Clone + FromPrimitive + AsPrimitive<f64>,
CMAP: ColorMapper<T>, CMAP: ColorMapper<T>,
{ {
type Data = Radar2d<T>; type Data = Radar2dRef<'a, T>;
fn render( fn render(
&self, &self,
@ -156,25 +139,6 @@ where
debug_assert_eq!(gl::GetError(), gl::NO_ERROR); debug_assert_eq!(gl::GetError(), gl::NO_ERROR);
} }
info!("Time to read pixels: {:?}", start.elapsed()); info!("Time to read pixels: {:?}", start.elapsed());
// let img: ImageBuffer<Rgba<u8>, Vec<u8>> = ImageBuffer::from_raw(w as u32, h as u32, pixels)
// .expect("Failed to create ImageBuffer");
// let thumbnail = resize(&img, 500, 500, image::imageops::FilterType::Lanczos3);
// let mut thumb_buffer = Cursor::new(Vec::new());
// img.write_to(&mut thumb_buffer, image::ImageOutputFormat::Png)
// .expect("Failed to write PNG buffer");
// info!("Time to write PNG: {:?}", start.elapsed());
// let thumb_data = thumb_buffer.into_inner();
// let thumbnail_tex =
// gtk::gdk::Texture::from_bytes(&gtk::glib::Bytes::from(&thumb_data)).unwrap();
// 将 ImageBuffer 编码为 PNG
// let mut png_buffer = Cursor::new(Vec::new());
// img.write_to(&mut png_buffer, image::ImageOutputFormat::Bmp)
// .expect("Failed to write PNG buffer");
// let png_data = png_buffer.into_inner();
let d1_start = (data.dim1.view()).first().unwrap().clone(); let d1_start = (data.dim1.view()).first().unwrap().clone();
let d1_end = (data.dim1.view()).last().unwrap().clone(); let d1_end = (data.dim1.view()).last().unwrap().clone();

View File

@ -2,7 +2,7 @@ use crate::coords::cms::CMS;
use crate::pipeline::element::Target; use crate::pipeline::element::Target;
use femtovg::{renderer::OpenGl, Canvas}; use femtovg::{renderer::OpenGl, Canvas};
pub trait DataRenderer { pub trait DataRenderer<'a> {
type Data; type Data;
fn render( fn render(
&self, &self,

View File

@ -1,6 +1,5 @@
use crate::{ use crate::{
coords::cms::CMS, data::Radar2d, errors::RenderError, coords::cms::CMS, data::Radar2d, errors::RenderError, predefined::color_mapper::BoundaryNorm,
widgets::predefined::color_mapper::BoundaryNorm,
}; };
use chrono::{prelude::*, Duration}; use chrono::{prelude::*, Duration};
use radarg_plugin_interface::*; use radarg_plugin_interface::*;

View File

@ -1,8 +1,42 @@
use crate::data::{CoordType, Radar2d}; use crate::data::{CoordType, Radar2d, Radar3d};
use ndarray::{Array1, Array2, Array3, ShapeBuilder}; use ndarray::{Array1, Array2, Array3, ShapeBuilder};
use num_traits::{AsPrimitive, FromPrimitive, Num}; use num_traits::{AsPrimitive, FromPrimitive, Num};
use radarg_plugin_interface::{Block, DataShape, PluginResult, VecResult}; use radarg_plugin_interface::{Block, DataShape, PluginResult, VecResult};
macro_rules! match_in_macro_3d {
// ($(($branch:path, $t:ty)),+, $block:ident)
($block:tt, $(($branch:path, $t:path)),+) => {
{
let data = $block.data;
let dim3: Vec<_> = $block.dimension_values.remove(0).into();
let dim2: Vec<_> = $block.dimension_values.remove(0).into();
let dim1: Vec<_> = $block.dimension_values.remove(0).into();
let fill_value = $block.fill_value;
let data_shape: Vec<usize> = $block.size.into();
let coord_type = match $block.coord_type{
radarg_plugin_interface::CoordType::Cartesian => CoordType::LatLon,
radarg_plugin_interface::CoordType::Polar => CoordType::Polar,
_ => panic!("Unsupported coord type")
};
match data {
$(
$branch(x) => {
let shape = [data_shape[0], data_shape[1], data_shape[2]];
Radar3d {
fill_value: T::from_f64(fill_value).unwrap(),
data: Array3::from_shape_vec(shape, x.into_iter().map(|x| $t(x).unwrap()).collect::<Vec<T>>()).unwrap(),
dim1: Array1::from_vec(dim1),
dim2: Array1::from_vec(dim2),
dim3: Array1::from_vec(dim3),
coord_type: coord_type,
}},
)+
_ => panic!("Unsupported data type"),
}
}
};
}
macro_rules! match_in_macro { macro_rules! match_in_macro {
// ($(($branch:path, $t:ty)),+, $block:ident) // ($(($branch:path, $t:ty)),+, $block:ident)
($block:tt, $(($branch:path, $t:path)),+) => { ($block:tt, $(($branch:path, $t:path)),+) => {
@ -61,3 +95,31 @@ where
} }
} }
} }
impl<T> From<Block> for Radar3d<T>
where
T: Num + Copy + PartialOrd + PartialEq,
T: FromPrimitive,
{
fn from(block: Block) -> Self {
let mut block = block;
let a = &block.dimension_values;
println!("{:?}", a);
if let DataShape::Cube = block.shape {
let result = match_in_macro_3d!(
block,
(VecResult::I8, T::from_i8),
(VecResult::I32, T::from_i32),
(VecResult::I64, T::from_i64),
(VecResult::U8, T::from_u8),
(VecResult::U32, T::from_u32),
(VecResult::U64, T::from_u64),
(VecResult::F32, T::from_f32),
(VecResult::F64, T::from_f64)
);
result
} else {
panic!("Expected matrix data shape");
}
}
}

View File

@ -1,20 +1,25 @@
use crate::map_tile_utils::*; use crate::map_tile_utils::*;
use slippy_map_tiles::{BBox, merc_location_to_tile_coords, size_bbox_zoom_metatiles, Tile}; use slippy_map_tiles::{merc_location_to_tile_coords, size_bbox_zoom_metatiles, BBox, Tile};
pub fn map_tile_layer(lat_range: (f64, f64), lon_range: (f64, f64), w: f32, h: f32) { pub fn map_tile_layer(lat_range: (f64, f64), lon_range: (f64, f64), w: f32, h: f32) {
let z = lat_lon_to_zoom(lat_range, lon_range, w, h); let z = lat_lon_to_zoom(lat_range, lon_range, w, h);
let bbox = BBox::new(lat_range.0 as f32, lon_range.0 as f32, lat_range.1 as f32, lon_range.1 as f32).unwrap(); let bbox = BBox::new(
lat_range.0 as f32,
lon_range.0 as f32,
lat_range.1 as f32,
lon_range.1 as f32,
)
.unwrap();
let size = size_bbox_zoom_metatiles(&bbox, z, 4); let size = size_bbox_zoom_metatiles(&bbox, z, 4);
let t = Tile::new(10, 547, 380).unwrap(); let t = Tile::new(10, 547, 380).unwrap();
println!("size: {:?}", size); println!("size: {:?}", size);
println!("tile: {:?}", t); println!("tile: {:?}", t);
} }
mod test { mod test {
use super::*; use super::*;
#[test] #[test]
fn test_map_tile_layer() { fn test_map_tile_layer() {
map_tile_layer((37.7749, 37.7749), (-122.4194, -122.4194), 1000.0, 1000.0); map_tile_layer((37.7749, 37.7749), (-122.4194, -122.4194), 1000.0, 1000.0);
} }
} }

View File

@ -1 +1,5 @@
pub mod map_tile; pub mod map_tile;
// pub mod grid_field_renderer;
// pub mod layers;
pub mod color_mapper;
pub mod widgets;

100
src/predefined/widgets.rs Normal file
View File

@ -0,0 +1,100 @@
use crate::components::widget::{Widget, WidgetType};
use crate::predefined::color_mapper::ColorMapper;
use crate::widgets::{AssoElement, Layer};
use femtovg::{renderer::OpenGl, Canvas, Color, Paint, Path};
use num_traits::*;
use std::any::Any;
use topojson::Arc;
#[derive(Debug)]
pub struct ColorBar {
padding: [f32; 4],
width: f32,
height: f32,
margin: [i32; 4],
}
impl ColorBar {
pub fn new(padding: [f32; 4], size: (f32, f32), margin: [i32; 4]) -> Self {
Self {
padding,
width: size.0,
height: size.1,
margin,
}
}
}
impl Widget for ColorBar {
fn cairo_render(&self, layers: &Vec<Layer>, canvas: &gtk::cairo::Context, w: f32, h: f32) {
let bar_width = 10;
let bar_height = h - self.padding[0] - self.padding[2];
let (x, y) = (self.padding[3], self.padding[0]);
let length = layers.len();
if length == 0 {
return;
}
let first = layers.first().unwrap();
match first.get_associated_element() {
AssoElement::Instant(i) => {
let imp = i.imp();
}
AssoElement::TimeSeries(t) => {
let c = t.lock().unwrap();
let imp = c.imp();
}
_ => {}
}
// for ((i, color), label) in self
// .color_list
// .iter()
// .enumerate()
// .zip(self.color_mapper.labels())
// {
// let y = y + i as f32 * b_h;
//
// canvas.set_source_rgba(
// color.r as f64,
// color.g as f64,
// color.b as f64,
// color.a as f64,
// );
// canvas.rectangle(x as f64, y as f64, bar_width as f64, b_h as f64);
// canvas.fill();
//
// let extents = canvas.text_extents(&label).unwrap();
//
// canvas.move_to(
// (x + bar_width as f32 + 5.0) as f64,
// y as f64 + extents.height() / 2.0 as f64,
// );
// canvas.set_source_rgba(1.0, 1.0, 1.0, 1.0);
// canvas.show_text(&label);
// }
}
fn location(&self) -> (gtk::Align, gtk::Align) {
(gtk::Align::End, gtk::Align::End)
}
fn size(&self) -> (f32, f32) {
(self.width, self.height)
}
fn widget_type(&self) -> WidgetType {
WidgetType::Cairo
}
fn margin(&self) -> [i32; 4] {
self.margin
}
fn padding(&self) -> [i32; 4] {
[10, 10, 10, 10]
}
}

View File

@ -11,7 +11,7 @@ use surfman::{
GLVersion, NativeConnection, NativeContext, SurfaceAccess, SurfaceType, GLVersion, NativeConnection, NativeContext, SurfaceAccess, SurfaceType,
}; };
use crate::widgets::render::predefined::color_mapper::BoundaryNorm; use crate::predefined::color_mapper::BoundaryNorm;
use crate::RUNTIME; use crate::RUNTIME;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;

View File

@ -1,6 +1,6 @@
use std::ops::Range;
use geo_types::LineString;
use crate::coords::Mapper; use crate::coords::Mapper;
use geo_types::LineString;
use std::ops::Range;
pub struct CMS { pub struct CMS {
mapper: Mapper, mapper: Mapper,

View File

@ -4,8 +4,7 @@ use gtk::subclass::prelude::*;
use std::cell::RefCell; use std::cell::RefCell;
#[derive(Default)] #[derive(Default)]
pub struct ExteriorWidget { pub struct ExteriorWidget {}
}
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for ExteriorWidget { impl ObjectSubclass for ExteriorWidget {
@ -13,4 +12,4 @@ impl ObjectSubclass for ExteriorWidget {
type Type = super::ExteriorWidget; type Type = super::ExteriorWidget;
} }
impl ObjectImpl for ExteriorWidget{} impl ObjectImpl for ExteriorWidget {}

View File

@ -1,9 +1,9 @@
use super::super::WindowCoord; use super::super::WindowCoord;
use super::layers::Layer;
use gtk::glib; use gtk::glib;
use gtk::subclass::prelude::*; use gtk::subclass::prelude::*;
use std::cell::RefCell; use std::cell::RefCell;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use super::layers::Layer;
#[derive(Default)] #[derive(Default)]
pub struct InteriorWidget { pub struct InteriorWidget {

View File

@ -1,17 +1,12 @@
use super::super::Render; use super::super::Render;
use crate::coords::cms::CMS; use crate::coords::cms::CMS;
use crate::errors::PipelineError; use crate::errors::PipelineError;
use crate::pipeline::element::{self, Element, ElementID, Target, TargetType}; use crate::pipeline::element::{self, Target};
use crate::pipeline::offscreen_renderer::CanvasWrapper; use crate::pipeline::offscreen_renderer::CanvasWrapper;
use crate::{coords::Range, widgets::widget::Widget};
use chrono::{prelude::*, DateTime}; use chrono::{prelude::*, DateTime};
use core_extensions::SelfOps; use femtovg::{renderer::OpenGl, Canvas};
use femtovg::{renderer::OpenGl, Canvas, ImageId};
use std::{ use std::{
cell::{Ref, RefCell},
fmt::Debug, fmt::Debug,
future::Future,
pin::Pin,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };

View File

@ -1,13 +1,11 @@
use tracing::info;
mod cms; mod cms;
mod exterior; mod exterior;
mod imp; mod imp;
mod interior; mod interior;
pub mod predefined; pub mod predefined;
pub mod renders; pub mod renders;
pub mod widget;
pub use self::imp::{RenderConfig, RenderMotion, RenderStatus}; pub use self::imp::{RenderConfig, RenderMotion, RenderStatus};
use crate::components::messages::MonitorInputMsg;
use crate::coords::cms::CMS; use crate::coords::cms::CMS;
use crate::coords::{Mapper, Range}; use crate::coords::{Mapper, Range};
use crate::errors::PipelineError; use crate::errors::PipelineError;
@ -21,9 +19,7 @@ use gtk::prelude::*;
use gtk::subclass::prelude::ObjectSubclassIsExt; use gtk::subclass::prelude::ObjectSubclassIsExt;
use gtk::EventControllerScrollFlags; use gtk::EventControllerScrollFlags;
pub use interior::*; pub use interior::*;
use slippy_map_tiles::Tile;
use std::cell::{Ref, RefCell, RefMut}; use std::cell::{Ref, RefCell, RefMut};
use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};

View File

@ -1,5 +1 @@
pub mod color_mapper;
pub mod gis; pub mod gis;
// pub mod grid_field_renderer;
// pub mod layers;
pub mod widgets;

View File

@ -1,103 +0,0 @@
use super::{
super::widget::{Widget as WidgetTrait, WidgetType},
super::Layer,
color_mapper::ColorMapper,
};
use femtovg::{renderer::OpenGl, Canvas, Color, Paint, Path};
use num_traits::*;
#[derive(Debug)]
pub struct ColorBar<V, T>
where
V: num_traits::NumOps + PartialOrd + FromPrimitive + AsPrimitive<f64>,
T: ColorMapper<V>,
{
color_mapper: T,
padding: [f32; 4],
width: f32,
height: f32,
margin: [i32; 4],
color_list: Vec<femtovg::Color>,
phantom: std::marker::PhantomData<V>,
}
impl<V, T> ColorBar<V, T>
where
V: num_traits::NumOps + PartialOrd + FromPrimitive + AsPrimitive<f64>,
T: ColorMapper<V>,
{
pub fn new(color_mapper: T, padding: [f32; 4], size: (f32, f32), margin: [i32; 4]) -> Self {
let (l, ll) = color_mapper.min_max();
let invalid = color_mapper.invalid();
let colors = color_mapper.map_min_to_max();
Self {
color_list: colors,
color_mapper,
padding,
width: size.0,
height: size.1,
margin,
phantom: std::marker::PhantomData,
}
}
}
impl<V, T> WidgetTrait for ColorBar<V, T>
where
V: num_traits::NumOps + PartialOrd + FromPrimitive + AsPrimitive<f64> + Send + Sync,
T: ColorMapper<V> + 'static,
{
fn cairo_render(&self, canvas: &gtk::cairo::Context, w: f32, h: f32) {
let bar_width = 10;
let bar_height = h - self.padding[0] - self.padding[2];
let (x, y) = (self.padding[3], self.padding[0]);
let b_h = bar_height / self.color_list.len() as f32;
for ((i, color), label) in self
.color_list
.iter()
.enumerate()
.zip(self.color_mapper.labels())
{
let y = y + i as f32 * b_h;
canvas.set_source_rgba(
color.r as f64,
color.g as f64,
color.b as f64,
color.a as f64,
);
canvas.rectangle(x as f64, y as f64, bar_width as f64, b_h as f64);
canvas.fill();
let extents = canvas.text_extents(&label).unwrap();
canvas.move_to(
(x + bar_width as f32 + 5.0) as f64,
y as f64 + extents.height() / 2.0 as f64,
);
canvas.set_source_rgba(1.0, 1.0, 1.0, 1.0);
canvas.show_text(&label);
}
}
fn location(&self) -> (gtk::Align, gtk::Align) {
(gtk::Align::End, gtk::Align::End)
}
fn size(&self) -> (f32, f32) {
(self.width, self.height)
}
fn widget_type(&self) -> WidgetType {
WidgetType::Cairo
}
fn margin(&self) -> [i32; 4] {
self.margin
}
fn padding(&self) -> [i32; 4] {
[10, 10, 10, 10]
}
}

View File

@ -1,7 +1,7 @@
use super::Render; use super::Render;
use crate::coords::cms::CMS; use crate::coords::cms::CMS;
use femtovg::{renderer::OpenGl, Canvas};
use crate::pipeline::element::Target; use crate::pipeline::element::Target;
use femtovg::{renderer::OpenGl, Canvas};
pub trait DataRenderer { pub trait DataRenderer {
type Data; type Data;

View File

@ -1,4 +1,4 @@
use crate::widgets::widget::Widget; use crate::components::monitor::Widget;
use chrono::{prelude::*, Duration}; use chrono::{prelude::*, Duration};
use gtk::glib::{self, prelude::*, ParamSpec, Properties, Value}; use gtk::glib::{self, prelude::*, ParamSpec, Properties, Value};
use gtk::prelude::*; use gtk::prelude::*;

View File

@ -1,4 +1,4 @@
use self::widget::Widget; use crate::components::monitor::Widget;
pub use super::*; pub use super::*;
mod imp; mod imp;
@ -66,7 +66,7 @@ impl WidgetFrame {
drawing_area.set_draw_func(clone!(@strong widget => move |_, canvas, x, y| { drawing_area.set_draw_func(clone!(@strong widget => move |_, canvas, x, y| {
let widget = widget.borrow(); let widget = widget.borrow();
let widget = widget.as_ref().unwrap(); let widget = widget.as_ref().unwrap();
widget.cairo_render(canvas,x as f32,y as f32); // widget.cairo_render(canvas,x as f32,y as f32);
})); }));
drawing_area.queue_draw(); drawing_area.queue_draw();
} }