sailor 0.1.0

A sailing navigation application.
use super::*;

pub struct Screen {
    pub center: Point,
    pub width: u32,
    pub height: u32,
    tile_size: u32,
}

impl Screen {
    pub fn new(center: Point, width: u32, height: u32, tile_size: u32, hidpi_factor: f64) -> Self {
        Self {
            center,
            width,
            height,
            tile_size: (tile_size as f64 * hidpi_factor) as u32,
        }
    }

    pub fn get_tile_size(&self) -> u32 {
        self.tile_size
    }

    pub fn get_tile_boundaries_for_zoom_level(&self, z: f32, scale: u32) -> TileField {
        let z = z.min(14.0);
        let px_to_world = self.width as f32 / self.get_tile_size() as f32 / 2.0 / 2f32.powi(z as i32) / scale as f32;
        let py_to_world = self.height as f32 / self.get_tile_size() as f32 / 2.0 / 2f32.powi(z as i32) / scale as f32;

        let top_left: TileId = global_to_num_space(&(self.center - vector(px_to_world, py_to_world)), z as u32).into();
        let bottom_right: TileId = global_to_num_space(&(self.center + vector(px_to_world, py_to_world)), z as u32).into();
        TileField::new(
            top_left,
            bottom_right
        )
    }

    pub fn tile_to_global_space(&self, z: f32, coordinate: &TileId) -> glm::TMat4<f32> {
        let zoom = 1.0/2f32.powi(coordinate.z as i32);
        let zoom = glm::scaling(&glm::vec3(zoom, zoom, 1.0));
        let pos = glm::translation(&glm::vec3(coordinate.x as f32, coordinate.y as f32, 0.0));
        self.global_to_screen(z) * zoom * pos
    }

    pub fn global_to_screen(&self, z: f32) -> glm::TMat4<f32> {
        let zoom_x = 2.0f32.powf(z) / (self.width as f32 / 2.0) * self.get_tile_size() as f32;
        let zoom_y = 2.0f32.powf(z) / (self.height as f32 / 2.0) * self.get_tile_size() as f32;
        let zoom = glm::scaling(&glm::vec3(zoom_x, zoom_y, 1.0));
        let position = glm::translation(&glm::vec3(-self.center.x, -self.center.y, 0.0));
        zoom * position
    }
}