update to zoom zone
This commit is contained in:
@@ -222,7 +222,20 @@ async fn fetch_cached(url: &str) -> Option<String> {
|
||||
}
|
||||
|
||||
fn get_visible_tiles(camera: &Camera) -> Vec<(i32, i32, i32)> {
|
||||
let z = 10; // Fixed zoom level for data
|
||||
// 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 < 500.0 {
|
||||
6
|
||||
} else if camera.zoom < 2000.0 {
|
||||
9
|
||||
} else if camera.zoom < 8000.0 {
|
||||
12
|
||||
} else {
|
||||
14
|
||||
};
|
||||
let n = 2.0f64.powi(z);
|
||||
|
||||
let half_width = 1.0 * camera.aspect / camera.zoom;
|
||||
@@ -360,8 +373,8 @@ pub async fn run() {
|
||||
if let Some(btn) = btn_zoom_in {
|
||||
let closure = wasm_bindgen::closure::Closure::<dyn FnMut()>::new(move || {
|
||||
let mut cam = camera_clone.lock().unwrap();
|
||||
cam.zoom *= 1.2;
|
||||
cam.zoom = cam.zoom.max(100.0).min(50000.0);
|
||||
cam.zoom *= 1.5;
|
||||
cam.zoom = cam.zoom.max(20.0).min(50000.0);
|
||||
window_clone.request_redraw();
|
||||
});
|
||||
btn.set_onclick(Some(closure.as_ref().unchecked_ref()));
|
||||
@@ -376,8 +389,8 @@ pub async fn run() {
|
||||
if let Some(btn) = btn_zoom_out {
|
||||
let closure = wasm_bindgen::closure::Closure::<dyn FnMut()>::new(move || {
|
||||
let mut cam = camera_clone.lock().unwrap();
|
||||
cam.zoom /= 1.2;
|
||||
cam.zoom = cam.zoom.max(100.0).min(50000.0);
|
||||
cam.zoom /= 1.5;
|
||||
cam.zoom = cam.zoom.max(20.0).min(50000.0);
|
||||
window_clone.request_redraw();
|
||||
});
|
||||
btn.set_onclick(Some(closure.as_ref().unchecked_ref()));
|
||||
@@ -505,7 +518,7 @@ pub async fn run() {
|
||||
};
|
||||
|
||||
let mut cam = camera.lock().unwrap();
|
||||
let zoom_factor = 1.1f32;
|
||||
let zoom_factor = 1.5f32;
|
||||
if scroll_y > 0.0 {
|
||||
cam.zoom *= zoom_factor;
|
||||
} else if scroll_y < 0.0 {
|
||||
@@ -513,7 +526,7 @@ pub async fn run() {
|
||||
}
|
||||
|
||||
// Clamp zoom
|
||||
cam.zoom = cam.zoom.max(100.0).min(50000.0);
|
||||
cam.zoom = cam.zoom.max(20.0).min(50000.0);
|
||||
|
||||
window.request_redraw();
|
||||
}
|
||||
@@ -713,7 +726,7 @@ pub async fn run() {
|
||||
contents: bytemuck::cast_slice(&landuse_vertex_data),
|
||||
usage: wgpu::BufferUsages::VERTEX,
|
||||
});
|
||||
web_sys::console::log_1(&format!("Created landuse buffer with {} vertices", landuse_vertex_data.len()).into());
|
||||
|
||||
|
||||
let water_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("Tile Water Buffer"),
|
||||
@@ -826,23 +839,17 @@ pub async fn run() {
|
||||
}
|
||||
|
||||
if let Some(landuse) = landuse_data {
|
||||
if !landuse.is_empty() {
|
||||
web_sys::console::log_1(&format!("Fetched {} landuse items for tile {}/{}/{}", landuse.len(), z, x, y).into());
|
||||
}
|
||||
|
||||
guard.landuse.insert((z, x, y), landuse);
|
||||
}
|
||||
|
||||
if let Some(water) = water_data {
|
||||
if !water.is_empty() {
|
||||
web_sys::console::log_1(&format!("Fetched {} water items for tile {}/{}/{}", water.len(), z, x, y).into());
|
||||
}
|
||||
|
||||
guard.water.insert((z, x, y), water);
|
||||
}
|
||||
|
||||
if let Some(railways) = railways_data {
|
||||
if !railways.is_empty() {
|
||||
web_sys::console::log_1(&format!("Fetched {} railway items for tile {}/{}/{}", railways.len(), z, x, y).into());
|
||||
}
|
||||
|
||||
guard.railways.insert((z, x, y), railways);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,49 @@ use scylla::{Session, SessionBuilder};
|
||||
use std::collections::HashMap;
|
||||
use tokio::task::JoinSet;
|
||||
|
||||
|
||||
const ZOOM_LEVELS: [u32; 4] = [6, 9, 12, 14];
|
||||
|
||||
fn should_include(tags: &HashMap<String, String>, zoom: u32) -> bool {
|
||||
if zoom >= 14 { return true; }
|
||||
|
||||
let highway = tags.get("highway").map(|s| s.as_str());
|
||||
let place = tags.get("place").map(|s| s.as_str());
|
||||
let natural = tags.get("natural").map(|s| s.as_str());
|
||||
let railway = tags.get("railway").map(|s| s.as_str());
|
||||
let waterway = tags.get("waterway").map(|s| s.as_str());
|
||||
|
||||
match zoom {
|
||||
6 => {
|
||||
matches!(highway, Some("motorway" | "trunk" | "primary" | "secondary")) ||
|
||||
matches!(place, Some("city")) ||
|
||||
matches!(natural, Some("water" | "wood" | "scrub" | "heath" | "wetland")) ||
|
||||
matches!(tags.get("landuse").map(|s| s.as_str()), Some("forest" | "meadow" | "grass" | "recreation_ground" | "farmland")) ||
|
||||
tags.contains_key("leisure") || // Parks, nature reserves, golf courses
|
||||
matches!(waterway, Some("river" | "riverbank"))
|
||||
},
|
||||
9 => {
|
||||
matches!(highway, Some("motorway" | "trunk" | "primary" | "secondary")) ||
|
||||
matches!(place, Some("city" | "town")) ||
|
||||
matches!(railway, Some("rail")) ||
|
||||
matches!(natural, Some("water" | "wood" | "scrub" | "heath" | "wetland")) ||
|
||||
tags.contains_key("landuse") ||
|
||||
tags.contains_key("leisure") ||
|
||||
matches!(waterway, Some("river" | "riverbank"))
|
||||
},
|
||||
12 => {
|
||||
matches!(highway, Some("motorway" | "trunk" | "primary" | "secondary" | "tertiary")) ||
|
||||
matches!(place, Some("city" | "town" | "village")) ||
|
||||
matches!(railway, Some("rail")) ||
|
||||
tags.contains_key("landuse") ||
|
||||
tags.contains_key("leisure") ||
|
||||
matches!(natural, Some("water" | "wood" | "scrub" | "wetland" | "heath")) ||
|
||||
matches!(waterway, Some("river" | "riverbank" | "stream"))
|
||||
},
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
// Connect to ScyllaDB
|
||||
@@ -46,8 +89,8 @@ async fn main() -> Result<()> {
|
||||
// Channel for backpressure
|
||||
// Producer (reader) -> Consumer (writer)
|
||||
enum DbTask {
|
||||
Node { id: i64, lat: f64, lon: f64, tags: HashMap<String, String>, x: i32, y: i32 },
|
||||
Way { table: &'static str, id: i64, tags: HashMap<String, String>, points: Vec<u8>, x: i32, y: i32 },
|
||||
Node { zoom: i32, id: i64, lat: f64, lon: f64, tags: HashMap<String, String>, x: i32, y: i32 },
|
||||
Way { zoom: i32, table: &'static str, id: i64, tags: HashMap<String, String>, points: Vec<u8>, x: i32, y: i32 },
|
||||
}
|
||||
|
||||
let (tx, mut rx) = tokio::sync::mpsc::channel::<DbTask>(10_000);
|
||||
@@ -72,20 +115,20 @@ async fn main() -> Result<()> {
|
||||
}
|
||||
|
||||
match task {
|
||||
DbTask::Node { id, lat, lon, tags, x, y } => {
|
||||
DbTask::Node { zoom, id, lat, lon, tags, x, y } => {
|
||||
join_set.spawn(async move {
|
||||
let _ = session.query(
|
||||
"INSERT INTO map_data.nodes (zoom, tile_x, tile_y, id, lat, lon, tags) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||||
(10, x, y, id, lat, lon, tags),
|
||||
(zoom, x, y, id, lat, lon, tags),
|
||||
).await;
|
||||
});
|
||||
}
|
||||
DbTask::Way { table, id, tags, points, x, y } => {
|
||||
DbTask::Way { zoom, table, id, tags, points, x, y } => {
|
||||
let query = format!("INSERT INTO map_data.{} (zoom, tile_x, tile_y, id, tags, points) VALUES (?, ?, ?, ?, ?, ?)", table);
|
||||
join_set.spawn(async move {
|
||||
let _ = session.query(
|
||||
query,
|
||||
(10, x, y, id, tags, points),
|
||||
(zoom, x, y, id, tags, points),
|
||||
).await;
|
||||
});
|
||||
}
|
||||
@@ -123,12 +166,16 @@ async fn main() -> Result<()> {
|
||||
let lat = node.lat();
|
||||
let lon = node.lon();
|
||||
let tags: HashMap<String, String> = node.tags().map(|(k, v)| (k.to_string(), v.to_string())).collect();
|
||||
let (x, y) = lat_lon_to_tile(lat, lon, 10);
|
||||
|
||||
let task = DbTask::Node { id, lat, lon, tags, x, y };
|
||||
for &zoom in &ZOOM_LEVELS {
|
||||
if should_include(&tags, zoom) {
|
||||
let (x, y) = lat_lon_to_tile(lat, lon, zoom);
|
||||
let task = DbTask::Node { zoom: zoom as i32, id, lat, lon, tags: tags.clone(), x, y };
|
||||
let _ = tx.blocking_send(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Element::DenseNode(node) => {
|
||||
node_count += 1;
|
||||
|
||||
@@ -144,12 +191,16 @@ async fn main() -> Result<()> {
|
||||
let lat = node.lat();
|
||||
let lon = node.lon();
|
||||
let tags: HashMap<String, String> = node.tags().map(|(k, v)| (k.to_string(), v.to_string())).collect();
|
||||
let (x, y) = lat_lon_to_tile(lat, lon, 10);
|
||||
|
||||
let task = DbTask::Node { id, lat, lon, tags, x, y };
|
||||
for &zoom in &ZOOM_LEVELS {
|
||||
if should_include(&tags, zoom) {
|
||||
let (x, y) = lat_lon_to_tile(lat, lon, zoom);
|
||||
let task = DbTask::Node { zoom: zoom as i32, id, lat, lon, tags: tags.clone(), x, y };
|
||||
let _ = tx.blocking_send(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Element::Way(way) => {
|
||||
way_count += 1;
|
||||
let tags: HashMap<String, String> = way.tags().map(|(k, v)| (k.to_string(), v.to_string())).collect();
|
||||
@@ -157,12 +208,12 @@ async fn main() -> Result<()> {
|
||||
// Filter for highways/roads OR buildings OR landuse OR water OR railways
|
||||
let is_highway = tags.contains_key("highway");
|
||||
let is_building = tags.contains_key("building");
|
||||
let is_water = tags.get("natural").map(|v| v == "water").unwrap_or(false) ||
|
||||
tags.get("waterway").map(|v| v == "riverbank").unwrap_or(false) ||
|
||||
tags.get("landuse").map(|v| v == "basin").unwrap_or(false);
|
||||
let is_landuse = tags.get("leisure").map(|v| v == "park" || v == "garden").unwrap_or(false) ||
|
||||
tags.get("landuse").map(|v| v == "grass" || v == "forest" || v == "meadow").unwrap_or(false) ||
|
||||
tags.get("natural").map(|v| v == "wood" || v == "scrub").unwrap_or(false);
|
||||
let is_water = tags.get("natural").map(|v| v == "water" || v == "wetland").unwrap_or(false) ||
|
||||
tags.get("waterway").map(|v| v == "riverbank" || v == "stream" || v == "river").unwrap_or(false) ||
|
||||
tags.get("landuse").map(|v| v == "basin" || v == "reservoir").unwrap_or(false);
|
||||
let is_landuse = tags.contains_key("leisure") ||
|
||||
tags.contains_key("landuse") ||
|
||||
tags.get("natural").map(|v| v == "wood" || v == "scrub" || v == "heath" || v == "wetland").unwrap_or(false);
|
||||
let is_railway = tags.contains_key("railway");
|
||||
|
||||
if is_highway || is_building || is_water || is_landuse || is_railway {
|
||||
@@ -183,7 +234,6 @@ async fn main() -> Result<()> {
|
||||
|
||||
// Insert into the tile of the first point
|
||||
let (first_lat, first_lon) = points[0];
|
||||
let (x, y) = lat_lon_to_tile(first_lat, first_lon, 10);
|
||||
|
||||
// Serialize points to blob (f64, f64) pairs
|
||||
let mut blob = Vec::with_capacity(points.len() * 16);
|
||||
@@ -192,33 +242,40 @@ async fn main() -> Result<()> {
|
||||
blob.extend_from_slice(&lon.to_be_bytes());
|
||||
}
|
||||
|
||||
for &zoom in &ZOOM_LEVELS {
|
||||
if !should_include(&tags, zoom) { continue; }
|
||||
|
||||
let (x, y) = lat_lon_to_tile(first_lat, first_lon, zoom);
|
||||
let zoom_i32 = zoom as i32;
|
||||
|
||||
if is_highway {
|
||||
let task = DbTask::Way { table: "ways", id, tags: tags.clone(), points: blob.clone(), x, y };
|
||||
let task = DbTask::Way { zoom: zoom_i32, table: "ways", id, tags: tags.clone(), points: blob.clone(), x, y };
|
||||
let _ = tx.blocking_send(task);
|
||||
}
|
||||
|
||||
if is_building {
|
||||
let task = DbTask::Way { table: "buildings", id, tags: tags.clone(), points: blob.clone(), x, y };
|
||||
let task = DbTask::Way { zoom: zoom_i32, table: "buildings", id, tags: tags.clone(), points: blob.clone(), x, y };
|
||||
let _ = tx.blocking_send(task);
|
||||
}
|
||||
|
||||
if is_water {
|
||||
let task = DbTask::Way { table: "water", id, tags: tags.clone(), points: blob.clone(), x, y };
|
||||
let task = DbTask::Way { zoom: zoom_i32, table: "water", id, tags: tags.clone(), points: blob.clone(), x, y };
|
||||
let _ = tx.blocking_send(task);
|
||||
}
|
||||
|
||||
if is_landuse {
|
||||
let task = DbTask::Way { table: "landuse", id, tags: tags.clone(), points: blob.clone(), x, y };
|
||||
let task = DbTask::Way { zoom: zoom_i32, table: "landuse", id, tags: tags.clone(), points: blob.clone(), x, y };
|
||||
let _ = tx.blocking_send(task);
|
||||
}
|
||||
|
||||
if is_railway {
|
||||
let task = DbTask::Way { table: "railways", id, tags: tags.clone(), points: blob.clone(), x, y };
|
||||
let task = DbTask::Way { zoom: zoom_i32, table: "railways", id, tags: tags.clone(), points: blob.clone(), x, y };
|
||||
let _ = tx.blocking_send(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user