This commit is contained in:
Dongho Kim
2025-12-29 03:44:27 +09:00
parent 3885ddd977
commit f3f1a568e2
14 changed files with 380 additions and 100 deletions

View File

@@ -501,7 +501,13 @@ async fn main() -> Result<()> {
if is_railway {
let (first_lat, first_lon) = simplified_points[0];
railway_store.insert_way(id, tags.clone(), line_blob.clone(), first_lat, first_lon);
// Serialize as f64 for high precision
let mut railway_blob = Vec::with_capacity(simplified_points.len() * 16);
for (lat, lon) in &simplified_points {
railway_blob.extend_from_slice(&lat.to_le_bytes());
railway_blob.extend_from_slice(&lon.to_le_bytes());
}
railway_store.insert_way(id, tags.clone(), railway_blob, first_lat, first_lon);
}
}
}
@@ -704,14 +710,28 @@ async fn main() -> Result<()> {
let (x, y) = TileService::lat_lon_to_tile(railway.first_lat, railway.first_lon, zoom);
let zoom_i32 = zoom as i32;
// Parse geometry from blob and generate railway mesh
// Parse geometry from blob (f64) and generate tile-relative railway mesh
let mut points: Vec<[f32; 2]> = Vec::new();
for chunk in railway.points.chunks(8) {
if chunk.len() < 8 { break; }
let lat = f32::from_le_bytes(chunk[0..4].try_into().unwrap_or([0u8; 4])) as f64;
let lon = f32::from_le_bytes(chunk[4..8].try_into().unwrap_or([0u8; 4])) as f64;
let (x, y) = GeometryService::project(lat, lon);
points.push([x, y]);
// Calculate tile origin and scale
let tile_count = 2_f64.powi(zoom as i32);
let tile_size = 1.0 / tile_count;
let tile_origin_x = x as f64 * tile_size;
let tile_origin_y = y as f64 * tile_size;
for chunk in railway.points.chunks(16) {
if chunk.len() < 16 { break; }
let lat = f64::from_le_bytes(chunk[0..8].try_into().unwrap_or([0u8; 8]));
let lon = f64::from_le_bytes(chunk[8..16].try_into().unwrap_or([0u8; 8]));
// Project to Global
let (gx, gy) = GeometryService::project_high_precision(lat, lon);
// Convert to Tile-Relative (0.0 to 1.0)
let rx = ((gx as f64 - tile_origin_x) / tile_size) as f32;
let ry = ((gy as f64 - tile_origin_y) / tile_size) as f32;
points.push([rx, ry]);
}
// Parse color and rail type
@@ -733,7 +753,7 @@ async fn main() -> Result<()> {
let rail_type_str = tags.get("railway").map(|s| s.as_str()).unwrap_or("rail");
let rail_type: f32 = match rail_type_str {
"subway" => 1.0,
"tram" => 2.0,
// "tram" => 2.0, // Disabled
_ => 0.0,
};

View File

@@ -59,7 +59,7 @@ impl FilteringService {
12 => {
matches!(highway, Some("motorway" | "trunk" | "primary" | "secondary" | "tertiary" | "residential" | "unclassified" | "pedestrian" | "service" | "track")) || // Added minor roads
matches!(place, Some("city" | "town" | "village")) ||
matches!(railway, Some("rail" | "subway" | "light_rail" | "narrow_gauge" | "tram")) || // Added tram
matches!(railway, Some("rail" | "subway" | "light_rail" | "narrow_gauge")) || // Removed tram
tags.contains_key("building") ||
tags.contains_key("landuse") ||
tags.contains_key("leisure") ||

View File

@@ -102,4 +102,17 @@ impl GeometryService {
(x, y)
}
/// High precision Web Mercator Projection
/// Returns (x, y) in range [0.0, 1.0] for the whole world as f64
pub fn project_high_precision(lat: f64, lon: f64) -> (f64, f64) {
let x = (lon + 180.0) / 360.0;
let lat_rad = lat.to_radians();
let y = (1.0 - (lat_rad.tan() + (1.0 / lat_rad.cos())).ln() / std::f64::consts::PI) / 2.0;
let x = if x.is_finite() { x.clamp(0.0, 1.0) } else { 0.5 };
let y = if y.is_finite() { y.clamp(0.0, 1.0) } else { 0.5 };
(x, y)
}
}

View File

@@ -176,7 +176,7 @@ impl MeshGenerationService {
let dx = p2[0] - p1[0];
let dy = p2[1] - p1[1];
let len = (dx * dx + dy * dy).sqrt();
if len < 0.000001 {
if len < 0.000000001 {
segment_normals.push([0.0, 0.0]);
degenerate_count += 1;
} else {
@@ -293,7 +293,7 @@ impl MeshGenerationService {
let dx = p2[0] - p1[0];
let dy = p2[1] - p1[1];
let len = (dx * dx + dy * dy).sqrt();
if len < 0.000001 {
if len < 0.000000001 {
segment_normals.push([0.0, 0.0]);
} else {
segment_normals.push([-dy / len, dx / len]);