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> { width: u32, height: u32, context: &'a Context, coord: C, marker: PhantomData, } impl<'a, T: Num + Clone, C: Coord> 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>(&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> Painter<'a, f64, C> { pub fn draw_radar_2d( &self, data: &RadarData2d, ) where D: ndarray::Data + Clone + ndarray::RawDataClone, { let levels: Vec = 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); } }) }); } }