sync
This commit is contained in:
parent
b6537055ba
commit
de324daada
50
Cargo.lock
generated
50
Cargo.lock
generated
@ -92,6 +92,19 @@ dependencies = [
|
|||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.8.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"getrandom",
|
||||||
|
"once_cell",
|
||||||
|
"version_check",
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
@ -525,6 +538,7 @@ dependencies = [
|
|||||||
"proj",
|
"proj",
|
||||||
"proj-sys",
|
"proj-sys",
|
||||||
"quadtree_rs",
|
"quadtree_rs",
|
||||||
|
"quick_cache",
|
||||||
"radarg_plugin_interface",
|
"radarg_plugin_interface",
|
||||||
"rayon",
|
"rayon",
|
||||||
"regex",
|
"regex",
|
||||||
@ -1023,9 +1037,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1"
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
@ -3272,6 +3286,18 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quick_cache"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "58c20af3800cee5134b79a3bd4a3d4b583c16ccfa5f53338f46400851a5b3819"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
"equivalent",
|
||||||
|
"hashbrown",
|
||||||
|
"parking_lot",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "0.6.13"
|
version = "0.6.13"
|
||||||
@ -5131,6 +5157,26 @@ dependencies = [
|
|||||||
"pkg-config",
|
"pkg-config",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.7.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.7.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.76",
|
||||||
|
"quote 1.0.35",
|
||||||
|
"syn 2.0.48",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zip"
|
name = "zip"
|
||||||
version = "0.6.6"
|
version = "0.6.6"
|
||||||
|
|||||||
@ -93,6 +93,7 @@ rgb = "0.8.37"
|
|||||||
slippy-map-tiles = "0.16.0"
|
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"
|
||||||
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
|||||||
@ -7,12 +7,12 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub enum MonitorInputMsg {
|
pub enum MonitorInputMsg {
|
||||||
NewElement((ElementKey, ElementID)),
|
|
||||||
AddWidget(Box<dyn Widget>),
|
AddWidget(Box<dyn Widget>),
|
||||||
RemoveWidget,
|
RemoveWidget,
|
||||||
AddMetaItem(HashMap<String, String>),
|
AddMetaItem(HashMap<String, String>),
|
||||||
ClearMetaItems,
|
ClearMetaItems,
|
||||||
UpdateMetaItem(HashMap<String, String>),
|
UpdateMetaItem(HashMap<String, String>),
|
||||||
|
RefreshTiles,
|
||||||
RefreshLayerList,
|
RefreshLayerList,
|
||||||
SetRenderRange(f64, f64, f64, f64),
|
SetRenderRange(f64, f64, f64, f64),
|
||||||
ChangeZoom(u8),
|
ChangeZoom(u8),
|
||||||
@ -22,10 +22,10 @@ pub enum MonitorInputMsg {
|
|||||||
impl Debug for MonitorInputMsg {
|
impl Debug for MonitorInputMsg {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
MonitorInputMsg::RefreshTiles => write!(f, "MonitorInputMsg::RefreshTiles"),
|
||||||
MonitorInputMsg::ChangeZoom(_) => write!(f, "MonitorInputMsg::ChangeZoom"),
|
MonitorInputMsg::ChangeZoom(_) => write!(f, "MonitorInputMsg::ChangeZoom"),
|
||||||
MonitorInputMsg::SetRenderRange(_, _, _, _) => write!(f, "MonitorInputMsg::SetRenderRange"),
|
MonitorInputMsg::SetRenderRange(_, _, _, _) => write!(f, "MonitorInputMsg::SetRenderRange"),
|
||||||
MonitorInputMsg::RefreshLayerList => write!(f, "MonitorInputMsg::RefreshLayerList"),
|
MonitorInputMsg::RefreshLayerList => write!(f, "MonitorInputMsg::RefreshLayerList"),
|
||||||
MonitorInputMsg::NewElement(_) => write!(f, "MonitorInputMsg::NewElement"),
|
|
||||||
MonitorInputMsg::None => write!(f, "MonitorInputMsg::None"),
|
MonitorInputMsg::None => write!(f, "MonitorInputMsg::None"),
|
||||||
MonitorInputMsg::AddWidget(_) => write!(f, "MonitorInputMsg::AddWidget"),
|
MonitorInputMsg::AddWidget(_) => write!(f, "MonitorInputMsg::AddWidget"),
|
||||||
MonitorInputMsg::RemoveWidget => write!(f, "MonitorInputMsg::RemoveWidget"),
|
MonitorInputMsg::RemoveWidget => write!(f, "MonitorInputMsg::RemoveWidget"),
|
||||||
|
|||||||
@ -26,6 +26,7 @@ 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 quick_cache::unsync::Cache;
|
||||||
use relm4::{component::Component, *};
|
use relm4::{component::Component, *};
|
||||||
use slippy_map_tiles::Tile;
|
use slippy_map_tiles::Tile;
|
||||||
use tokio::task;
|
use tokio::task;
|
||||||
@ -44,7 +45,9 @@ pub struct MonitorModel {
|
|||||||
sidebar_width: i32,
|
sidebar_width: i32,
|
||||||
zoom: u8,
|
zoom: u8,
|
||||||
#[do_not_track]
|
#[do_not_track]
|
||||||
map_tile_getter: Arc<MapTile>,
|
tile_cache: Cache<Tile, Target>,
|
||||||
|
#[do_not_track]
|
||||||
|
map_tile_getter: Arc<tokio::sync::Mutex<MapTile>>,
|
||||||
#[do_not_track]
|
#[do_not_track]
|
||||||
tiles: Rc<RefCell<HashMap<Tile, Option<Target>>>>,
|
tiles: Rc<RefCell<HashMap<Tile, Option<Target>>>>,
|
||||||
new_layer: i8,
|
new_layer: i8,
|
||||||
@ -102,41 +105,15 @@ impl Component for MonitorModel {
|
|||||||
},
|
},
|
||||||
set_tiles: model.tiles.clone(),
|
set_tiles: model.tiles.clone(),
|
||||||
connect_range_changing_notify[sender] => move |r| {
|
connect_range_changing_notify[sender] => move |r| {
|
||||||
let map_tile_getter = map_tile_getter.clone();
|
sender.input(MonitorInputMsg::RefreshTiles);
|
||||||
let ((x1 , x2), (y1,y2))= r.render_range();
|
|
||||||
let new_tiles = map_tile_getter.new_tiles(model.zoom ,(y1 as f32, y2 as f32),(x1 as f32,x2 as f32));
|
|
||||||
let mut tiles = (*tiles).borrow_mut();
|
|
||||||
let new_tiles = new_tiles.filter(|x| !tiles.contains_key(x)).collect::<Vec<_>>();
|
|
||||||
tiles.extend(new_tiles.iter().map(|x| (*x, None)));
|
|
||||||
|
|
||||||
|
|
||||||
if new_tiles.len() > 0 {
|
|
||||||
let new_sender = sender.clone();
|
|
||||||
sender.oneshot_command(async move {
|
|
||||||
for tile in new_tiles {
|
|
||||||
let map_tile_getter = map_tile_getter.clone();
|
|
||||||
let sender = new_sender.clone();
|
|
||||||
task::spawn(async move {
|
|
||||||
info!("Loading tile {:?}", tile);
|
|
||||||
let result = map_tile_getter.get_tile(&tile).await;
|
|
||||||
if let Ok(result) = result {
|
|
||||||
let origin = tile.nw_corner();
|
|
||||||
let rb = tile.se_corner();
|
|
||||||
let bounds = ((origin.lon() as f64..rb.lon() as f64).into(), (origin.lat() as f64..rb.lat() as f64).into());
|
|
||||||
sender.command_sender().emit(MonitorCommand::LoadTile(tile, result,(origin.lon() as f64, origin.lat() as f64), bounds));
|
|
||||||
}
|
|
||||||
}).await;
|
|
||||||
}
|
|
||||||
MonitorCommand::None
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
connect_scale_notify[sender] => move |r| {
|
connect_scale_notify[sender] => move |r| {
|
||||||
// let ((x1 , x2), (y1,y2))= r.render_range();
|
let scale_factor = r.scale();
|
||||||
// let w = r.width() as f32;
|
let zoom = scale_factor.log2().round() as u8;
|
||||||
// let h = r.height() as f32;
|
let new_zoom = model.zoom + zoom;
|
||||||
// let zoom = lat_lon_to_zoom((y1,y2), (x1,x2),w, h);
|
if model.zoom != new_zoom {
|
||||||
// sender.input(MonitorInputMsg::ChangeZoom(zoom));
|
sender.input(MonitorInputMsg::ChangeZoom(new_zoom));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
set_interior_layers: model.layers.clone(),
|
set_interior_layers: model.layers.clone(),
|
||||||
},
|
},
|
||||||
@ -183,6 +160,10 @@ impl Component for MonitorModel {
|
|||||||
self.sidebar.emit(SideBarInputMsg::ClearMetaItems);
|
self.sidebar.emit(SideBarInputMsg::ClearMetaItems);
|
||||||
self.sidebar.emit(SideBarInputMsg::AddMetaItems(map))
|
self.sidebar.emit(SideBarInputMsg::AddMetaItems(map))
|
||||||
}
|
}
|
||||||
|
MonitorInputMsg::RefreshTiles => {
|
||||||
|
let ((x1 , x2), (y1,y2)) = widgets.renderer.render_range();
|
||||||
|
// Self::load_cache_tile(&mut self.tile_cache,&sender, &self.map_tile_getter, self.zoom, ((y1 as f32, y2 as f32),(x1 as f32,x2 as f32)));
|
||||||
|
}
|
||||||
MonitorInputMsg::AddWidget(widget) => match widget.widget_type() {
|
MonitorInputMsg::AddWidget(widget) => match widget.widget_type() {
|
||||||
WidgetType::Cairo => {
|
WidgetType::Cairo => {
|
||||||
let frame = WidgetFrame::new();
|
let frame = WidgetFrame::new();
|
||||||
@ -195,14 +176,7 @@ impl Component for MonitorModel {
|
|||||||
MonitorInputMsg::ChangeZoom(zoom) => {
|
MonitorInputMsg::ChangeZoom(zoom) => {
|
||||||
if self.zoom != zoom {
|
if self.zoom != zoom {
|
||||||
self.zoom = zoom;
|
self.zoom = zoom;
|
||||||
|
sender.input(MonitorInputMsg::RefreshTiles);
|
||||||
let mut ts = self.tiles.borrow_mut();
|
|
||||||
|
|
||||||
for (k,v) in ts.drain() {
|
|
||||||
if let Some(v) = v {
|
|
||||||
widgets.renderer.delete_img(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MonitorInputMsg::RemoveWidget => {}
|
MonitorInputMsg::RemoveWidget => {}
|
||||||
@ -239,24 +213,19 @@ impl Component for MonitorModel {
|
|||||||
widgets: vec![],
|
widgets: vec![],
|
||||||
tiles: Rc::new(RefCell::new(HashMap::new())),
|
tiles: Rc::new(RefCell::new(HashMap::new())),
|
||||||
render_cfg,
|
render_cfg,
|
||||||
|
tile_cache: Cache::new(32),
|
||||||
sidebar_open: true,
|
sidebar_open: true,
|
||||||
sidebar_width: 400,
|
sidebar_width: 400,
|
||||||
layers: init,
|
layers: init,
|
||||||
zoom: 4,
|
zoom: 4,
|
||||||
map_tile_getter: Arc::new(MapTile::default()),
|
map_tile_getter: Arc::new(tokio::sync::Mutex::new( MapTile::default())),
|
||||||
sidebar,
|
sidebar,
|
||||||
tracker: 0,
|
tracker: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
let map_tile_getter = model.map_tile_getter.clone();
|
let map_tile_getter = model.map_tile_getter.clone();
|
||||||
let tiles = model.tiles.clone();
|
let tiles = model.tiles.clone();
|
||||||
|
|
||||||
let widgets = view_output! {};
|
let widgets = view_output! {};
|
||||||
|
|
||||||
// let (h, w) = (widgets.renderer.height(), widgets.renderer.width());
|
|
||||||
// let zoom = lat_lon_to_zoom((4.0, 53.3), (73.3, 135.0), w as f32, h as f32);
|
|
||||||
// model.zoom = zoom;
|
|
||||||
|
|
||||||
ComponentParts { model, widgets }
|
ComponentParts { model, widgets }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,13 +243,56 @@ impl Component for MonitorModel {
|
|||||||
.renderer
|
.renderer
|
||||||
.load_img_mem(&tile, origin, (256f32, 256f32), bounds)
|
.load_img_mem(&tile, origin, (256f32, 256f32), bounds)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// self.tiles.borrow_mut().insert(key, target);
|
let mut binding = self.tiles.borrow_mut();
|
||||||
// *self.tiles.borrow_mut().get_mut(&key) = Some(target);
|
if !binding.contains_key(&key) {
|
||||||
self.tiles.borrow_mut().entry(key).and_modify(|x| *x = Some(target));
|
return ;
|
||||||
widgets.render.queue_draw();
|
}
|
||||||
|
binding.entry(key).and_modify(|x| *x = Some(target));
|
||||||
|
widgets.renderer.queue_draw();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
self.update_view(widgets, sender);
|
self.update_view(widgets, sender);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl MonitorModel {
|
||||||
|
fn load_tile(tiles: &Rc<RefCell<HashMap<Tile, Option<Target>>>> ,sender: &ComponentSender<Self>, map_tile_getter: &Arc<MapTile>, zoom:u8, range:((f32,f32), (f32,f32))) {
|
||||||
|
|
||||||
|
let map_tile_getter = map_tile_getter.clone();
|
||||||
|
let new_tiles = map_tile_getter.new_tiles(zoom ,range.0, range.1);
|
||||||
|
let mut tiles = (*tiles).borrow_mut();
|
||||||
|
let new_tiles = new_tiles.filter(|x| !tiles.contains_key(x)).collect::<Vec<_>>();
|
||||||
|
tiles.extend(new_tiles.iter().map(|x| (*x, None)));
|
||||||
|
|
||||||
|
if new_tiles.len() > 0 {
|
||||||
|
let new_sender = sender.clone();
|
||||||
|
sender.oneshot_command(async move {
|
||||||
|
for tile in new_tiles {
|
||||||
|
let map_tile_getter = map_tile_getter.clone();
|
||||||
|
let sender = new_sender.clone();
|
||||||
|
task::spawn(async move {
|
||||||
|
let result = map_tile_getter.get_tile(&tile).await;
|
||||||
|
if let Ok(result) = result {
|
||||||
|
let origin = tile.nw_corner();
|
||||||
|
let rb = tile.se_corner();
|
||||||
|
let bounds = ((origin.lon() as f64..rb.lon() as f64).into(), (origin.lat() as f64..rb.lat() as f64).into());
|
||||||
|
sender.command_sender().emit(MonitorCommand::LoadTile(tile, result,(origin.lon() as f64, origin.lat() as f64), bounds));
|
||||||
|
}
|
||||||
|
}).await;
|
||||||
|
}
|
||||||
|
MonitorCommand::None
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_tiles(&self, sender: &ComponentSender<Self>,range:((f32,f32), (f32,f32))) {
|
||||||
|
|
||||||
|
// sender.oneshot_command(async move {
|
||||||
|
// MapTile::load_tiles(self.map_tile_getter.clone(), self.zoom, range).await;
|
||||||
|
// MonitorCommand::None
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
149
src/map_tile.rs
149
src/map_tile.rs
@ -1,14 +1,30 @@
|
|||||||
use crate::map_tile_utils::lat_lon_to_zoom;
|
|
||||||
use femtovg::ImageSource;
|
|
||||||
use reqwest::{Client, Error, Url};
|
|
||||||
use slippy_map_tiles::{BBox, merc_location_to_tile_coords, Tile};
|
|
||||||
use crate::coords::Range;
|
use crate::coords::Range;
|
||||||
|
use crate::map_tile_utils::lat_lon_to_zoom;
|
||||||
|
use crate::pipeline::element::{Target, TargetType};
|
||||||
|
use femtovg::ImageSource;
|
||||||
|
use futures::future::BoxFuture;
|
||||||
|
use gtk::ffi::gtk_about_dialog_add_credit_section;
|
||||||
|
use quick_cache::sync::Cache;
|
||||||
|
use reqwest::{Client, Error, Url};
|
||||||
|
use slippy_map_tiles::{merc_location_to_tile_coords, BBox, Tile};
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
use sorted_vec::SortedSet;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use relm4::{ComponentSender, Sender};
|
||||||
|
use tokio::sync::Mutex;
|
||||||
|
use tokio::task;
|
||||||
|
use tracing::{debug, info};
|
||||||
|
use crate::components::messages::MonitorInputMsg;
|
||||||
|
use crate::components::MonitorModel;
|
||||||
|
|
||||||
pub struct MapTile {
|
pub struct MapTile {
|
||||||
server: String,
|
server: String,
|
||||||
api_key: String,
|
api_key: String,
|
||||||
style: String,
|
style: String,
|
||||||
client: Client,
|
client: Client,
|
||||||
|
onloading: HashSet<Tile>,
|
||||||
|
cache: Arc<std::sync::Mutex<Cache<Tile, Arc<Target>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MapTile {
|
impl Default for MapTile {
|
||||||
@ -18,24 +34,45 @@ impl Default for MapTile{
|
|||||||
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_terrain/".to_string(),
|
||||||
client: Client::new(),
|
client: Client::new(),
|
||||||
|
onloading: HashSet::new(),
|
||||||
|
cache: Arc::new(std::sync::Mutex::new(Cache::new(32))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MapTile {
|
impl MapTile {
|
||||||
|
pub fn new_tiles(
|
||||||
pub fn new_tiles(&self, zoom: u8, lat_range: (f32, f32), lon_range: (f32, f32)) -> impl Iterator<Item = Tile> + Sized {
|
&self,
|
||||||
|
zoom: u8,
|
||||||
|
lat_range: (f32, f32),
|
||||||
|
lon_range: (f32, f32),
|
||||||
|
) -> impl Iterator<Item = Tile> + Sized {
|
||||||
let bbox = BBox::new(lat_range.1, lon_range.0, lat_range.0, lon_range.1).unwrap();
|
let bbox = BBox::new(lat_range.1, lon_range.0, lat_range.0, lon_range.1).unwrap();
|
||||||
let tiles = bbox.tiles_for_zoom(zoom);
|
let tiles = bbox.tiles_for_zoom(zoom);
|
||||||
tiles
|
tiles
|
||||||
}
|
}
|
||||||
pub async fn get_tile(
|
|
||||||
&self,
|
fn get_tile_task(&self, tile: &Tile) -> BoxFuture<'static, Result<Vec<u8>, Error>> {
|
||||||
tile: &Tile
|
let base_url = Url::parse(&self.server).unwrap();
|
||||||
) -> Result<Vec<u8>, Error>
|
let mut request_url = base_url
|
||||||
{
|
.join(&self.style)
|
||||||
|
.unwrap()
|
||||||
|
.join(&format!("{}/{}/{}.png", tile.zoom(), tile.x(), tile.y()))
|
||||||
|
.unwrap();
|
||||||
|
let client = self.client.clone();
|
||||||
|
let key = self.api_key.clone();
|
||||||
|
Box::pin(async move {
|
||||||
|
let result = client
|
||||||
|
.get(request_url)
|
||||||
|
.query(&[("api_key", &key)])
|
||||||
|
.send()
|
||||||
|
.await?;
|
||||||
|
let bytes = result.bytes().await?;
|
||||||
|
Ok(bytes.to_vec())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub async fn get_tile(&self, tile: &Tile) -> Result<Vec<u8>, Error> {
|
||||||
let base_url = Url::parse(&self.server).unwrap();
|
let base_url = Url::parse(&self.server).unwrap();
|
||||||
// let zoom = lat_lon_to_zoom(lat_range, lat_range, w, h);
|
|
||||||
let mut request_url = base_url
|
let mut request_url = base_url
|
||||||
.join(&self.style)
|
.join(&self.style)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -51,4 +88,92 @@ impl MapTile {
|
|||||||
let bytes = result.bytes().await?;
|
let bytes = result.bytes().await?;
|
||||||
Ok(bytes.to_vec())
|
Ok(bytes.to_vec())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn load_tiles(
|
||||||
|
&self,
|
||||||
|
zoom: u8,
|
||||||
|
range: ((f32, f32), (f32, f32)),
|
||||||
|
sender: ComponentSender<MonitorModel>,
|
||||||
|
) -> BoxFuture<'static, ()> {
|
||||||
|
let new_tiles = self.new_tiles(zoom, range.0, range.1);
|
||||||
|
let cache = (*self.cache).lock().unwrap();
|
||||||
|
let new_tiles = new_tiles
|
||||||
|
.filter(|x| cache.peek(x).is_none() && !self.onloading.contains(x))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if new_tiles.len() > 0 {
|
||||||
|
let tasks = new_tiles.into_iter().map(move |tile| {
|
||||||
|
let _task = self.get_tile_task(&tile);
|
||||||
|
let sender = sender.clone();
|
||||||
|
let cache = self.cache.clone();
|
||||||
|
task::spawn(async move {
|
||||||
|
let result = _task.await;
|
||||||
|
if let Ok(result) = result {
|
||||||
|
let origin = tile.nw_corner();
|
||||||
|
let rb = tile.se_corner();
|
||||||
|
let bounds = (
|
||||||
|
(origin.lon() as f64..rb.lon() as f64).into(),
|
||||||
|
(origin.lat() as f64..rb.lat() as f64).into(),
|
||||||
|
);
|
||||||
|
let result = Target::new(
|
||||||
|
TargetType::Mem(result),
|
||||||
|
256.0,
|
||||||
|
256.0,
|
||||||
|
bounds,
|
||||||
|
None,
|
||||||
|
None
|
||||||
|
);
|
||||||
|
cache.lock().unwrap().insert(tile, Arc::new(result));
|
||||||
|
sender.input(MonitorInputMsg::RefreshTiles);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
Box::pin(async move {
|
||||||
|
for task in tasks {
|
||||||
|
task.await.unwrap();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
debug!("No new tiles to load");
|
||||||
|
}
|
||||||
|
|
||||||
|
Box::pin(async move {})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current_tiles(&self, zoom: u8, range: ((f32, f32), (f32, f32))) -> Vec<Arc<Target>> {
|
||||||
|
let current = self.new_tiles(zoom, range.0, range.1);
|
||||||
|
let mut total_len = 0;
|
||||||
|
let mut results = Vec::new();
|
||||||
|
let mut cached = Vec::new();
|
||||||
|
let cache = self.cache.lock().unwrap();
|
||||||
|
for tile in current {
|
||||||
|
total_len += 1;
|
||||||
|
if let Some(target) = cache.get(&tile) {
|
||||||
|
results.push(target);
|
||||||
|
} else {
|
||||||
|
debug!("Tile {:?} is not in cache", tile);
|
||||||
|
let center = tile.center_point();
|
||||||
|
let mut start_zoom = zoom - 1;
|
||||||
|
while start_zoom > 0 {
|
||||||
|
let (tile, (x, y)) = merc_location_to_tile_coords(
|
||||||
|
center.lon() as f64,
|
||||||
|
center.lat() as f64,
|
||||||
|
start_zoom,
|
||||||
|
);
|
||||||
|
let tile = Tile::new(start_zoom, x, y).unwrap();
|
||||||
|
if cached.contains(&tile) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
cached.push(tile);
|
||||||
|
}
|
||||||
|
if let Some(target) = cache.get(&tile) {
|
||||||
|
results.insert(0, target);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
start_zoom -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
results
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,7 @@ 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 slippy_map_tiles::Tile;
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy, PartialEq)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq)]
|
||||||
pub struct RenderConfig {
|
pub struct RenderConfig {
|
||||||
@ -43,6 +44,7 @@ pub struct RenderStatus {
|
|||||||
pub(super) translate: Option<(f32, f32)>,
|
pub(super) translate: Option<(f32, f32)>,
|
||||||
pub(super) view_range: Option<((f64, f64), (f64, f64))>,
|
pub(super) view_range: Option<((f64, f64), (f64, f64))>,
|
||||||
translation: Option<(f64, f64)>,
|
translation: Option<(f64, f64)>,
|
||||||
|
init_scale_rate: f64,
|
||||||
init_translation: (f64, f64),
|
init_translation: (f64, f64),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,6 +189,7 @@ impl GLAreaImpl for Render {
|
|||||||
|
|
||||||
let scale = ((lat1 - lat2).abs() / h as f64).max((lon1 - lon2).abs() / w as f64);
|
let scale = ((lat1 - lat2).abs() / h as f64).max((lon1 - lon2).abs() / w as f64);
|
||||||
status.scale_rate.replace(scale);
|
status.scale_rate.replace(scale);
|
||||||
|
status.init_scale_rate = scale;
|
||||||
|
|
||||||
status.view_range = None;
|
status.view_range = None;
|
||||||
} else {
|
} else {
|
||||||
@ -206,6 +209,7 @@ impl GLAreaImpl for Render {
|
|||||||
RenderMotion::Scale => {
|
RenderMotion::Scale => {
|
||||||
let scale_rate = status.scale_rate.unwrap();
|
let scale_rate = status.scale_rate.unwrap();
|
||||||
let scale_flag = status.scale as f64;
|
let scale_flag = status.scale as f64;
|
||||||
|
let initial = status.init_scale_rate;
|
||||||
let step = scale_rate * 0.1;
|
let step = scale_rate * 0.1;
|
||||||
|
|
||||||
let (tx, ty) = status.translation.unwrap();
|
let (tx, ty) = status.translation.unwrap();
|
||||||
@ -213,7 +217,7 @@ impl GLAreaImpl for Render {
|
|||||||
|
|
||||||
let scaled = scale_rate + scale_flag * step;
|
let scaled = scale_rate + scale_flag * step;
|
||||||
status.scale_rate = Some(scaled);
|
status.scale_rate = Some(scaled);
|
||||||
self.obj().set_scale(scaled as f64);
|
self.obj().set_scale(initial / scaled);
|
||||||
let sx = scale_flag * step * px as f64;
|
let sx = scale_flag * step * px as f64;
|
||||||
let sy = scale_flag * step * py as f64;
|
let sy = scale_flag * step * py as f64;
|
||||||
status.translation = Some((tx - sx, ty - sy));
|
status.translation = Some((tx - sx, ty - sy));
|
||||||
|
|||||||
@ -69,7 +69,6 @@ impl Render {
|
|||||||
status.scale = y as f32;
|
status.scale = y as f32;
|
||||||
status.motion = RenderMotion::Scale;
|
status.motion = RenderMotion::Scale;
|
||||||
});
|
});
|
||||||
r.set_range_changing(0.0);
|
|
||||||
r.queue_render();
|
r.queue_render();
|
||||||
Inhibit(false)
|
Inhibit(false)
|
||||||
}
|
}
|
||||||
@ -233,10 +232,12 @@ impl Render {
|
|||||||
pub fn delete_img(&self, img: Target) {
|
pub fn delete_img(&self, img: Target) {
|
||||||
let mut canvas = self.get_canvas();
|
let mut canvas = self.get_canvas();
|
||||||
let cvs = canvas.as_mut().unwrap();
|
let cvs = canvas.as_mut().unwrap();
|
||||||
// cvs.delete_image()
|
|
||||||
|
|
||||||
if let TargetType::ImageId(id) = img.target {
|
if let TargetType::ImageId(id) = img.target {
|
||||||
cvs.delete_image(id);
|
cvs.delete_image(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_scale(&self) -> f32 {
|
||||||
|
self.imp().status.borrow().scale
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user