This commit is contained in:
Tsuki 2024-04-12 18:37:41 +08:00
parent cd4c46f9c6
commit e0c02a4e35
15 changed files with 1221 additions and 413 deletions

15
Cargo.lock generated
View File

@ -529,6 +529,7 @@ dependencies = [
"core_extensions", "core_extensions",
"crossbeam", "crossbeam",
"dirs", "dirs",
"enum_dispatch",
"epoxy", "epoxy",
"euclid", "euclid",
"femtovg", "femtovg",
@ -986,7 +987,7 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412"
dependencies = [ dependencies = [
"libloading 0.7.4", "libloading 0.8.3",
] ]
[[package]] [[package]]
@ -1032,6 +1033,18 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "enum_dispatch"
version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f33313078bb8d4d05a2733a94ac4c2d8a0df9a2b84424ebf4f33bfc224a890e"
dependencies = [
"once_cell",
"proc-macro2 1.0.76",
"quote 1.0.35",
"syn 2.0.48",
]
[[package]] [[package]]
name = "env_logger" name = "env_logger"
version = "0.9.3" version = "0.9.3"

View File

@ -72,6 +72,7 @@ reqwest = "0.11.25"
url = "2.5.0" url = "2.5.0"
quick_cache = "0.4.1" quick_cache = "0.4.1"
fns = "0.0.7" fns = "0.0.7"
enum_dispatch = "0.3.12"
[build-dependencies] [build-dependencies]

View File

@ -7,7 +7,9 @@ use super::{
ControlPanelOutputMsg, TimelineMsg, ControlPanelOutputMsg, TimelineMsg,
}; };
use crate::components::sidebar::{SideBarInputMsg, SideBarModel}; use crate::components::sidebar::{SideBarInputMsg, SideBarModel};
use crate::pipeline::{GridElementImpl, OffscreenRenderer}; use crate::data_utils::tools;
use crate::pipeline::element::DataTarget;
use crate::pipeline::OffscreenRenderer;
use crate::predefined::widgets::ColorBar; use crate::predefined::widgets::ColorBar;
use crate::widgets::{AssoElement, DynamicCol}; use crate::widgets::{AssoElement, DynamicCol};
use crate::{ use crate::{
@ -22,12 +24,11 @@ use crate::{
}, },
data::MetaInfo, data::MetaInfo,
errors::RenderError, errors::RenderError,
pipeline::{utils::data_to_element, Dispatcher, Pipeline, RenderResult}, pipeline::{Dispatcher, Pipeline, RenderResult},
plugin_system::init_plugin, plugin_system::init_plugin,
widgets::render::Layer, widgets::render::Layer,
CONFIG, PLUGIN_MANAGER, CONFIG, PLUGIN_MANAGER,
}; };
use crate::{data_utils::plugin_result_impl, pipeline::element::DataTarget};
use abi_stable::std_types::RStr; use abi_stable::std_types::RStr;
use adw::prelude::*; use adw::prelude::*;
use chrono::{prelude::*, Duration}; use chrono::{prelude::*, Duration};
@ -272,27 +273,29 @@ impl Component for AppModel {
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 imp = tools(&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 = Layer::new( // let layer = Layer::new(
true, // true,
"New Layer".to_string(), // "New Layer".to_string(),
AssoElement::Instant(element), // AssoElement::Instant(element),
); // );
dialog_sidebar_sender.emit(SideBarInputMsg::AddMetaItems(meta.to_map())); // dialog_sidebar_sender.emit(SideBarInputMsg::AddMetaItems(meta.to_map()));
dialog_render_sender.emit(MonitorInputMsg::SetRenderRange( // dialog_render_sender.emit(MonitorInputMsg::SetRenderRange(
lon_start, lon_end, lat_start, lat_end, // lon_start, lon_end, lat_start, lat_end,
)); // ));
let layer = Layer::new(true, "New Layer".to_string(), AssoElement::Test);
AppMsg::LayerManager(LayerMsg::Add(layer)) AppMsg::LayerManager(LayerMsg::Add(layer))
} }
@ -425,8 +428,9 @@ impl AppModel {
.load(RStr::from_str(path.as_ref().to_str().unwrap())) .load(RStr::from_str(path.as_ref().to_str().unwrap()))
.unwrap(); .unwrap();
let block = result.blocks.first().unwrap(); let block = result.blocks.first().unwrap();
data_to_element(block, dispatcher, cms) // data_to_element(block, dispatcher, cms)
.map(|v| (Some(Box::new(result) as Box<dyn Any + Send + Sync>), v)) // .map(|v| (Some(Box::new(result) as Box<dyn Any + Send + Sync>), v))
None
} }
fn open_file_only(path: impl AsRef<std::path::Path>) -> PluginResult { fn open_file_only(path: impl AsRef<std::path::Path>) -> PluginResult {

View File

@ -1,4 +1,5 @@
use crate::coords::Mapper; use crate::coords::Mapper;
use epoxy::XOR;
use geo_types::LineString; use geo_types::LineString;
use std::ops::Range; use std::ops::Range;
@ -48,6 +49,18 @@ impl CMS {
}) })
} }
pub fn fore_map(&self, loc: (f32, f32)) -> Option<(f64, f64)> {
let (x, y) = loc;
let (x, y) = (x as f64, y as f64);
let (x, y) = (
self.bounds.0 + x * (self.bounds.1 - self.bounds.0),
self.bounds.1 + y * (self.bounds.3 - self.bounds.2),
);
self.mapper.inverse_map((x, y)).ok()
}
pub fn ring_map(&self, line: &LineString) -> Option<LineString<f32>> { pub fn ring_map(&self, line: &LineString) -> Option<LineString<f32>> {
Some( Some(
line.points() line.points()

View File

@ -18,6 +18,20 @@ pub type Radar2dRef<'a, T> = RadarData2d<T, ViewRepr<&'a T>, ViewRepr<&'a f64>,
pub type Radar3dRef<'a, T> = pub type Radar3dRef<'a, T> =
RadarData3d<T, ViewRepr<&'a T>, ViewRepr<&'a f64>, ViewRepr<&'a f64>, ViewRepr<&'a f64>>; RadarData3d<T, ViewRepr<&'a T>, ViewRepr<&'a f64>, ViewRepr<&'a f64>, ViewRepr<&'a f64>>;
#[derive(Debug, Clone, Copy)]
pub enum DataType {
F64,
I64,
U64,
F32,
I32,
U32,
I16,
U16,
I8,
U8,
}
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub enum CoordType { pub enum CoordType {
Polar, Polar,

View File

@ -1,44 +1,33 @@
use crate::pipeline::element::ElementImpl; use crate::pipeline::element_imp::*;
use crate::pipeline::GridElementImpl;
use crate::utils::*; use crate::utils::*;
use radarg_plugin_interface::{CoordType, DataShape, PluginResult, PluginResultType}; use radarg_plugin_interface::{CoordType, DataShape, PluginResult, PluginResultType};
use std::any::Any;
use std::sync::Arc; use std::sync::Arc;
macro_rules! data_to_grid {
($_type:ident,$(($branch:path ,$boundary_norm: expr)),+) => { pub fn tools(data: &PluginResult) -> ElementImpl {
match $_type { let blocks_num = data.blocks.len();
$(
$branch => { if blocks_num == 0 {
let element_impl = GridElementImpl::new($boundary_norm); panic!("No blocks found");
Arc::new(element_impl)
}
),+
_ => panic!("Invalid type")
} }
}; if blocks_num > 1 {
} panic!("Too many blocks found");
pub fn plugin_result_impl(a: &PluginResult) -> Arc<dyn ElementImpl> { }
let block = a.blocks.first().unwrap();
let block = data.blocks.first().unwrap();
match block.coord_type { match block.coord_type {
CoordType::Cartesian => { CoordType::Polar => {
let _type = block.data_type; todo!();
data_to_grid!(
_type,
(PluginResultType::R, create_dbz_boundarynorm()),
(PluginResultType::V, create_vel_boundarynorm()),
(PluginResultType::CC, create_cc_boundarynorm()),
(PluginResultType::ZDR, create_zdr_boundarynorm()),
(PluginResultType::PHIDP, create_phidp_boundarynorm()),
(PluginResultType::KDP, create_kdp_boundarynorm()),
(PluginResultType::DBZ, create_dbz_boundarynorm()),
(PluginResultType::VIL, create_vil_boundarynorm()),
(PluginResultType::OHP, create_vil_boundarynorm()),
(PluginResultType::THP, create_vil_boundarynorm()),
(PluginResultType::ET, create_et_boundarynorm())
)
} }
CoordType::Other | CoordType::Polar => { CoordType::Cartesian => match block.shape {
panic!("Invalid type"); DataShape::Cube => MultiLayerGridImp().into(),
DataShape::Matrix => GridImp().into(),
_ => panic!("Invalid shape"),
},
_ => {
panic!("Invalid type")
} }
} }
} }

View File

@ -34,6 +34,7 @@ mod map_tile;
mod map_tile_utils; mod map_tile_utils;
mod predefined; mod predefined;
mod widgets; mod widgets;
// mod element_imp;
#[cfg(target_env = "msvc")] #[cfg(target_env = "msvc")]
declare_surfman!(); declare_surfman!();

351
src/pipeline/element_imp.rs Normal file
View File

@ -0,0 +1,351 @@
use super::Target;
use crate::coords::cms::CMS;
use crate::data::Radar2dRef;
use crate::pipeline::offscreen_renderer::CanvasWrapper;
use crate::predefined::color_mapper::{CMap, ColorMapper, ColorMapperComb, VMap};
use abi_stable::std_types::RVec;
use femtovg::{Paint, Path};
use ndarray::{ArrayBase, ArrayView1, ArrayView2, ArrayViewD, Axis, Ix2, Ix3};
use num_traits::{AsPrimitive, FromPrimitive, Num, NumOps};
use radarg_plugin_interface::{DataShape, PluginResult, VecResult};
use std::any::Any;
use std::fmt::Debug;
const EARTH_RADIUS: f64 = 6371.0;
macro_rules! impl_element_imp_dispatch {
($({$Abc: ident, $t:ty},)+) => {
impl ElementImpl {
pub fn process<T>(&self,
dims: (ArrayView2<f64>, ArrayView2<f64>),
input: ArrayViewD<'_, T>,
config: &dyn Any,
context: &mut Context
)
where
T: Sync + Send + Debug + PartialOrd + PartialEq + Copy + Clone + 'static,
{
match self {
$(
Self::$Abc(imp) => {
let config = config.downcast_ref::<<$t as ElementImp>::Config<T>>().unwrap();
imp.process(dims, input, config, context);
}
)+
}
}
}
};
}
macro_rules! impl_element_try_from_dispatch {
($({ $Abc: ident, $t:ty},)+) => {
$(
impl TryFrom<ElementImpl> for $t {
type Error = &'static str;
fn try_from(value: ElementImpl) -> Result<Self, Self::Error> {
match value {
ElementImpl::$Abc(imp) => Ok(imp),
_ => Err("Invalid type"),
}
}
}
)+
};
}
macro_rules! impl_element_into_dispatch {
($({ $Abc: ident, $t:ty},)+) => {
$(
impl From<$t> for ElementImpl {
fn from(value: $t) -> Self {
Self::$Abc(value)
}
}
)+
};
}
macro_rules! for_all_variants {
($macro: tt) => {
$macro! {
{Grid, GridImp},
{MultiLayerGrid, MultiLayerGridImp},
{Polar, PolarElementImp},
}
};
}
pub struct Context {
cms: CMS,
canvas: CanvasWrapper,
}
pub trait ElementImp: Debug + TryFrom<ElementImpl> + Into<ElementImpl> {
type Config<T: Sync + Send + Debug + PartialOrd + PartialEq>;
fn process<T>(
&self,
dims: (ArrayView2<f64>, ArrayView2<f64>),
input: ArrayViewD<'_, T>,
config: &Self::Config<T>,
context: &mut Context,
) where
T: Sync + Send + Debug + PartialOrd + PartialEq + Copy + Clone;
}
#[derive(Debug)]
pub struct GridImp();
pub struct GridImpConfig<T>
where
T: PartialOrd + PartialEq + Send + Sync + Debug,
{
color_map: ColorMapperComb<T>,
}
impl GridImp {
fn draw_2d<T>(
&self,
config: &GridImpConfig<T>,
data: ArrayView2<T>,
dims: (ArrayView2<f64>, ArrayView2<f64>),
context: &mut Context,
) where
T: PartialEq + PartialOrd + Copy + Clone + Send + Sync + Debug,
{
let cms = &context.cms;
let canvas = &mut context.canvas;
let shape = data.shape();
let mapper = &config.color_map;
let (rows, cols) = (shape[0], shape[1]);
let (dim1, dim2) = dims;
let d1_s = dim1[[0, 0]];
let d1_e = dim1[[0, cols - 1]];
let d2_s = dim2[[0, 0]];
let d2_e = dim2[[rows - 1, 0]];
for r in 0..rows - 1 {
for c in 0..cols - 1 {
let lb_lat = dim2[[r, c]];
let lb_lon = dim1[[r, c]];
let rt_lat = dim2[[r + 1, c + 1]];
let rt_lon = dim1[[r + 1, c + 1]];
let v = &data[[r, c]];
let mapped_color = mapper.color(*v);
if mapped_color.is_none() {
continue;
}
let (ox, oy) = cms.map((lb_lon, lb_lat)).unwrap();
let (rx, ry) = cms.map((rt_lon, rt_lat)).unwrap();
let mut path = Path::new();
path.rect(ox, oy, (rx - ox) * 1.5, (ry - oy) * 1.5);
canvas.fill_path(&path, &Paint::color(mapped_color.unwrap()));
}
}
}
}
impl ElementImp for GridImp {
type Config<T: Sync + Send + Debug + PartialOrd + PartialEq> = GridImpConfig<T>;
fn process<T>(
&self,
dims: (ArrayView2<f64>, ArrayView2<f64>),
input: ArrayViewD<'_, T>,
config: &Self::Config<T>,
context: &mut Context,
) where
T: Send + Sync + Debug + PartialOrd + PartialEq + Copy + Clone,
{
let shape = input.shape();
if shape.len() == 2 {
let data = input.into_dimensionality::<Ix2>().unwrap();
let target = self.draw_2d(config, data, dims, context);
} else if shape.len() == 3 {
let data = input.into_dimensionality::<Ix3>().unwrap();
}
}
}
#[derive(Debug)]
pub struct MultiLayerGridImp();
pub struct MultiLayerGridImpConfig<T>
where
T: PartialOrd + PartialEq + Send + Sync + Debug,
{
twod: GridImp,
two_d_config: GridImpConfig<T>,
layer: usize,
}
impl ElementImp for MultiLayerGridImp {
type Config<T: Sync + Send + Debug + PartialOrd + PartialEq> = MultiLayerGridImpConfig<T>;
fn process<T>(
&self,
dims: (ArrayView2<f64>, ArrayView2<f64>),
input: ArrayViewD<'_, T>,
config: &Self::Config<T>,
context: &mut Context,
) where
T: Sync + Send + Debug + PartialOrd + PartialEq + Copy + Clone,
{
let data = input.into_dimensionality::<Ix3>().unwrap();
let layer = config.layer;
let layer_data = data.index_axis(Axis(0), layer);
config
.twod
.process(dims, layer_data.into_dyn(), &config.two_d_config, context);
}
}
#[derive(Debug)]
pub struct PolarElementImp();
pub struct PolarElementConfig<T>
where
T: PartialOrd + PartialEq + Send + Sync + Debug,
{
color_map: ColorMapperComb<T>,
center: (f64, f64),
}
impl PolarElementImp {
fn closest_value(&self, x: f64, dpi: f64) -> f64 {
let n_floor = (x / dpi).floor() as i64;
let value_at_n_floor = n_floor as f64 * dpi;
let value_at_n_floor_plus_one = (n_floor + 1) as f64 * dpi;
if (x - value_at_n_floor).abs() < (value_at_n_floor_plus_one - x).abs() {
value_at_n_floor
} else {
value_at_n_floor_plus_one
}
}
fn map_to_polar(
&self,
center: (f64, f64),
dpi: (f64, f64),
max_r: f64,
point: (f64, f64),
) -> Option<(f64, f64)> {
let (center_lon, center_lat) = center;
let (lon, lat) = point;
let center_lon_rad = center_lon.to_radians();
let center_lat_rad = center_lat.to_radians();
let lon_rad = lon.to_radians();
let lat_rad = lat.to_radians();
let delta_lat = lat_rad - center_lat_rad;
let delta_lon = lon_rad - center_lon_rad;
let a = (delta_lat / 2.0).sin().powi(2)
+ center_lat_rad.cos() * lat_rad.cos() * (delta_lon / 2.0).sin().powi(2);
let c = 2.0 * a.sqrt().atan2((1.0 - a).sqrt());
let distance = EARTH_RADIUS * c * 1000.0;
if distance > max_r + dpi.1 {
return None;
}
let x = delta_lon.cos() * lat_rad.sin();
let y = center_lat_rad.cos() * lat_rad.sin()
- center_lat_rad.sin() * lat_rad.cos() * delta_lon.cos();
let ori_degree = y.atan2(x).to_degrees();
let degree = (ori_degree + 360.0) % 360.0;
let distance_dpi = dpi.1;
let degree_dpi = dpi.0;
let final_degree = self.closest_value(degree, degree_dpi);
let final_distance = self.closest_value(distance, distance_dpi);
Some((final_degree, final_distance))
}
fn draw<T>(
&self,
dims: (ArrayView2<f64>, ArrayView2<f64>),
center: (f64, f64),
data: ArrayView2<T>,
config: &PolarElementConfig<T>,
context: &mut Context,
) where
T: PartialOrd + PartialEq + Send + Sync + Debug + Copy,
{
let canvas = &mut context.canvas;
let mapper = &context.cms;
let start_point = mapper.fore_map((0.0, 0.0));
let dpi = (
dims.0[[0, 1]] - dims.0[[0, 0]],
dims.1[[1, 1]] - dims.1[[1, 0]],
);
let (azs, rs) = dims;
let (w, h) = (canvas.width(), canvas.height());
for x in 0..w {
for y in 0..h {
let map_point = mapper.fore_map((x as f32 / w as f32, y as f32 / h as f32));
if map_point.is_none() {
continue;
}
if let Some((_x, _y)) = self.map_to_polar(center, dpi, 0.0, map_point.unwrap()) {
let (_x, _y) = (_x as usize, _y as usize);
let value = data[[_x, _y]];
let color = config.color_map.color(value);
if color.is_none() {
continue;
}
let mut path = Path::new();
path.rect(x as f32, y as f32, 1.0, 1.0);
canvas.fill_path(&path, &Paint::color(color.unwrap()));
}
}
}
}
}
impl ElementImp for PolarElementImp {
type Config<T: Sync + Send + Debug + PartialOrd + PartialEq> = PolarElementConfig<T>;
fn process<T>(
&self,
dims: (ArrayView2<f64>, ArrayView2<f64>),
input: ArrayViewD<'_, T>,
config: &Self::Config<T>,
context: &mut Context,
) where
T: Sync + Send + Debug + PartialOrd + PartialEq + Copy + Clone,
{
let shape = input.shape();
if shape.len() == 2 {
let data = input.into_dimensionality::<Ix2>().unwrap();
self.draw(dims, config.center, data, config, context);
} else if shape.len() == 3 {
let data = input.into_dimensionality::<Ix3>().unwrap();
}
}
}
#[derive(Debug)]
pub enum ElementImpl {
Grid(GridImp),
MultiLayerGrid(MultiLayerGridImp),
Polar(PolarElementImp),
}
for_all_variants!(impl_element_into_dispatch);
for_all_variants!(impl_element_try_from_dispatch);
for_all_variants!(impl_element_imp_dispatch);

View File

@ -1,14 +1,17 @@
pub mod dispatcher; pub mod dispatcher;
pub mod element; pub mod element;
mod element_impl; // mod element_impl;
// mod new_element;
// mod new_element_impl;
mod new_pipeline; mod new_pipeline;
pub mod offscreen_renderer; pub mod offscreen_renderer;
mod predefined; // mod predefined;
pub mod element_imp;
mod renders; mod renders;
pub mod utils; // pub mod utils;
pub use dispatcher::Dispatcher; pub use dispatcher::Dispatcher;
pub use element::*; pub use element::*;
pub use element_impl::*; // pub use element_impl::*;
pub use new_pipeline::Pipeline; pub use new_pipeline::Pipeline;
pub use offscreen_renderer::OffscreenRenderer; pub use offscreen_renderer::OffscreenRenderer;

196
src/pipeline/new_element.rs Normal file
View File

@ -0,0 +1,196 @@
use super::dispatcher;
use super::new_element_impl::ElementConfig;
use super::new_element_impl::ElementImp;
use super::offscreen_renderer::CanvasWrapper;
use super::Dispatcher;
use super::RenderResult;
use super::Target;
use crate::coords::cms::CMS;
use crate::pipeline::OffscreenRenderer;
use crate::PLUGIN_MANAGER;
use chrono::prelude::*;
use num_traits::AsPrimitive;
use num_traits::FromPrimitive;
use num_traits::Num;
use num_traits::NumOps;
use quick_cache::sync::Cache;
use radarg_plugin_interface::PluginResult;
use std::any::Any;
use std::collections::HashMap;
use std::fmt::Debug;
use std::hash::Hash;
use std::rc::Rc;
use std::sync::atomic::AtomicI32;
use std::sync::Arc;
use std::sync::RwLock;
use std::time::Duration;
use tokio::sync::oneshot;
use tokio::sync::{mpsc, Mutex};
static ELEMENT_ID: AtomicI32 = AtomicI32::new(0);
pub type ElementID = i32;
pub type Buffer<T> = Cache<T, Arc<Mutex<RenderResult>>>;
pub struct Element<T: Eq + Hash + Send + Clone + Copy + 'static, V>
where
V: Num + NumOps + PartialOrd + FromPrimitive + AsPrimitive<f64> + Send + Sync + Debug,
{
pub id: i32,
pub name: String,
pub description: String,
imp: Arc<ElementImp<V>>,
buffer: Arc<Mutex<Buffer<T>>>,
config: Arc<RwLock<Box<ElementConfig>>>,
subscribers: Arc<Mutex<HashMap<T, Vec<oneshot::Sender<Arc<Mutex<Vec<u8>>>>>>>>,
cancellers: Arc<Mutex<HashMap<T, oneshot::Sender<()>>>>,
dispatcher: Rc<Dispatcher>,
cms: Arc<Mutex<CMS>>,
}
impl<T: Eq + Hash + Send + Clone + Copy + 'static, V> Element<T, V>
where
V: Num + NumOps + PartialOrd + FromPrimitive + AsPrimitive<f64> + Send + Sync + Debug,
{
pub fn new(
name: String,
description: String,
imp: ElementImp<V>,
config: Box<ElementConfig>,
cms: CMS,
dispatcher: Rc<Dispatcher>,
) -> Self {
let id = ELEMENT_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
Element {
id,
name,
description,
imp: Arc::new(imp),
buffer: Arc::new(Mutex::new(Buffer::new(100))),
subscribers: Arc::new(Mutex::new(HashMap::new())),
config: Arc::new(RwLock::new(config)),
cancellers: Arc::new(Mutex::new(HashMap::new())),
cms: Arc::new(Mutex::new(cms)),
dispatcher,
}
}
pub fn new_with_buffer(
name: String,
description: String,
imp: ElementImp<V>,
buffer: Buffer<T>,
config: Box<ElementConfig>,
cms: CMS,
dispatcher: Rc<Dispatcher>,
) -> Self {
let id = ELEMENT_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
Element {
id,
name,
description,
imp: Arc::new(imp),
buffer: Arc::new(Mutex::new(buffer)),
subscribers: Arc::new(Mutex::new(HashMap::new())),
config: Arc::new(RwLock::new(config)),
cancellers: Arc::new(Mutex::new(HashMap::new())),
cms: Arc::new(Mutex::new(cms)),
dispatcher,
}
}
pub async fn get(&self, key: T) -> Arc<Mutex<RenderResult>> {
{
let cache = self.buffer.lock().await;
if cache.peek(&key).is_some() {
return cache.get(&key).unwrap();
}
}
{
let mut subscribers = self.subscribers.lock().await;
let (tx, rx) = oneshot::channel();
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, vec![tx]);
drop(subscribers);
{
let mut cancellers = self.cancellers.lock().await;
cancellers.insert(key, canceller_tx);
}
let buffer = self.buffer.clone();
let config = self.config.clone();
let imp = self.imp.clone();
let cancellers = self.cancellers.clone();
let subscribers = self.subscribers.clone();
use tokio::task;
tokio::spawn(async move {
tokio::select! {
_ = async move {
tokio::time::sleep(Duration::new(5, 0)).await;
let handle = task::spawn_blocking(move || {
let config = config.read().unwrap();
let config: &ElementConfig = &*(*config);
let loader = PLUGIN_MANAGER.get_plugin_by_name("etws_loader").unwrap();
let mut loaded_data = loader.load(path.as_ref().into()).unwrap();
let meta = loaded_data.meta.clone().into();
let mut offscreen_renderer = OffscreenRenderer::new(3000, 3000).unwrap();
// imp.render()
});
let result = handle.await.unwrap();
{
let bf = Arc::new(Mutex::new(result));
buffer.lock().await.insert(key, bf.clone());
let mut subscribers = subscribers.lock().await;
for tx in subscribers.remove(&key).unwrap() {
let _ = tx.send(bf.clone());
}
}
} => {}
_ = canceller_rx => {}
}
let mut cancellers = cancellers.lock().await;
cancellers.remove(&key);
});
}
rx.await.unwrap()
}
}
pub async fn cancel_task_for_timestamp(&self, key: T) {
let mut cancellers = self.cancellers.lock().await;
if let Some(canceller) = cancellers.remove(&key) {
let _ = canceller.send(()); // 发送取消信号
}
}
pub async fn cancel_all_tasks(&self) {
let mut cancellers = self.cancellers.lock().await;
for (_timestamp, canceller) in cancellers.drain() {
let _ = canceller.send(()); // 发送取消信号
}
}
}
pub trait ElementImpl: Debug + Send + Sync + 'static {
type Config;
fn render(
&self,
data: &PluginResult,
canvas: &mut CanvasWrapper,
cms: &mut CMS,
config: &Self::Config,
) -> Target;
}

View File

@ -0,0 +1,104 @@
use super::{
new_element::ElementImpl, offscreen_renderer::CanvasWrapper, predefined::GridFieldRenderer,
renders::DataRenderer, Target,
};
use crate::{
data::{Radar2d, Radar3d},
predefined::color_mapper::{BoundaryNorm, ColorMapper},
};
use num_traits::{AsPrimitive, FromPrimitive, Num, NumOps};
use radarg_plugin_interface::{DataShape, PluginResult};
use std::{any::Any, fmt::Debug, marker::PhantomData};
macro_rules! create_element_imp {
($imp: expr) => {{
let c: ElementImp = $imp.into();
c
}};
}
macro_rules! element {
($generic:ident,$(($branch:tt,$imp:ty)),+) => {
pub(super) type ElementConfig = dyn Any + Send + Sync + 'static;
pub enum ElementImp<$generic>
where
$generic: NumOps + PartialOrd + FromPrimitive + AsPrimitive<f64> + Send + Sync + Debug,
{
$(
$branch($imp),
)+
}
impl<$generic> ElementImp<$generic>
where
$generic: Num + NumOps + PartialOrd + FromPrimitive + AsPrimitive<f64> + Send + Sync + Debug,
{
pub fn render(
&self,
data: &PluginResult,
canvas: &mut CanvasWrapper,
cms: &mut crate::coords::cms::CMS,
config: &ElementConfig) -> Target
{
match self {
$(
ElementImp::$branch(imp) => imp.render(data,canvas,cms,config.downcast_ref::<<$imp as ElementImpl>::Config>().unwrap()),
)+
}
}
}
$(
impl<$generic> From<$imp> for ElementImp<$generic>
where
$generic: NumOps + PartialOrd + FromPrimitive + AsPrimitive<f64> + Send + Sync + Debug,
{
fn from(imp: $imp) -> Self {
ElementImp::$branch(imp)
}
}
)+
};
}
// element!(T, (Grid, GridElementImpl<T>));
#[derive(Debug)]
pub struct GridElementImpl {}
impl GridElementImpl {
pub fn new() -> Self {
Self {}
}
}
impl ElementImpl for GridElementImpl {
type Config = GridFieldRenderer<BoundaryNorm<T>, T>;
fn render(
&self,
data: &PluginResult,
canvas: &mut CanvasWrapper,
cms: &mut crate::coords::cms::CMS,
config: &Self::Config<T>,
) -> super::Target {
let first_block = data.blocks.first().unwrap();
match first_block.shape {
DataShape::Vector => {
panic!("Vector data is not supported")
}
DataShape::Matrix => {
let data: Radar2d<T> = first_block.clone().into();
let data = data.as_ref();
let result = config.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 = config.render(canvas, cms, &data, (3000.0, 3000.0));
result
}
}
}
}

View File

@ -2,7 +2,7 @@ use super::{
dispatcher::Dispatcher, dispatcher::Dispatcher,
element::{DataTarget, RenderResult}, element::{DataTarget, RenderResult},
offscreen_renderer::{CanvasWrapper, OffscreenRenderer}, offscreen_renderer::{CanvasWrapper, OffscreenRenderer},
utils::data_to_element, // utils::data_to_element,
}; };
use crate::coords::cms::CMS; use crate::coords::cms::CMS;
use crate::pipeline::element::Target; use crate::pipeline::element::Target;

View File

@ -1,4 +1,4 @@
use super::utils::*; // use super::utils::*;
use crate::pipeline::element::Target; use crate::pipeline::element::Target;
use euclid::Size2D; use euclid::Size2D;
use femtovg::{renderer::OpenGl, Canvas}; use femtovg::{renderer::OpenGl, Canvas};

View File

@ -1,117 +1,236 @@
use std::fmt::Debug; use std::fmt::Debug;
use femtovg::Color; use femtovg::Color;
use image::imageops::ColorMap;
use num_traits::{AsPrimitive, FromPrimitive, NumOps}; use num_traits::{AsPrimitive, FromPrimitive, NumOps};
pub trait ColorMapper<T: NumOps + PartialOrd + FromPrimitive + AsPrimitive<f64>>:
Debug + Send + Sync type BoundaryNormDiscrete<T> = ColorMapper<T, Discrete, BoundaryNorm<T>>;
macro_rules! color_mapper_comb {
($comb: ident, $($key: tt,)+) => {
impl<T: PartialEq + PartialOrd + Debug> $comb<T> {
pub fn color(&self, value: T) -> Option<femtovg::Color> {
match self {
$(
Self::$key(mapper) => mapper.color(value),
)+
}
}
}
};
}
pub enum ColorMapperComb<T: PartialEq + PartialOrd + Debug> {
BoundaryNormDiscrete(BoundaryNormDiscrete<T>),
}
color_mapper_comb!(ColorMapperComb, BoundaryNormDiscrete,);
pub trait VMap {
type Ty;
fn map(&self, v: Self::Ty) -> Option<f32>;
}
pub trait CMap {
fn map(&self, v: f32) -> femtovg::Color;
}
pub struct ColorMapper<T, CMAP, VMAP>
where
CMAP: CMap,
VMAP: VMap<Ty = T>,
{ {
fn map_value_to_color(&self, value: T, invalid: T) -> Option<femtovg::Color>; cmap: CMAP,
vmap: VMAP,
fn map_min_to_max(&self) -> Vec<femtovg::Color>;
fn labels(&self) -> Vec<String>;
fn min_max(&self) -> (T, T);
fn invalid(&self) -> T;
} }
#[derive(Debug, Clone)] impl<T, CMAP, VMAP> ColorMapper<T, CMAP, VMAP>
pub struct BoundaryNorm<T: NumOps + PartialOrd> { where
T: PartialEq + PartialOrd,
CMAP: CMap,
VMAP: VMap<Ty = T>,
{
pub fn new(cmap: CMAP, vmap: VMAP) -> Self {
Self { cmap, vmap }
}
pub fn color(&self, value: T) -> Option<femtovg::Color> {
self.vmap.map(value).map(|v| self.cmap.map(v))
}
}
#[derive(Debug)]
pub struct BoundaryNorm<T: PartialOrd + PartialEq> {
boundaries: Vec<T>, boundaries: Vec<T>,
extrand: bool, extrand: bool,
colors: Vec<femtovg::Color>, invalid_value: Option<T>,
invalid_value: T,
} }
impl<T> VMap for BoundaryNorm<T>
impl Default for BoundaryNorm<i8> { where
fn default() -> Self { T: PartialOrd + PartialEq + Debug,
Self { {
boundaries: vec![0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65], type Ty = T;
extrand: true, fn map(&self, v: Self::Ty) -> Option<f32> {
colors: 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),
],
invalid_value: -125,
}
}
}
impl<T: NumOps + PartialOrd> BoundaryNorm<T> {
pub fn new(
boundaries: Vec<T>,
colors: Vec<femtovg::Color>,
extrand: bool,
invalid_value: T,
) -> Self {
// assert_eq!(boundaries.len(), colors.len() + 1);
BoundaryNorm {
boundaries,
extrand,
colors,
invalid_value,
}
}
pub fn map_value_to_color(&self, value: T, invalid_value: T) -> Option<femtovg::Color> {
let mut index = 0; let mut index = 0;
if value == invalid_value { if let Some(invalid_value) = &self.invalid_value {
if v == *invalid_value {
return None; return None;
} }
}
for (i, boundary) in self.boundaries.iter().enumerate() { for (i, boundary) in self.boundaries.iter().enumerate() {
if value < *boundary { if v < *boundary {
break; break;
} }
index = i; index = i;
} }
index = index.saturating_sub(1).min(self.colors.len() - 1);
Some(self.colors[index]) Some(index as f32 / self.boundaries.len() as f32)
} }
} }
impl<T> ColorMapper<T> for BoundaryNorm<T> #[derive(Debug)]
where pub struct Gradient {}
T: NumOps + PartialOrd + FromPrimitive + AsPrimitive<f64> + Send + Sync + Debug,
{
fn map_value_to_color(&self, value: T, invalid_value: T) -> Option<femtovg::Color> {
self.map_value_to_color(value, invalid_value)
}
fn min_max(&self) -> (T, T) { #[derive(Debug)]
( pub struct Discrete {
self.boundaries.first().unwrap().clone(), colors: Vec<femtovg::Color>,
self.boundaries.last().unwrap().clone(), }
)
}
fn invalid(&self) -> T { impl CMap for Discrete {
self.invalid_value.clone() fn map(&self, v: f32) -> Color {
} let size = (self.colors.len() as f32 * v) as usize;
self.colors.get(size).unwrap().clone()
fn map_min_to_max(&self) -> Vec<femtovg::Color> {
self.boundaries
.iter()
.map(|x| self.map_value_to_color(*x, self.invalid_value).unwrap())
.collect()
}
fn labels(&self) -> Vec<String> {
self.boundaries
.iter()
.map(|x| format!("{:.2}", x.as_()))
.collect()
} }
} }
// #[derive(Debug, Clone)]
// pub struct BoundaryNorm<T: NumOps + PartialOrd> {
// boundaries: Vec<T>,
// extrand: bool,
// colors: Vec<femtovg::Color>,
// invalid_value: T,
// }
//
// impl Default for BoundaryNorm<i8> {
// fn default() -> Self {
// Self {
// boundaries: vec![0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65],
// extrand: true,
// colors: 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),
// ],
// invalid_value: -125,
// }
// }
// }
//
// impl<T: NumOps + PartialOrd> BoundaryNorm<T> {
// pub fn new(
// boundaries: Vec<T>,
// colors: Vec<femtovg::Color>,
// extrand: bool,
// invalid_value: T,
// ) -> Self {
// // assert_eq!(boundaries.len(), colors.len() + 1);
// BoundaryNorm {
// boundaries,
// extrand,
// colors,
// invalid_value,
// }
// }
//
// pub fn map_value_to_color(&self, value: f64, invalid_value: f64) -> Option<femtovg::Color> {
// let mut index = 0;
// if value == invalid_value {
// return None;
// }
// for (i, boundary) in self.boundaries.iter().enumerate() {
// if value < *boundary {
// break;
// }
// index = i;
// }
// index = index.saturating_sub(1).min(self.colors.len() - 1);
// Some(self.colors[index])
// }
// }
//
// impl<T> ColorMapper for BoundaryNorm<T>
// where
// T: NumOps + PartialOrd + FromPrimitive + AsPrimitive<f64> + Send + Sync + Debug,
// {
//
// type Ty<V> = T;
// fn map_value_to_color<T>(&self, value: Self::Ty<T>, invalid_value: Self::Ty<T>) -> Option<femtovg::Color> {
// self.map_value_to_color(value, invalid_value)
// }
//
// fn min_max(&self) -> (f64, f64) {
// (
// self.boundaries.first().unwrap().clone().as_(),
// self.boundaries.last().unwrap().clone().as_(),
// )
// }
//
// fn invalid(&self) -> f64 {
// self.invalid_value.clone().as_()
// }
//
// fn map_min_to_max(&self) -> Vec<femtovg::Color> {
// self.boundaries
// .iter()
// .map(|x| self.map_value_to_color(*x, self.invalid_value).unwrap())
// .collect()
// }
// }
// pub struct BoundaryNorm();
//
// impl ColorMapper for BoundaryNorm {
// type Ty<T> = T;
// fn map_value_to_color<T>(&self, value: Self::Ty<T>, invalid: T) -> Option<femtovg::Color> {
// let mut index = 0;
// if value == invalid_value {
// return None;
// }
// for (i, boundary) in self.boundaries.iter().enumerate() {
// if value < *boundary {
// break;
// }
// index = i;
// }
// index = index.saturating_sub(1).min(self.colors.len() - 1);
// Some(self.colors[index])
// }
//
// fn map_min_to_max(&self) -> Vec<femtovg::Color> {
// vec![]
// }
//
// fn min_max(&self) -> (f64, f64) {
// (0.0, 0.0)
// }
//
// fn invalid(&self) -> f64 {
// 0.0
// }
// }

