Files
maps/frontend/src/tiles.rs
Dongho Kim 45807e3a90 update
2025-12-15 23:10:38 +09:00

103 lines
3.4 KiB
Rust

//! Tile visibility and data fetching utilities
use wasm_bindgen::JsCast;
use crate::camera::Camera;
/// Fetch tile data with caching
pub async fn fetch_cached(url: &str) -> Option<Vec<u8>> {
let window = web_sys::window()?;
let caches = window.caches().ok()?;
let cache_name = "map-data-v5-sand";
let cache = wasm_bindgen_futures::JsFuture::from(caches.open(cache_name)).await.ok()?;
let cache: web_sys::Cache = cache.dyn_into().ok()?;
let request = web_sys::Request::new_with_str(url).ok()?;
let match_promise = cache.match_with_request(&request);
let match_val = wasm_bindgen_futures::JsFuture::from(match_promise).await.ok()?;
if !match_val.is_undefined() {
let response: web_sys::Response = match_val.dyn_into().ok()?;
let buffer_promise = response.array_buffer().ok()?;
let buffer = wasm_bindgen_futures::JsFuture::from(buffer_promise).await.ok()?;
let array = js_sys::Uint8Array::new(&buffer);
return Some(array.to_vec());
}
// Network fetch
let response_val = wasm_bindgen_futures::JsFuture::from(window.fetch_with_request(&request)).await.ok()?;
let response: web_sys::Response = response_val.dyn_into().ok()?;
// Clone response for cache
let response_clone = response.clone().ok()?;
let put_promise = cache.put_with_request(&request, &response_clone);
wasm_bindgen_futures::JsFuture::from(put_promise).await.ok()?;
let buffer_promise = response.array_buffer().ok()?;
let buffer = wasm_bindgen_futures::JsFuture::from(buffer_promise).await.ok()?;
let array = js_sys::Uint8Array::new(&buffer);
Some(array.to_vec())
}
/// Get visible tiles based on current camera position
pub fn get_visible_tiles(camera: &Camera) -> Vec<(i32, i32, i32)> {
// Select zoom level based on camera zoom
// Zoom 6: World/Country view
// Zoom 9: Region view
// Zoom 12: City view
// Zoom 14: Street view
let z = if camera.zoom < 100.0 {
2
} else if camera.zoom < 500.0 {
4
} else if camera.zoom < 2000.0 {
6
} else if camera.zoom < 5000.0 {
9
} else if camera.zoom < 10000.0 {
12
} else {
14
};
let n = 2.0f64.powi(z);
let half_width = 1.0 * camera.aspect / camera.zoom;
let half_height = 1.0 / camera.zoom;
let min_x = (camera.x - half_width).max(0.0) as f64;
let max_x = (camera.x + half_width).min(1.0) as f64;
let min_y = (camera.y - half_height).max(0.0) as f64;
let max_y = (camera.y + half_height).min(1.0) as f64;
let min_tile_x = (min_x * n).floor() as i32;
let max_tile_x = (max_x * n).floor() as i32;
let min_tile_y = (min_y * n).floor() as i32;
let max_tile_y = (max_y * n).floor() as i32;
let mut tiles = Vec::new();
for x in min_tile_x..=max_tile_x {
for y in min_tile_y..=max_tile_y {
tiles.push((z, x, y));
}
}
tiles
}
/// Get parent tile for the tile retention hierarchy
pub fn get_parent_tile(z: i32, x: i32, y: i32) -> Option<(i32, i32, i32)> {
// Hierarchy: 14 -> 12 -> 9 -> 6 -> 2
let parent_z = match z {
14 => 12,
12 => 9,
9 => 6,
6 => 4,
4 => 2,
_ => return None,
};
// Calculate scale difference
let diff = z - parent_z;
let factor = 2i32.pow(diff as u32);
Some((parent_z, x / factor, y / factor))
}