aboutsummaryrefslogtreecommitdiff
path: root/src/renderer/marktile.rs
blob: 1e3020f421e501fbbe7628c16de561fbe5c5041e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//! 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 color_eyre::eyre::Result;
use crossbeam_channel::Sender;
use fnv::FnvHashSet;

use super::{
    super::{
        gpx::Coordinates,
        layer::{TILE_HEIGHT, TILE_WIDTH},
    },
    RenderedTile,
};

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Renderer;

impl super::Renderer for Renderer {
    type Prepared = FnvHashSet<(u64, u64)>;

    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(zoom);
                let tile_x = merc.0 / TILE_WIDTH;
                let tile_y = merc.1 / TILE_HEIGHT;
                marked.insert((tile_x, tile_y));
            }

            tick.send(()).unwrap();
        }

        Ok(marked)
    }

    fn colorize(&self, layer: Self::Prepared, tx: Sender<RenderedTile>) -> Result<()> {
        // The tile is hand-crafted to be very small. See
        // <https://www.mjt.me.uk/posts/smallest-png/> for a reference, and of course the actual
        // PNG specification <http://www.libpng.org/pub/png/spec/1.2/PNG-Contents.html>.
        static IMAGE_DATA: &[u8] = include_bytes!("tile-marked.png");
        for (tile_x, tile_y) in layer {
            tx.send(RenderedTile {
                x: tile_x,
                y: tile_y,
                data: IMAGE_DATA.to_vec(),
            })?;
        }
        Ok(())
    }

    fn tile_count(&self, layer: &Self::Prepared) -> Result<u64> {
        Ok(layer.len().try_into().unwrap())
    }
}