radar-g/src/painter/painter.rs

211 lines
6.7 KiB
Rust

use std::marker::PhantomData;
use crate::{data::RadarData2d, tree::get};
use super::coords::{Coord, ScreenCoord};
use gtk::{
cairo::*,
gdk::{builders::RGBABuilder, RGBA},
};
use num_traits::{FromPrimitive, Num};
pub struct Painter<'a, T: Num, C: Coord<T>> {
width: u32,
height: u32,
context: &'a Context,
coord: C,
marker: PhantomData<T>,
}
impl<'a, T: Num + Clone, C: Coord<T>> Painter<'a, T, C> {
pub fn new(context: &'a Context, coord: C, width: u32, height: u32) -> Self {
Self {
context,
coord,
width,
height,
marker: PhantomData,
}
}
fn set_color(&self, color: &RGBA) {
self.context.set_source_rgba(
color.red() as f64,
color.green() as f64,
color.blue() as f64,
color.alpha() as f64,
);
}
fn draw_pixel(&self, point: ScreenCoord, color: &RGBA) {
self.context
.rectangle(f64::from(point.0), f64::from(point.1), 1.0, 1.0);
self.set_color(color);
self.context.fill();
}
fn draw_rect(&self, point: ScreenCoord, width: f64, height: f64, color: &RGBA, fill: bool) {
self.set_color(color);
self.set_stroke_width(1);
self.context.rectangle(point.0, point.1, width, height);
self.context.fill();
// if fill {
// self.context.fill();
// } else {
// self.context.stroke();
// }
}
fn set_stroke_width(&self, width: u32) {
self.context.set_line_width(f64::from(width));
}
fn draw_line(&self, start: ScreenCoord, end: ScreenCoord) {
self.set_color(&RGBA::BLACK);
self.set_stroke_width(1);
self.context.move_to(start.0, start.1);
self.context.line_to(end.0, end.1);
self.context.stroke();
}
fn draw_path<I: IntoIterator<Item = ScreenCoord>>(&self, path: I) {
let mut path = path.into_iter();
if let Some((x, y)) = path.next() {
self.context.move_to(x, y);
}
for (x, y) in path {
self.context.line_to(x, y);
}
self.context.stroke();
}
}
impl<'a, C: Coord<f64>> Painter<'a, f64, C> {
pub fn draw_radar_2d<T: Num + Clone + PartialEq + PartialOrd + FromPrimitive + Copy, D>(
&self,
data: &RadarData2d<T, D>,
) where
D: ndarray::Data<Elem = T> + Clone + ndarray::RawDataClone,
{
let levels: Vec<T> = vec![
T::from_i8(0).unwrap(),
T::from_i8(5).unwrap(),
T::from_i8(10).unwrap(),
T::from_i8(15).unwrap(),
T::from_i8(20).unwrap(),
T::from_i8(25).unwrap(),
T::from_i8(30).unwrap(),
T::from_i8(35).unwrap(),
T::from_i8(40).unwrap(),
T::from_i8(45).unwrap(),
T::from_i8(50).unwrap(),
T::from_i8(55).unwrap(),
T::from_i8(60).unwrap(),
T::from_i8(65).unwrap(),
];
let colors = vec![
RGBABuilder::default()
.red(0 as f32 / 255.0)
.green(172 as f32 / 255.0)
.blue(164 as f32 / 255.0)
.build(),
RGBABuilder::default()
.red(192 as f32 / 255.0)
.green(192 as f32 / 255.0)
.blue(254 as f32 / 255.0)
.build(),
RGBABuilder::default()
.red(122 as f32 / 255.0)
.green(114 as f32 / 255.0)
.blue(238 as f32 / 255.0)
.build(),
RGBABuilder::default()
.red(30 as f32 / 255.0)
.green(38 as f32 / 255.0)
.blue(208 as f32 / 255.0)
.build(),
RGBABuilder::default()
.red(166 as f32 / 255.0)
.green(252 as f32 / 255.0)
.blue(168 as f32 / 255.0)
.build(),
RGBABuilder::default()
.red(0 as f32 / 255.0)
.green(234 as f32 / 255.0)
.blue(0 as f32 / 255.0)
.build(),
RGBABuilder::default()
.red(16 as f32 / 255.0)
.green(146 as f32 / 255.0)
.blue(26 as f32 / 255.0)
.build(),
RGBABuilder::default()
.red(252 as f32 / 255.0)
.green(244 as f32 / 255.0)
.blue(100 as f32 / 255.0)
.build(),
RGBABuilder::default()
.red(200 as f32 / 255.0)
.green(200 as f32 / 255.0)
.blue(2 as f32 / 255.0)
.build(),
RGBABuilder::default()
.red(140 as f32 / 255.0)
.green(140 as f32 / 255.0)
.blue(0 as f32 / 255.0)
.build(),
RGBABuilder::default()
.red(254 as f32 / 255.0)
.green(172 as f32 / 255.0)
.blue(172 as f32 / 255.0)
.build(),
RGBABuilder::default()
.red(254 as f32 / 255.0)
.green(100 as f32 / 255.0)
.blue(92 as f32 / 255.0)
.build(),
RGBABuilder::default()
.red(238 as f32 / 255.0)
.green(2 as f32 / 255.0)
.blue(48 as f32 / 255.0)
.build(),
RGBABuilder::default()
.red(212 as f32 / 255.0)
.green(142 as f32 / 255.0)
.blue(254 as f32 / 255.0)
.build(),
RGBABuilder::default()
.red(170 as f32 / 255.0)
.green(36 as f32 / 255.0)
.blue(250 as f32 / 255.0)
.build(),
];
let mut polygons: Vec<(shapefile::Polygon, _)> =
shapefile::read_as::<_, shapefile::Polygon, shapefile::dbase::Record>(
"/Users/ruomu/china/省界_region.shp",
)
.unwrap();
// for (polygon, _) in polygons.into_iter() {
// let x_range = polygon.bbox().x_range();
// let y_range = polygon.bbox().y_range();
// let lon_range = self.coord.dim1_range();
// let lat_range = self.coord.dim2_range();
// }
data.data.outer_iter().enumerate().for_each(|(r_num, row)| {
row.iter().enumerate().for_each(|(c_num, v)| {
let point = self.coord.map(data.dim1[c_num], data.dim2[r_num]);
if *v > T::from_i8(-125).unwrap() {
let color = get(&levels, &colors, *v);
// self.draw_pixel(point, &color);
self.draw_rect(point, 1.5, 1.5, &color, true);
}
})
});
}
}