drag animation 60 fps testing

This commit is contained in:
sleptworld 2023-06-12 19:07:17 +08:00
parent 6d670afdbf
commit 0a90e486c3
7 changed files with 122 additions and 62 deletions

9
Cargo.lock generated
View File

@ -209,6 +209,7 @@ dependencies = [
"geo-types",
"glib",
"glib-build-tools",
"glib-macros",
"gtk4",
"ndarray",
"npyz",
@ -657,15 +658,15 @@ dependencies = [
[[package]]
name = "glib-build-tools"
version = "0.17.10"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a65d79efe318ef2cbbbb37032b125866fd82c34ea44c816132621bbc552e716"
checksum = "8f8480c9ba9cc06aa8d5baf446037f8dc237bee127e9b62080c4db7e293d8ea0"
[[package]]
name = "glib-macros"
version = "0.17.9"
version = "0.17.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a7206c5c03851ef126ea1444990e81fdd6765fb799d5bc694e4897ca01bb97f"
checksum = "eca5c79337338391f1ab8058d6698125034ce8ef31b72a442437fa6c8580de26"
dependencies = [
"anyhow",
"heck",

View File

@ -22,6 +22,7 @@ npyz = { version = "0.8.0", features = ["npz"] }
ndarray = "0.15.6"
quadtree_rs = "0.1.2"
proj-sys = "0.23.1"
glib-macros = "0.17.10"
[build-dependencies]

View File

@ -1,3 +1,9 @@
use std::cell::RefCell;
use std::rc::Rc;
use std::time::Duration;
use glib::{timeout_add, timeout_add_local};
use glib_macros::clone;
use gtk::gdk::Display;
use gtk::{
gio, glib, style_context_add_provider_for_display, Application, ApplicationWindow, CssProvider,
@ -11,9 +17,10 @@ mod painter;
mod render;
mod tree;
mod window;
use data::{CoordType, Npz, Radar2d};
use painter::wgs84::{LatLonCoord, Mercator, Range};
use painter::Painter;
use data::{Npz, Radar2d, RadarData2d};
use num_traits::{FromPrimitive, Num};
use painter::wgs84::{LatLonCoord, Mercator, ProjectionS, Range};
use painter::{Coord, Painter};
const APP_ID: &str = "org.gtk_rs.HelloWorld2";
@ -33,33 +40,55 @@ fn main() -> glib::ExitCode {
fn build_ui(app: &Application) {
// Create a window and set the title
// let window = Window::new(app);
let window = ApplicationWindow::builder()
.application(app)
.title("My GTK App")
.build();
let drawing_area = DrawingArea::new();
let path = "/Users/ruomu/test2.npz";
let path = "/home/ruomu/Desktop/test.npz";
let data = Radar2d::<i8>::load(path, Npz).unwrap();
let data = Rc::new(RefCell::new(data));
let data3_clone = data.clone();
let projection = Mercator::new();
let aa = Range::from((
*data.borrow().0.dim1.first().unwrap(),
*data.borrow().0.dim1.last().unwrap(),
));
let ab = Range::from((
*data.borrow().0.dim2.first().unwrap(),
*data.borrow().0.dim2.last().unwrap(),
));
let coord = LatLonCoord::new(Some(aa), Some(ab), ((0, 1000), (0, 1000)), projection);
let painter = Rc::new(RefCell::new(Painter::new(coord, 1000, 1000)));
let painter_b = painter.clone();
let gesture = GestureDrag::new();
// gesture.connect_drag_end(|s, x, y| {
// (&drawing_area).queue_draw();
// });
// drawing_area.add_controller(gesture);
drawing_area.set_draw_func(move |a, b, c, d| {
let projection = Mercator::new();
let aa = Range::from((*data.0.dim1.first().unwrap(), *data.0.dim1.last().unwrap()));
let ab = Range::from((*data.0.dim2.first().unwrap(), *data.0.dim2.last().unwrap()));
gesture.connect_drag_update(clone!(
@strong drawing_area => move |_, x,y| {
let painter = painter.clone();
painter.borrow_mut().set_shift(x,y);
println!("{:.2},{:.2}",x,y);
}
));
let coord = LatLonCoord::new(Some(aa), Some(ab), ((0, c), (0, d)), projection);
let painter: Painter<'_, f64, LatLonCoord<Mercator>> =
Painter::new(b, coord, c as u32, c as u32);
painter.draw_radar_2d(&data.0);
drawing_area.add_controller(gesture);
drawing_area.set_draw_func(move |a, b, c, d| {
painter_b.borrow().draw_radar_2d(b, &data3_clone.borrow().0);
});
timeout_add_local(
Duration::from_micros(1000u64 / 20u64),
clone!(@strong drawing_area => move || {
drawing_area.queue_draw();
Continue(true)
}),
);
window.set_child(Some(&drawing_area));
window.set_default_width(1000);
window.set_default_height(800);

View File

@ -8,4 +8,5 @@ pub trait Coord<T: Num> {
fn dim1_range(&self) -> (T, T);
fn dim2_range(&self) -> (T, T);
}

View File

@ -69,6 +69,10 @@ impl<T: ProjectionS> LatLonCoord<T> {
}
}
pub fn set_actual(&mut self,actual: ((i32, i32), (i32, i32))) {
self.actual = (Range::from(actual.0), Range::from(actual.1));
}
pub fn lon_range(&self) -> Range {
self.pcs.lon_range
}
@ -102,6 +106,7 @@ impl<T: ProjectionS> Coord<f64> for LatLonCoord<T> {
let v = self.lat_range();
(v.0, v.1)
}
}
#[derive(Clone, Debug)]

View File

@ -3,3 +3,4 @@ mod painter;
pub use painter::Painter;
pub use coords::wgs84;
pub use coords::Coord;

View File

@ -1,4 +1,8 @@
use std::marker::PhantomData;
use std::{
cell::{Ref, RefCell},
marker::PhantomData,
rc::{self, Rc},
};
use crate::{data::RadarData2d, tree::get};
@ -8,27 +12,27 @@ use gtk::{
gdk::{builders::RGBABuilder, RGBA},
};
use num_traits::{FromPrimitive, Num};
pub struct Painter<'a, T: Num, C: Coord<T>> {
pub struct Painter<T: Num, C: Coord<T>> {
width: u32,
height: u32,
context: &'a Context,
shift: (f64, f64),
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 {
impl<T: Num + Clone, C: Coord<T>> Painter<T, C> {
pub fn new(coord: C, width: u32, height: u32) -> Self {
Self {
context,
coord,
width,
height,
shift: (0f64, 0f64),
marker: PhantomData,
}
}
fn set_color(&self, color: &RGBA) {
self.context.set_source_rgba(
fn set_color(&self, context: &Context, color: &RGBA) {
context.set_source_rgba(
color.red() as f64,
color.green() as f64,
color.blue() as f64,
@ -36,19 +40,30 @@ impl<'a, T: Num + Clone, C: Coord<T>> Painter<'a, T, C> {
);
}
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);
fn draw_pixel(&self, context: &Context, point: ScreenCoord, color: &RGBA) {
context.rectangle(f64::from(point.0), f64::from(point.1), 1.0, 1.0);
self.set_color(context, color);
self.context.fill();
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();
pub fn set_shift(&mut self, dx: f64, dy: f64) {
self.shift = (self.shift.0 + dx, self.shift.1 + dy);
}
fn draw_rect(
&self,
context: &Context,
point: ScreenCoord,
width: f64,
height: f64,
color: &RGBA,
fill: bool,
) {
self.set_color(context, color);
self.set_stroke_width(context, 1);
context.rectangle(point.0, point.1, width, height);
context.fill();
// if fill {
// self.context.fill();
// } else {
@ -56,35 +71,40 @@ impl<'a, T: Num + Clone, C: Coord<T>> Painter<'a, T, C> {
// }
}
fn set_stroke_width(&self, width: u32) {
self.context.set_line_width(f64::from(width));
fn translate(&self,context:&Context) {
context.translate(self.shift.0, self.shift.1);
}
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 set_stroke_width(&self, context: &Context, width: u32) {
context.set_line_width(f64::from(width));
}
fn draw_path<I: IntoIterator<Item = ScreenCoord>>(&self, path: I) {
fn draw_line(&self, context: &Context, start: ScreenCoord, end: ScreenCoord) {
self.set_color(context, &RGBA::BLACK);
self.set_stroke_width(context, 1);
context.move_to(start.0, start.1);
context.line_to(end.0, end.1);
context.stroke();
}
fn draw_path<I: IntoIterator<Item = ScreenCoord>>(&self, context: &Context, path: I) {
let mut path = path.into_iter();
if let Some((x, y)) = path.next() {
self.context.move_to(x, y);
context.move_to(x, y);
}
for (x, y) in path {
self.context.line_to(x, y);
context.line_to(x, y);
}
self.context.stroke();
context.stroke();
}
}
impl<'a, C: Coord<f64>> Painter<'a, f64, C> {
impl<C: Coord<f64>> Painter<f64, C> {
pub fn draw_radar_2d<T: Num + Clone + PartialEq + PartialOrd + FromPrimitive + Copy, D>(
&self,
context: &Context,
data: &RadarData2d<T, D>,
) where
D: ndarray::Data<Elem = T> + Clone + ndarray::RawDataClone,
@ -183,11 +203,11 @@ impl<'a, C: Coord<f64>> Painter<'a, f64, C> {
.build(),
];
let mut polygons: Vec<(shapefile::Polygon, _)> =
shapefile::read_as::<_, shapefile::Polygon, shapefile::dbase::Record>(
"/Users/ruomu/china/省界_region.shp",
)
.unwrap();
// 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();
@ -196,13 +216,15 @@ impl<'a, C: Coord<f64>> Painter<'a, f64, C> {
// let lon_range = self.coord.dim1_range();
// let lat_range = self.coord.dim2_range();
// }
self.translate(context);
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);
self.draw_rect(context, point, 1.5, 1.5, &color, true);
}
})
});