update
This commit is contained in:
102
frontend/src/tiles.rs
Normal file
102
frontend/src/tiles.rs
Normal file
@@ -0,0 +1,102 @@
|
||||
//! 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))
|
||||
}
|
||||
Reference in New Issue
Block a user