aboutsummaryrefslogtreecommitdiff
path: root/src/renderer/tilehunt.rs
diff options
context:
space:
mode:
authorDaniel Schadt <kingdread@gmx.de>2025-06-26 22:10:31 +0200
committerDaniel Schadt <kingdread@gmx.de>2025-06-26 22:10:31 +0200
commit99150875308e0cac89f4de2996cfd1954305dcfe (patch)
treef19224064543aed367522b05778a992d7385c712 /src/renderer/tilehunt.rs
parent6adcd94a6747fe7ec6f1ad1073453636847a0bff (diff)
downloadhittekaart-99150875308e0cac89f4de2996cfd1954305dcfe.tar.gz
hittekaart-99150875308e0cac89f4de2996cfd1954305dcfe.tar.bz2
hittekaart-99150875308e0cac89f4de2996cfd1954305dcfe.zip
split crate into core and clipy
Diffstat (limited to 'src/renderer/tilehunt.rs')
-rw-r--r--src/renderer/tilehunt.rs153
1 files changed, 0 insertions, 153 deletions
diff --git a/src/renderer/tilehunt.rs b/src/renderer/tilehunt.rs
deleted file mode 100644
index 9081523..0000000
--- a/src/renderer/tilehunt.rs
+++ /dev/null
@@ -1,153 +0,0 @@
-//! Actual rendering functions for tile hunts.
-//!
-//! This renders a tile as "transparent green" if any track passes through it.
-//!
-//! Note that is version of "tile hunt" is a bit silly, as the tile size changes with the zoom
-//! level. For a better version, the "tile hunt size" should be fixed to a given zoom.
-use std::cmp::Ordering;
-
-use color_eyre::eyre::Result;
-use crossbeam_channel::Sender;
-use fnv::{FnvHashMap, FnvHashSet};
-use image::RgbaImage;
-use imageproc::{drawing::draw_filled_rect_mut, rect::Rect};
-use rayon::iter::{IntoParallelIterator, ParallelIterator};
-
-use super::{
- super::{
- gpx::Coordinates,
- layer::{self, TILE_HEIGHT, TILE_WIDTH},
- },
- RenderedTile,
-};
-
-fn render_squares(grid: u32, inner: Vec<(u8, u8)>) -> Result<Vec<u8>> {
- // We re-use the tiny PNG if possible
- static FULL_TILE: &[u8] = include_bytes!("tile-marked.png");
- if grid == 1 && !inner.is_empty() {
- return Ok(FULL_TILE.to_vec());
- }
- let mut base =
- RgbaImage::from_pixel(TILE_WIDTH as u32, TILE_HEIGHT as u32, [0, 0, 0, 0].into());
- let patch_size = TILE_WIDTH as u32 / grid;
-
- for (patch_x, patch_y) in inner {
- draw_filled_rect_mut(
- &mut base,
- Rect::at(
- patch_x as i32 * patch_size as i32,
- patch_y as i32 * patch_size as i32,
- )
- .of_size(patch_size, patch_size),
- [0, 255, 0, 128].into(),
- );
- }
-
- layer::compress_png_as_bytes(&base)
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct Renderer(u32);
-
-impl Renderer {
- pub fn new(hunter_zoom: u32) -> Self {
- Renderer(hunter_zoom)
- }
-
- #[inline]
- pub fn hunter_zoom(&self) -> u32 {
- self.0
- }
-}
-
-impl super::Renderer for Renderer {
- type Prepared = (u32, FnvHashMap<(u64, u64), Vec<(u8, u8)>>);
-
- fn prepare(
- &self,
- zoom: u32,
- tracks: &[Vec<Coordinates>],
- tick: Sender<()>,
- ) -> Result<Self::Prepared> {
- let mut marked = FnvHashSet::default();
-
- for track in tracks {
- for point in track {
- let merc = point.web_mercator(self.hunter_zoom());
- let tile_x = merc.0 / TILE_WIDTH;
- let tile_y = merc.1 / TILE_HEIGHT;
- marked.insert((tile_x, tile_y));
- }
-
- tick.send(()).unwrap();
- }
-
- let scale = i32::try_from(zoom).unwrap() - i32::try_from(self.hunter_zoom()).unwrap();
- let grid = if scale >= 0 {
- 1
- } else {
- 2u64.pow(scale.abs().min(8) as u32)
- };
-
- let mut result = FnvHashMap::<(u64, u64), Vec<(u8, u8)>>::default();
-
- for (tile_x, tile_y) in marked {
- match scale.cmp(&0) {
- Ordering::Equal =>
- // The current zoom level is the same as the hunter level, so the tiles have a 1:1
- // mapping
- {
- result.entry((tile_x, tile_y)).or_default().push((0u8, 0u8))
- }
- Ordering::Less =>
- // In this case we are "zoomed out" further than the hunter level, so a marked tile
- // has to be scaled down and we need to figure out where in the "big tile" our
- // marked tile is
- {
- result
- .entry((tile_x / grid, tile_y / grid))
- .or_default()
- .push((
- (tile_x % grid).try_into().unwrap(),
- (tile_y % grid).try_into().unwrap(),
- ))
- }
- Ordering::Greater => {
- // In this case, we are zoomed in more than the hunter level. Each marked tile
- // expands to multiple tiles.
- let multiplier = 2u64.pow(scale as u32);
- for dx in 0..multiplier {
- for dy in 0..multiplier {
- result
- .entry((tile_x * multiplier + dx, tile_y * multiplier + dy))
- .or_default()
- .push((0u8, 0u8));
- }
- }
- }
- }
- }
-
- Ok((grid.try_into().unwrap(), result))
- }
-
- fn colorize(&self, layer: Self::Prepared, tx: Sender<RenderedTile>) -> Result<()> {
- let grid = layer.0;
- layer
- .1
- .into_par_iter()
- .try_for_each_with(tx, |tx, ((tile_x, tile_y), inner)| {
- let data = render_squares(grid, inner)?;
- tx.send(RenderedTile {
- x: tile_x,
- y: tile_y,
- data,
- })?;
- Ok(())
- })
- }
-
- fn tile_count(&self, layer: &Self::Prepared) -> Result<u64> {
- Ok(layer.1.len().try_into().unwrap())
- }
-}