sync
This commit is contained in:
parent
f860aadfa8
commit
763ff502da
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -511,6 +511,7 @@ dependencies = [
|
|||||||
"euclid",
|
"euclid",
|
||||||
"femtovg",
|
"femtovg",
|
||||||
"flate2",
|
"flate2",
|
||||||
|
"fns",
|
||||||
"futures",
|
"futures",
|
||||||
"geo",
|
"geo",
|
||||||
"geo-macros",
|
"geo-macros",
|
||||||
@ -1187,6 +1188,15 @@ dependencies = [
|
|||||||
"spin",
|
"spin",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fns"
|
||||||
|
version = "0.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f9d318f82a68feac152dab48e8a6f1eb665a915ea6a0c76e4ad5ed137f80c368"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
|
|||||||
@ -94,6 +94,7 @@ slippy-map-tiles = "0.16.0"
|
|||||||
reqwest = "0.11.25"
|
reqwest = "0.11.25"
|
||||||
url = "2.5.0"
|
url = "2.5.0"
|
||||||
quick_cache = "0.4.1"
|
quick_cache = "0.4.1"
|
||||||
|
fns = "0.0.7"
|
||||||
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
|||||||
@ -26,10 +26,12 @@ use crate::map_tile_utils::lat_lon_to_zoom;
|
|||||||
use crate::pipeline::element::Target;
|
use crate::pipeline::element::Target;
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use femtovg::ImageId;
|
use femtovg::ImageId;
|
||||||
|
use fns::debounce;
|
||||||
use relm4::{component::Component, *};
|
use relm4::{component::Component, *};
|
||||||
use slippy_map_tiles::Tile;
|
use slippy_map_tiles::Tile;
|
||||||
use tokio::task;
|
use tokio::task;
|
||||||
use tracing::instrument::WithSubscriber;
|
use tracing::instrument::WithSubscriber;
|
||||||
|
use crate::utils::estimate_zoom_level;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum MonitorCommand {
|
pub enum MonitorCommand {
|
||||||
@ -42,8 +44,12 @@ pub struct MonitorModel {
|
|||||||
render_range: (f64, f64, f64, f64),
|
render_range: (f64, f64, f64, f64),
|
||||||
sidebar_open: bool,
|
sidebar_open: bool,
|
||||||
sidebar_width: i32,
|
sidebar_width: i32,
|
||||||
|
#[do_not_track]
|
||||||
|
debouncer: Rc<dyn Fn(u8)>,
|
||||||
zoom: u8,
|
zoom: u8,
|
||||||
#[do_not_track]
|
#[do_not_track]
|
||||||
|
last_call: Rc<RefCell<std::time::Instant>>,
|
||||||
|
#[do_not_track]
|
||||||
map_tile_getter: Rc<MapTile>,
|
map_tile_getter: Rc<MapTile>,
|
||||||
new_layer: i8,
|
new_layer: i8,
|
||||||
#[no_eq]
|
#[no_eq]
|
||||||
@ -99,17 +105,17 @@ impl Component for MonitorModel {
|
|||||||
connect_render_status_notify[sender] => move |r| {
|
connect_render_status_notify[sender] => move |r| {
|
||||||
sender.output(MonitorOutputMsg::LayerRenderFinished);
|
sender.output(MonitorOutputMsg::LayerRenderFinished);
|
||||||
},
|
},
|
||||||
connect_range_changing_notify[sender] => move |r| {
|
// connect_range_changing_notify[sender] => move |r| {
|
||||||
sender.input(MonitorInputMsg::RefreshTiles);
|
// sender.input(MonitorInputMsg::RefreshTiles);
|
||||||
},
|
// },
|
||||||
connect_scale_notify[sender] => move |r| {
|
// connect_scale_notify => move |r| {
|
||||||
let scale_factor = r.scale();
|
// let ((x1,x2), (y1,y2)) = r.render_range();
|
||||||
let zoom = scale_factor.log2().round() as u8;
|
// let (w, h) = r.window_size();
|
||||||
let new_zoom = model.zoom + zoom;
|
// let new_zoom = estimate_zoom_level(x1,x2,y1,y2,w as f64, h as f64);
|
||||||
if model.zoom != new_zoom {
|
// if model.zoom != new_zoom {
|
||||||
sender.input(MonitorInputMsg::ChangeZoom(new_zoom));
|
// debouncer(new_zoom);
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
set_interior_layers: model.layers.clone(),
|
set_interior_layers: model.layers.clone(),
|
||||||
},
|
},
|
||||||
add_overlay=>k::Button{
|
add_overlay=>k::Button{
|
||||||
@ -152,6 +158,8 @@ impl Component for MonitorModel {
|
|||||||
}
|
}
|
||||||
MonitorInputMsg::SetRenderRange(lon_start, lon_end, lat_start, lat_end) => {
|
MonitorInputMsg::SetRenderRange(lon_start, lon_end, lat_start, lat_end) => {
|
||||||
self.set_render_range((lat_start, lat_end, lon_start, lon_end));
|
self.set_render_range((lat_start, lat_end, lon_start, lon_end));
|
||||||
|
let r = &widgets.renderer;
|
||||||
|
(*self.debouncer)(10);
|
||||||
}
|
}
|
||||||
MonitorInputMsg::ClearMetaItems => self.sidebar.emit(SideBarInputMsg::ClearMetaItems),
|
MonitorInputMsg::ClearMetaItems => self.sidebar.emit(SideBarInputMsg::ClearMetaItems),
|
||||||
MonitorInputMsg::UpdateMetaItem(map) => {
|
MonitorInputMsg::UpdateMetaItem(map) => {
|
||||||
@ -206,6 +214,16 @@ impl Component for MonitorModel {
|
|||||||
padding: [20.0, 40.0, 20.0, 40.0],
|
padding: [20.0, 40.0, 20.0, 40.0],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let new_sender = sender.clone();
|
||||||
|
|
||||||
|
let _debouncer = fns::debounce(move |new_zoom: u8| {
|
||||||
|
new_sender.input(MonitorInputMsg::ChangeZoom(new_zoom));
|
||||||
|
}, std::time::Duration::from_millis(500));
|
||||||
|
|
||||||
|
let debouncer = move |zoom: u8| {
|
||||||
|
_debouncer.call(zoom);
|
||||||
|
};
|
||||||
|
|
||||||
let mut model = MonitorModel {
|
let mut model = MonitorModel {
|
||||||
render_range: (4.0, 53.3, 73.3, 135.0),
|
render_range: (4.0, 53.3, 73.3, 135.0),
|
||||||
new_layer: 0,
|
new_layer: 0,
|
||||||
@ -213,13 +231,18 @@ impl Component for MonitorModel {
|
|||||||
render_cfg,
|
render_cfg,
|
||||||
sidebar_open: true,
|
sidebar_open: true,
|
||||||
sidebar_width: 400,
|
sidebar_width: 400,
|
||||||
|
last_call : Rc::new(RefCell::new(std::time::Instant::now())),
|
||||||
layers: init,
|
layers: init,
|
||||||
zoom: 4,
|
zoom: 4,
|
||||||
|
debouncer : Rc::new(debouncer),
|
||||||
map_tile_getter: Rc::new(MapTile::default()),
|
map_tile_getter: Rc::new(MapTile::default()),
|
||||||
sidebar,
|
sidebar,
|
||||||
tracker: 0,
|
tracker: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let last_call = model.last_call.clone();
|
||||||
|
let debouncer = model.debouncer.clone();
|
||||||
|
|
||||||
let widgets = view_output! {};
|
let widgets = view_output! {};
|
||||||
ComponentParts { model, widgets }
|
ComponentParts { model, widgets }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,7 +34,7 @@ impl Default for MapTile {
|
|||||||
Self {
|
Self {
|
||||||
server: "https://tiles.stadiamaps.com/tiles/".to_string(),
|
server: "https://tiles.stadiamaps.com/tiles/".to_string(),
|
||||||
api_key: "06f1aeed-5d91-48e3-9ce5-1e99063f7f73".to_string(),
|
api_key: "06f1aeed-5d91-48e3-9ce5-1e99063f7f73".to_string(),
|
||||||
style: "stamen_terrain/".to_string(),
|
style: "stamen_toner".to_string(),
|
||||||
client: Client::new(),
|
client: Client::new(),
|
||||||
onloading: Arc::new(std::sync::Mutex::new( HashSet::new())),
|
onloading: Arc::new(std::sync::Mutex::new( HashSet::new())),
|
||||||
cache: Arc::new(std::sync::Mutex::new(Cache::new(32))),
|
cache: Arc::new(std::sync::Mutex::new(Cache::new(32))),
|
||||||
@ -58,7 +58,7 @@ impl MapTile {
|
|||||||
fn get_tile_task(&self, tile: &Tile) -> BoxFuture<'static, Result<Vec<u8>, Error>> {
|
fn get_tile_task(&self, tile: &Tile) -> BoxFuture<'static, Result<Vec<u8>, Error>> {
|
||||||
let base_url = Url::parse(&self.server).unwrap();
|
let base_url = Url::parse(&self.server).unwrap();
|
||||||
let mut request_url = base_url
|
let mut request_url = base_url
|
||||||
.join(&self.style)
|
.join(&format!("{}/", self.style))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.join(&format!("{}/{}/{}.png", tile.zoom(), tile.x(), tile.y()))
|
.join(&format!("{}/{}/{}.png", tile.zoom(), tile.x(), tile.y()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -164,7 +164,6 @@ impl MapTile {
|
|||||||
if let Some(target) = cache.get(&tile) {
|
if let Some(target) = cache.get(&tile) {
|
||||||
results.push(target);
|
results.push(target);
|
||||||
} else {
|
} else {
|
||||||
debug!("Tile {:?} is not in cache", tile);
|
|
||||||
let center = tile.center_point();
|
let center = tile.center_point();
|
||||||
let mut start_zoom = zoom - 1;
|
let mut start_zoom = zoom - 1;
|
||||||
while start_zoom > 0 {
|
while start_zoom > 0 {
|
||||||
|
|||||||
26
src/utils.rs
26
src/utils.rs
@ -12,6 +12,10 @@ use surfman::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::widgets::render::predefined::color_mapper::BoundaryNorm;
|
use crate::widgets::render::predefined::color_mapper::BoundaryNorm;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::time::{Duration};
|
||||||
|
use tokio::{time, sync::{Mutex, mpsc, oneshot}};
|
||||||
|
use crate::RUNTIME;
|
||||||
|
|
||||||
pub fn meshgrid<T>(x: ArrayView1<T>, y: ArrayView1<T>) -> (Array2<T>, Array2<T>)
|
pub fn meshgrid<T>(x: ArrayView1<T>, y: ArrayView1<T>) -> (Array2<T>, Array2<T>)
|
||||||
where
|
where
|
||||||
@ -331,3 +335,25 @@ pub fn create_kdp_boundarynorm() -> BoundaryNorm<f32> {
|
|||||||
-125.0,
|
-125.0,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn estimate_zoom_level(lat_min: f64, lon_min: f64, lat_max: f64, lon_max: f64, screen_width: f64, screen_height: f64) -> u8 {
|
||||||
|
let r: f64 = 6371.0;
|
||||||
|
let avg_lat = (lat_min + lat_max) / 2.0;
|
||||||
|
// 将经纬度范围转换为在该纬度下的公里数
|
||||||
|
let delta_lon = (lon_max - lon_min) * (r * std::f64::consts::PI / 180.0) * (avg_lat * std::f64::consts::PI / 180.0).cos().abs();
|
||||||
|
let delta_lat = (lat_max - lat_min) * 111.32;
|
||||||
|
|
||||||
|
// 估算每个像素代表的实际距离(公里/像素)
|
||||||
|
let km_per_pixel_x = delta_lon / screen_width;
|
||||||
|
let km_per_pixel_y = delta_lat / screen_height;
|
||||||
|
|
||||||
|
// 选择较小的比例尺
|
||||||
|
let km_per_pixel = km_per_pixel_x.min(km_per_pixel_y);
|
||||||
|
|
||||||
|
// 根据比例尺估算Zoom Level
|
||||||
|
// 这里的比例尺和Zoom Level的对应关系可能需要根据实际地图服务进行调整
|
||||||
|
let zoom_level_estimation = 14.0 - km_per_pixel.log10();
|
||||||
|
|
||||||
|
zoom_level_estimation.round() as u8
|
||||||
|
}
|
||||||
@ -3,19 +3,19 @@ use super::interior::InteriorWidget;
|
|||||||
use super::{Layer, WindowCoord};
|
use super::{Layer, WindowCoord};
|
||||||
use crate::coords::proj::Mercator;
|
use crate::coords::proj::Mercator;
|
||||||
use crate::coords::Mapper;
|
use crate::coords::Mapper;
|
||||||
|
use crate::map_tile::MapTile;
|
||||||
use crate::pipeline::element::{Target, TargetType};
|
use crate::pipeline::element::{Target, TargetType};
|
||||||
use femtovg::{Canvas, Color, FontId, Paint, Renderer};
|
use femtovg::{Canvas, Color, FontId, Paint, Renderer};
|
||||||
use gtk::glib::{self, prelude::*, Properties};
|
use gtk::glib::{self, prelude::*, Properties};
|
||||||
use gtk::subclass::prelude::*;
|
use gtk::subclass::prelude::*;
|
||||||
use gtk::traits::{GLAreaExt, WidgetExt};
|
use gtk::traits::{GLAreaExt, WidgetExt};
|
||||||
|
use slippy_map_tiles::Tile;
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use slippy_map_tiles::Tile;
|
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
use crate::map_tile::MapTile;
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy, PartialEq)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq)]
|
||||||
pub struct RenderConfig {
|
pub struct RenderConfig {
|
||||||
@ -41,12 +41,11 @@ pub struct RenderStatus {
|
|||||||
pub(super) scale_rate: Option<f64>,
|
pub(super) scale_rate: Option<f64>,
|
||||||
pub(super) pointer_location: WindowCoord,
|
pub(super) pointer_location: WindowCoord,
|
||||||
pub(super) motion: RenderMotion,
|
pub(super) motion: RenderMotion,
|
||||||
pub(super) scale: f32,
|
pub(super) view_range: ((f64, f64), (f64, f64)),
|
||||||
pub(super) translate: Option<(f32, f32)>,
|
pub(super) translation: (f64, f64),
|
||||||
pub(super) view_range: Option<((f64, f64), (f64, f64))>,
|
pub(super) init_scale_rate: f64,
|
||||||
translation: Option<(f64, f64)>,
|
pub(super) init_lat_lon: ((f64, f64), (f64, f64)),
|
||||||
init_scale_rate: f64,
|
pub(super) init_translation: (f64, f64),
|
||||||
init_translation: (f64, f64),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Properties)]
|
#[derive(Properties)]
|
||||||
@ -119,7 +118,10 @@ impl WidgetImpl for Render {}
|
|||||||
|
|
||||||
impl GLAreaImpl for Render {
|
impl GLAreaImpl for Render {
|
||||||
fn resize(&self, width: i32, height: i32) {
|
fn resize(&self, width: i32, height: i32) {
|
||||||
self.status.borrow_mut().window_size = Some((width, height));
|
{
|
||||||
|
let mut status = self.status.borrow_mut();
|
||||||
|
status.window_size = Some((width, height));
|
||||||
|
}
|
||||||
self.ensure_canvas();
|
self.ensure_canvas();
|
||||||
let mut canvas = self.canvas.borrow_mut();
|
let mut canvas = self.canvas.borrow_mut();
|
||||||
let canvas = canvas.as_mut().unwrap();
|
let canvas = canvas.as_mut().unwrap();
|
||||||
@ -129,33 +131,35 @@ impl GLAreaImpl for Render {
|
|||||||
self.obj().scale_factor() as f32,
|
self.obj().scale_factor() as f32,
|
||||||
);
|
);
|
||||||
|
|
||||||
let translation = self.status.borrow().translation;
|
let scale_rate = self.status.borrow_mut().scale_rate;
|
||||||
let scale_rate = self.status.borrow().scale_rate;
|
|
||||||
let mapper = self.mapper.borrow();
|
|
||||||
|
|
||||||
if let None = translation {
|
if let Some(scale) = scale_rate {
|
||||||
|
let ((x1,x2), (y1, y2)) = self.view_range().unwrap();
|
||||||
|
// let (x1, y1) = self.map((x1, y1)).unwrap();
|
||||||
|
// let (x2, y2) = self.map((x2, y2)).unwrap();
|
||||||
|
// let scale = ((y2 - y1) / height as f32).min((x2 - x1) / width as f32) as f64;
|
||||||
|
// let mut status = self.status.borrow_mut();
|
||||||
|
// status.scale_rate = Some(scale);
|
||||||
|
} else {
|
||||||
let mut status = self.status.borrow_mut();
|
let mut status = self.status.borrow_mut();
|
||||||
status.translation = Some((mapper.get_bounds().0, mapper.get_bounds().2));
|
let ((y1, y2), (x1, x2)) = status.init_lat_lon;
|
||||||
status.init_translation = (mapper.get_bounds().0, mapper.get_bounds().2);
|
let mapper = self.mapper.borrow();
|
||||||
}
|
let (x1, y1) = mapper.map((x1, y1)).unwrap();
|
||||||
|
let (x2, y2) = mapper.map((x2, y2)).unwrap();
|
||||||
if let None = scale_rate {
|
let scale = ((y2 - y1) / height as f64).min((x2 - x1) / width as f64);
|
||||||
let scale = (mapper.get_bounds().3 - mapper.get_bounds().2) / canvas.height() as f64;
|
status.scale_rate = Some(scale);
|
||||||
self.status.borrow_mut().scale_rate = Some(scale);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&self, context: >k::gdk::GLContext) -> bool {
|
fn render(&self, context: >k::gdk::GLContext) -> bool {
|
||||||
self.ensure_canvas();
|
self.ensure_canvas();
|
||||||
let configs = self.config.borrow();
|
|
||||||
let (w, h) = {
|
{
|
||||||
let mut canvas = self.canvas.borrow_mut();
|
let mut canvas = self.canvas.borrow_mut();
|
||||||
let canvas = canvas.as_mut().unwrap();
|
let canvas = canvas.as_mut().unwrap();
|
||||||
|
|
||||||
let dpi = self.obj().scale_factor();
|
let dpi = self.obj().scale_factor();
|
||||||
let w = canvas.width();
|
let w = canvas.width();
|
||||||
let h = canvas.height();
|
let h = canvas.height();
|
||||||
|
|
||||||
canvas.clear_rect(
|
canvas.clear_rect(
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@ -163,78 +167,27 @@ impl GLAreaImpl for Render {
|
|||||||
(h as i32 * dpi) as u32,
|
(h as i32 * dpi) as u32,
|
||||||
Color::rgba(0, 0, 0, 255),
|
Color::rgba(0, 0, 0, 255),
|
||||||
);
|
);
|
||||||
(w, h)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let binding = self.tiles.borrow();
|
let binding = self.tiles.borrow();
|
||||||
if let Some(tiles) = binding.as_ref() {
|
if let Some(tiles) = binding.as_ref() {
|
||||||
let ((x1 , x2), (y1,y2)) = self.view_range().unwrap();
|
let ((x1, x2), (y1, y2)) = self.view_range().unwrap();
|
||||||
let mut tiles = tiles.current_tiles( ((y1 as f32, y2 as f32), (x1 as f32, x2 as f32)));
|
let mut tiles = tiles.current_tiles(((y1 as f32, y2 as f32), (x1 as f32, x2 as f32)));
|
||||||
for tile in tiles.iter_mut() {
|
for tile in tiles.iter_mut() {
|
||||||
let mut binding = (*tile).lock().unwrap();
|
let mut binding = (*tile).lock().unwrap();
|
||||||
self.draw_target(&mut *binding);
|
self.draw_target(&mut *binding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let render_range = self.status.borrow().view_range.clone();
|
{
|
||||||
if let Some(((lat1, lat2), (lon1, lon2))) = render_range {
|
let configs = self.config.borrow();
|
||||||
let mut status = self.status.borrow_mut();
|
let c = self.interior_layers.borrow();
|
||||||
|
let c = &mut *c.borrow_mut();
|
||||||
let mapper = self.mapper.borrow();
|
self.interior
|
||||||
|
.borrow()
|
||||||
let (tx, ty) = mapper.map((lon1, lat1)).unwrap();
|
.draw(c, &self.obj(), self.status.borrow(), configs);
|
||||||
status.translation.replace((tx, ty));
|
|
||||||
status.init_translation = (tx, ty);
|
|
||||||
|
|
||||||
let (lon1, lat1) = mapper.map((lon1, lat1)).unwrap();
|
|
||||||
let (lon2, lat2) = mapper.map((lon2, lat2)).unwrap();
|
|
||||||
|
|
||||||
let scale = ((lat1 - lat2).abs() / h as f64).max((lon1 - lon2).abs() / w as f64);
|
|
||||||
status.scale_rate.replace(scale);
|
|
||||||
status.init_scale_rate = scale;
|
|
||||||
|
|
||||||
status.view_range = None;
|
|
||||||
} else {
|
|
||||||
let mut status = self.status.borrow_mut();
|
|
||||||
match status.motion {
|
|
||||||
RenderMotion::Translate => {
|
|
||||||
if let Some((x, y)) = status.translate {
|
|
||||||
let (ix, iy) = status.init_translation;
|
|
||||||
status.translation = Some((
|
|
||||||
ix + x as f64 * status.scale_rate.unwrap(),
|
|
||||||
iy + y as f64 * status.scale_rate.unwrap(),
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
status.init_translation = status.translation.unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RenderMotion::Scale => {
|
|
||||||
let scale_rate = status.scale_rate.unwrap();
|
|
||||||
let scale_flag = status.scale as f64;
|
|
||||||
let initial = status.init_scale_rate;
|
|
||||||
let step = scale_rate * 0.1;
|
|
||||||
|
|
||||||
let (tx, ty) = status.translation.unwrap();
|
|
||||||
let (px, py) = status.pointer_location;
|
|
||||||
|
|
||||||
let scaled = scale_rate + scale_flag * step;
|
|
||||||
status.scale_rate = Some(scaled);
|
|
||||||
self.obj().set_scale(initial / scaled);
|
|
||||||
let sx = scale_flag * step * px as f64;
|
|
||||||
let sy = scale_flag * step * py as f64;
|
|
||||||
status.translation = Some((tx - sx, ty - sy));
|
|
||||||
status.init_translation = status.translation.unwrap();
|
|
||||||
}
|
|
||||||
RenderMotion::None => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let c = self.interior_layers.borrow();
|
|
||||||
let c = &mut *c.borrow_mut();
|
|
||||||
self.interior
|
|
||||||
.borrow()
|
|
||||||
.draw(c, &self.obj(), self.status.borrow(), configs);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut canvas = self.canvas.borrow_mut();
|
let mut canvas = self.canvas.borrow_mut();
|
||||||
let canvas = canvas.as_mut().unwrap();
|
let canvas = canvas.as_mut().unwrap();
|
||||||
@ -293,33 +246,27 @@ impl Render {
|
|||||||
h as f32 - padding[0] - padding[2],
|
h as f32 - padding[0] - padding[2],
|
||||||
);
|
);
|
||||||
let (w, h) = (w as f64, h as f64);
|
let (w, h) = (w as f64, h as f64);
|
||||||
|
|
||||||
let mapper = self.mapper.borrow();
|
let mapper = self.mapper.borrow();
|
||||||
|
|
||||||
let status = self.status.borrow();
|
let status = self.status.borrow();
|
||||||
status.translation.and_then(|(tx, ty)| {
|
let (tx, ty) = status.translation;
|
||||||
status.scale_rate.and_then(|scale| {
|
let scale = status.scale_rate;
|
||||||
let (x1, y1) = (tx + padding[3] as f64, ty + padding[2] as f64);
|
let (x1, y1) = (tx + padding[3] as f64, ty + padding[2] as f64);
|
||||||
let (x2, y2) = (
|
let (x2, y2) = (
|
||||||
tx + w * scale + padding[3] as f64,
|
tx + w * scale.unwrap() + padding[3] as f64,
|
||||||
ty + h * scale + padding[2] as f64,
|
ty + h * scale.unwrap() + padding[2] as f64,
|
||||||
);
|
);
|
||||||
let (x1, y1) = mapper.inverse_map((x1, y1)).unwrap();
|
let (x1, y1) = mapper.inverse_map((x1, y1)).unwrap();
|
||||||
let (x2, y2) = mapper.inverse_map((x2, y2)).unwrap();
|
let (x2, y2) = mapper.inverse_map((x2, y2)).unwrap();
|
||||||
Some(((x1, x2), (y1, y2)))
|
Some(((x1, x2), (y1, y2)))
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn inverse_map(&self, loc: (f32, f32)) -> Option<(f64, f64)> {
|
pub(super) fn inverse_map(&self, loc: (f32, f32)) -> Option<(f64, f64)> {
|
||||||
let (x, y) = loc;
|
let (x, y) = loc;
|
||||||
let status = self.status.borrow();
|
let status = self.status.borrow();
|
||||||
status.translation.and_then(|(tx, ty)| {
|
let (tx, ty) = status.translation;
|
||||||
status.scale_rate.and_then(|scale| {
|
let scale = status.scale_rate;
|
||||||
let (x, y) = (x as f64, y as f64);
|
let (x, y) = (x as f64, y as f64);
|
||||||
Some((tx + x * scale, (ty + y * scale)))
|
Some((tx + x * scale.unwrap(), (ty + y * scale.unwrap())))
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn padding(&self) -> [f32; 4] {
|
fn padding(&self) -> [f32; 4] {
|
||||||
@ -330,19 +277,13 @@ impl Render {
|
|||||||
let (x, y) = loc;
|
let (x, y) = loc;
|
||||||
let (_, h) = self.window_size().unwrap();
|
let (_, h) = self.window_size().unwrap();
|
||||||
let status = self.status.borrow();
|
let status = self.status.borrow();
|
||||||
status.translation.and_then(|(tx, ty)| {
|
let (tx, ty) = status.translation;
|
||||||
status.scale_rate.and_then(|scale| {
|
let scale = status.scale_rate;
|
||||||
Some((
|
|
||||||
(x - tx as f64) as f32 / scale as f32,
|
|
||||||
h as f32 - (y - ty as f64) as f32 / scale as f32,
|
|
||||||
))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn set_translation(&self, translation: (f64, f64)) {
|
Some((
|
||||||
let mut status = self.status.borrow_mut();
|
(x - tx) as f32 / scale.unwrap() as f32,
|
||||||
status.translation = Some(translation);
|
h as f32 - (y - ty) as f32 / scale.unwrap() as f32,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pointer_loc(&self) -> (f32, f32) {
|
fn pointer_loc(&self) -> (f32, f32) {
|
||||||
@ -353,10 +294,21 @@ impl Render {
|
|||||||
|
|
||||||
pub(super) fn set_view(&self, range: (f64, f64, f64, f64)) {
|
pub(super) fn set_view(&self, range: (f64, f64, f64, f64)) {
|
||||||
let (lat1, lat2, lon1, lon2) = range;
|
let (lat1, lat2, lon1, lon2) = range;
|
||||||
self.status
|
let mapper = self.mapper.borrow();
|
||||||
.borrow_mut()
|
let lb = mapper.map((lon1, lat1)).unwrap();
|
||||||
.view_range
|
let rt = mapper.map((lon2, lat2)).unwrap();
|
||||||
.replace(((lat1, lat2), (lon1, lon2)));
|
let mut s = self.status.borrow_mut();
|
||||||
|
s.translation = (lb.0, lb.1);
|
||||||
|
s.init_translation = (lb.0, lb.1);
|
||||||
|
s.init_lat_lon = ((lat1, lat2), (lon1, lon2));
|
||||||
|
|
||||||
|
if let Some((w, h)) = s.window_size {
|
||||||
|
let scale = ((rt.0 - lb.0) / w as f64).min((rt.1 - lb.1) / h as f64);
|
||||||
|
s.scale_rate = Some(scale);
|
||||||
|
} else {
|
||||||
|
s.scale_rate = None;
|
||||||
|
}
|
||||||
|
s.view_range = ((lat1, lat2), (lon1, lon2));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn draw_target(&self, target: &mut Target) {
|
pub(super) fn draw_target(&self, target: &mut Target) {
|
||||||
@ -365,13 +317,15 @@ impl Render {
|
|||||||
|
|
||||||
let obj = self.obj();
|
let obj = self.obj();
|
||||||
|
|
||||||
let (ox,oy) = target.origin(&obj);
|
let (ox, oy) = target.origin(&obj);
|
||||||
let (x, y) = target.size(&obj);
|
let (x, y) = target.size(&obj);
|
||||||
|
|
||||||
let id = match target.target{
|
let id = match target.target {
|
||||||
TargetType:: ImageId(id) => id,
|
TargetType::ImageId(id) => id,
|
||||||
TargetType::Mem(ref mem) => {
|
TargetType::Mem(ref mem) => {
|
||||||
let converted = canvas.load_image_mem(mem, femtovg::ImageFlags::empty()).unwrap();
|
let converted = canvas
|
||||||
|
.load_image_mem(mem, femtovg::ImageFlags::empty())
|
||||||
|
.unwrap();
|
||||||
target.set_target(TargetType::ImageId(converted));
|
target.set_target(TargetType::ImageId(converted));
|
||||||
converted
|
converted
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,25 +6,26 @@ pub mod predefined;
|
|||||||
pub mod renders;
|
pub mod renders;
|
||||||
pub mod widget;
|
pub mod widget;
|
||||||
// pub use self::cms::CMS;
|
// pub use self::cms::CMS;
|
||||||
use crate::coords::cms::CMS;
|
|
||||||
pub use self::imp::{RenderConfig, RenderMotion, RenderStatus};
|
pub use self::imp::{RenderConfig, RenderMotion, RenderStatus};
|
||||||
|
use crate::components::messages::MonitorInputMsg;
|
||||||
|
use crate::coords::cms::CMS;
|
||||||
use crate::coords::{Mapper, Range};
|
use crate::coords::{Mapper, Range};
|
||||||
|
use crate::errors::PipelineError;
|
||||||
|
use crate::map_tile::MapTile;
|
||||||
|
use crate::pipeline::element::{Target, TargetType};
|
||||||
use adw::prelude::{GLAreaExt, GestureDragExt};
|
use adw::prelude::{GLAreaExt, GestureDragExt};
|
||||||
|
use femtovg::ImageFlags;
|
||||||
use geo_types::LineString;
|
use geo_types::LineString;
|
||||||
use glib::clone;
|
use glib::clone;
|
||||||
pub use glib::subclass::prelude::*;
|
pub use glib::subclass::prelude::*;
|
||||||
use gtk::traits::WidgetExt;
|
use gtk::traits::WidgetExt;
|
||||||
use gtk::{EventControllerScrollFlags, Inhibit};
|
use gtk::{EventControllerScrollFlags, Inhibit};
|
||||||
pub use interior::*;
|
pub use interior::*;
|
||||||
|
use slippy_map_tiles::Tile;
|
||||||
use std::cell::{Ref, RefCell, RefMut};
|
use std::cell::{Ref, RefCell, RefMut};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use femtovg::ImageFlags;
|
|
||||||
use slippy_map_tiles::Tile;
|
|
||||||
use crate::errors::PipelineError;
|
|
||||||
use crate::map_tile::MapTile;
|
|
||||||
use crate::pipeline::element::{Target, TargetType};
|
|
||||||
|
|
||||||
pub type WindowCoord = (f32, f32);
|
pub type WindowCoord = (f32, f32);
|
||||||
|
|
||||||
@ -42,15 +43,12 @@ impl Default for Render {
|
|||||||
impl Render {
|
impl Render {
|
||||||
pub fn new(mapper: Option<Mapper>, cfg: RenderConfig) -> Self {
|
pub fn new(mapper: Option<Mapper>, cfg: RenderConfig) -> Self {
|
||||||
let this: Self = glib::Object::new();
|
let this: Self = glib::Object::new();
|
||||||
{
|
|
||||||
let mut status = this.imp().status.borrow_mut();
|
|
||||||
status.scale = 1.0;
|
|
||||||
}
|
|
||||||
this.imp().config.replace(cfg);
|
this.imp().config.replace(cfg);
|
||||||
if let Some(mapper) = mapper {
|
if let Some(mapper) = mapper {
|
||||||
this.set_mapper(mapper);
|
this.set_mapper(mapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let dpi = this.scale_factor() as f32;
|
||||||
let pointer_location_detecture = gtk::EventControllerMotion::new();
|
let pointer_location_detecture = gtk::EventControllerMotion::new();
|
||||||
pointer_location_detecture.connect_motion(
|
pointer_location_detecture.connect_motion(
|
||||||
clone!( @weak this as r => move |_context, x, y| {
|
clone!( @weak this as r => move |_context, x, y| {
|
||||||
@ -64,35 +62,57 @@ impl Render {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let scale_detecture = gtk::EventControllerScroll::new(EventControllerScrollFlags::VERTICAL);
|
let scale_detecture = gtk::EventControllerScroll::new(EventControllerScrollFlags::VERTICAL);
|
||||||
|
let _r = Mutex::new(this.clone());
|
||||||
|
|
||||||
|
let debouncer = fns::debounce(
|
||||||
|
move |scale: f64| {
|
||||||
|
_r.lock().unwrap().set_scale(scale);
|
||||||
|
},
|
||||||
|
std::time::Duration::from_millis(500),
|
||||||
|
);
|
||||||
|
|
||||||
scale_detecture.connect_scroll(clone!(
|
scale_detecture.connect_scroll(clone!(
|
||||||
@weak this as r => @default-panic,move |_context, _x, y| {
|
@weak this as r => @default-panic,move |_context, _x, y| {
|
||||||
r.update_status(|status|{
|
let mut rate = 0.0;
|
||||||
status.scale = y as f32;
|
r.update_status(|s|{
|
||||||
status.motion = RenderMotion::Scale;
|
let scale_rate = s.scale_rate.unwrap();
|
||||||
});
|
let scale_flag = y as f64;
|
||||||
r.queue_render();
|
let step = scale_rate * 0.1;
|
||||||
Inhibit(false)
|
let (tx, ty) = s.translation;
|
||||||
}
|
let (px, py) = s.pointer_location;
|
||||||
|
let scaled = scale_rate + scale_flag * step;
|
||||||
|
s.scale_rate = Some(scaled);
|
||||||
|
rate = scaled / 1.0;
|
||||||
|
let sx = scale_flag * step * px as f64;
|
||||||
|
let sy = scale_flag * step * py as f64;
|
||||||
|
s.translation = (tx - sx, ty - sy);
|
||||||
|
s.init_translation = s.translation;
|
||||||
|
s.motion = RenderMotion::Scale;
|
||||||
|
});
|
||||||
|
r.queue_render();
|
||||||
|
debouncer.call(rate);
|
||||||
|
Inhibit(true)
|
||||||
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
let drag_detecture = gtk::GestureDrag::new();
|
let drag_detecture = gtk::GestureDrag::new();
|
||||||
drag_detecture.connect_drag_update(clone!(
|
drag_detecture.connect_drag_update(clone!(@weak this as r => move |this, _, _| {
|
||||||
@weak this as r => move |this, _, _| {
|
|
||||||
let (ox, oy) = this.offset().unwrap_or((0.0,0.0));
|
let (ox, oy) = this.offset().unwrap_or((0.0,0.0));
|
||||||
let dpi = r.scale_factor() as f32;
|
|
||||||
r.update_status(|s| {
|
r.update_status(|s| {
|
||||||
s.translate = Some((-ox as f32 * dpi , oy as f32 * dpi));
|
let (ix, iy) = s.init_translation;
|
||||||
|
let x = -ox as f32 * dpi;
|
||||||
|
let y = oy as f32 * dpi;
|
||||||
|
s.translation = (ix + x as f64 * s.scale_rate.unwrap(), iy + y as f64 * s.scale_rate.unwrap());
|
||||||
s.motion = RenderMotion::Translate;
|
s.motion = RenderMotion::Translate;
|
||||||
});
|
});
|
||||||
r.set_range_changing(0.0);
|
r.set_range_changing(0.0);
|
||||||
r.queue_render();
|
r.queue_render();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
drag_detecture.connect_drag_end(clone!(
|
drag_detecture.connect_drag_end(clone!(
|
||||||
@weak this as r => move |_,_,_|{
|
@weak this as r => move |_,_,_|{
|
||||||
r.update_status(|cfg| {
|
r.update_status(|s| {
|
||||||
cfg.translate = None;
|
s.init_translation = s.translation;
|
||||||
cfg.motion = RenderMotion::Translate;
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
r.queue_render();
|
r.queue_render();
|
||||||
@ -103,7 +123,6 @@ impl Render {
|
|||||||
this.add_controller(pointer_location_detecture);
|
this.add_controller(pointer_location_detecture);
|
||||||
this.add_controller(scale_detecture);
|
this.add_controller(scale_detecture);
|
||||||
this.add_controller(drag_detecture);
|
this.add_controller(drag_detecture);
|
||||||
|
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,12 +240,25 @@ impl Render {
|
|||||||
self.queue_render();
|
self.queue_render();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_img_mem(&self, img: &[u8], origin:(f64,f64),size :(f32,f32), bounds: (Range, Range)) -> Result<Target, PipelineError> {
|
pub fn load_img_mem(
|
||||||
|
&self,
|
||||||
|
img: &[u8],
|
||||||
|
origin: (f64, f64),
|
||||||
|
size: (f32, f32),
|
||||||
|
bounds: (Range, Range),
|
||||||
|
) -> Result<Target, PipelineError> {
|
||||||
let mut canvas = self.get_canvas();
|
let mut canvas = self.get_canvas();
|
||||||
let cvs = canvas.as_mut().unwrap();
|
let cvs = canvas.as_mut().unwrap();
|
||||||
let img_id = cvs.load_image_mem(img, ImageFlags::empty()).unwrap();
|
let img_id = cvs.load_image_mem(img, ImageFlags::empty()).unwrap();
|
||||||
let (width, height) = size;
|
let (width, height) = size;
|
||||||
Ok(Target::new(TargetType::ImageId(img_id), width, height, bounds, None, None))
|
Ok(Target::new(
|
||||||
|
TargetType::ImageId(img_id),
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
bounds,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_img(&self, img: Target) {
|
pub fn delete_img(&self, img: Target) {
|
||||||
@ -236,8 +268,6 @@ impl Render {
|
|||||||
cvs.delete_image(id);
|
cvs.delete_image(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_scale(&self) -> f32 {
|
|
||||||
self.imp().status.borrow().scale
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for Render {}
|
||||||
Loading…
Reference in New Issue
Block a user