View File

@ -31,272 +31,272 @@ where
(xx, yy) (xx, yy)
} }
pub fn create_dbz_boundarynorm() -> BoundaryNorm<i8> { // pub fn create_dbz_boundarynorm() -> BoundaryNorm<i8> {
BoundaryNorm::new( // BoundaryNorm::new(
vec![ // vec![
-5, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, // -5, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75,
], // ],
vec![ // vec![
Color::rgb(23, 174, 165), // Color::rgb(23, 174, 165),
Color::rgb(198, 195, 253), // Color::rgb(198, 195, 253),
Color::rgb(124, 114, 236), // Color::rgb(124, 114, 236),
Color::rgb(1, 160, 246), // Color::rgb(1, 160, 246),
Color::rgb(0, 236, 236), // Color::rgb(0, 236, 236),
Color::rgb(0, 216, 0), // Color::rgb(0, 216, 0),
Color::rgb(1, 144, 0), // Color::rgb(1, 144, 0),
Color::rgb(255, 255, 0), // Color::rgb(255, 255, 0),
Color::rgb(231, 192, 0), // Color::rgb(231, 192, 0),
Color::rgb(255, 144, 0), // Color::rgb(255, 144, 0),
Color::rgb(255, 0, 0), // Color::rgb(255, 0, 0),
Color::rgb(214, 0, 0), // Color::rgb(214, 0, 0),
Color::rgb(192, 0, 0), // Color::rgb(192, 0, 0),
Color::rgb(255, 0, 240), // Color::rgb(255, 0, 240),
Color::rgb(150, 0, 180), // Color::rgb(150, 0, 180),
Color::rgb(139, 0, 255), // Color::rgb(139, 0, 255),
], // ],
true, // true,
-125, // -125,
) // )
} // }
pub fn create_vel_boundarynorm() -> BoundaryNorm<f32> { // pub fn create_vel_boundarynorm() -> BoundaryNorm<f32> {
BoundaryNorm::new( // BoundaryNorm::new(
vec![ // vec![
-35.0, -27.0, -20.0, -15.0, -10.0, -5.0, -1.0, 0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 27.0, // -35.0, -27.0, -20.0, -15.0, -10.0, -5.0, -1.0, 0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 27.0,
35.0, // 35.0,
], // ],
vec![ // vec![
Color::rgb(0, 224, 255), // Color::rgb(0, 224, 255),
Color::rgb(0, 128, 255), // Color::rgb(0, 128, 255),
Color::rgb(50, 0, 150), // Color::rgb(50, 0, 150),
Color::rgb(0, 251, 144), // Color::rgb(0, 251, 144),
Color::rgb(0, 187, 144), // Color::rgb(0, 187, 144),
Color::rgb(0, 143, 0), // Color::rgb(0, 143, 0),
Color::rgb(205, 192, 159), // Color::rgb(205, 192, 159),
Color::rgb(255, 255, 255), // Color::rgb(255, 255, 255),
Color::rgb(248, 135, 0), // Color::rgb(248, 135, 0),
Color::rgb(255, 207, 0), // Color::rgb(255, 207, 0),
Color::rgb(255, 255, 0), // Color::rgb(255, 255, 0),
Color::rgb(174, 0, 0), // Color::rgb(174, 0, 0),
Color::rgb(208, 112, 0), // Color::rgb(208, 112, 0),
Color::rgb(255, 0, 0), // Color::rgb(255, 0, 0),
], // ],
true, // true,
-125.0, // -125.0,
) // )
} // }
pub fn create_phidp_boundarynorm() -> BoundaryNorm<f32> { // pub fn create_phidp_boundarynorm() -> BoundaryNorm<f32> {
BoundaryNorm::new( // BoundaryNorm::new(
vec![ // 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, // 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, // 292.0, 314.0, 359.0,
], // ],
vec![ // vec![
Color::rgb(0, 60, 255), // Color::rgb(0, 60, 255),
Color::rgb(0, 239, 239), // Color::rgb(0, 239, 239),
Color::rgb(0, 186, 191), // Color::rgb(0, 186, 191),
Color::rgb(0, 131, 125), // Color::rgb(0, 131, 125),
Color::rgb(0, 137, 56), // Color::rgb(0, 137, 56),
Color::rgb(0, 183, 41), // Color::rgb(0, 183, 41),
Color::rgb(0, 218, 13), // Color::rgb(0, 218, 13),
Color::rgb(0, 255, 0), // Color::rgb(0, 255, 0),
Color::rgb(255, 255, 59), // Color::rgb(255, 255, 59),
Color::rgb(255, 240, 0), // Color::rgb(255, 240, 0),
Color::rgb(255, 198, 0), // Color::rgb(255, 198, 0),
Color::rgb(255, 165, 0), // Color::rgb(255, 165, 0),
Color::rgb(255, 114, 0), // Color::rgb(255, 114, 0),
Color::rgb(255, 31, 0), // Color::rgb(255, 31, 0),
Color::rgb(193, 0, 0), // Color::rgb(193, 0, 0),
], // ],
true, // true,
-125.0, // -125.0,
) // )
} // }
pub fn create_zdr_boundarynorm() -> BoundaryNorm<f32> { // pub fn create_zdr_boundarynorm() -> BoundaryNorm<f32> {
BoundaryNorm::new( // BoundaryNorm::new(
vec![ // 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, // -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![ // vec![
Color::rgb(70, 70, 70), // Color::rgb(70, 70, 70),
Color::rgb(80, 80, 80), // Color::rgb(80, 80, 80),
Color::rgb(90, 90, 90), // Color::rgb(90, 90, 90),
Color::rgb(100, 100, 100), // Color::rgb(100, 100, 100),
Color::rgb(110, 110, 110), // Color::rgb(110, 110, 110),
Color::rgb(120, 120, 120), // Color::rgb(120, 120, 120),
Color::rgb(130, 130, 130), // Color::rgb(130, 130, 130),
Color::rgb(140, 140, 140), // Color::rgb(140, 140, 140),
Color::rgb(150, 150, 150), // Color::rgb(150, 150, 150),
Color::rgb(175, 175, 175), // Color::rgb(175, 175, 175),
Color::rgb(200, 200, 200), // Color::rgb(200, 200, 200),
Color::rgb(220, 240, 220), // Color::rgb(220, 240, 220),
Color::rgb(0, 192, 39), // Color::rgb(0, 192, 39),
], // ],
true, // true,
-125.0, // -125.0,
) // )
} // }
pub fn create_cc_boundarynorm() -> BoundaryNorm<f32> { // pub fn create_cc_boundarynorm() -> BoundaryNorm<f32> {
BoundaryNorm::new( // BoundaryNorm::new(
vec![ // 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, // 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![ // vec![
Color::rgb(0, 60, 255), // Color::rgb(0, 60, 255),
Color::rgb(0, 239, 239), // Color::rgb(0, 239, 239),
Color::rgb(0, 186, 191), // Color::rgb(0, 186, 191),
Color::rgb(0, 131, 125), // Color::rgb(0, 131, 125),
Color::rgb(0, 137, 56), // Color::rgb(0, 137, 56),
Color::rgb(0, 183, 41), // Color::rgb(0, 183, 41),
Color::rgb(0, 218, 13), // Color::rgb(0, 218, 13),
Color::rgb(0, 255, 0), // Color::rgb(0, 255, 0),
Color::rgb(255, 255, 59), // Color::rgb(255, 255, 59),
Color::rgb(255, 240, 0), // Color::rgb(255, 240, 0),
Color::rgb(255, 198, 0), // Color::rgb(255, 198, 0),
Color::rgb(255, 165, 0), // Color::rgb(255, 165, 0),
Color::rgb(255, 114, 0), // Color::rgb(255, 114, 0),
Color::rgb(255, 31, 0), // Color::rgb(255, 31, 0),
Color::rgb(193, 0, 0), // Color::rgb(193, 0, 0),
], // ],
true, // true,
-125.0, // -125.0,
) // )
} // }
pub fn create_vil_boundarynorm() -> BoundaryNorm<f32> { // pub fn create_vil_boundarynorm() -> BoundaryNorm<f32> {
BoundaryNorm::new( // BoundaryNorm::new(
vec![ // vec![
1.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35., 40., 45., 50., 55., 60., 65., 70., // 1.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35., 40., 45., 50., 55., 60., 65., 70.,
], // ],
vec![ // vec![
Color::rgb(156, 156, 156), // Color::rgb(156, 156, 156),
Color::rgb(118, 118, 118), // Color::rgb(118, 118, 118),
Color::rgb(250, 170, 170), // Color::rgb(250, 170, 170),
Color::rgb(238, 140, 140), // Color::rgb(238, 140, 140),
Color::rgb(201, 112, 112), // Color::rgb(201, 112, 112),
Color::rgb(0, 251, 144), // Color::rgb(0, 251, 144),
Color::rgb(0, 187, 0), // Color::rgb(0, 187, 0),
Color::rgb(255, 255, 112), // Color::rgb(255, 255, 112),
Color::rgb(208, 208, 96), // Color::rgb(208, 208, 96),
Color::rgb(255, 96, 96), // Color::rgb(255, 96, 96),
Color::rgb(218, 0, 0), // Color::rgb(218, 0, 0),
Color::rgb(174, 0, 0), // Color::rgb(174, 0, 0),
Color::rgb(0, 0, 255), // Color::rgb(0, 0, 255),
Color::rgb(255, 255, 255), // Color::rgb(255, 255, 255),
], // ],
true, // true,
-125.0, // -125.0,
) // )
} // }
pub fn create_hgt_boundarynorm() -> BoundaryNorm<f32> { // pub fn create_hgt_boundarynorm() -> BoundaryNorm<f32> {
BoundaryNorm::new( // BoundaryNorm::new(
vec![ // vec![
0.0, 2.0, 3.0, 5.0, 6.0, 8.0, 9.0, 11., 12., 14., 15., 17., 18., 20., 21., // 0.0, 2.0, 3.0, 5.0, 6.0, 8.0, 9.0, 11., 12., 14., 15., 17., 18., 20., 21.,
], // ],
vec![ // vec![
Color::rgb(0, 0, 0), // Color::rgb(0, 0, 0),
Color::rgb(118, 118, 118), // Color::rgb(118, 118, 118),
Color::rgb(0, 224, 255), // Color::rgb(0, 224, 255),
Color::rgb(0, 176, 255), // Color::rgb(0, 176, 255),
Color::rgb(0, 144, 204), // Color::rgb(0, 144, 204),
Color::rgb(50, 0, 150), // Color::rgb(50, 0, 150),
Color::rgb(0, 251, 144), // Color::rgb(0, 251, 144),
Color::rgb(0, 187, 0), // Color::rgb(0, 187, 0),
Color::rgb(0, 239, 0), // Color::rgb(0, 239, 0),
Color::rgb(254, 191, 0), // Color::rgb(254, 191, 0),
Color::rgb(255, 255, 0), // Color::rgb(255, 255, 0),
Color::rgb(174, 0, 0), // Color::rgb(174, 0, 0),
Color::rgb(255, 0, 0), // Color::rgb(255, 0, 0),
Color::rgb(255, 255, 255), // Color::rgb(255, 255, 255),
], // ],
true, // true,
-125.0, // -125.0,
) // )
} // }
pub fn create_et_boundarynorm() -> BoundaryNorm<f32> { // pub fn create_et_boundarynorm() -> BoundaryNorm<f32> {
BoundaryNorm::new( // BoundaryNorm::new(
vec![ // 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, // 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, // 18.0, 20.0, 21.0,
], // ],
vec![ // vec![
Color::rgb(204, 253, 255), // Color::rgb(204, 253, 255),
Color::rgb(153, 248, 255), // Color::rgb(153, 248, 255),
Color::rgb(101, 239, 255), // Color::rgb(101, 239, 255),
Color::rgb(50, 227, 255), // Color::rgb(50, 227, 255),
Color::rgb(134, 255, 134), // Color::rgb(134, 255, 134),
Color::rgb(80, 255, 80), // Color::rgb(80, 255, 80),
Color::rgb(0, 241, 1), // Color::rgb(0, 241, 1),
Color::rgb(0, 187, 0), // Color::rgb(0, 187, 0),
Color::rgb(255, 255, 84), // Color::rgb(255, 255, 84),
Color::rgb(255, 240, 0), // Color::rgb(255, 240, 0),
Color::rgb(255, 191, 0), // Color::rgb(255, 191, 0),
Color::rgb(255, 168, 0), // Color::rgb(255, 168, 0),
Color::rgb(255, 89, 89), // Color::rgb(255, 89, 89),
Color::rgb(255, 64, 64), // Color::rgb(255, 64, 64),
Color::rgb(255, 13, 13), // Color::rgb(255, 13, 13),
Color::rgb(237, 0, 0), // Color::rgb(237, 0, 0),
Color::rgb(205, 0, 0), // Color::rgb(205, 0, 0),
Color::rgb(139, 0, 0), // Color::rgb(139, 0, 0),
], // ],
true, // true,
-125.0, // -125.0,
) // )
} // }
pub fn create_cpc_boundarynorm() -> BoundaryNorm<i8> { // pub fn create_cpc_boundarynorm() -> BoundaryNorm<i8> {
BoundaryNorm::new( // BoundaryNorm::new(
vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], // vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
vec![ // vec![
Color::rgb(201, 196, 191), // Color::rgb(201, 196, 191),
Color::rgb(112, 188, 73), // Color::rgb(112, 188, 73),
Color::rgb(245, 163, 110), // Color::rgb(245, 163, 110),
Color::rgb(208, 119, 52), // Color::rgb(208, 119, 52),
Color::rgb(234, 37, 47), // Color::rgb(234, 37, 47),
Color::rgb(199, 53, 47), // Color::rgb(199, 53, 47),
Color::rgb(145, 71, 152), // Color::rgb(145, 71, 152),
Color::rgb(178, 177, 65), // Color::rgb(178, 177, 65),
Color::rgb(103, 199, 208), // Color::rgb(103, 199, 208),
Color::rgb(55, 90, 165), // Color::rgb(55, 90, 165),
Color::rgb(187, 165, 204), // Color::rgb(187, 165, 204),
], // ],
true, // true,
-125, // -125,
) // )
} // }
pub fn create_kdp_boundarynorm() -> BoundaryNorm<f32> { // pub fn create_kdp_boundarynorm() -> BoundaryNorm<f32> {
BoundaryNorm::new( // BoundaryNorm::new(
vec![ // 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, // -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![ // vec![
Color::rgb(0, 255, 255), // Color::rgb(0, 255, 255),
Color::rgb(0, 239, 239), // Color::rgb(0, 239, 239),
Color::rgb(0, 168, 172), // Color::rgb(0, 168, 172),
Color::rgb(180, 180, 180), // Color::rgb(180, 180, 180),
Color::rgb(180, 180, 180), // Color::rgb(180, 180, 180),
Color::rgb(0, 192, 39), // Color::rgb(0, 192, 39),
Color::rgb(0, 232, 10), // Color::rgb(0, 232, 10),
Color::rgb(36, 255, 36), // Color::rgb(36, 255, 36),
Color::rgb(255, 255, 30), // Color::rgb(255, 255, 30),
Color::rgb(255, 230, 0), // Color::rgb(255, 230, 0),
Color::rgb(255, 188, 0), // Color::rgb(255, 188, 0),
Color::rgb(255, 152, 0), // Color::rgb(255, 152, 0),
Color::rgb(255, 94, 0), // Color::rgb(255, 94, 0),
Color::rgb(242, 15, 0), // Color::rgb(242, 15, 0),
Color::rgb(187, 0, 58), // Color::rgb(187, 0, 58),
Color::rgb(253, 6, 253), // Color::rgb(253, 6, 253),
], // ],
true, // true,
-125.0, // -125.0,
) // )
} // }
pub fn estimate_zoom_level( pub fn estimate_zoom_level(
lat_min: f64, lat_min: f64,