From a07acecea2e76a5a5664c72f14d754d2c9144afe Mon Sep 17 00:00:00 2001 From: Tsuki Date: Mon, 6 May 2024 18:30:58 +0800 Subject: [PATCH] sync --- src/components/app.rs | 43 +--- src/components/setting/dispatcher_list.rs | 4 +- src/components/setting/setting.rs | 55 ++-- src/config.rs | 270 +++++++++++++++++-- src/data_utils.rs | 66 ++++- src/main.rs | 12 +- src/pipeline/dispatcher.rs | 243 ++++++++--------- src/pipeline/element_imp.rs | 55 ++-- src/pipeline/new_element.rs | 217 ++-------------- src/pipeline/runner.rs | 1 - src/plugin_system/mod.rs | 7 +- src/predefined/color_mapper.rs | 45 +++- src/utils.rs | 301 +++++++++++++++++++++- src/widgets/render/imp.rs | 2 +- src/widgets/render/interior/layers.rs | 2 +- 15 files changed, 859 insertions(+), 464 deletions(-) diff --git a/src/components/app.rs b/src/components/app.rs index abf9f23..743d26f 100644 --- a/src/components/app.rs +++ b/src/components/app.rs @@ -87,10 +87,11 @@ pub enum AppMsg { DeleteElement(ElementKey), } type RcDispatcher = Rc; +type ArcDispatcher = Arc; #[tracker::track] pub struct AppModel { #[do_not_track] - dispatcher: RcDispatcher, + dispatcher: ArcDispatcher, #[do_not_track] cms: CMS, waiting_for: Option>, @@ -262,7 +263,7 @@ impl Component for AppModel { .launch(()) .forward(sender.input_sender(), |a| AppMsg::Close); - let mut dispatcher = Rc::new(Dispatcher::new(5, 5, chrono::Duration::minutes(1))); + let mut dispatcher = Arc::new(Dispatcher::new(5, 5, chrono::Duration::minutes(1))); let cms = CMS::new(Mercator::default().into(), (3000.0, 3000.0)); let dialog_buffer = buffer.clone(); let dialog_cms = cms.clone(); @@ -282,45 +283,15 @@ impl Component for AppModel { let meta: MetaInfo = (&data.meta).clone().into(); let (lat_start, lat_end) = meta.lat_range.unwrap(); let (lon_start, lon_end) = meta.lon_range.unwrap(); - let imp = tools(&data); - + let (imp, cfg) = tools(&data); dialog_file_pool.insert(path.clone(), Arc::new(data)); - use femtovg::Color; - let config = GridImpConfig { - color_map: ColorMapperComb::BoundaryNormDiscrete(ColorMapper::new( - Discrete::new(vec![ - Color::rgb(0, 172, 164), - Color::rgb(192, 192, 254), - Color::rgb(122, 114, 238), - Color::rgb(30, 38, 208), - Color::rgb(166, 252, 168), - Color::rgb(0, 234, 0), - Color::rgb(16, 146, 26), - Color::rgb(252, 244, 100), - Color::rgb(200, 200, 2), - Color::rgb(140, 140, 0), - Color::rgb(254, 172, 172), - Color::rgb(254, 100, 92), - Color::rgb(238, 2, 48), - Color::rgb(212, 142, 254), - Color::rgb(170, 36, 250), - ]), - BoundaryNorm::new( - vec![ - 0i8, 5i8, 10i8, 15i8, 20i8, 25i8, 30i8, 35i8, 40i8, 45i8, - 50i8, 55i8, 60i8, 65i8, 70i8, 75i8, - ], - false, - Some(-125), - ), - )), - }; + let element = Rc::new(RefCell::new(Element::new( "CR", dialog_cms.clone(), dialog_dispatcher.clone(), - true, - Arc::new(config), + false, + cfg, path.clone(), dialog_buffer.clone(), dialog_file_pool.clone(), diff --git a/src/components/setting/dispatcher_list.rs b/src/components/setting/dispatcher_list.rs index c3efabe..ea91a36 100644 --- a/src/components/setting/dispatcher_list.rs +++ b/src/components/setting/dispatcher_list.rs @@ -12,12 +12,12 @@ pub enum OutputMsg { } pub struct PathItem { - title: String, + title: &'static str, path: String, } impl PathItem { - pub fn new(title: String, path: String) -> Self { + pub fn new(title: &'static str, path: String) -> Self { Self { title, path } } } diff --git a/src/components/setting/setting.rs b/src/components/setting/setting.rs index 72d4782..26ce557 100644 --- a/src/components/setting/setting.rs +++ b/src/components/setting/setting.rs @@ -1,6 +1,5 @@ use super::dispatcher_list::PathItem; use crate::{ - config::PATH_FORMATS, data::{self, CoordType, Radar2d}, predefined::color_mapper::BoundaryNorm, widgets::render::Layer, @@ -100,15 +99,15 @@ impl SimpleComponent for SettingModel { .forward(sender.input_sender(), |msg| match msg { _ => SettingMsg::SaveConfig, }); - { - let config = CONFIG.lock().unwrap(); - let etws_config = config.plugins.get("etws_loader").unwrap(); - let paths = etws_config.path_formats.as_ref().unwrap_or(&PATH_FORMATS); - let mut list_guard = path_list.guard(); - for p in paths { - list_guard.push_back(PathItem::new(p.0.clone(), p.1.clone())); - } - } + // { + // let config = CONFIG.lock().unwrap(); + // let etws_config = config.plugins.get("etws_loader").unwrap(); + // // let paths = etws_config.path_formats.as_ref().unwrap_or(&PATH_FORMATS); + // let mut list_guard = path_list.guard(); + // for p in paths { + // list_guard.push_back(PathItem::new(p.0, p.1.clone())); + // } + // } let model = SettingModel { path_list }; let my_view = model.path_list.widget(); @@ -118,22 +117,22 @@ impl SimpleComponent for SettingModel { ComponentParts { model, widgets } } - fn update(&mut self, msg: Self::Input, _sender: ComponentSender) { - match msg { - SettingMsg::PathFormats((plugin, (k, v))) => { - let mut config = CONFIG.lock().unwrap(); - let mut pluging_cfg = config.plugins.get_mut(&plugin).unwrap(); - if pluging_cfg.path_formats.is_none() { - pluging_cfg.path_formats = Some(HashMap::new()); - } - pluging_cfg.path_formats.as_mut().unwrap().insert(k, v); - let mut list_guard = self.path_list.guard(); - // list_guard.push_back(PathItem::new(k, v)); - } - SettingMsg::SaveConfig => { - let mut config = CONFIG.lock().unwrap(); - config.save(); - } - } - } + // fn update(&mut self, msg: Self::Input, _sender: ComponentSender) { + // match msg { + // SettingMsg::PathFormats((plugin, (k, v))) => { + // let mut config = CONFIG.lock().unwrap(); + // let mut pluging_cfg = config.plugins.get_mut(&plugin).unwrap(); + // if pluging_cfg.path_formats.is_none() { + // pluging_cfg.path_formats = Some(HashMap::new()); + // } + // pluging_cfg.path_formats.as_mut().unwrap().insert(&k, v); + // let mut list_guard = self.path_list.guard(); + // // list_guard.push_back(PathItem::new(k, v)); + // } + // SettingMsg::SaveConfig => { + // let mut config = CONFIG.lock().unwrap(); + // config.save(); + // } + // } + // } } diff --git a/src/config.rs b/src/config.rs index e99457b..4161fb4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,41 +1,238 @@ use crate::errors::ConfigError; +use crate::predefined::color_mapper::{ + BoundaryNorm, BoundaryNormDiscrete, ColorMapper, ColorMapperComb, Discrete, +}; +use crate::utils::{ + create_cc_default_cvmapper, create_hgt_default_cvmapper, create_kdp_default_cvmapper, + create_reflect_default_cvmapper, create_vel_default_cvmapper, create_vil_default_cvmapper, + parse_hex_color, +}; use dirs; +use gtk::ResponseType::No; +use num_traits::{AsPrimitive, FromPrimitive}; use serde::{Deserialize, Serialize}; +use std::fmt::Debug; use std::{collections::HashMap, env, io::Write, path::PathBuf}; use toml; -lazy_static! { - pub static ref PATH_FORMATS: HashMap = { - let mut map = HashMap::new(); - map.insert("R".to_string(), String::new()); - map.insert("V".to_string(), String::new()); - map.insert("SW".to_string(), String::new()); - map.insert("CC".to_string(), String::new()); - map.insert("ZDR".to_string(), String::new()); - map.insert("PHIDP".to_string(), String::new()); - map.insert("KDP".to_string(), String::new()); - map.insert("HCA".to_string(), String::new()); - map.insert("DBZ".to_string(), String::new()); - map.insert("QPE".to_string(), String::new()); - map.insert("QPF".to_string(), String::new()); - map.insert("VIL".to_string(), String::new()); - map.insert("OHP".to_string(), String::new()); - map.insert("THP".to_string(), String::new()); - map.insert("ET".to_string(), String::new()); - map.insert("EB".to_string(), String::new()); - map +macro_rules! cvmap { + ($config:ident, + $({ + $cmap: literal, $vmap: literal, $value: expr + },)+ + ) => { + match ($config.cmap.as_str(), $config.vmap.as_str()) { + $( + ($cmap, $vmap) => { + $value + } + )+ + _ => { + panic!("Invalid color and value mapping") + } + } + }; } +macro_rules! drawers { + ($m:ident, $({ + $key: literal, $a: ident + },)+) => { + { + let mut defa = Drawers::default(); + $( + let $a = { + let kv = $m.remove($key); + if let Some(v) = kv { + defa.$a = v.try_into()?; + } + }; + )+ + // Drawers { + // $( + // $a, + // )+ + // } + defa + } + + }; +} + +#[derive(Debug)] +pub struct Settings { + pub plugin_config: Vec, + pub drawers: Drawers, +} + +#[derive(Debug)] +pub struct Drawers { + pub reflectivity: DrawerConfig, + pub velocity: DrawerConfig, + pub spectrum_width: DrawerConfig, + pub correlation_coefficient: DrawerConfig, + pub differential_reflectivity: DrawerConfig, + pub differential_phase: DrawerConfig, + pub specific_differential_phase: DrawerConfig, + pub hydrometeor_classification: DrawerConfig, + pub radar_rainfall_accumulation: DrawerConfig, + pub radar_rainfall_forecast: DrawerConfig, + pub vertically_integrated_liquid: DrawerConfig, + pub one_hour_precipitation: DrawerConfig, + pub three_hour_precipitation: DrawerConfig, + pub echo_tops: DrawerConfig, + pub echo_bases: DrawerConfig, +} + +impl Default for Drawers { + fn default() -> Self { + Self { + reflectivity: DrawerConfig { + title: "Reflectivity", + color_mapper: create_reflect_default_cvmapper().into(), + }, + velocity: DrawerConfig { + title: "Velocity", + color_mapper: create_vel_default_cvmapper().into(), + }, + spectrum_width: DrawerConfig { + title: "Spectrum Width", + color_mapper: ColorMapperComb::default(), + }, + + correlation_coefficient: DrawerConfig { + title: "Correlation Coefficient", + color_mapper: create_cc_default_cvmapper().into(), + }, + + differential_reflectivity: DrawerConfig { + title: "Differential Reflectivity", + color_mapper: create_kdp_default_cvmapper().into(), + }, + + differential_phase: DrawerConfig { + title: "Differential Phase", + color_mapper: create_kdp_default_cvmapper().into(), + }, + + specific_differential_phase: DrawerConfig { + title: "Specific Differential Phase", + color_mapper: create_kdp_default_cvmapper().into(), + }, + + hydrometeor_classification: DrawerConfig { + title: "Hydrometeor Classification", + color_mapper: ColorMapperComb::default(), + }, + + radar_rainfall_accumulation: DrawerConfig { + title: "Radar Rainfall Accumulation", + color_mapper: create_vil_default_cvmapper().into(), + }, + + radar_rainfall_forecast: DrawerConfig { + title: "Radar Rainfall Forecast", + color_mapper: create_vil_default_cvmapper().into(), + }, + + vertically_integrated_liquid: DrawerConfig { + title: "Vertically Integrated Liquid", + color_mapper: create_vil_default_cvmapper().into(), + }, + + one_hour_precipitation: DrawerConfig { + title: "One Hour Precipitation", + color_mapper: create_vil_default_cvmapper().into(), + }, + + three_hour_precipitation: DrawerConfig { + title: "Three Hour Precipitation", + color_mapper: create_vil_default_cvmapper().into(), + }, + + echo_tops: DrawerConfig { + title: "Echo Tops", + color_mapper: create_hgt_default_cvmapper().into(), + }, + + echo_bases: DrawerConfig { + title: "Echo Bases", + color_mapper: create_hgt_default_cvmapper().into(), + }, + } + } +} + +#[derive(Debug, Default)] +pub struct DrawerConfig +where + T: PartialEq + PartialOrd + Debug + Clone, +{ + pub title: &'static str, + pub color_mapper: ColorMapperComb, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct SeDrawerConfig { + pub cmap: String, + pub vmap: String, + pub colors: Option>, + pub values: Option>, + pub extrand: Option, +} + +impl TryFrom for DrawerConfig +where + T: FromPrimitive + PartialEq + PartialOrd + Debug + Copy + 'static, + f32: AsPrimitive, +{ + type Error = &'static str; + fn try_from(value: SeDrawerConfig) -> Result { + let boundaries = value + .values + .map(|x| x.iter().map(|x| x.as_()).collect::>()) + .unwrap(); + let colors = if let Some(v) = value.colors { + let mut colors = Vec::new(); + for value in v.iter() { + let (r, g, b) = parse_hex_color(value)?; + colors.push(femtovg::Color::rgb(r, g, b)); + } + Some(colors) + } else { + None + }; + + let c = cvmap!( + value, + { + "boundary_norm", "discrete", + ColorMapper::new( + Discrete::new(colors.unwrap()), + BoundaryNorm::new(boundaries, value.extrand.unwrap_or(false), T::from_f32(-125.0)), + ) + }, + ); + + Ok(Self { + title: "Reflectivity", + color_mapper: c.into(), + }) + } +} + #[derive(Debug, Serialize, Deserialize, Default)] pub struct Config { - pub plugins: HashMap, + pub plugins: Vec, + pub drawer_config: HashMap, } #[derive(Debug, Serialize, Deserialize)] pub struct PluginConfig { pub version: String, - pub path_formats: Option>, + pub name: String, + pub publisher: String, } impl Config { @@ -84,3 +281,32 @@ impl Config { } } } + +impl TryFrom for Settings { + type Error = &'static str; + fn try_from(value: Config) -> Result { + let mut map = value.drawer_config; + let c = drawers!(map, + {"reflectivity", reflectivity}, + {"velocity", velocity}, + {"spectrum_width", spectrum_width}, + {"correlation_coefficient", correlation_coefficient}, + {"differential_reflectivity", differential_reflectivity}, + {"differential_phase", differential_phase}, + {"specific_differential_phase", specific_differential_phase}, + {"hydrometeor_classification", hydrometeor_classification}, + {"radar_rainfall_accumulation", radar_rainfall_accumulation}, + {"radar_rainfall_forecast", radar_rainfall_forecast}, + {"vertically_integrated_liquid", vertically_integrated_liquid}, + {"one_hour_precipitation", one_hour_precipitation}, + {"three_hour_precipitation", three_hour_precipitation}, + {"echo_tops", echo_tops}, + {"echo_bases", echo_bases}, + ); + + Ok(Self { + plugin_config: value.plugins, + drawers: c, + }) + } +} diff --git a/src/data_utils.rs b/src/data_utils.rs index 97bdfa5..ae4fb17 100644 --- a/src/data_utils.rs +++ b/src/data_utils.rs @@ -1,10 +1,45 @@ use crate::pipeline::element_imp::*; use crate::utils::*; +use crate::CONFIG; use radarg_plugin_interface::{CoordType, DataShape, PluginResult, PluginResultType}; use std::any::Any; use std::sync::Arc; -pub fn tools(data: &PluginResult) -> ElementImpl { +macro_rules! dispatch { + ($block:ident,$conf:ident, $wrap:tt , $fill_value: ident, $( + { + $t:ty | $branch: pat => $v:ident + } + ),+ $(,)?) => { + match $block.data_type { + $( + $branch => { + let mut $v = $wrap::default(); + $v.color_map = $conf.drawers.$v.color_mapper.clone(); + $v.fill_value = <$t>::from_f64($fill_value); + Arc::new($v) as Arc + } + )+ + + _ => { panic!("") } + } + }; +} + +macro_rules! dis { + ($block:ident, $config:ident, $wrap:tt, $fill_value: ident) => { + dispatch!( + $block, $config, $wrap, $fill_value, + { i8|PluginResultType::R => reflectivity }, + { i8|PluginResultType::DBZ => reflectivity }, + { f32|PluginResultType::ZDR => differential_reflectivity }, + { f32|PluginResultType::KDP => specific_differential_phase }, + { i8|PluginResultType::PHIDP => differential_phase } + ) + }; +} + +pub fn tools(data: &PluginResult) -> (ElementImpl, Arc) { let blocks_num = data.blocks.len(); if blocks_num == 0 { @@ -16,16 +51,29 @@ pub fn tools(data: &PluginResult) -> ElementImpl { } let block = data.blocks.first().unwrap(); + let fill_value = block.fill_value; + let config = CONFIG.read().unwrap(); - match block.coord_type { - CoordType::Polar => PolarElementImp().into(), - CoordType::Cartesian => match block.shape { - DataShape::Cube => MultiLayerGridImp().into(), - DataShape::Matrix => GridImp().into(), - _ => panic!("Invalid shape"), - }, + let imp = match block.coord_type { + CoordType::Polar => { + let cfg = dis!(block, config, PolarElementConfig, fill_value); + (PolarElementImp().into(), cfg) + } + CoordType::Cartesian => { + let cfg = dis!(block, config, GridImpConfig, fill_value); + ( + match block.shape { + DataShape::Cube => MultiLayerGridImp().into(), + DataShape::Matrix => GridImp().into(), + _ => panic!("Invalid shape"), + }, + cfg, + ) + } _ => { panic!("Invalid type") } - } + }; + + imp } diff --git a/src/main.rs b/src/main.rs index 6fa10a2..805834d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,12 +4,11 @@ mod utils; #[macro_use] extern crate lazy_static; -use config::Config; -use gtk::{ - gio::{self, Settings}, - prelude::SettingsExt, -}; +use config::{Config, Settings}; +use gtk::{gio, prelude::SettingsExt}; use plugin_system::{init_plugin, PluginManager}; +use std::convert::TryInto; +use std::sync::RwLock; use std::{ptr, sync::Mutex}; use tokio::runtime::Runtime; mod actions; @@ -41,7 +40,8 @@ declare_surfman!(); const APP_ID: &str = "org.tsuki.radar_g"; static RUNTIME: SafeLazy = SafeLazy::new(|| Runtime::new().expect("Setting up tokio runtime needs to succeed.")); -static CONFIG: SafeLazy> = SafeLazy::new(|| Mutex::new(Config::from_env().unwrap())); +static CONFIG: SafeLazy> = + SafeLazy::new(|| RwLock::new(Config::from_env().unwrap().try_into().unwrap())); static PLUGIN_MANAGER: SafeLazy = SafeLazy::new(|| PluginManager::new().unwrap()); fn main() { diff --git a/src/pipeline/dispatcher.rs b/src/pipeline/dispatcher.rs index 1d5e886..ebe6bf6 100644 --- a/src/pipeline/dispatcher.rs +++ b/src/pipeline/dispatcher.rs @@ -63,41 +63,42 @@ impl Dispatcher { ) -> Option { let datetime_format: regex::Regex = Regex::new(r"(?:%[YHMSmd](?:[-/:_]?%[YHMSmd])*)").unwrap(); - let config = CONFIG.lock().unwrap(); - let path_format = config - .plugins - .get("etws_loader") - .unwrap() - .path_formats - .as_ref(); - if path_format.is_none() { - return None; - } - let c = path_format.unwrap().get(name).map(|s| { - let path = s.clone(); - let need_formated = datetime_format.captures_iter(&path).collect::>(); - let mut result_path = path.clone(); - - for need_format in need_formated.iter() { - let fmt = need_format.get(0).unwrap().as_str(); - let t = current_time.format(fmt).to_string(); - result_path = result_path.replace(fmt, &t); - } - result_path - }); - if let Some(c) = c { - if check_existed { - if std::path::Path::new(&c).exists() { - Some(c) - } else { - None - } - } else { - Some(c) - } - } else { - None - } + let config = CONFIG.read().unwrap(); + // let path_format = config + // .plugins + // .get("etws_loader") + // .unwrap() + // .path_formats + // .as_ref(); + return None; + // if path_format.is_none() { + // return None; + // } + // let c = path_format.unwrap().get(name).map(|s| { + // let path = s.clone(); + // let need_formated = datetime_format.captures_iter(&path).collect::>(); + // let mut result_path = path.clone(); + // + // for need_format in need_formated.iter() { + // let fmt = need_format.get(0).unwrap().as_str(); + // let t = current_time.format(fmt).to_string(); + // result_path = result_path.replace(fmt, &t); + // } + // result_path + // }); + // if let Some(c) = c { + // if check_existed { + // if std::path::Path::new(&c).exists() { + // Some(c) + // } else { + // None + // } + // } else { + // Some(c) + // } + // } else { + // None + // } } pub fn get_path( @@ -108,92 +109,94 @@ impl Dispatcher { mut max_retry_time: usize, file_path: &PathBuf, ) -> Option)>> { - let config = CONFIG.lock().unwrap(); - let path_format = config - .plugins - .get("etws_loader") - .unwrap() - .path_formats - .as_ref(); - if path_format.is_none() { - return None; - } - path_format.unwrap().get(name).map(|s| { - let path = s.clone(); - // let file_path = { file_path_root.lock().unwrap().clone() }; - let path = if path.starts_with("./") { - let file_root = file_root(&file_path, path.replace("./", "")); - file_root.map(|root| { - let splited = path.split_at(2); - root.join(PathBuf::from(splited.1)) - }) - } else { - Some(PathBuf::from(path)) - }; + let config = CONFIG.read().unwrap(); - let mut result_paths = Vec::new(); - if let Some(path_uninit) = path { - let mut path_str = path_uninit.to_string_lossy().to_string(); - let prefixs = get_prefix(&file_path, &path_str); - - for (idx, prefix) in prefixs.iter().enumerate() { - if let Some(s) = prefix.as_ref() { - path_str = path_str.replacen("{prefix}", &s, 1); - } - } - - let need_formated = DATETIME_FORMAT.captures_iter(&path_str).collect::>(); - let mut fore = self.fore_len; - let mut back = 1; - - while fore > 0 { - let mut result_path = path_str.clone(); - let t = current_time - self.step * fore as i32; - for need_format in need_formated.iter() { - let fmt = need_format.get(0).unwrap().as_str(); - let t = t.format(fmt).to_string(); - result_path = result_path.replace(fmt, &t); - } - - if check_existed { - // if max_retry_time == 0 { - // break; - // } - if !std::path::Path::new(&result_path).exists() { - } else { - result_paths.push((result_path.clone(), t)); - } - } else { - result_paths.push((result_path.clone(), t)); - } - fore = fore - 1; - } - - while back < self.back_len + 1 { - let mut result_path = path_str.clone(); - let t = current_time + self.step * back as i32; - for need_format in need_formated.iter() { - let fmt = need_format.get(0).unwrap().as_str(); - let t = t.format(fmt).to_string(); - result_path = result_path.replace(fmt, &t); - } - - if check_existed { - // if max_retry_time == 0 { - // break; - // } - if !std::path::Path::new(&result_path).exists() { - } else { - result_paths.push((result_path.clone(), t)); - } - } else { - result_paths.push((result_path.clone(), t)); - } - back = back + 1; - } - } - result_paths - }) + return None; + // let path_format = config + // .plugins + // .get("etws_loader") + // .unwrap() + // .path_formats + // .as_ref(); + // if path_format.is_none() { + // return None; + // } + // path_format.unwrap().get(name).map(|s| { + // let path = s.clone(); + // // let file_path = { file_path_root.lock().unwrap().clone() }; + // let path = if path.starts_with("./") { + // let file_root = file_root(&file_path, path.replace("./", "")); + // file_root.map(|root| { + // let splited = path.split_at(2); + // root.join(PathBuf::from(splited.1)) + // }) + // } else { + // Some(PathBuf::from(path)) + // }; + // + // let mut result_paths = Vec::new(); + // if let Some(path_uninit) = path { + // let mut path_str = path_uninit.to_string_lossy().to_string(); + // let prefixs = get_prefix(&file_path, &path_str); + // + // for (idx, prefix) in prefixs.iter().enumerate() { + // if let Some(s) = prefix.as_ref() { + // path_str = path_str.replacen("{prefix}", &s, 1); + // } + // } + // + // let need_formated = DATETIME_FORMAT.captures_iter(&path_str).collect::>(); + // let mut fore = self.fore_len; + // let mut back = 1; + // + // while fore > 0 { + // let mut result_path = path_str.clone(); + // let t = current_time - self.step * fore as i32; + // for need_format in need_formated.iter() { + // let fmt = need_format.get(0).unwrap().as_str(); + // let t = t.format(fmt).to_string(); + // result_path = result_path.replace(fmt, &t); + // } + // + // if check_existed { + // // if max_retry_time == 0 { + // // break; + // // } + // if !std::path::Path::new(&result_path).exists() { + // } else { + // result_paths.push((result_path.clone(), t)); + // } + // } else { + // result_paths.push((result_path.clone(), t)); + // } + // fore = fore - 1; + // } + // + // while back < self.back_len + 1 { + // let mut result_path = path_str.clone(); + // let t = current_time + self.step * back as i32; + // for need_format in need_formated.iter() { + // let fmt = need_format.get(0).unwrap().as_str(); + // let t = t.format(fmt).to_string(); + // result_path = result_path.replace(fmt, &t); + // } + // + // if check_existed { + // // if max_retry_time == 0 { + // // break; + // // } + // if !std::path::Path::new(&result_path).exists() { + // } else { + // result_paths.push((result_path.clone(), t)); + // } + // } else { + // result_paths.push((result_path.clone(), t)); + // } + // back = back + 1; + // } + // } + // result_paths + // }) } } diff --git a/src/pipeline/element_imp.rs b/src/pipeline/element_imp.rs index 4a4367a..16be8c9 100644 --- a/src/pipeline/element_imp.rs +++ b/src/pipeline/element_imp.rs @@ -25,7 +25,7 @@ macro_rules! impl_element_imp_dispatch { context: &mut Context<'b> ) where - T: Sync + Send + Debug + PartialOrd + PartialEq + Copy + Clone + 'static, + T: Sync + Send + Debug + PartialOrd + PartialEq + Copy + Clone + FromPrimitive + 'static, { match self { $( @@ -147,7 +147,7 @@ pub enum ElementOutput { } pub trait ElementImp: Debug + TryFrom + Into { - type Config<'a, T: Sync + Send + Debug + PartialOrd + PartialEq + 'a>: ElementConfig + type Config<'a, T: Sync + Send + Debug + PartialOrd + PartialEq + 'a + Clone + FromPrimitive>: ElementConfig where Self: 'a; type Input<'a, T: 'a> @@ -161,7 +161,7 @@ pub trait ElementImp: Debug + TryFrom + Into { config: &Self::Config<'a, T>, context: &mut Context<'b>, ) where - T: Sync + Send + Debug + PartialOrd + PartialEq + Copy + Clone; + T: Sync + Send + Debug + PartialOrd + PartialEq + Copy + Clone + FromPrimitive; fn output_type(&self) -> ElementOutput; } @@ -175,11 +175,13 @@ pub trait ElementConfig { #[derive(Debug, Clone, Copy)] pub struct GridImp(); +#[derive(Default)] pub struct GridImpConfig where - T: PartialOrd + PartialEq + Send + Sync + Debug, + T: PartialOrd + PartialEq + Send + Sync + Debug + Clone, { pub color_map: ColorMapperComb, + pub fill_value: T } impl GridImp { @@ -213,8 +215,10 @@ impl GridImp { let rt_lat = dim2[[r + 1, c + 1]]; let rt_lon = dim1[[r + 1, c + 1]]; let v = &data[[r, c]]; + if v == &config.fill_value { + continue; + } let mapped_color = mapper.color(*v); - if mapped_color.is_none() { continue; } @@ -231,7 +235,7 @@ impl GridImp { } impl ElementImp for GridImp { - type Config<'a, T: Sync + Send + Debug + PartialOrd + PartialEq> = GridImpConfig where + type Config<'a, T: Sync + Send + Debug + PartialOrd + PartialEq + Clone + FromPrimitive> = GridImpConfig where T: 'a; type Input<'a, T: 'a> = ArrayViewD<'a, T>; fn process<'a, 'b: 'a, T>( @@ -241,7 +245,7 @@ impl ElementImp for GridImp { config: &Self::Config<'a, T>, context: &mut Context<'b>, ) where - T: Send + Sync + Debug + PartialOrd + PartialEq + Copy + Clone, + T: Send + Sync + Debug + PartialOrd + PartialEq + Copy + Clone + FromPrimitive, { let shape = input.shape(); if shape.len() == 2 { @@ -268,7 +272,7 @@ impl MultiLayerGridImp { config: &MultiLayerGridImpConfig, context: &mut Context<'b>, ) where - T: PartialOrd + PartialEq + Send + Sync + Debug + Copy, + T: PartialOrd + PartialEq + Send + Sync + Debug + Copy + FromPrimitive, { let two = config.twod.clone(); let _layer = data.into_dimensionality::().unwrap(); @@ -280,7 +284,7 @@ impl MultiLayerGridImp { pub struct MultiLayerGridImpConfig where - T: PartialOrd + PartialEq + Send + Sync + Debug, + T: PartialOrd + PartialEq + Send + Sync + Debug + Clone, { twod: GridImp, two_d_config: GridImpConfig, @@ -288,7 +292,7 @@ where } impl ElementImp for MultiLayerGridImp { - type Config<'a, T: Sync + Send + Debug + PartialOrd + PartialEq + 'a> = + type Config<'a, T: Sync + Send + Debug + PartialOrd + PartialEq + Clone + FromPrimitive + 'a> = MultiLayerGridImpConfig; type Input<'a, T: 'a> = ArrayViewD<'a, T>; @@ -299,7 +303,7 @@ impl ElementImp for MultiLayerGridImp { config: &Self::Config<'a, T>, context: &mut Context<'b>, ) where - T: Sync + Send + Debug + PartialOrd + PartialEq + Copy + Clone, + T: Sync + Send + Debug + PartialOrd + PartialEq + Copy + Clone + FromPrimitive, { self.draw(dims, input, config.upcast_ref(), context); } @@ -312,12 +316,14 @@ impl ElementImp for MultiLayerGridImp { #[derive(Debug, Clone, Copy)] pub struct PolarElementImp(); +#[derive(Default)] pub struct PolarElementConfig where - T: PartialOrd + PartialEq + Send + Sync + Debug, + T: PartialOrd + PartialEq + Send + Sync + Debug + Clone + FromPrimitive, { - color_map: ColorMapperComb, - center: (f64, f64), + pub color_map: ColorMapperComb, + pub fill_value: T, + pub center: (f64, f64), } impl PolarElementImp { @@ -382,7 +388,7 @@ impl PolarElementImp { config: &'a PolarElementConfig, context: &mut Context<'a>, ) where - T: PartialOrd + PartialEq + Send + Sync + Debug + Copy, + T: PartialOrd + PartialEq + Send + Sync + Debug + Copy + FromPrimitive, { let canvas = &mut context.canvas; let mapper = &context.cms; @@ -422,7 +428,7 @@ impl PolarElementImp { } impl ElementImp for PolarElementImp { - type Config<'a, T: Sync + Send + Debug + PartialOrd + PartialEq> = PolarElementConfig where + type Config<'a, T: Sync + Send + Debug + PartialOrd + PartialEq + Clone + FromPrimitive> = PolarElementConfig where T: 'a; type Input<'a, T: 'a> = ArrayViewD<'a, T>; fn process<'a, 'b: 'a, T>( @@ -432,7 +438,7 @@ impl ElementImp for PolarElementImp { config: &Self::Config<'a, T>, context: &mut Context<'b>, ) where - T: Sync + Send + Debug + PartialOrd + PartialEq + Copy + Clone, + T: Sync + Send + Debug + PartialOrd + PartialEq + Copy + Clone + FromPrimitive, { let shape = input.shape(); if shape.len() == 2 { @@ -448,13 +454,18 @@ impl ElementImp for PolarElementImp { } } -impl ElementConfig for GridImpConfig where T: Sync + Send + Debug + PartialOrd + PartialEq {} -impl ElementConfig for MultiLayerGridImpConfig where - T: Sync + Send + Debug + PartialOrd + PartialEq +impl ElementConfig for GridImpConfig where + T: Sync + Send + Debug + PartialOrd + PartialEq + Clone +{ +} +impl ElementConfig for MultiLayerGridImpConfig where + T: Sync + Send + Debug + PartialOrd + PartialEq + Clone +{ +} +impl ElementConfig for PolarElementConfig where + T: Sync + Send + Debug + PartialOrd + PartialEq + Clone + FromPrimitive { } -impl ElementConfig for PolarElementConfig where T: Sync + Send + Debug + PartialOrd + PartialEq -{} #[derive(Debug, Clone, Copy)] pub enum ElementImpl { diff --git a/src/pipeline/new_element.rs b/src/pipeline/new_element.rs index 09cf2cb..c1eab15 100644 --- a/src/pipeline/new_element.rs +++ b/src/pipeline/new_element.rs @@ -18,6 +18,7 @@ use chrono::prelude::*; use femtovg::ImageFlags; use femtovg::ImageId; use futures::future::BoxFuture; +use glow::HasContext; use num_traits::AsPrimitive; use num_traits::FromPrimitive; use num_traits::Num; @@ -108,8 +109,7 @@ impl Target { if let TargetType::NativeBuffer(ref mem) = self.target { use glow::*; let texture = unsafe { - // let id = gl.create_texture().unwrap(); - let id = gl.create_named_texture(1).unwrap(); + let id = gl.create_texture().unwrap(); gl.bind_texture(glow::TEXTURE_2D, Some(id)); gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1); gl.pixel_store_i32(glow::UNPACK_ROW_LENGTH, 3000 as i32); @@ -279,11 +279,9 @@ impl RenderResult { pub fn new(target: DataTarget, meta_info: MetaInfo) -> Self { Self { target, meta_info } } - pub fn get_meta_info(&self) -> MetaInfo { self.meta_info.clone() } - pub fn get_mut_target(&mut self) -> &mut Target { &mut self.target.target } @@ -300,7 +298,7 @@ pub struct Element { subscribers: Arc>>>>>>, cancellers: Arc>>>, current_key: Option, - dispatcher: Rc, + dispatcher: Arc, buffer: Arc>, file_pool: Arc>>, current_target: Option>>, @@ -318,11 +316,10 @@ impl Element { pub fn new( name: impl Into, cms: CMS, - dispatcher: Rc, + dispatcher: Arc, cache: bool, config: Arc, root: std::path::PathBuf, - buffer: Arc>, file_pool: Arc>>, imp: ElementImpl, @@ -350,7 +347,12 @@ impl Element { let need_cache = self.cache; let output_type = self.imp.output_type(); - fn _init(this: &mut Element, need_cache: bool, output_type: ElementOutput, render: &Render) { + fn _init( + this: &mut Element, + need_cache: bool, + output_type: ElementOutput, + render: &Render, + ) { let data = this.file_pool.get(&this.root); if let Some(data) = data { let target = this._rrrr(data, need_cache, output_type, render); @@ -369,13 +371,12 @@ impl Element { _init(self, need_cache, output_type, render); } ElementEvent::Draw => { - if let Some(current) = self.current_target.as_ref(){ + if let Some(current) = self.current_target.as_ref() { let mut img = current.write().unwrap(); let mut img = img.get_mut_target(); render.draw_img(img); } else { _init(self, need_cache, output_type, render); - if let ElementOutput::Target = output_type { let mut _img = self.current_target.as_ref().unwrap(); let mut img = _img.write().unwrap(); @@ -395,71 +396,6 @@ impl Element { self.buffer.get(key); } } - - // match key { - // ElementEvent::Init => { - // let data = self.get_file(&self.root); - // } - // ElementEvent::DateTime(key) => { - // let key = &Key { - // id: self.id, - // name: self.name.clone(), - // root: self.root.clone(), - // datetime: Some(key), - // }; - - // if self.cache { - // if let ElementOutput::Target = self.imp.output_type() { - // let target = self.run(key.to_owned()).await; - // // if let Some(target) = target { - // // let mut target = target.lock().await; - // // let target = target.get_mut_target(); - // // render.draw_img(target); - // // } - // } else { - // let path = (&*self.dispatcher).borrow_mut().get_single_path( - // &self.name, - // key.datetime.to_owned().unwrap(), - // true, - // ); - - // if let Some(path) = path { - // let data = self.get_file(path); - // let mut _canvas = render.get_canvas(); - // let mut canvas = _canvas.as_mut().unwrap(); - // let cms = render.create_cms(); - // let context = Context::new(cms, canvas); - // let mut runner = Runner::new(self.imp, self.config.clone(), context); - // runner.run_without_target(&data); - // } - // } - // } else { - // let path = (&*self.dispatcher).borrow_mut().get_single_path( - // &self.name, - // key.datetime.to_owned().unwrap(), - // true, - // ); - // if let Some(path) = path { - // let data = self.get_file(path); - // let mut _canvas = render.get_canvas(); - // let mut canvas = _canvas.as_mut().unwrap(); - // let cms = render.create_cms(); - // let context = Context::new(cms, canvas); - // let mut runner = Runner::new(self.imp, self.config.clone(), context); - // runner.run_without_target(&data); - // } - // } - // } - - // ElementEvent::Data(data) => { - // let mut _canvas = render.get_canvas(); - // let mut canvas = _canvas.as_mut().unwrap(); - // let cms = render.create_cms(); - // let context = Context::new(cms, canvas); - // let mut runner = Runner::new(self.imp, self.config.clone(), context); - // runner.run_without_target(&data); - // } - // } } fn insert_target_to_buffer(&self, key: Key, render_result: RenderResult) { @@ -476,13 +412,23 @@ impl Element { ) -> Option { match output_type { ElementOutput::Target => { - let mut offscreen_renderer = OffscreenRenderer::new(3000, 3000).unwrap(); - let mut canvas = offscreen_renderer.create_canvas(); - let mut context = Context::new(self.cms.clone(), &mut canvas); - let mut runner = Runner::new(self.imp, self.config.clone(), context); - let target = runner.run(&data); - let meta = data.meta.clone().into(); - Some(RenderResult::new(DataTarget::new(Some(data), target), meta)) + use tokio::task; + let cms = self.cms.clone(); + let imp = self.imp.clone(); + let config = self.config.clone(); + + let handle = task::spawn_blocking(move || { + let mut offscreen_renderer = OffscreenRenderer::new(3000, 3000).unwrap(); + let mut canvas = offscreen_renderer.create_canvas(); + let mut context = Context::new(cms, &mut canvas); + let mut runner = Runner::new(imp, config, context); + let target = runner.run(&data); + let meta = data.meta.clone().into(); + Some(RenderResult::new(DataTarget::new(Some(data), target), meta)) + }); + let result = RUNTIME.block_on(handle).ok().flatten(); + result + // let result = RUNTIME.spawn(async {handle.await}); } _ => { @@ -508,38 +454,6 @@ impl Element { self.current_key.clone().unwrap() } - // async fn run(&self, key: Key) -> Option>> { - // { - // let cache = &self.buffer; - // if cache.peek(&key).is_some() { - // return Some(cache.get(&key).unwrap()); - // } - // } - - // let datetime = key.datetime.unwrap(); - - // let dispatcher = (&*self.dispatcher); - - // let current_path = dispatcher.get_single_path(&self.name, datetime, true); - // let paths = dispatcher.get_path(&self.name, datetime, true, 3, &self.root); - // if let Some(paths) = paths { - // paths.iter().for_each(|(p, d)| { - // let key = self.generate_key(d.to_owned()); - // let f = self._run(p, &key); - // let handle = tokio::task::spawn(f); - // }); - // } - - // if let Some(path) = current_path { - // let key = self.generate_key(datetime); - // let f = self._run(path, &key); - // let handle = tokio::task::spawn(f); - // let result = handle.await.unwrap(); - // Some(result) - // } else { - // None - // } - // } fn generate_key(&self, datetime: DateTime) -> Key { Key { id: self.id, @@ -548,81 +462,6 @@ impl Element { datetime: Some(datetime), } } - - // fn _run( - // &self, - // p: impl AsRef, - // key: &Key, - // ) -> BoxFuture<'static, Arc>> { - // let (tx, rx) = oneshot::channel(); - // let buffer = self.buffer.clone(); - // let config = self.config.clone(); - // let canceller = self.cancellers.clone(); - // let subscriber = self.subscribers.clone(); - // let mut dialog_cms = self.cms.clone(); - // let mut dialog_config = self.config.clone(); - // let mut dialog_imp = self.imp.clone(); - - // let _key = key.to_owned(); - // Box::pin(async move { - // let key = &_key; - // let mut subscribers = subscriber.lock().await; - // if subscribers.contains_key(key) { - // subscribers.get_mut(key).unwrap().push(tx); - // drop(subscribers); - // } else { - // let (canceller_tx, canceller_rx) = oneshot::channel(); - // subscribers.insert(key.to_owned(), vec![tx]); - // drop(subscribers); - - // let mut cancellers = canceller.lock().await; - // cancellers.insert(key.clone(), canceller_tx); - // drop(cancellers); - - // use tokio::task; - - // let key = key.to_owned(); - // tokio::spawn(async move { - // let new_key = key.clone(); - // tokio::select! { - // _ = async move { - // let handle = task::spawn_blocking(move || { - // let mut offscreen_renderer = OffscreenRenderer::new(3000, 3000).unwrap(); - // let mut canvas = offscreen_renderer.create_canvas(); - // let mut context = Context::new(dialog_cms, &mut canvas); - // let mut runner = Runner::new(dialog_imp, dialog_config, context); - - // let loader = PLUGIN_MANAGER.get_plugin_by_name("etws_loader").unwrap(); - // let mut loaded_data = loader.load("".into()).unwrap(); - // let meta = loaded_data.meta.clone().into(); - - // let target = runner.run(&loaded_data); - - // RenderResult::new( - // DataTarget::new(Some(loaded_data), target), - // meta - // ) - // }); - // let result = handle.await.unwrap(); - // let bf = Arc::new(Mutex::new(result)); - // buffer.insert(key.clone(), bf.clone()); - // let mut subscribers = subscriber.lock().await; - // for tx in subscribers.remove(&key).unwrap() { - // let _ = tx.send(bf.clone()); - // } - - // } => {} - // _ = canceller_rx => {} - // } - // let mut cancellers = canceller.lock().await; - // cancellers.remove(&new_key); - // }); - // } - - // rx.await.unwrap() - // }) - // } - fn key(&self) -> String { format!("{}-{}", self.id, self.name) } diff --git a/src/pipeline/runner.rs b/src/pipeline/runner.rs index 98409a5..c9ca982 100644 --- a/src/pipeline/runner.rs +++ b/src/pipeline/runner.rs @@ -141,7 +141,6 @@ impl<'a> Runner<'a> { { I32 }, { F64 }, { I64 }, - { Bool }, { F32 }, { I8 }, { U8 }, diff --git a/src/plugin_system/mod.rs b/src/plugin_system/mod.rs index 2744efb..e353864 100644 --- a/src/plugin_system/mod.rs +++ b/src/plugin_system/mod.rs @@ -73,9 +73,10 @@ impl PluginManager { let mut this = Self { registered_plugins: HashMap::new(), }; - for (plugin_name, config) in CONFIG.lock().unwrap().plugins.iter() { - if let Ok((id, p)) = init_plugin(plugin_name.to_owned()) { - println!("Loaded plugin: {}", plugin_name); + + for plugin in CONFIG.read().unwrap().plugin_config.iter() { + if let Ok((id, p)) = init_plugin(plugin.name.to_owned()) { + println!("Loaded plugin: {}", plugin.name); this.registered_plugins.insert(id, p); } } diff --git a/src/predefined/color_mapper.rs b/src/predefined/color_mapper.rs index 83ba8c6..dad0ac5 100644 --- a/src/predefined/color_mapper.rs +++ b/src/predefined/color_mapper.rs @@ -1,30 +1,52 @@ -use std::fmt::Debug; - +use abi_stable::type_level::trait_marker::Default; use femtovg::Color; use image::imageops::ColorMap; use num_traits::{AsPrimitive, FromPrimitive, NumOps}; +use std::fmt::Debug; -type BoundaryNormDiscrete = ColorMapper>; +pub type BoundaryNormDiscrete = ColorMapper>; macro_rules! color_mapper_comb { ($comb: ident, $($key: tt,)+) => { - impl $comb { + impl $comb { pub fn color(&self, value: T) -> Option { match self { $( Self::$key(mapper) => mapper.color(value), )+ + + _ => None, } } } + impl From> for $comb + where + T: PartialEq + PartialOrd + Debug + Clone, + { + fn from(v: BoundaryNormDiscrete) -> Self { + Self::BoundaryNormDiscrete(v) + } + } + }; } -pub enum ColorMapperComb { +#[derive(Debug, Clone)] +pub enum ColorMapperComb { BoundaryNormDiscrete(BoundaryNormDiscrete), + Unknown, +} + +impl std::default::Default for ColorMapperComb +where + T: PartialEq + PartialOrd + Debug + Clone, +{ + fn default() -> Self { + Self::Unknown + } } color_mapper_comb!(ColorMapperComb, BoundaryNormDiscrete,); @@ -38,10 +60,11 @@ pub trait CMap { fn map(&self, v: f32) -> femtovg::Color; } +#[derive(Debug, Clone)] pub struct ColorMapper where - CMAP: CMap, - VMAP: VMap, + CMAP: CMap + Clone, + VMAP: VMap + Clone, { cmap: CMAP, vmap: VMAP, @@ -50,8 +73,8 @@ where impl ColorMapper where T: PartialEq + PartialOrd, - CMAP: CMap, - VMAP: VMap, + CMAP: CMap + Clone, + VMAP: VMap + Clone, { pub fn new(cmap: CMAP, vmap: VMAP) -> Self { Self { cmap, vmap } @@ -62,7 +85,7 @@ where } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct BoundaryNorm { boundaries: Vec, extrand: bool, @@ -106,7 +129,7 @@ where #[derive(Debug)] pub struct Gradient {} -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Discrete { colors: Vec, } diff --git a/src/utils.rs b/src/utils.rs index 91e9ac0..2eb02dc 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,17 +1,16 @@ use chrono::{DateTime, Utc}; -use femtovg::Color; -use gtk::glib::{HasParamSpec, ParamSpecInt64, ParamSpecInt64Builder}; -use std::{borrow::BorrowMut, num::NonZeroU32}; - use euclid::Size2D; use femtovg::Canvas; +use femtovg::Color; +use gtk::glib::{HasParamSpec, ParamSpecInt64, ParamSpecInt64Builder}; use ndarray::{Array2, ArrayView1}; +use std::{borrow::BorrowMut, num::NonZeroU32}; use surfman::{ Connection, Context, ContextAttributeFlags, ContextAttributes, ContextDescriptor, Device, GLVersion, NativeConnection, NativeContext, SurfaceAccess, SurfaceType, }; -use crate::predefined::color_mapper::BoundaryNorm; +use crate::predefined::color_mapper::{BoundaryNorm, BoundaryNormDiscrete, Discrete}; use crate::RUNTIME; use std::sync::Arc; use std::time::Duration; @@ -31,7 +30,268 @@ where (xx, yy) } +macro_rules! default_cvmapers { + ($({ + $key: ident, $value: expr, $colors: expr, $_ty:ty + }),+ $(,)?) => { + $( + pub fn $key() -> BoundaryNormDiscrete<$_ty> { + let discrete = Discrete::new($colors); + let boundarynorm = BoundaryNorm::new($value, true, None); + BoundaryNormDiscrete::new(discrete, boundarynorm) + } + )+ + }; +} + +default_cvmapers! { + { + create_reflect_default_cvmapper, + vec![-5, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75], + vec![ + Color::rgb(23, 174, 165), + Color::rgb(198, 195, 253), + Color::rgb(124, 114, 236), + Color::rgb(1, 160, 246), + Color::rgb(0, 236, 236), + Color::rgb(0, 216, 0), + Color::rgb(1, 144, 0), + Color::rgb(255, 255, 0), + Color::rgb(231, 192, 0), + Color::rgb(255, 144, 0), + Color::rgb(255, 0, 0), + Color::rgb(214, 0, 0), + Color::rgb(192, 0, 0), + Color::rgb(255, 0, 240), + Color::rgb(150, 0, 180), + Color::rgb(139, 0, 255), + ], + i8 + }, + + { + create_vel_default_cvmapper, + vec![ + -35, -27, -20, -15, -10, -5, -1, 0, 1, 5, 10, 15, 20, 27, + 35, + ], + vec![ + Color::rgb(0, 224, 255), + Color::rgb(0, 128, 255), + Color::rgb(50, 0, 150), + Color::rgb(0, 251, 144), + Color::rgb(0, 187, 144), + Color::rgb(0, 143, 0), + Color::rgb(205, 192, 159), + Color::rgb(255, 255, 255), + Color::rgb(248, 135, 0), + Color::rgb(255, 207, 0), + Color::rgb(255, 255, 0), + Color::rgb(174, 0, 0), + Color::rgb(208, 112, 0), + Color::rgb(255, 0, 0), + ], + i8 + }, + { + create_phidp_default_cvmapper, + vec![ + 0.0, 22.0, 46.0, 68.0, 90.0, 112.0, 136.0, 158.0, 180.0, 202.0, 224.0, 248.0, 270.0, + 292.0, 314.0, 359.0, + ], + vec![ + Color::rgb(0, 60, 255), + Color::rgb(0, 239, 239), + Color::rgb(0, 186, 191), + Color::rgb(0, 131, 125), + Color::rgb(0, 137, 56), + Color::rgb(0, 183, 41), + Color::rgb(0, 218, 13), + Color::rgb(0, 255, 0), + Color::rgb(255, 255, 59), + Color::rgb(255, 240, 0), + Color::rgb(255, 198, 0), + Color::rgb(255, 165, 0), + Color::rgb(255, 114, 0), + Color::rgb(255, 31, 0), + Color::rgb(193, 0, 0), + ], + f32 + }, + { + create_zdr_default_cvmapper, + vec![ + -5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, + ], + vec![ + Color::rgb(70, 70, 70), + Color::rgb(80, 80, 80), + Color::rgb(90, 90, 90), + Color::rgb(100, 100, 100), + Color::rgb(110, 110, 110), + Color::rgb(120, 120, 120), + Color::rgb(130, 130, 130), + Color::rgb(140, 140, 140), + Color::rgb(150, 150, 150), + Color::rgb(175, 175, 175), + Color::rgb(200, 200, 200), + Color::rgb(220, 240, 220), + Color::rgb(0, 192, 39), + ], + f32 + }, + { + create_cc_default_cvmapper, + vec![ + 0.0, 0.1, 0.3, 0.5, 0.6, 0.7, 0.8, 0.85, 0.9, 0.92, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, + ], + vec![ + Color::rgb(0, 60, 255), + Color::rgb(0, 239, 239), + Color::rgb(0, 186, 191), + Color::rgb(0, 131, 125), + Color::rgb(0, 137, 56), + Color::rgb(0, 183, 41), + Color::rgb(0, 218, 13), + Color::rgb(0, 255, 0), + Color::rgb(255, 255, 59), + Color::rgb(255, 240, 0), + Color::rgb(255, 198, 0), + Color::rgb(255, 165, 0), + Color::rgb(255, 114, 0), + Color::rgb(255, 31, 0), + Color::rgb(193, 0, 0), + ], + f32 + }, + { + create_vil_default_cvmapper, + vec![ + 1.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35., 40., 45., 50., 55., 60., 65., 70., + ], + vec![ + Color::rgb(156, 156, 156), + Color::rgb(118, 118, 118), + Color::rgb(250, 170, 170), + Color::rgb(238, 140, 140), + Color::rgb(201, 112, 112), + Color::rgb(0, 251, 144), + Color::rgb(0, 187, 0), + Color::rgb(255, 255, 112), + Color::rgb(208, 208, 96), + Color::rgb(255, 96, 96), + Color::rgb(218, 0, 0), + Color::rgb(174, 0, 0), + Color::rgb(0, 0, 255), + Color::rgb(255, 255, 255), + ], + f32 + }, + { + create_hgt_default_cvmapper, + vec![ + 0.0, 2.0, 3.0, 5.0, 6.0, 8.0, 9.0, 11., 12., 14., 15., 17., 18., 20., 21., + ], + vec![ + Color::rgb(0, 0, 0), + Color::rgb(118, 118, 118), + Color::rgb(0, 224, 255), + Color::rgb(0, 176, 255), + Color::rgb(0, 144, 204), + Color::rgb(50, 0, 150), + Color::rgb(0, 251, 144), + Color::rgb(0, 187, 0), + Color::rgb(0, 239, 0), + Color::rgb(254, 191, 0), + Color::rgb(255, 255, 0), + Color::rgb(174, 0, 0), + Color::rgb(255, 0, 0), + Color::rgb(255, 255, 255), + ], + f32 + }, + { + create_et_default_cvmapper, + vec![ + 0.1, 0.2, 0.5, 1.0, 1.5, 2.0, 3.0, 5.0, 6.0, 8.0, 9.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 18.0, 20.0, 21.0, + ], + vec![ + Color::rgb(204, 253, 255), + Color::rgb(153, 248, 255), + Color::rgb(101, 239, 255), + Color::rgb(50, 227, 255), + Color::rgb(134, 255, 134), + Color::rgb(80, 255, 80), + Color::rgb(0, 241, 1), + Color::rgb(0, 187, 0), + Color::rgb(255, 255, 84), + Color::rgb(255, 240, 0), + Color::rgb(255, 191, 0), + Color::rgb(255, 168, 0), + Color::rgb(255, 89, 89), + Color::rgb(255, 64, 64), + Color::rgb(255, 13, 13), + Color::rgb(237, 0, 0), + Color::rgb(205, 0, 0), + Color::rgb(139, 0, 0), + ], + f32 + }, + { + create_cpc_default_cvmapper, + vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], + vec![ + Color::rgb(201, 196, 191), + Color::rgb(112, 188, 73), + Color::rgb(245, 163, 110), + Color::rgb(208, 119, 52), + Color::rgb(234, 37, 47), + Color::rgb(199, 53, 47), + Color::rgb(145, 71, 152), + Color::rgb(178, 177, 65), + Color::rgb(103, 199, 208), + Color::rgb(55, 90, 165), + Color::rgb(187, 165, 204), + ], + i8 + }, + { + create_kdp_default_cvmapper, + vec![ + -0.8, -0.4, -0.2, -0.1, 0.1, 0.15, 0.22, 0.33, 0.5, 0.75, 1.1, 1.7, 2.4, 3.1, 7.0, 20.0, + ], + vec![ + Color::rgb(0, 255, 255), + Color::rgb(0, 239, 239), + Color::rgb(0, 168, 172), + Color::rgb(180, 180, 180), + Color::rgb(180, 180, 180), + Color::rgb(0, 192, 39), + Color::rgb(0, 232, 10), + Color::rgb(36, 255, 36), + Color::rgb(255, 255, 30), + Color::rgb(255, 230, 0), + Color::rgb(255, 188, 0), + Color::rgb(255, 152, 0), + Color::rgb(255, 94, 0), + Color::rgb(242, 15, 0), + Color::rgb(187, 0, 58), + Color::rgb(253, 6, 253), + ], + f32 + } +} + // pub fn create_dbz_boundarynorm() -> BoundaryNorm { +// +// // Discrete::new() +// +// // BoundaryNorm::new() +// +// BoundaryNormDiscrete::new( +// +// ) // BoundaryNorm::new( // vec![ // -5, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, @@ -85,7 +345,7 @@ where // -125.0, // ) // } - +// // pub fn create_phidp_boundarynorm() -> BoundaryNorm { // BoundaryNorm::new( // vec![ @@ -113,7 +373,7 @@ where // -125.0, // ) // } - +// // pub fn create_zdr_boundarynorm() -> BoundaryNorm { // BoundaryNorm::new( // vec![ @@ -138,7 +398,7 @@ where // -125.0, // ) // } - +// // pub fn create_cc_boundarynorm() -> BoundaryNorm { // BoundaryNorm::new( // vec![ @@ -165,7 +425,7 @@ where // -125.0, // ) // } - +// // pub fn create_vil_boundarynorm() -> BoundaryNorm { // BoundaryNorm::new( // vec![ @@ -191,7 +451,7 @@ where // -125.0, // ) // } - +// // pub fn create_hgt_boundarynorm() -> BoundaryNorm { // BoundaryNorm::new( // vec![ @@ -217,7 +477,7 @@ where // -125.0, // ) // } - +// // pub fn create_et_boundarynorm() -> BoundaryNorm { // BoundaryNorm::new( // vec![ @@ -248,7 +508,7 @@ where // -125.0, // ) // } - +// // pub fn create_cpc_boundarynorm() -> BoundaryNorm { // BoundaryNorm::new( // vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], @@ -269,7 +529,7 @@ where // -125, // ) // } - +// // pub fn create_kdp_boundarynorm() -> BoundaryNorm { // BoundaryNorm::new( // vec![ @@ -327,3 +587,18 @@ pub fn estimate_zoom_level( zoom_level_estimation.round() as u8 } + +pub fn parse_hex_color(hex: &str) -> Result<(u8, u8, u8), &'static str> { + if hex.starts_with('#') && hex.len() == 7 { + let r = u8::from_str_radix(&hex[1..3], 16); + let g = u8::from_str_radix(&hex[3..5], 16); + let b = u8::from_str_radix(&hex[5..7], 16); + + match (r, g, b) { + (Ok(r), Ok(g), Ok(b)) => Ok((r, g, b)), + _ => Err("Invalid hexadecimal value"), + } + } else { + Err("Invalid color format") + } +} diff --git a/src/widgets/render/imp.rs b/src/widgets/render/imp.rs index 268fda1..892784a 100644 --- a/src/widgets/render/imp.rs +++ b/src/widgets/render/imp.rs @@ -6,6 +6,7 @@ use crate::coords::Mapper; use crate::map_tile::MapTile; use crate::pipeline::new_element::{Target, TargetType}; use femtovg::{Canvas, Color, FontId, Paint, Renderer}; +use glow::HasContext; use gtk::glib::{self, prelude::*, Properties}; use gtk::prelude::*; use gtk::subclass::prelude::*; @@ -15,7 +16,6 @@ use std::collections::HashMap; use std::num::NonZeroU32; use std::rc::Rc; use std::sync::{Arc, Mutex}; -use glow::HasContext; use tracing::info; #[derive(Debug, Default, Clone, Copy, PartialEq)] diff --git a/src/widgets/render/interior/layers.rs b/src/widgets/render/interior/layers.rs index cc72b4d..d2afc49 100644 --- a/src/widgets/render/interior/layers.rs +++ b/src/widgets/render/interior/layers.rs @@ -4,12 +4,12 @@ use crate::pipeline::new_element::{self, Target}; use crate::pipeline::new_element::{Element, ElementEvent}; use crate::RUNTIME; use femtovg::{renderer::OpenGl, Canvas}; +use std::cell::RefCell; use std::rc::Rc; use std::{ fmt::Debug, sync::{Arc, Mutex}, }; -use std::cell::RefCell; #[derive(Clone, Copy, Debug)] pub enum ElementType {