This commit is contained in:
Tsuki 2024-04-15 22:29:35 +08:00
parent e0c02a4e35
commit 26939857c9
11 changed files with 326 additions and 62 deletions

View File

@ -9,8 +9,12 @@ use super::{
use crate::components::sidebar::{SideBarInputMsg, SideBarModel}; use crate::components::sidebar::{SideBarInputMsg, SideBarModel};
use crate::data_utils::tools; use crate::data_utils::tools;
use crate::pipeline::element::DataTarget; use crate::pipeline::element::DataTarget;
use crate::pipeline::element_imp::{Context, ElementInput, GridImpConfig};
use crate::pipeline::runner::Runner;
use crate::pipeline::OffscreenRenderer; use crate::pipeline::OffscreenRenderer;
use crate::predefined::color_mapper::{BoundaryNorm, ColorMapper, ColorMapperComb, Discrete};
use crate::predefined::widgets::ColorBar; use crate::predefined::widgets::ColorBar;
use crate::utils::meshgrid;
use crate::widgets::{AssoElement, DynamicCol}; use crate::widgets::{AssoElement, DynamicCol};
use crate::{ use crate::{
actions::register_layer_actions, actions::register_layer_actions,
@ -35,8 +39,9 @@ use chrono::{prelude::*, Duration};
use futures::future::BoxFuture; use futures::future::BoxFuture;
use gtk::glib::clone; use gtk::glib::clone;
use gtk::prelude::*; use gtk::prelude::*;
use ndarray::{ArrayView1, ArrayViewD};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use radarg_plugin_interface::PluginResult; use radarg_plugin_interface::{PluginResult, VecResult};
use relm4::actions::{AccelsPlus, RelmAction, RelmActionGroup}; use relm4::actions::{AccelsPlus, RelmAction, RelmActionGroup};
use relm4::*; use relm4::*;
use relm4::{gtk, Component, ComponentParts, ComponentSender, RelmWidgetExt, SimpleComponent}; use relm4::{gtk, Component, ComponentParts, ComponentSender, RelmWidgetExt, SimpleComponent};
@ -278,6 +283,63 @@ impl Component for AppModel {
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 mut context = Context::new(dialog_cms, canvas);
use femtovg::Color;
let mut runner = Runner::new(
imp,
Arc::new(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),
),
)),
}),
context,
);
let target = runner.run(&data);
let data_target = DataTarget::new(Some(data), target);
let element = Element::create_instant(
InstantElementDrawerType::Prepared(data_target),
dialog_dispatcher.clone(),
"ET".to_string(),
)
.get_instance();
let layer = Layer::new(
true,
"New Layer".to_string(),
AssoElement::Instant(element),
);
dialog_sidebar_sender.emit(SideBarInputMsg::AddMetaItems(meta.to_map()));
dialog_render_sender.emit(MonitorInputMsg::SetRenderRange(
lon_start, lon_end, lat_start, lat_end,
));
// 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(
@ -295,7 +357,7 @@ impl Component for AppModel {
// 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); // let layer = Layer::new(true, "New Layer".to_string(), AssoElement::Test);
AppMsg::LayerManager(LayerMsg::Add(layer)) AppMsg::LayerManager(LayerMsg::Add(layer))
} }

View File

