diff options
Diffstat (limited to 'src/renderer/tilehunt.rs')
-rw-r--r-- | src/renderer/tilehunt.rs | 153 |
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()) - } -} |