mod background; mod foreground; mod exterior; mod imp; use crate::coords::Mapper; use crate::data::{MultiDimensionData, RadarData2d}; use crate::pipeline::ProjPipe; use crate::pipeline::{Pipeline, ShadePipe}; use std::fmt::Debug; pub use self::background::{BackgroundConfig, BackgroundWidget}; use self::exterior::ExteriorWidget; pub use self::foreground::{ForegroundConfig, ForegroundWidget}; use self::imp::RenderConfig; use crate::data::DownSampleMeth; use adw::prelude::WidgetExt; use femtovg::Color; pub use glib::subclass::prelude::*; use image::RgbImage; use ndarray::{self, s, Array2, Axis, Dimension, Ix2, Zip}; use num_traits::{AsPrimitive, FromPrimitive, Num}; use proj::ProjError; pub(super) type WindowCoord = (f32, f32); glib::wrapper! { pub struct Render(ObjectSubclass) @extends gtk::GLArea, gtk::Widget; } impl Default for Render { fn default() -> Self { Self::new( BackgroundWidget::default(), ForegroundWidget::default(), None, ) } } impl Render { pub fn new( background: BackgroundWidget, foreground: ForegroundWidget, mapper: Option, ) -> Self { let this: Self = glib::Object::new(); this.imp().background.replace(background); this.imp().foreground.replace(foreground); { let mut configs = this.imp().config.borrow_mut(); configs.scale = 1.0; } if let Some(mapper) = mapper { this.set_mapper(mapper); } this } pub fn change_cfg(&self, mut f: F) where F: FnMut(&mut RenderConfig), { let mut cfg = self.imp().config.borrow_mut(); f(&mut cfg); } pub fn change_pointer(&mut self, x: f32, y: f32) { if let Some(canvas) = self.imp().canvas.borrow().as_ref() { let dpi = self.scale_factor(); let cw = canvas.width(); let ch = canvas.height(); let (tx, ty) = self.imp().translate(); let scale = self.imp().config.borrow().scale; let (lon, lat) = self .imp() .mapper .borrow() .fore_map(( (x * dpi as f32 + tx) / cw / scale, (1.0 - (y * dpi as f32 + ty) / ch / scale), )) .unwrap(); let mut cfg = self.imp().config.borrow_mut(); cfg.pointer_lon_lat = (lon, lat); cfg.pointer_location = (x, y); } } pub fn set_translate(&self, trans: (f32, f32)) { if let Some(c) = self.imp().canvas.borrow().as_ref() { self.imp().config.borrow_mut().translate = (c.width() * trans.0, c.height() * trans.1); } } pub fn set_mapper(&self, mapper: Mapper) { self.imp().mapper.replace(mapper); } pub(super) fn load_data_2d( &self, mut data: RadarData2d, ) -> Result<(), ProjError> where T: Num + Clone + PartialEq + PartialOrd + AsPrimitive + AsPrimitive + Debug + FromPrimitive, Raw: ndarray::Data + Clone + ndarray::RawDataClone, { assert!(data.dim1.shape().len() == data.dim2.shape().len()); let levels: Vec = vec![0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65] .into_iter() .map(|b| T::from_i8(b).unwrap()) .collect(); let 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), ]; let mapper = self.imp().mapper.borrow(); let pjp = ProjPipe::new(&mapper); let rrp = ShadePipe::new(levels, colors.into_iter().map(|v| v.into()).collect()); let rainbow = pjp.run(&data).unwrap(); self.imp().foreground.borrow_mut().set_data(rainbow); let pbow: Array2> = rrp.run(&data).unwrap(); self.imp().foreground.borrow_mut().set_colors(pbow); Ok(()) } }