@ -55,7 +55,7 @@ impl CMS {
let (x, y) = ( let (x, y) = (
self.bounds.0 + x * (self.bounds.1 - self.bounds.0), self.bounds.0 + x * (self.bounds.1 - self.bounds.0),
self.bounds.1 + y * (self.bounds.3 - self.bounds.2), self.bounds.2 + y * (self.bounds.3 - self.bounds.2),
); );
self.mapper.inverse_map((x, y)).ok() self.mapper.inverse_map((x, y)).ok()

View File

@ -18,9 +18,7 @@ pub fn tools(data: &PluginResult) -> ElementImpl {
let block = data.blocks.first().unwrap(); let block = data.blocks.first().unwrap();
match block.coord_type { match block.coord_type {
CoordType::Polar => { CoordType::Polar => PolarElementImp().into(),
todo!();
}
CoordType::Cartesian => match block.shape { CoordType::Cartesian => match block.shape {
DataShape::Cube => MultiLayerGridImp().into(), DataShape::Cube => MultiLayerGridImp().into(),
DataShape::Matrix => GridImp().into(), DataShape::Matrix => GridImp().into(),

View File

@ -101,7 +101,7 @@ pub struct TimeSeriesElement {
#[derive(Clone)] #[derive(Clone)]
pub enum InstantElementDrawerType { pub enum InstantElementDrawerType {
Draw(DrawFunc), Draw(DrawFunc),
Prepared((DataTarget, Arc<dyn ElementImpl>)), Prepared(DataTarget),
} }
impl Debug for InstantElementDrawerType { impl Debug for InstantElementDrawerType {
@ -141,7 +141,7 @@ impl InstantElement {
InstantElementDrawerType::Draw(ref func) => { InstantElementDrawerType::Draw(ref func) => {
func(render); func(render);
} }
InstantElementDrawerType::Prepared((ref mut target, _)) => { InstantElementDrawerType::Prepared(ref mut target) => {
render.draw_img(target); render.draw_img(target);
} }
} }
@ -157,21 +157,21 @@ impl InstantElement {
cms: CMS, cms: CMS,
) -> (TimeSeriesElement, DateTime<Utc>) { ) -> (TimeSeriesElement, DateTime<Utc>) {
// let imp = Arc::new(InstantElementImpl::new(self)); // let imp = Arc::new(InstantElementImpl::new(self));
if let InstantElementDrawerType::Prepared((mut target, imp)) = self.draw_type { // if let InstantElementDrawerType::Prepared(mut target) = self.draw_type {
let mut time_series = TimeSeriesElement::new(imp, dispatcher, cms, self.key); // let mut time_series = TimeSeriesElement::new(imp, dispatcher, cms, self.key);
let data = target.take_data().unwrap(); // let data = target.take_data().unwrap();
let time_stamp = data.blocks.first().unwrap().datetime; // let time_stamp = data.blocks.first().unwrap().datetime;
let meta_info: MetaInfo = data.meta.clone().into(); // let meta_info: MetaInfo = data.meta.clone().into();
use chrono::prelude::*; // use chrono::prelude::*;
let time = Utc.timestamp_opt(time_stamp, 0).unwrap(); // let time = Utc.timestamp_opt(time_stamp, 0).unwrap();
(*time_series.buffer) // (*time_series.buffer)
.lock() // .lock()
.unwrap() // .unwrap()
.insert(time, Some(RenderResult::new(target, meta_info))); // .insert(time, Some(RenderResult::new(target, meta_info)));
(time_series, time) // (time_series, time)
} else { // } else {
panic!("InstantElementDrawerType is not prepared"); panic!("InstantElementDrawerType is not prepared");
} // }
} }
} }

View File

@ -5,7 +5,7 @@ use crate::pipeline::offscreen_renderer::CanvasWrapper;
use crate::predefined::color_mapper::{CMap, ColorMapper, ColorMapperComb, VMap}; use crate::predefined::color_mapper::{CMap, ColorMapper, ColorMapperComb, VMap};
use abi_stable::std_types::RVec; use abi_stable::std_types::RVec;
use femtovg::{Paint, Path}; use femtovg::{Paint, Path};
use ndarray::{ArrayBase, ArrayView1, ArrayView2, ArrayViewD, Axis, Ix2, Ix3}; use ndarray::{ArrayBase, ArrayView1, ArrayView2, ArrayView3, ArrayViewD, Axis, Ix2, Ix3};
use num_traits::{AsPrimitive, FromPrimitive, Num, NumOps}; use num_traits::{AsPrimitive, FromPrimitive, Num, NumOps};
use radarg_plugin_interface::{DataShape, PluginResult, VecResult}; use radarg_plugin_interface::{DataShape, PluginResult, VecResult};
use std::any::Any; use std::any::Any;
@ -16,9 +16,9 @@ const EARTH_RADIUS: f64 = 6371.0;
macro_rules! impl_element_imp_dispatch { macro_rules! impl_element_imp_dispatch {
($({$Abc: ident, $t:ty},)+) => { ($({$Abc: ident, $t:ty},)+) => {
impl ElementImpl { impl ElementImpl {
pub fn process<T>(&self, pub fn process<'a, T>(&'a self,
dims: (ArrayView2<f64>, ArrayView2<f64>), dims: (ArrayView2<f64>, ArrayView2<f64>),
input: ArrayViewD<'_, T>, input: ElementInput<'a, T>,
config: &dyn Any, config: &dyn Any,
context: &mut Context context: &mut Context
) )
@ -29,11 +29,16 @@ macro_rules! impl_element_imp_dispatch {
$( $(
Self::$Abc(imp) => { Self::$Abc(imp) => {
let config = config.downcast_ref::<<$t as ElementImp>::Config<T>>().unwrap(); let config = config.downcast_ref::<<$t as ElementImp>::Config<T>>().unwrap();
imp.process(dims, input, config, context); if let ElementInput::$Abc(data) = input {
imp.process(dims, data, config, context);
} else {
panic!("Invalid input type");
}
} }
)+ )+
} }
} }
} }
}; };
} }
@ -66,6 +71,18 @@ macro_rules! impl_element_into_dispatch {
}; };
} }
macro_rules! impl_element_input_into_dispatch {
($({$Abc: ident, $t: ty},)+) => {
$(
impl<'a, T> From<$t> for ElementInput<'a, T> {
fn from(value: $t) -> Self {
Self::$Abc(value)
}
}
)+
};
}
macro_rules! for_all_variants { macro_rules! for_all_variants {
($macro: tt) => { ($macro: tt) => {
$macro! { $macro! {
@ -76,17 +93,43 @@ macro_rules! for_all_variants {
}; };
} }
macro_rules! result_to_array {
($v: ident, $shape: expr) => {
match $v {
VecResult::I16(v) => ArrayViewD::from_shape($shape, v.as_ref()).unwrap(),
VecResult::U8(v) => ArrayViewD::from_shape($shape, v.as_ref()).unwrap(),
VecResult::I8(v) => ArrayViewD::from_shape($shape, v.as_ref()).unwrap(),
VecResult::Bool(v) => ArrayViewD::from_shape($shape, v.as_ref()).unwrap(),
VecResult::F32(v) => ArrayViewD::from_shape($shape, v.as_ref()).unwrap(),
VecResult::F64(v) => ArrayViewD::from_shape($shape, v.as_ref()).unwrap(),
VecResult::I32(v) => ArrayViewD::from_shape($shape, v.as_ref()).unwrap(),
VecResult::I64(v) => ArrayViewD::from_shape($shape, v.as_ref()).unwrap(),
VecResult::U32(v) => ArrayViewD::from_shape($shape, v.as_ref()).unwrap(),
VecResult::U64(v) => ArrayViewD::from_shape($shape, v.as_ref()).unwrap(),
}
};
}
pub struct Context { pub struct Context {
cms: CMS, pub cms: CMS,
canvas: CanvasWrapper, pub canvas: CanvasWrapper,
}
impl Context {
pub fn new(cms: CMS, canvas: CanvasWrapper) -> Self {
Self { cms, canvas }
}
} }
pub trait ElementImp: Debug + TryFrom<ElementImpl> + Into<ElementImpl> { pub trait ElementImp: Debug + TryFrom<ElementImpl> + Into<ElementImpl> {
type Config<T: Sync + Send + Debug + PartialOrd + PartialEq>; type Config<T: Sync + Send + Debug + PartialOrd + PartialEq>;
fn process<T>( type Input<'a, T: 'a>
&self, where
Self: 'a;
fn process<'a, T>(
&'a self,
dims: (ArrayView2<f64>, ArrayView2<f64>), dims: (ArrayView2<f64>, ArrayView2<f64>),
input: ArrayViewD<'_, T>, input: Self::Input<'a, T>,
config: &Self::Config<T>, config: &Self::Config<T>,
context: &mut Context, context: &mut Context,
) where ) where
@ -100,7 +143,7 @@ pub struct GridImpConfig<T>
where where
T: PartialOrd + PartialEq + Send + Sync + Debug, T: PartialOrd + PartialEq + Send + Sync + Debug,
{ {
color_map: ColorMapperComb<T>, pub color_map: ColorMapperComb<T>,
} }
impl GridImp { impl GridImp {
@ -153,10 +196,11 @@ impl GridImp {
impl ElementImp for GridImp { impl ElementImp for GridImp {
type Config<T: Sync + Send + Debug + PartialOrd + PartialEq> = GridImpConfig<T>; type Config<T: Sync + Send + Debug + PartialOrd + PartialEq> = GridImpConfig<T>;
fn process<T>( type Input<'a, T: 'a> = ArrayViewD<'a, T>;
&self, fn process<'a, T>(
&'a self,
dims: (ArrayView2<f64>, ArrayView2<f64>), dims: (ArrayView2<f64>, ArrayView2<f64>),
input: ArrayViewD<'_, T>, input: Self::Input<'a, T>,
config: &Self::Config<T>, config: &Self::Config<T>,
context: &mut Context, context: &mut Context,
) where ) where
@ -186,11 +230,12 @@ where
impl ElementImp for MultiLayerGridImp { impl ElementImp for MultiLayerGridImp {
type Config<T: Sync + Send + Debug + PartialOrd + PartialEq> = MultiLayerGridImpConfig<T>; type Config<T: Sync + Send + Debug + PartialOrd + PartialEq> = MultiLayerGridImpConfig<T>;
type Input<'a, T: 'a> = ArrayViewD<'a, T>;
fn process<T>( fn process<'a, T>(
&self, &'a self,
dims: (ArrayView2<f64>, ArrayView2<f64>), dims: (ArrayView2<f64>, ArrayView2<f64>),
input: ArrayViewD<'_, T>, input: Self::Input<'a, T>,
config: &Self::Config<T>, config: &Self::Config<T>,
context: &mut Context, context: &mut Context,
) where ) where
@ -320,10 +365,11 @@ impl PolarElementImp {
impl ElementImp for PolarElementImp { impl ElementImp for PolarElementImp {
type Config<T: Sync + Send + Debug + PartialOrd + PartialEq> = PolarElementConfig<T>; type Config<T: Sync + Send + Debug + PartialOrd + PartialEq> = PolarElementConfig<T>;
fn process<T>( type Input<'a, T: 'a> = ArrayViewD<'a, T>;
&self, fn process<'a, T>(
&'a self,
dims: (ArrayView2<f64>, ArrayView2<f64>), dims: (ArrayView2<f64>, ArrayView2<f64>),
input: ArrayViewD<'_, T>, input: Self::Input<'a, T>,
config: &Self::Config<T>, config: &Self::Config<T>,
context: &mut Context, context: &mut Context,
) where ) where
@ -346,6 +392,13 @@ pub enum ElementImpl {
Polar(PolarElementImp), Polar(PolarElementImp),
} }
#[derive(Debug)]
pub enum ElementInput<'a, T> {
Grid(ArrayViewD<'a, T>),
MultiLayerGrid(ArrayViewD<'a, T>),
Polar(ArrayViewD<'a, T>),
}
for_all_variants!(impl_element_into_dispatch); for_all_variants!(impl_element_into_dispatch);
for_all_variants!(impl_element_try_from_dispatch); for_all_variants!(impl_element_try_from_dispatch);
for_all_variants!(impl_element_imp_dispatch); for_all_variants!(impl_element_imp_dispatch);

View File

@ -58,7 +58,7 @@ where
panic!("Vector data is not supported") panic!("Vector data is not supported")
} }
DataShape::Matrix => { DataShape::Matrix => {
let data:Radar2d<T> = first_block.clone().into(); let data: Radar2d<T> = first_block.clone().into();
let data = data.as_ref(); let data = data.as_ref();
let result = self.renderer.render(canvas, cms, &data, (3000.0, 3000.0)); let result = self.renderer.render(canvas, cms, &data, (3000.0, 3000.0));
result result

View File

@ -8,6 +8,7 @@ pub mod offscreen_renderer;
// mod predefined; // mod predefined;
pub mod element_imp; pub mod element_imp;
mod renders; mod renders;
pub mod runner;
// pub mod utils; // pub mod utils;
pub use dispatcher::Dispatcher; pub use dispatcher::Dispatcher;

View File

@ -29,18 +29,6 @@ use tokio::{
task, task,
}; };
// #[derive(Clone, Debug)]
// pub struct RenderResult {
// target: Target,
// meta_info: MetaInfo,
// }
// impl RenderResult {
// pub fn new(target: Target, meta_info: MetaInfo) -> Self {
// Self { target, meta_info }
// }
// }
type RenderR = Result<RenderResult, RenderError>; type RenderR = Result<RenderResult, RenderError>;
pub struct Pipeline { pub struct Pipeline {
pool: Vec<BoxFuture<'static, ()>>, pool: Vec<BoxFuture<'static, ()>>,

View File

@ -1,4 +1,3 @@
// 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};

146
src/pipeline/runner.rs Normal file
View File

@ -0,0 +1,146 @@
use std::{any::Any, sync::Arc};
use femtovg::RenderTarget;
use gl::types::GLvoid;
use image::Rgba;
use ndarray::{ArrayView1, ArrayViewD};
use radarg_plugin_interface::{PluginResult, VecResult};
use crate::{
pipeline::{
element_imp::{ElementInput, GridImpConfig},
TargetType,
},
utils::meshgrid,
};
use super::{
element_imp::{Context, ElementImp, ElementImpl},
Target,
};
macro_rules! impl_for_runner {
($imp:ident, $data:ident, $dims:expr, $size:ident, $config:ident, $context:ident, $({$t:tt},)+) => {
match $data {
$(
$t(ref v) => {
let input = ArrayViewD::from_shape($size, v.as_ref()).unwrap();
let data = ElementInput::Grid(input);
$imp.process($dims, data, $config, $context );
}
)+
}
};
}
pub struct Runner {
imp: ElementImpl,
config: Arc<dyn Any>,
context: Context,
}
impl Runner {
pub fn new(imp: ElementImpl, config: Arc<dyn Any>, context: Context) -> Self {
Self {
imp,
config,
context,
}
}
pub fn run(&mut self, data: &PluginResult) -> Target {
let block = data.blocks.first().unwrap();
let data = &block.data;
let dims = &block.dimension_values;
let dims = if dims.len() == 3 {
let (a, b) = (
ArrayView1::from(dims[2].as_ref()),
ArrayView1::from(dims[1].as_ref()),
);
meshgrid(a, b)
} else {
let (a, b) = (
ArrayView1::from(dims[1].as_ref()),
ArrayView1::from(dims[0].as_ref()),
);
meshgrid(a, b)
};
let size = block.size.to_owned().to_vec();
let config = &*self.config;
let imp: &ElementImpl = &self.imp;
let context: &mut Context = &mut self.context;
let cms = &mut context.cms;
let canvas = &mut context.canvas;
let (w, h) = (canvas.width(), canvas.height());
use femtovg::{ImageFlags, PixelFormat::Rgba8};
let new_img = canvas
.create_image_empty(w as usize, h as usize, Rgba8, ImageFlags::empty())
.expect("Can't Create Image");
canvas.image_size(new_img).unwrap();
canvas.set_render_target(RenderTarget::Image(new_img));
let lat_start = dims.1.view().first().unwrap().clone();
let lat_end = dims.1.view().last().unwrap().clone();
let lon_start = dims.0.view().first().unwrap().clone();
let lon_end = dims.0.view().last().unwrap().clone();
cms.set_lat_range(lat_start..lat_end);
cms.set_lon_range(lon_start..lon_end);
use VecResult::*;
impl_for_runner!(
imp,
data,
(dims.0.view(), dims.1.view()),
size,
config,
context,
{ I32 },
{ F64 },
{ I64 },
{ Bool },
{ F32 },
{ I8 },
{ U8 },
{ I16 },
{ U64 },
{ U32 },
);
context.canvas.flush();
let mut pixels: Vec<u8> = vec![0; w as usize * h as usize * 4];
unsafe {
gl::ReadPixels(
0,
0,
w as i32,
h as i32,
gl::RGBA,
gl::UNSIGNED_BYTE,
pixels.as_mut_ptr() as *mut GLvoid,
);
debug_assert_eq!(gl::GetError(), gl::NO_ERROR);
}
let d1_start = (dims.0.view()).first().unwrap().clone();
let d1_end = (dims.0.view()).last().unwrap().clone();
let d2_start = dims.1.view().first().unwrap().clone();
let d2_end = dims.1.view().last().unwrap().clone();
context.canvas.set_render_target(RenderTarget::Screen);
Target::new(
TargetType::NativeBuffer(pixels),
w as f32,
h as f32,
((d1_start, d1_end).into(), (d2_start, d2_end).into()),
None,
)
}
}

View File

@ -68,6 +68,17 @@ pub struct BoundaryNorm<T: PartialOrd + PartialEq> {
extrand: bool, extrand: bool,
invalid_value: Option<T>, invalid_value: Option<T>,
} }
impl<T: PartialEq + PartialOrd> BoundaryNorm<T> {
pub fn new(boundaries: Vec<T>, extrand: bool, invalid_value: Option<T>) -> Self {
Self {
boundaries,
extrand,
invalid_value,
}
}
}
impl<T> VMap for BoundaryNorm<T> impl<T> VMap for BoundaryNorm<T>
where where
T: PartialOrd + PartialEq + Debug, T: PartialOrd + PartialEq + Debug,
@ -100,6 +111,12 @@ pub struct Discrete {
colors: Vec<femtovg::Color>, colors: Vec<femtovg::Color>,
} }
impl Discrete {
pub fn new(colors: Vec<femtovg::Color>) -> Self {
Self { colors }
}
}
impl CMap for Discrete { impl CMap for Discrete {
fn map(&self, v: f32) -> Color { fn map(&self, v: f32) -> Color {
let size = (self.colors.len() as f32 * v) as usize; let size = (self.colors.len() as f32 * v) as usize;