drag animation 60 fps testing
This commit is contained in:
parent
6d670afdbf
commit
0a90e486c3
9
Cargo.lock
generated
9
Cargo.lock
generated
@ -209,6 +209,7 @@ dependencies = [
|
|||||||
"geo-types",
|
"geo-types",
|
||||||
"glib",
|
"glib",
|
||||||
"glib-build-tools",
|
"glib-build-tools",
|
||||||
|
"glib-macros",
|
||||||
"gtk4",
|
"gtk4",
|
||||||
"ndarray",
|
"ndarray",
|
||||||
"npyz",
|
"npyz",
|
||||||
@ -657,15 +658,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glib-build-tools"
|
name = "glib-build-tools"
|
||||||
version = "0.17.10"
|
version = "0.17.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a65d79efe318ef2cbbbb37032b125866fd82c34ea44c816132621bbc552e716"
|
checksum = "8f8480c9ba9cc06aa8d5baf446037f8dc237bee127e9b62080c4db7e293d8ea0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glib-macros"
|
name = "glib-macros"
|
||||||
version = "0.17.9"
|
version = "0.17.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0a7206c5c03851ef126ea1444990e81fdd6765fb799d5bc694e4897ca01bb97f"
|
checksum = "eca5c79337338391f1ab8058d6698125034ce8ef31b72a442437fa6c8580de26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"heck",
|
"heck",
|
||||||
|
|||||||
@ -22,6 +22,7 @@ npyz = { version = "0.8.0", features = ["npz"] }
|
|||||||
ndarray = "0.15.6"
|
ndarray = "0.15.6"
|
||||||
quadtree_rs = "0.1.2"
|
quadtree_rs = "0.1.2"
|
||||||
proj-sys = "0.23.1"
|
proj-sys = "0.23.1"
|
||||||
|
glib-macros = "0.17.10"
|
||||||
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
|||||||
67
src/main.rs
67
src/main.rs
@ -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::gdk::Display;
|
||||||
use gtk::{
|
use gtk::{
|
||||||
gio, glib, style_context_add_provider_for_display, Application, ApplicationWindow, CssProvider,
|
gio, glib, style_context_add_provider_for_display, Application, ApplicationWindow, CssProvider,
|
||||||
@ -11,9 +17,10 @@ mod painter;
|
|||||||
mod render;
|
mod render;
|
||||||
mod tree;
|
mod tree;
|
||||||
mod window;
|
mod window;
|
||||||
use data::{CoordType, Npz, Radar2d};
|
use data::{Npz, Radar2d, RadarData2d};
|
||||||
use painter::wgs84::{LatLonCoord, Mercator, Range};
|
use num_traits::{FromPrimitive, Num};
|
||||||
use painter::Painter;
|
use painter::wgs84::{LatLonCoord, Mercator, ProjectionS, Range};
|
||||||
|
use painter::{Coord, Painter};
|
||||||
|
|
||||||
const APP_ID: &str = "org.gtk_rs.HelloWorld2";
|
const APP_ID: &str = "org.gtk_rs.HelloWorld2";
|
||||||
|
|
||||||
@ -33,33 +40,55 @@ fn main() -> glib::ExitCode {
|
|||||||
|
|
||||||
fn build_ui(app: &Application) {
|
fn build_ui(app: &Application) {
|
||||||
// Create a window and set the title
|
// Create a window and set the title
|
||||||
|
|
||||||
// let window = Window::new(app);
|
|
||||||
|
|
||||||
let window = ApplicationWindow::builder()
|
let window = ApplicationWindow::builder()
|
||||||
.application(app)
|
.application(app)
|
||||||
.title("My GTK App")
|
.title("My GTK App")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let drawing_area = DrawingArea::new();
|
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 = 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();
|
let gesture = GestureDrag::new();
|
||||||
|
|
||||||
// gesture.connect_drag_end(|s, x, y| {
|
gesture.connect_drag_update(clone!(
|
||||||
// (&drawing_area).queue_draw();
|
@strong drawing_area => move |_, x,y| {
|
||||||
// });
|
let painter = painter.clone();
|
||||||
// drawing_area.add_controller(gesture);
|
painter.borrow_mut().set_shift(x,y);
|
||||||
drawing_area.set_draw_func(move |a, b, c, d| {
|
println!("{:.2},{:.2}",x,y);
|
||||||
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()));
|
|
||||||
|
|
||||||
let coord = LatLonCoord::new(Some(aa), Some(ab), ((0, c), (0, d)), projection);
|
drawing_area.add_controller(gesture);
|
||||||
let painter: Painter<'_, f64, LatLonCoord<Mercator>> =
|
|
||||||
Painter::new(b, coord, c as u32, c as u32);
|
drawing_area.set_draw_func(move |a, b, c, d| {
|
||||||
painter.draw_radar_2d(&data.0);
|
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_child(Some(&drawing_area));
|
||||||
window.set_default_width(1000);
|
window.set_default_width(1000);
|
||||||
window.set_default_height(800);
|
window.set_default_height(800);
|
||||||
|
|||||||
@ -8,4 +8,5 @@ pub trait Coord<T: Num> {
|
|||||||
|
|
||||||
fn dim1_range(&self) -> (T, T);
|
fn dim1_range(&self) -> (T, T);
|
||||||
fn dim2_range(&self) -> (T, T);
|
fn dim2_range(&self) -> (T, T);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 {
|
pub fn lon_range(&self) -> Range {
|
||||||
self.pcs.lon_range
|
self.pcs.lon_range
|
||||||
}
|
}
|
||||||
@ -102,6 +106,7 @@ impl<T: ProjectionS> Coord<f64> for LatLonCoord<T> {
|
|||||||
let v = self.lat_range();
|
let v = self.lat_range();
|
||||||
(v.0, v.1)
|
(v.0, v.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|||||||
@ -2,4 +2,5 @@ mod coords;
|
|||||||
mod painter;
|
mod painter;
|
||||||
|
|
||||||
pub use painter::Painter;
|
pub use painter::Painter;
|
||||||
pub use coords::wgs84;
|
pub use coords::wgs84;
|
||||||
|
pub use coords::Coord;
|
||||||
@ -1,4 +1,8 @@
|
|||||||
use std::marker::PhantomData;
|
use std::{
|
||||||
|
cell::{Ref, RefCell},
|
||||||
|
marker::PhantomData,
|
||||||
|
rc::{self, Rc},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{data::RadarData2d, tree::get};
|
use crate::{data::RadarData2d, tree::get};
|
||||||
|
|
||||||
@ -8,27 +12,27 @@ use gtk::{
|
|||||||
gdk::{builders::RGBABuilder, RGBA},
|
gdk::{builders::RGBABuilder, RGBA},
|
||||||
};
|
};
|
||||||
use num_traits::{FromPrimitive, Num};
|
use num_traits::{FromPrimitive, Num};
|
||||||
pub struct Painter<'a, T: Num, C: Coord<T>> {
|
pub struct Painter<T: Num, C: Coord<T>> {
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
context: &'a Context,
|
shift: (f64, f64),
|
||||||
coord: C,
|
coord: C,
|
||||||
marker: PhantomData<T>,
|
marker: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Num + Clone, C: Coord<T>> Painter<'a, T, C> {
|
impl<T: Num + Clone, C: Coord<T>> Painter<T, C> {
|
||||||
pub fn new(context: &'a Context, coord: C, width: u32, height: u32) -> Self {
|
pub fn new(coord: C, width: u32, height: u32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
context,
|
|
||||||
coord,
|
coord,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
shift: (0f64, 0f64),
|
||||||
marker: PhantomData,
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_color(&self, color: &RGBA) {
|
fn set_color(&self, context: &Context, color: &RGBA) {
|
||||||
self.context.set_source_rgba(
|
context.set_source_rgba(
|
||||||
color.red() as f64,
|
color.red() as f64,
|
||||||
color.green() as f64,
|
color.green() as f64,
|
||||||
color.blue() 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) {
|
fn draw_pixel(&self, context: &Context, point: ScreenCoord, color: &RGBA) {
|
||||||
self.context
|
context.rectangle(f64::from(point.0), f64::from(point.1), 1.0, 1.0);
|
||||||
.rectangle(f64::from(point.0), f64::from(point.1), 1.0, 1.0);
|
self.set_color(context, color);
|
||||||
self.set_color(color);
|
|
||||||
|
|
||||||
self.context.fill();
|
context.fill();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_rect(&self, point: ScreenCoord, width: f64, height: f64, color: &RGBA, fill: bool) {
|
pub fn set_shift(&mut self, dx: f64, dy: f64) {
|
||||||
self.set_color(color);
|
self.shift = (self.shift.0 + dx, self.shift.1 + dy);
|
||||||
self.set_stroke_width(1);
|
}
|
||||||
self.context.rectangle(point.0, point.1, width, height);
|
|
||||||
self.context.fill();
|
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 {
|
// if fill {
|
||||||
// self.context.fill();
|
// self.context.fill();
|
||||||
// } else {
|
// } else {
|
||||||
@ -56,35 +71,40 @@ impl<'a, T: Num + Clone, C: Coord<T>> Painter<'a, T, C> {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_stroke_width(&self, width: u32) {
|
fn translate(&self,context:&Context) {
|
||||||
self.context.set_line_width(f64::from(width));
|
context.translate(self.shift.0, self.shift.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_line(&self, start: ScreenCoord, end: ScreenCoord) {
|
fn set_stroke_width(&self, context: &Context, width: u32) {
|
||||||
self.set_color(&RGBA::BLACK);
|
context.set_line_width(f64::from(width));
|
||||||
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) {
|
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();
|
let mut path = path.into_iter();
|
||||||
if let Some((x, y)) = path.next() {
|
if let Some((x, y)) = path.next() {
|
||||||
self.context.move_to(x, y);
|
context.move_to(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (x, y) in path {
|
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>(
|
pub fn draw_radar_2d<T: Num + Clone + PartialEq + PartialOrd + FromPrimitive + Copy, D>(
|
||||||
&self,
|
&self,
|
||||||
|
context: &Context,
|
||||||
data: &RadarData2d<T, D>,
|
data: &RadarData2d<T, D>,
|
||||||
) where
|
) where
|
||||||
D: ndarray::Data<Elem = T> + Clone + ndarray::RawDataClone,
|
D: ndarray::Data<Elem = T> + Clone + ndarray::RawDataClone,
|
||||||
@ -183,11 +203,11 @@ impl<'a, C: Coord<f64>> Painter<'a, f64, C> {
|
|||||||
.build(),
|
.build(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut polygons: Vec<(shapefile::Polygon, _)> =
|
// let mut polygons: Vec<(shapefile::Polygon, _)> =
|
||||||
shapefile::read_as::<_, shapefile::Polygon, shapefile::dbase::Record>(
|
// shapefile::read_as::<_, shapefile::Polygon, shapefile::dbase::Record>(
|
||||||
"/Users/ruomu/china/省界_region.shp",
|
// "/Users/ruomu/china/省界_region.shp",
|
||||||
)
|
// )
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
|
|
||||||
// for (polygon, _) in polygons.into_iter() {
|
// for (polygon, _) in polygons.into_iter() {
|
||||||
// let x_range = polygon.bbox().x_range();
|
// 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 lon_range = self.coord.dim1_range();
|
||||||
// let lat_range = self.coord.dim2_range();
|
// let lat_range = self.coord.dim2_range();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
self.translate(context);
|
||||||
data.data.outer_iter().enumerate().for_each(|(r_num, row)| {
|
data.data.outer_iter().enumerate().for_each(|(r_num, row)| {
|
||||||
row.iter().enumerate().for_each(|(c_num, v)| {
|
row.iter().enumerate().for_each(|(c_num, v)| {
|
||||||
let point = self.coord.map(data.dim1[c_num], data.dim2[r_num]);
|
let point = self.coord.map(data.dim1[c_num], data.dim2[r_num]);
|
||||||
if *v > T::from_i8(-125).unwrap() {
|
if *v > T::from_i8(-125).unwrap() {
|
||||||
let color = get(&levels, &colors, *v);
|
let color = get(&levels, &colors, *v);
|
||||||
// self.draw_pixel(point, &color);
|
// 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);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user