From 41c71222bc8bf351778846bb37ca63676a5147fb Mon Sep 17 00:00:00 2001 From: Piotr Podusowski Date: Sun, 24 Nov 2024 11:05:19 +0100 Subject: [PATCH 01/15] consider other values --- walkers/src/tiles.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/walkers/src/tiles.rs b/walkers/src/tiles.rs index 2272957..de7c0a7 100644 --- a/walkers/src/tiles.rs +++ b/walkers/src/tiles.rs @@ -8,6 +8,7 @@ use crate::download::{download_continuously, HttpOptions, MAX_PARALLEL_DOWNLOADS use crate::io::Runtime; use crate::mercator::TileId; use crate::sources::{Attribution, TileSource}; +use crate::zoom::Zoom; pub(crate) fn rect(screen_position: Vec2, tile_size: f64) -> Rect { Rect::from_min_size(screen_position.to_pos2(), Vec2::splat(tile_size as f32)) @@ -168,17 +169,18 @@ impl HttpTiles { /// Find tile with a different zoom, which could be used as a placeholder. fn placeholder_with_different_zoom(&mut self, tile_id: TileId) -> Option { - // Currently, only a single zoom level down is supported. + let mut zoom_candidate = tile_id.zoom; - let (zoomed_tile_id, uv) = interpolate_higher_zoom(tile_id, tile_id.zoom.checked_sub(1)?); + loop { + zoom_candidate = zoom_candidate.checked_sub(1)?; + let (zoomed_tile_id, uv) = interpolate_higher_zoom(tile_id, zoom_candidate); - if let Some(Some(texture)) = self.cache.get(&zoomed_tile_id) { - Some(TextureWithUv { - texture: texture.clone(), - uv, - }) - } else { - None + if let Some(Some(texture)) = self.cache.get(&zoomed_tile_id) { + break Some(TextureWithUv { + texture: texture.clone(), + uv, + }); + } } } } From a04711d5acea1bb7f1af64cdc7b0106b44ca2b3e Mon Sep 17 00:00:00 2001 From: Piotr Podusowski Date: Sun, 24 Nov 2024 11:19:38 +0100 Subject: [PATCH 02/15] warning fixed --- walkers/src/tiles.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/walkers/src/tiles.rs b/walkers/src/tiles.rs index de7c0a7..2698aa9 100644 --- a/walkers/src/tiles.rs +++ b/walkers/src/tiles.rs @@ -8,7 +8,6 @@ use crate::download::{download_continuously, HttpOptions, MAX_PARALLEL_DOWNLOADS use crate::io::Runtime; use crate::mercator::TileId; use crate::sources::{Attribution, TileSource}; -use crate::zoom::Zoom; pub(crate) fn rect(screen_position: Vec2, tile_size: f64) -> Rect { Rect::from_min_size(screen_position.to_pos2(), Vec2::splat(tile_size as f32)) From ed81c8c596ea02474f5697a115ec2419b2b3b162 Mon Sep 17 00:00:00 2001 From: Piotr Podusowski Date: Sun, 24 Nov 2024 11:20:52 +0100 Subject: [PATCH 03/15] comment --- walkers/src/tiles.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/walkers/src/tiles.rs b/walkers/src/tiles.rs index 2698aa9..f862fb6 100644 --- a/walkers/src/tiles.rs +++ b/walkers/src/tiles.rs @@ -171,7 +171,9 @@ impl HttpTiles { let mut zoom_candidate = tile_id.zoom; loop { + // Keep zooming out until we find a tile or there is no more zoom levels. zoom_candidate = zoom_candidate.checked_sub(1)?; + let (zoomed_tile_id, uv) = interpolate_higher_zoom(tile_id, zoom_candidate); if let Some(Some(texture)) = self.cache.get(&zoomed_tile_id) { From 93a1a8efcbdd354c90f94281f505e3cc90274548 Mon Sep 17 00:00:00 2001 From: Piotr Podusowski Date: Sun, 24 Nov 2024 19:40:00 +0100 Subject: [PATCH 04/15] put download request into a fn --- walkers/src/tiles.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/walkers/src/tiles.rs b/walkers/src/tiles.rs index f862fb6..2f4485c 100644 --- a/walkers/src/tiles.rs +++ b/walkers/src/tiles.rs @@ -136,7 +136,7 @@ impl HttpTiles { } } - fn put_next_downloaded_tile_in_cache(&mut self) { + fn put_single_downloaded_tile_in_cache(&mut self) { // This is called every frame, so take just one at the time. match self.tile_rx.try_next() { Ok(Some((tile_id, tile))) => { @@ -151,17 +151,21 @@ impl HttpTiles { } } + fn download(&mut self, tile_id: TileId) { + if let Ok(()) = self.request_tx.try_send(tile_id) { + log::trace!("Requested tile: {:?}", tile_id); + + // None acts as a placeholder for the tile, preventing multiple + // requests for the same tile. + self.cache.put(tile_id, None); + } else { + log::debug!("Request queue is full."); + } + } + fn request_tile(&mut self, tile_id: TileId) -> Option { self.cache.get(&tile_id).cloned().unwrap_or_else(|| { - if let Ok(()) = self.request_tx.try_send(tile_id) { - log::trace!("Requested tile: {:?}", tile_id); - - // None acts as a placeholder for the tile, preventing multiple - // requests for the same tile. - self.cache.put(tile_id, None); - } else { - log::debug!("Request queue is full."); - } + self.download(tile_id); None }) } @@ -220,7 +224,7 @@ impl Tiles for HttpTiles { /// Return a tile if already in cache, schedule a download otherwise. fn at(&mut self, tile_id: TileId) -> Option { - self.put_next_downloaded_tile_in_cache(); + self.put_single_downloaded_tile_in_cache(); if tile_id.zoom <= self.max_zoom { self.request_tile(tile_id) From 6c5b29af44f4d1395851bea0ee995a31f76a270c Mon Sep 17 00:00:00 2001 From: Piotr Podusowski Date: Tue, 3 Dec 2024 22:49:50 +0100 Subject: [PATCH 05/15] reworked at logic --- walkers/src/tiles.rs | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/walkers/src/tiles.rs b/walkers/src/tiles.rs index 2f4485c..ef2dc7c 100644 --- a/walkers/src/tiles.rs +++ b/walkers/src/tiles.rs @@ -123,7 +123,7 @@ impl HttpTiles { // Just arbitrary value which seemed right. #[allow(clippy::unwrap_used)] - let cache_size = std::num::NonZeroUsize::new(256).unwrap(); + let cache_size = std::num::NonZeroUsize::new(1024).unwrap(); Self { attribution, @@ -152,6 +152,10 @@ impl HttpTiles { } fn download(&mut self, tile_id: TileId) { + if self.cache.contains(&tile_id) { + return; + } + if let Ok(()) = self.request_tx.try_send(tile_id) { log::trace!("Requested tile: {:?}", tile_id); @@ -226,21 +230,31 @@ impl Tiles for HttpTiles { fn at(&mut self, tile_id: TileId) -> Option { self.put_single_downloaded_tile_in_cache(); - if tile_id.zoom <= self.max_zoom { - self.request_tile(tile_id) - .map(|texture| TextureWithUv { + let tile = self.cache.get(&tile_id).cloned(); + + match tile { + Some(Some(texture)) => { + return Some(TextureWithUv { texture, uv: Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0)), - }) - .or_else(|| self.placeholder_with_different_zoom(tile_id)) - } else { - let (zoomed_tile_id, uv) = interpolate_higher_zoom(tile_id, self.max_zoom); - - self.request_tile(zoomed_tile_id) - .map(|texture| TextureWithUv { - texture: texture.clone(), - uv, - }) + }); + } + Some(None) => { + // Tile is being downloaded. + return self.placeholder_with_different_zoom(tile_id); + } + None => { + // Tile is not in cache. + let tile_id_to_download = if tile_id.zoom > self.max_zoom { + let (donor_tile_id, uv) = interpolate_higher_zoom(tile_id, self.max_zoom); + donor_tile_id + } else { + tile_id + }; + + self.download(tile_id_to_download); + return self.placeholder_with_different_zoom(tile_id); + } } } From 3762833389baaa2faef11b8b4b61f52a5c4231f5 Mon Sep 17 00:00:00 2001 From: Piotr Podusowski Date: Tue, 3 Dec 2024 22:51:53 +0100 Subject: [PATCH 06/15] make placeholder_with_different_zoom work for the same zoom --- walkers/src/tiles.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/walkers/src/tiles.rs b/walkers/src/tiles.rs index ef2dc7c..bd9967e 100644 --- a/walkers/src/tiles.rs +++ b/walkers/src/tiles.rs @@ -179,9 +179,6 @@ impl HttpTiles { let mut zoom_candidate = tile_id.zoom; loop { - // Keep zooming out until we find a tile or there is no more zoom levels. - zoom_candidate = zoom_candidate.checked_sub(1)?; - let (zoomed_tile_id, uv) = interpolate_higher_zoom(tile_id, zoom_candidate); if let Some(Some(texture)) = self.cache.get(&zoomed_tile_id) { @@ -190,13 +187,16 @@ impl HttpTiles { uv, }); } + + // Keep zooming out until we find a tile or there is no more zoom levels. + zoom_candidate = zoom_candidate.checked_sub(1)?; } } } /// Take a piece of a tile with higher zoom level and use it as a tile with lower zoom level. fn interpolate_higher_zoom(tile_id: TileId, available_zoom: u8) -> (TileId, Rect) { - assert!(tile_id.zoom > available_zoom); + assert!(tile_id.zoom >= available_zoom); let dzoom = 2u32.pow((tile_id.zoom - available_zoom) as u32); From 90473211a7b6509f5bd0673c5f4a619c5a51e871 Mon Sep 17 00:00:00 2001 From: Piotr Podusowski Date: Tue, 3 Dec 2024 22:55:32 +0100 Subject: [PATCH 07/15] rename --- walkers/src/tiles.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/walkers/src/tiles.rs b/walkers/src/tiles.rs index bd9967e..4d5e433 100644 --- a/walkers/src/tiles.rs +++ b/walkers/src/tiles.rs @@ -174,8 +174,8 @@ impl HttpTiles { }) } - /// Find tile with a different zoom, which could be used as a placeholder. - fn placeholder_with_different_zoom(&mut self, tile_id: TileId) -> Option { + /// Get at tile, or interpolate it from lower zoom levels. + fn get_or_interpolate(&mut self, tile_id: TileId) -> Option { let mut zoom_candidate = tile_id.zoom; loop { @@ -188,7 +188,7 @@ impl HttpTiles { }); } - // Keep zooming out until we find a tile or there is no more zoom levels. + // Keep zooming out until we find a donor or there is no more zoom levels. zoom_candidate = zoom_candidate.checked_sub(1)?; } } @@ -241,7 +241,7 @@ impl Tiles for HttpTiles { } Some(None) => { // Tile is being downloaded. - return self.placeholder_with_different_zoom(tile_id); + return self.get_or_interpolate(tile_id); } None => { // Tile is not in cache. @@ -253,7 +253,7 @@ impl Tiles for HttpTiles { }; self.download(tile_id_to_download); - return self.placeholder_with_different_zoom(tile_id); + return self.get_or_interpolate(tile_id); } } } From cfa45cb2249513388b69f5aab00aabfe297d71dc Mon Sep 17 00:00:00 2001 From: Piotr Podusowski Date: Tue, 3 Dec 2024 23:06:00 +0100 Subject: [PATCH 08/15] get from cache using get_or_interpolate --- walkers/src/tiles.rs | 37 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/walkers/src/tiles.rs b/walkers/src/tiles.rs index 4d5e433..ac6adfd 100644 --- a/walkers/src/tiles.rs +++ b/walkers/src/tiles.rs @@ -230,32 +230,19 @@ impl Tiles for HttpTiles { fn at(&mut self, tile_id: TileId) -> Option { self.put_single_downloaded_tile_in_cache(); - let tile = self.cache.get(&tile_id).cloned(); + let tile = self.get_or_interpolate(tile_id); - match tile { - Some(Some(texture)) => { - return Some(TextureWithUv { - texture, - uv: Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0)), - }); - } - Some(None) => { - // Tile is being downloaded. - return self.get_or_interpolate(tile_id); - } - None => { - // Tile is not in cache. - let tile_id_to_download = if tile_id.zoom > self.max_zoom { - let (donor_tile_id, uv) = interpolate_higher_zoom(tile_id, self.max_zoom); - donor_tile_id - } else { - tile_id - }; - - self.download(tile_id_to_download); - return self.get_or_interpolate(tile_id); - } - } + // Make sure the tile is downloaded. + let tile_id_to_download = if tile_id.zoom > self.max_zoom { + let (donor_tile_id, uv) = interpolate_higher_zoom(tile_id, self.max_zoom); + donor_tile_id + } else { + tile_id + }; + + self.download(tile_id_to_download); + + tile } fn tile_size(&self) -> u32 { From 68dae2a1929bb0f7e7e2437746fe5f28b91fa7aa Mon Sep 17 00:00:00 2001 From: Piotr Podusowski Date: Tue, 3 Dec 2024 23:09:07 +0100 Subject: [PATCH 09/15] simplify --- walkers/src/tiles.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/walkers/src/tiles.rs b/walkers/src/tiles.rs index ac6adfd..5bc8420 100644 --- a/walkers/src/tiles.rs +++ b/walkers/src/tiles.rs @@ -232,10 +232,8 @@ impl Tiles for HttpTiles { let tile = self.get_or_interpolate(tile_id); - // Make sure the tile is downloaded. let tile_id_to_download = if tile_id.zoom > self.max_zoom { - let (donor_tile_id, uv) = interpolate_higher_zoom(tile_id, self.max_zoom); - donor_tile_id + interpolate_higher_zoom(tile_id, self.max_zoom).0 } else { tile_id }; From c8c3334401e4c4e46bfef939fa6ab5a52af46a37 Mon Sep 17 00:00:00 2001 From: Piotr Podusowski Date: Tue, 3 Dec 2024 23:10:55 +0100 Subject: [PATCH 10/15] condense code --- walkers/src/tiles.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/walkers/src/tiles.rs b/walkers/src/tiles.rs index 5bc8420..c9111ea 100644 --- a/walkers/src/tiles.rs +++ b/walkers/src/tiles.rs @@ -230,17 +230,13 @@ impl Tiles for HttpTiles { fn at(&mut self, tile_id: TileId) -> Option { self.put_single_downloaded_tile_in_cache(); - let tile = self.get_or_interpolate(tile_id); - - let tile_id_to_download = if tile_id.zoom > self.max_zoom { + self.download(if tile_id.zoom > self.max_zoom { interpolate_higher_zoom(tile_id, self.max_zoom).0 } else { tile_id - }; - - self.download(tile_id_to_download); + }); - tile + self.get_or_interpolate(tile_id) } fn tile_size(&self) -> u32 { From e2c711dca412f803fd7a8ed0747a0579f1314f7c Mon Sep 17 00:00:00 2001 From: Piotr Podusowski Date: Tue, 3 Dec 2024 23:14:49 +0100 Subject: [PATCH 11/15] rename --- walkers/src/tiles.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/walkers/src/tiles.rs b/walkers/src/tiles.rs index c9111ea..7558a86 100644 --- a/walkers/src/tiles.rs +++ b/walkers/src/tiles.rs @@ -151,7 +151,7 @@ impl HttpTiles { } } - fn download(&mut self, tile_id: TileId) { + fn make_sure_is_downloaded(&mut self, tile_id: TileId) { if self.cache.contains(&tile_id) { return; } @@ -169,7 +169,7 @@ impl HttpTiles { fn request_tile(&mut self, tile_id: TileId) -> Option { self.cache.get(&tile_id).cloned().unwrap_or_else(|| { - self.download(tile_id); + self.make_sure_is_downloaded(tile_id); None }) } @@ -230,7 +230,7 @@ impl Tiles for HttpTiles { fn at(&mut self, tile_id: TileId) -> Option { self.put_single_downloaded_tile_in_cache(); - self.download(if tile_id.zoom > self.max_zoom { + self.make_sure_is_downloaded(if tile_id.zoom > self.max_zoom { interpolate_higher_zoom(tile_id, self.max_zoom).0 } else { tile_id From cf959b9027f18c3f27dc17a3b9a2fe2e016f35a6 Mon Sep 17 00:00:00 2001 From: Piotr Podusowski Date: Tue, 3 Dec 2024 23:26:41 +0100 Subject: [PATCH 12/15] single lookup --- walkers/src/tiles.rs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/walkers/src/tiles.rs b/walkers/src/tiles.rs index 7558a86..2941357 100644 --- a/walkers/src/tiles.rs +++ b/walkers/src/tiles.rs @@ -1,6 +1,6 @@ use egui::{pos2, Color32, Context, Mesh, Rect, Vec2}; use egui::{ColorImage, TextureHandle}; -use futures::channel::mpsc::{channel, Receiver, Sender}; +use futures::channel::mpsc::{channel, Receiver, Sender, TrySendError}; use image::ImageError; use lru::LruCache; @@ -152,17 +152,18 @@ impl HttpTiles { } fn make_sure_is_downloaded(&mut self, tile_id: TileId) { - if self.cache.contains(&tile_id) { - return; - } - - if let Ok(()) = self.request_tx.try_send(tile_id) { - log::trace!("Requested tile: {:?}", tile_id); - - // None acts as a placeholder for the tile, preventing multiple - // requests for the same tile. - self.cache.put(tile_id, None); - } else { + if self + .cache + .try_get_or_insert( + tile_id, + || -> Result, TrySendError> { + self.request_tx.try_send(tile_id)?; + log::trace!("Requested tile: {:?}", tile_id); + Ok(None) + }, + ) + .is_err() + { log::debug!("Request queue is full."); } } From 591a16470ae0cf58bc232e0662c653bd2ad9c874 Mon Sep 17 00:00:00 2001 From: Piotr Podusowski Date: Tue, 3 Dec 2024 23:28:24 +0100 Subject: [PATCH 13/15] obsolete fn removed --- walkers/src/tiles.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/walkers/src/tiles.rs b/walkers/src/tiles.rs index 2941357..c433999 100644 --- a/walkers/src/tiles.rs +++ b/walkers/src/tiles.rs @@ -168,13 +168,6 @@ impl HttpTiles { } } - fn request_tile(&mut self, tile_id: TileId) -> Option { - self.cache.get(&tile_id).cloned().unwrap_or_else(|| { - self.make_sure_is_downloaded(tile_id); - None - }) - } - /// Get at tile, or interpolate it from lower zoom levels. fn get_or_interpolate(&mut self, tile_id: TileId) -> Option { let mut zoom_candidate = tile_id.zoom; From 6f32749ed475b0f0e21e5d4f39d4b77732f8ccdc Mon Sep 17 00:00:00 2001 From: Piotr Podusowski Date: Tue, 3 Dec 2024 23:34:29 +0100 Subject: [PATCH 14/15] changelog updated --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bdb7d5b..feb0648 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file. ## Unreleased * Tile download optimized by no longer queueing older requests. +* Interpolation of higher zoom levels is now improved, trying many different levels instead of just + one. ## 0.30.0 From c70e1d6cfe2522f4a488452e4b1080ca576e09ce Mon Sep 17 00:00:00 2001 From: Piotr Podusowski Date: Tue, 3 Dec 2024 23:54:38 +0100 Subject: [PATCH 15/15] revert --- walkers/src/tiles.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/walkers/src/tiles.rs b/walkers/src/tiles.rs index c433999..c4a52a5 100644 --- a/walkers/src/tiles.rs +++ b/walkers/src/tiles.rs @@ -123,7 +123,7 @@ impl HttpTiles { // Just arbitrary value which seemed right. #[allow(clippy::unwrap_used)] - let cache_size = std::num::NonZeroUsize::new(1024).unwrap(); + let cache_size = std::num::NonZeroUsize::new(256).unwrap(); Self { attribution,