radar-g/src/render/mod.rs
2023-09-20 19:54:38 +08:00

151 lines
4.5 KiB
Rust

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<imp::Render>)
@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<Mapper>,
) -> 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<F>(&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<T, Raw>(
&self,
mut data: RadarData2d<T, Raw>,
) -> Result<(), ProjError>
where
T: Num
+ Clone
+ PartialEq
+ PartialOrd
+ AsPrimitive<i8>
+ AsPrimitive<f64>
+ Debug
+ FromPrimitive,
Raw: ndarray::Data<Elem = T> + Clone + ndarray::RawDataClone,
{
assert!(data.dim1.shape().len() == data.dim2.shape().len());
let levels: Vec<T> = 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<Option<Color>> = rrp.run(&data).unwrap();
self.imp().foreground.borrow_mut().set_colors(pbow);
Ok(())
}
}