udpate sick
This commit is contained in:
@@ -269,12 +269,28 @@ async fn main() -> Result<()> {
|
||||
|
||||
if is_highway || treat_as_water_line {
|
||||
// Generate road geometry
|
||||
let projected_points: Vec<[f32; 2]> = simplified_points.iter()
|
||||
let projected_points_raw: Vec<[f32; 2]> = simplified_points.iter()
|
||||
.map(|(lat, lon)| {
|
||||
let (x, y) = GeometryService::project(*lat, *lon);
|
||||
[x, y]
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Fix degenerate segments: Deduplicate consecutive points that are too close
|
||||
let mut projected_points = Vec::with_capacity(projected_points_raw.len());
|
||||
if !projected_points_raw.is_empty() {
|
||||
projected_points.push(projected_points_raw[0]);
|
||||
for i in 1..projected_points_raw.len() {
|
||||
let prev = projected_points.last().unwrap();
|
||||
let curr = projected_points_raw[i];
|
||||
let dx = curr[0] - prev[0];
|
||||
let dy = curr[1] - prev[1];
|
||||
// 1.0e-11 is approx (3e-6)^2, which ensures we are safely above the 1e-6 degenerate threshold
|
||||
if (dx * dx + dy * dy) > 1.0e-11 {
|
||||
projected_points.push(curr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let highway_tag = tags.get("highway").map(|s| s.as_str());
|
||||
let road_type = match highway_tag.unwrap_or("") {
|
||||
@@ -293,20 +309,67 @@ async fn main() -> Result<()> {
|
||||
.and_then(|s| s.parse().ok())
|
||||
.unwrap_or(default_lanes);
|
||||
|
||||
// DEBUG: Log first way to validate mesh generation
|
||||
if way_count == 1 {
|
||||
println!("DEBUG Way {}: {} projected points, generating mesh...", id, projected_points.len());
|
||||
// DEBUG: Enable verbose logging for specific way ID via environment variable
|
||||
let debug_way_id: Option<i64> = std::env::var("DEBUG_WAY_ID")
|
||||
.ok()
|
||||
.and_then(|s| s.parse().ok());
|
||||
|
||||
if debug_way_id == Some(id) {
|
||||
println!("DEBUG Way {}: Processing at zoom {}", id, zoom);
|
||||
println!(" - is_highway: {}", is_highway);
|
||||
println!(" - treat_as_water_line: {}", treat_as_water_line);
|
||||
println!(" - is_water_line: {}", is_water_line);
|
||||
println!(" - is_water_area: {}", is_water_area);
|
||||
println!(" - Original points: {}", points.len());
|
||||
println!(" - Simplified points: {}", simplified_points.len());
|
||||
println!(" - Projected points: {}", projected_points.len());
|
||||
println!(" - First 5 simplified (lat/lon):");
|
||||
for (i, p) in simplified_points.iter().take(5).enumerate() {
|
||||
println!(" [{:2}] lat={:.8}, lon={:.8}", i, p.0, p.1);
|
||||
}
|
||||
println!(" - First 5 projected (x/y):");
|
||||
for (i, p) in projected_points.iter().take(5).enumerate() {
|
||||
println!(" [{:2}] x={:.8}, y={:.8}", i, p[0], p[1]);
|
||||
}
|
||||
|
||||
// Check for consecutive duplicates
|
||||
let mut duplicates = 0;
|
||||
for i in 0..projected_points.len().saturating_sub(1) {
|
||||
let p1 = projected_points[i];
|
||||
let p2 = projected_points[i + 1];
|
||||
let dx = p2[0] - p1[0];
|
||||
let dy = p2[1] - p1[1];
|
||||
let dist = (dx * dx + dy * dy).sqrt();
|
||||
if dist < 0.000001 {
|
||||
duplicates += 1;
|
||||
if duplicates <= 3 {
|
||||
println!(" DEGENERATE segment {}: dist={:.12}, p1=[{:.8},{:.8}], p2=[{:.8},{:.8}]",
|
||||
i, dist, p1[0], p1[1], p2[0], p2[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if duplicates > 0 {
|
||||
println!(" - Total degenerate segments: {}/{}", duplicates, projected_points.len() - 1);
|
||||
}
|
||||
println!(" - Tags: {:?}", tags);
|
||||
}
|
||||
|
||||
let vertex_buffer = if treat_as_water_line {
|
||||
if debug_way_id == Some(id) {
|
||||
println!(" - Using generate_polygon_geometry for water line");
|
||||
}
|
||||
mesh_svc.generate_polygon_geometry(&projected_points)
|
||||
} else {
|
||||
if debug_way_id == Some(id) {
|
||||
println!(" - Using generate_road_geometry with lanes={}, road_type={}", lanes, road_type);
|
||||
}
|
||||
mesh_svc.generate_road_geometry(&projected_points, lanes, road_type)
|
||||
};
|
||||
|
||||
// DEBUG: Log buffer size
|
||||
if way_count == 1 {
|
||||
println!("DEBUG Way {}: vertex_buffer size = {} bytes", id, vertex_buffer.len());
|
||||
// DEBUG: Log buffer size for tracked way
|
||||
if debug_way_id == Some(id) {
|
||||
println!(" - vertex_buffer size = {} bytes", vertex_buffer.len());
|
||||
println!(" - Expected vertex size: {} bytes", if treat_as_water_line { 8 } else { 24 });
|
||||
}
|
||||
|
||||
let task = DbTask::Way {
|
||||
@@ -358,27 +421,58 @@ async fn main() -> Result<()> {
|
||||
}
|
||||
|
||||
if treat_as_water_area {
|
||||
// Generate water polygon mesh
|
||||
let projected_points: Vec<[f32; 2]> = final_points.iter()
|
||||
.map(|(lat, lon)| {
|
||||
let (x, y) = GeometryService::project(*lat, *lon);
|
||||
[x, y]
|
||||
})
|
||||
.collect();
|
||||
// Calculate bounding box for multi-tile insertion
|
||||
let mut min_lat = f64::MAX;
|
||||
let mut max_lat = f64::MIN;
|
||||
let mut min_lon = f64::MAX;
|
||||
let mut max_lon = f64::MIN;
|
||||
|
||||
let vertex_buffer = mesh_svc.generate_polygon_geometry(&projected_points);
|
||||
for (lat, lon) in &final_points {
|
||||
if *lat < min_lat { min_lat = *lat; }
|
||||
if *lat > max_lat { max_lat = *lat; }
|
||||
if *lon < min_lon { min_lon = *lon; }
|
||||
if *lon > max_lon { max_lon = *lon; }
|
||||
}
|
||||
|
||||
let task = DbTask::Way {
|
||||
zoom: zoom_i32,
|
||||
table: "water",
|
||||
id,
|
||||
tags: tags.clone(),
|
||||
points: polygon_blob.clone(),
|
||||
vertex_buffer,
|
||||
x,
|
||||
y
|
||||
};
|
||||
let _ = tx.blocking_send(task);
|
||||
// Get tiles covered by bounding box
|
||||
let (min_tile_x, min_tile_y) = TileService::lat_lon_to_tile(min_lat, min_lon, zoom);
|
||||
let (max_tile_x, max_tile_y) = TileService::lat_lon_to_tile(max_lat, max_lon, zoom);
|
||||
|
||||
// Iterate over all tiles in bbox
|
||||
for tile_x in min_tile_x..=max_tile_x {
|
||||
for tile_y in min_tile_y..=max_tile_y {
|
||||
// Calculate tile origin and scale for relative coordinates
|
||||
let tile_count = 2_f64.powi(zoom as i32);
|
||||
let tile_size = 1.0 / tile_count;
|
||||
let tile_origin_x = tile_x as f64 * tile_size;
|
||||
let tile_origin_y = tile_y as f64 * tile_size;
|
||||
|
||||
// Project points to global space then make relative to this tile
|
||||
let projected_points: Vec<[f32; 2]> = final_points.iter()
|
||||
.map(|(lat, lon)| {
|
||||
let (global_x, global_y) = GeometryService::project(*lat, *lon);
|
||||
// Convert to tile-relative (0..1 within tile)
|
||||
let relative_x = ((global_x as f64 - tile_origin_x) / tile_size) as f32;
|
||||
let relative_y = ((global_y as f64 - tile_origin_y) / tile_size) as f32;
|
||||
[relative_x, relative_y]
|
||||
})
|
||||
.collect();
|
||||
|
||||
let vertex_buffer = mesh_svc.generate_polygon_geometry(&projected_points);
|
||||
|
||||
let task = DbTask::Way {
|
||||
zoom: zoom_i32,
|
||||
table: "water",
|
||||
id,
|
||||
tags: tags.clone(),
|
||||
points: polygon_blob.clone(),
|
||||
vertex_buffer,
|
||||
x: tile_x,
|
||||
y: tile_y,
|
||||
};
|
||||
let _ = tx.blocking_send(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if treat_as_landuse {
|
||||
@@ -434,8 +528,11 @@ async fn main() -> Result<()> {
|
||||
if let Some(line_ref) = tags.get("ref") {
|
||||
// Only propagate S-Bahn/U-Bahn style refs (starts with S or U followed by digit)
|
||||
if (line_ref.starts_with('S') || line_ref.starts_with('U')) && line_ref.len() >= 2 {
|
||||
let member_count = rel.members().filter(|m| matches!(m.member_type, osmpbf::RelMemberType::Way)).count();
|
||||
println!("DEBUG: Found transit line ref '{}' with {} way members", line_ref, member_count);
|
||||
// Only log if verbose debugging is enabled
|
||||
if std::env::var("VERBOSE_DEBUG").is_ok() {
|
||||
let member_count = rel.members().filter(|m| matches!(m.member_type, osmpbf::RelMemberType::Way)).count();
|
||||
println!("DEBUG: Found transit line ref '{}' with {} way members", line_ref, member_count);
|
||||
}
|
||||
for member in rel.members() {
|
||||
if let osmpbf::RelMemberType::Way = member.member_type {
|
||||
railway_store.set_ref(member.member_id, line_ref.clone());
|
||||
@@ -497,27 +594,81 @@ async fn main() -> Result<()> {
|
||||
|
||||
let table = if is_water { "water" } else { "landuse" };
|
||||
|
||||
// Generate polygon mesh for multipolygons
|
||||
let projected_points: Vec<[f32; 2]> = final_points.iter()
|
||||
.map(|(lat, lon)| {
|
||||
let (x, y) = GeometryService::project(*lat, *lon);
|
||||
[x, y]
|
||||
})
|
||||
.collect();
|
||||
|
||||
let vertex_buffer = mesh_svc.generate_polygon_geometry(&projected_points);
|
||||
|
||||
let task = DbTask::Way {
|
||||
zoom: zoom_i32,
|
||||
table,
|
||||
id,
|
||||
tags: tags.clone(),
|
||||
points: polygon_blob.clone(),
|
||||
vertex_buffer,
|
||||
x,
|
||||
y
|
||||
};
|
||||
let _ = tx.blocking_send(task);
|
||||
// For water, use multi-tile insertion with tile-relative coords
|
||||
if is_water {
|
||||
// Calculate bounding box
|
||||
let mut min_lat = f64::MAX;
|
||||
let mut max_lat = f64::MIN;
|
||||
let mut min_lon = f64::MAX;
|
||||
let mut max_lon = f64::MIN;
|
||||
|
||||
for (lat, lon) in &final_points {
|
||||
if *lat < min_lat { min_lat = *lat; }
|
||||
if *lat > max_lat { max_lat = *lat; }
|
||||
if *lon < min_lon { min_lon = *lon; }
|
||||
if *lon > max_lon { max_lon = *lon; }
|
||||
}
|
||||
|
||||
let (min_tile_x, min_tile_y) = TileService::lat_lon_to_tile(min_lat, min_lon, zoom);
|
||||
let (max_tile_x, max_tile_y) = TileService::lat_lon_to_tile(max_lat, max_lon, zoom);
|
||||
|
||||
// Iterate over all tiles
|
||||
for tile_x in min_tile_x..=max_tile_x {
|
||||
for tile_y in min_tile_y..=max_tile_y {
|
||||
let tile_count = 2_f64.powi(zoom as i32);
|
||||
let tile_size = 1.0 / tile_count;
|
||||
let tile_origin_x = tile_x as f64 * tile_size;
|
||||
let tile_origin_y = tile_y as f64 * tile_size;
|
||||
|
||||
let projected_points: Vec<[f32; 2]> = final_points.iter()
|
||||
.map(|(lat, lon)| {
|
||||
let (global_x, global_y) = GeometryService::project(*lat, *lon);
|
||||
let relative_x = ((global_x as f64 - tile_origin_x) / tile_size) as f32;
|
||||
let relative_y = ((global_y as f64 - tile_origin_y) / tile_size) as f32;
|
||||
[relative_x, relative_y]
|
||||
})
|
||||
.collect();
|
||||
|
||||
let vertex_buffer = mesh_svc.generate_polygon_geometry(&projected_points);
|
||||
|
||||
let task = DbTask::Way {
|
||||
zoom: zoom_i32,
|
||||
table,
|
||||
id,
|
||||
tags: tags.clone(),
|
||||
points: polygon_blob.clone(),
|
||||
vertex_buffer,
|
||||
x: tile_x,
|
||||
y: tile_y,
|
||||
};
|
||||
let _ = tx.blocking_send(task);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Landuse: keep old single-tile logic for now
|
||||
let (x, y) = TileService::lat_lon_to_tile(first_lat, first_lon, zoom);
|
||||
|
||||
let projected_points: Vec<[f32; 2]> = final_points.iter()
|
||||
.map(|(lat, lon)| {
|
||||
let (x, y) = GeometryService::project(*lat, *lon);
|
||||
[x, y]
|
||||
})
|
||||
.collect();
|
||||
|
||||
let vertex_buffer = mesh_svc.generate_polygon_geometry(&projected_points);
|
||||
|
||||
let task = DbTask::Way {
|
||||
zoom: zoom_i32,
|
||||
table,
|
||||
id,
|
||||
tags: tags.clone(),
|
||||
points: polygon_blob.clone(),
|
||||
vertex_buffer,
|
||||
x,
|
||||
y,
|
||||
};
|
||||
let _ = tx.blocking_send(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,12 +158,18 @@ impl MeshGenerationService {
|
||||
}
|
||||
|
||||
fn generate_road_mesh(points: &[[f32; 2]], lanes: f32, road_type: f32) -> Vec<RoadVertex> {
|
||||
let debug_mesh = std::env::var("DEBUG_MESH").is_ok();
|
||||
|
||||
if points.len() < 2 {
|
||||
if debug_mesh {
|
||||
println!("DEBUG MESH: Too few points ({})", points.len());
|
||||
}
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
// Compute normals for each segment
|
||||
let mut segment_normals = Vec::with_capacity(points.len() - 1);
|
||||
let mut degenerate_count = 0;
|
||||
for i in 0..points.len() - 1 {
|
||||
let p1 = points[i];
|
||||
let p2 = points[i + 1];
|
||||
@@ -172,10 +178,15 @@ impl MeshGenerationService {
|
||||
let len = (dx * dx + dy * dy).sqrt();
|
||||
if len < 0.000001 {
|
||||
segment_normals.push([0.0, 0.0]);
|
||||
degenerate_count += 1;
|
||||
} else {
|
||||
segment_normals.push([-dy / len, dx / len]);
|
||||
}
|
||||
}
|
||||
|
||||
if debug_mesh && degenerate_count > 0 {
|
||||
println!("DEBUG MESH: {}/{} segments degenerate", degenerate_count, segment_normals.len());
|
||||
}
|
||||
|
||||
// Generate vertex pairs with miter joins
|
||||
let mut point_pairs = Vec::with_capacity(points.len() * 2);
|
||||
@@ -233,8 +244,10 @@ impl MeshGenerationService {
|
||||
|
||||
// Triangulate
|
||||
let mut triangle_vertices = Vec::with_capacity((points.len() - 1) * 6);
|
||||
let mut skipped = 0;
|
||||
for i in 0..points.len() - 1 {
|
||||
if Self::dot(segment_normals[i], segment_normals[i]) == 0.0 {
|
||||
skipped += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -255,6 +268,11 @@ impl MeshGenerationService {
|
||||
triangle_vertices.push(v3);
|
||||
}
|
||||
|
||||
if debug_mesh {
|
||||
println!("DEBUG MESH: Generated {} vertices from {} points (skipped {} segments)",
|
||||
triangle_vertices.len(), points.len(), skipped);
|
||||
}
|
||||
|
||||
triangle_vertices
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user