kapta 0.0.4

Kapta ~ Inspired by leaflet. Draw map with wasm
Documentation
use crate::{
    consts::{BOUND_LAT_3857, BOUND_LON_3857},
    coords::{Coord, Proj, ProjCoord},
};

use super::SeriesPC;

#[derive(Debug, Default, Clone, PartialEq)]
pub struct KaptaView {
    pub center_p3857: ProjCoord,
    pub center: ProjCoord,
    pub top_left: ProjCoord,
    pub bottom_right: ProjCoord,
    pub origin: Coord,
    pub zoom: u8,
    pub width: u32,
    pub height: u32,
    pub pixel_x: f64,
    pub pixel_y: f64,
    pub preload: u8,
}

impl KaptaView {
    pub fn new(
        center_p3857: ProjCoord,
        origin: Coord,
        width: u32,
        height: u32,
        zoom: u8,
        preload: u8,
    ) -> Self {
        let (top_left, center, bottom_right) =
            center_p3857.bound_rec_tile(zoom, width, height, preload);
        let length_hafl_tile = (2 as i64).pow((zoom - 1).into());
        let pixel_x = BOUND_LON_3857 / 256. / length_hafl_tile as f64;
        let pixel_y = BOUND_LAT_3857 / 256. / length_hafl_tile as f64;
        Self {
            center_p3857,
            center,
            origin,
            zoom,
            width,
            height,
            top_left,
            bottom_right,
            pixel_x,
            pixel_y,
            preload,
        }
    }

    pub fn new_collection(&self) -> SeriesPC {
        let mut collection: Vec<ProjCoord> = [].to_vec();
        let length_x = self.bottom_right.coord.x as i64 - self.top_left.coord.x as i64 + 1;
        let length_y =
            self.bottom_right.coord.y.floor() as i64 - self.top_left.coord.y.floor() as i64 + 1;
        dbg!(length_x, length_y);
        let length_tile = (2 as i64).pow(self.zoom.into());

        for m in 0..length_y {
            for n in 0..length_x {
                let x = self.top_left.coord.x + n as f64;
                let y = self.top_left.coord.y + m as f64;
                if 0. <= y && y < length_tile as f64 {
                    let distance2 = (x.floor() + 0.5 - self.center.coord.x).powf(2.)
                        + (y.floor() + 0.5 - self.center.coord.y).powf(2.);
                    collection.push(ProjCoord {
                        coord: Coord { x, y: y },
                        kind: Proj::Tile,
                        distance2: distance2,
                    })
                }
            }
        }

        collection.sort_by(|a, b| a.distance2.partial_cmp(&b.distance2).unwrap());

        SeriesPC { series: collection }
    }

    pub fn change_collection(
        &self,
        bottom_right: ProjCoord,
        center: ProjCoord,
        top_left: ProjCoord,
    ) -> SeriesPC {
        let mut collection: Vec<ProjCoord> = [].to_vec();
        let length_x = bottom_right.coord.x as u64 - top_left.coord.x as u64 + 1;
        let length_y = bottom_right.coord.y.floor() as u64 - top_left.coord.y.floor() as u64 + 1;

        let length_tile = (2 as i64).pow(self.zoom.into());

        for m in 0..length_y {
            for n in 0..length_x {
                let hack_y = if top_left.coord.y < 0. {
                    0.
                } else {
                    top_left.coord.y
                };
                let x = top_left.coord.x + n as f64;
                let y = hack_y + m as f64;
                if 0. <= y && y < length_tile as f64 {
                    let distance2 = (x.floor() + 0.5 - center.coord.x).powf(2.)
                        + (y.floor() + 0.5 - center.coord.y).powf(2.);
                    collection.push(ProjCoord {
                        coord: Coord { x, y: y },
                        kind: Proj::Tile,
                        distance2: distance2,
                    })
                }
            }
        }

        collection.sort_by(|a, b| a.distance2.partial_cmp(&b.distance2).unwrap());
        SeriesPC { series: collection }
    }

    // TODO: Can toi uu lai
    pub fn drap_change_bound(
        &self,
        delta_pixel_x: f64,
        delta_pixel_y: f64,
    ) -> (bool, ProjCoord, ProjCoord, ProjCoord, ProjCoord) {
        let delta_proj_x = delta_pixel_x * self.pixel_x;
        let delta_proj_y = delta_pixel_y * self.pixel_y;
        let proj_3857_new = ProjCoord::new(
            self.center_p3857.coord.x - delta_proj_x,
            self.center_p3857.coord.y - delta_proj_y,
        );

        let (top_left, center, bottom_right) =
            proj_3857_new.bound_rec_tile(self.zoom, self.width, self.height, self.preload);

        let check = (self.top_left.coord.x as i64) > (top_left.coord.x as i64)
            || (self.top_left.coord.y as i64) > (top_left.coord.y as i64)
            || (self.bottom_right.coord.x as i64) < (bottom_right.coord.x as i64)
            || (self.bottom_right.coord.y as i64) < (bottom_right.coord.y as i64);
        (check, top_left, center, bottom_right, proj_3857_new)
    }

    pub fn to_img(&self, data: SeriesPC) -> Vec<(String, String)> {
        let mut vec_img: Vec<(String, String)> = [].to_vec();
        for data in data.series {
            let trans_x = (self.width / 2 - 128) as f64
                + (data.coord.x.floor() + 0.5 - self.center.coord.x) * 256.
                + self.origin.x;
            let trans_y = (self.height / 2 - 128) as f64
                + (data.coord.y.floor() + 0.5 - self.center.coord.y) * 256.
                + self.origin.y;
            let trans = format!("translate3d({}px, {}px, 0px)", trans_x, trans_y);
            let count = (2 as i64).pow(self.zoom.into());
            let url = format!(
                "https://tile.openstreetmap.org/{}/{}/{}.png",
                self.zoom,
                (data.coord.x as i64).rem_euclid(count),
                (data.coord.y as i64 % count),
            );
            vec_img.push((url, trans))
        }

        vec_img
    }
}