update
This commit is contained in:
2
.env
2
.env
@@ -16,5 +16,5 @@ CLIENT_PORT=8080
|
|||||||
|
|
||||||
SERVICE_LOG_LEVEL=debug
|
SERVICE_LOG_LEVEL=debug
|
||||||
|
|
||||||
HOST_PBF_PATH=../maps_data/europe-latest.osm.pbf
|
HOST_PBF_PATH=../maps_data/oberbayern-latest.osm.pbf
|
||||||
HOST_CACHE_DIR=./cache
|
HOST_CACHE_DIR=./cache
|
||||||
|
|||||||
10
Dockerfile
10
Dockerfile
@@ -1,5 +1,5 @@
|
|||||||
# Build Frontend
|
# Build Frontend
|
||||||
FROM rust:latest as frontend-builder
|
FROM rust:latest AS frontend-builder
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY frontend ./frontend
|
COPY frontend ./frontend
|
||||||
COPY backend ./backend
|
COPY backend ./backend
|
||||||
@@ -11,7 +11,7 @@ RUN wasm-pack build --target web --out-name wasm --out-dir ../backend/static
|
|||||||
RUN cp index.html ../backend/static/index.html
|
RUN cp index.html ../backend/static/index.html
|
||||||
|
|
||||||
# Build Backend
|
# Build Backend
|
||||||
FROM rust:latest as backend-builder
|
FROM rust:latest AS backend-builder
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY backend ./backend
|
COPY backend ./backend
|
||||||
COPY --from=frontend-builder /app/backend/static ./backend/static
|
COPY --from=frontend-builder /app/backend/static ./backend/static
|
||||||
@@ -19,14 +19,14 @@ WORKDIR /app/backend
|
|||||||
RUN cargo build --release
|
RUN cargo build --release
|
||||||
|
|
||||||
# Build Importer
|
# Build Importer
|
||||||
FROM rust:latest as importer-builder
|
FROM rust:latest AS importer-builder
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY importer ./importer
|
COPY importer ./importer
|
||||||
WORKDIR /app/importer
|
WORKDIR /app/importer
|
||||||
RUN cargo build --release
|
RUN cargo build --release
|
||||||
|
|
||||||
# Backend Runtime
|
# Backend Runtime
|
||||||
FROM debian:forky-slim as backend
|
FROM debian:forky-slim AS backend
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=backend-builder /app/backend/target/release/backend ./backend
|
COPY --from=backend-builder /app/backend/target/release/backend ./backend
|
||||||
COPY --from=frontend-builder /app/backend/static ./static
|
COPY --from=frontend-builder /app/backend/static ./static
|
||||||
@@ -37,7 +37,7 @@ EXPOSE 3000
|
|||||||
CMD ["./backend"]
|
CMD ["./backend"]
|
||||||
|
|
||||||
# Importer Runtime
|
# Importer Runtime
|
||||||
FROM debian:forky-slim as importer
|
FROM debian:forky-slim AS importer
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=importer-builder /app/importer/target/release/importer ./importer
|
COPY --from=importer-builder /app/importer/target/release/importer ./importer
|
||||||
# Install ca-certificates for HTTPS if needed
|
# Install ca-certificates for HTTPS if needed
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use scylla::{Session, SessionBuilder};
|
use scylla::Session;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
pub async fn initialize_schema(session: &Session) -> Result<(), Box<dyn std::error::Error>> {
|
pub async fn initialize_schema(session: &Session) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
// Create keyspace
|
// Create keyspace
|
||||||
|
|||||||
@@ -183,6 +183,32 @@
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Apple Maps-style street labels */
|
||||||
|
.label-street {
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #555;
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
text-shadow:
|
||||||
|
0 0 2px rgba(255, 255, 255, 0.9),
|
||||||
|
0 0 4px rgba(255, 255, 255, 0.8),
|
||||||
|
1px 1px 1px rgba(255, 255, 255, 0.95);
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Apple Maps-style POI labels */
|
||||||
|
.label-poi {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #c44;
|
||||||
|
letter-spacing: 0.2px;
|
||||||
|
text-shadow:
|
||||||
|
0 0 3px rgba(255, 255, 255, 0.95),
|
||||||
|
0 0 5px rgba(255, 255, 255, 0.9),
|
||||||
|
1px 1px 2px rgba(255, 255, 255, 1);
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue", sans-serif;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div id="ui-container">
|
<div id="ui-container">
|
||||||
|
|||||||
1084
frontend/src/lib.rs
1084
frontend/src/lib.rs
File diff suppressed because it is too large
Load Diff
@@ -165,8 +165,8 @@ fn should_include(tags: &HashMap<String, String>, zoom: u32) -> bool {
|
|||||||
|
|
||||||
2 => {
|
2 => {
|
||||||
// Space View: Continents and Countries
|
// Space View: Continents and Countries
|
||||||
matches!(place, Some("continent" | "country")) ||
|
matches!(place, Some("continent" | "country" | "sea" | "ocean")) ||
|
||||||
matches!(natural, Some("water")) || // Major water bodies
|
matches!(natural, Some("water" | "bay" | "strait")) || // Major water bodies
|
||||||
matches!(highway, Some("motorway")) || // Added motorway
|
matches!(highway, Some("motorway")) || // Added motorway
|
||||||
matches!(tags.get("landuse").map(|s| s.as_str()), Some("forest" | "grass" | "meadow" | "farmland" | "residential")) || // Added more green + farmland/residential
|
matches!(tags.get("landuse").map(|s| s.as_str()), Some("forest" | "grass" | "meadow" | "farmland" | "residential")) || // Added more green + farmland/residential
|
||||||
matches!(tags.get("leisure").map(|s| s.as_str()), Some("park" | "nature_reserve")) || // Added parks
|
matches!(tags.get("leisure").map(|s| s.as_str()), Some("park" | "nature_reserve")) || // Added parks
|
||||||
@@ -175,8 +175,8 @@ fn should_include(tags: &HashMap<String, String>, zoom: u32) -> bool {
|
|||||||
4 => {
|
4 => {
|
||||||
// Regional View (NEW)
|
// Regional View (NEW)
|
||||||
matches!(highway, Some("motorway" | "trunk")) ||
|
matches!(highway, Some("motorway" | "trunk")) ||
|
||||||
matches!(place, Some("city" | "town")) ||
|
matches!(place, Some("city" | "town" | "sea" | "ocean")) ||
|
||||||
matches!(natural, Some("water" | "wood" | "scrub" | "heath" | "wetland")) ||
|
matches!(natural, Some("water" | "wood" | "scrub" | "heath" | "wetland" | "bay" | "strait")) ||
|
||||||
matches!(tags.get("landuse").map(|s| s.as_str()), Some("forest" | "grass" | "meadow" | "farmland" | "residential")) ||
|
matches!(tags.get("landuse").map(|s| s.as_str()), Some("forest" | "grass" | "meadow" | "farmland" | "residential")) ||
|
||||||
matches!(tags.get("leisure").map(|s| s.as_str()), Some("park" | "nature_reserve")) ||
|
matches!(tags.get("leisure").map(|s| s.as_str()), Some("park" | "nature_reserve")) ||
|
||||||
matches!(waterway, Some("river"))
|
matches!(waterway, Some("river"))
|
||||||
@@ -185,8 +185,8 @@ fn should_include(tags: &HashMap<String, String>, zoom: u32) -> bool {
|
|||||||
// Enterprise Grade: ONLY Motorways and Trunk roads. No primary/secondary.
|
// Enterprise Grade: ONLY Motorways and Trunk roads. No primary/secondary.
|
||||||
// ONLY Cities. No nature/landuse.
|
// ONLY Cities. No nature/landuse.
|
||||||
matches!(highway, Some("motorway" | "trunk" | "primary")) || // Added primary
|
matches!(highway, Some("motorway" | "trunk" | "primary")) || // Added primary
|
||||||
matches!(place, Some("city")) ||
|
matches!(place, Some("city" | "sea" | "ocean")) ||
|
||||||
matches!(natural, Some("water" | "wood" | "scrub" | "heath" | "wetland")) ||
|
matches!(natural, Some("water" | "wood" | "scrub" | "heath" | "wetland" | "bay" | "strait")) ||
|
||||||
matches!(tags.get("landuse").map(|s| s.as_str()), Some("forest" | "grass" | "meadow" | "farmland" | "residential")) ||
|
matches!(tags.get("landuse").map(|s| s.as_str()), Some("forest" | "grass" | "meadow" | "farmland" | "residential")) ||
|
||||||
matches!(tags.get("leisure").map(|s| s.as_str()), Some("park" | "nature_reserve")) ||
|
matches!(tags.get("leisure").map(|s| s.as_str()), Some("park" | "nature_reserve")) ||
|
||||||
matches!(waterway, Some("river"))
|
matches!(waterway, Some("river"))
|
||||||
@@ -196,9 +196,9 @@ fn should_include(tags: &HashMap<String, String>, zoom: u32) -> bool {
|
|||||||
// Add Towns.
|
// Add Towns.
|
||||||
// Limited nature.
|
// Limited nature.
|
||||||
matches!(highway, Some("motorway" | "trunk" | "primary")) ||
|
matches!(highway, Some("motorway" | "trunk" | "primary")) ||
|
||||||
matches!(place, Some("city" | "town")) ||
|
matches!(place, Some("city" | "town" | "sea" | "ocean")) ||
|
||||||
matches!(railway, Some("rail")) ||
|
matches!(railway, Some("rail")) ||
|
||||||
matches!(natural, Some("water" | "wood")) ||
|
matches!(natural, Some("water" | "wood" | "bay" | "strait")) ||
|
||||||
matches!(tags.get("landuse").map(|s| s.as_str()), Some("forest")) ||
|
matches!(tags.get("landuse").map(|s| s.as_str()), Some("forest")) ||
|
||||||
matches!(tags.get("leisure").map(|s| s.as_str()), Some("park")) ||
|
matches!(tags.get("leisure").map(|s| s.as_str()), Some("park")) ||
|
||||||
matches!(waterway, Some("river" | "riverbank"))
|
matches!(waterway, Some("river" | "riverbank"))
|
||||||
@@ -210,7 +210,7 @@ fn should_include(tags: &HashMap<String, String>, zoom: u32) -> bool {
|
|||||||
tags.contains_key("building") ||
|
tags.contains_key("building") ||
|
||||||
tags.contains_key("landuse") ||
|
tags.contains_key("landuse") ||
|
||||||
tags.contains_key("leisure") ||
|
tags.contains_key("leisure") ||
|
||||||
matches!(natural, Some("water" | "wood" | "scrub" | "wetland" | "heath")) ||
|
matches!(natural, Some("water" | "wood" | "scrub" | "wetland" | "heath" | "bay" | "strait")) ||
|
||||||
matches!(waterway, Some("river" | "riverbank" | "stream"))
|
matches!(waterway, Some("river" | "riverbank" | "stream"))
|
||||||
},
|
},
|
||||||
_ => false
|
_ => false
|
||||||
@@ -404,7 +404,8 @@ async fn main() -> Result<()> {
|
|||||||
// Filter for highways/roads OR buildings OR landuse OR water OR railways
|
// Filter for highways/roads OR buildings OR landuse OR water OR railways
|
||||||
let is_highway = tags.contains_key("highway");
|
let is_highway = tags.contains_key("highway");
|
||||||
let is_building = tags.contains_key("building");
|
let is_building = tags.contains_key("building");
|
||||||
let is_water = tags.get("natural").map(|v| v == "water" || v == "wetland").unwrap_or(false) ||
|
let is_water = tags.get("natural").map(|v| v == "water" || v == "wetland" || v == "bay" || v == "strait").unwrap_or(false) ||
|
||||||
|
tags.get("place").map(|v| v == "sea" || v == "ocean").unwrap_or(false) ||
|
||||||
tags.get("waterway").map(|v| v == "riverbank" || v == "stream" || v == "river").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);
|
tags.get("landuse").map(|v| v == "basin" || v == "reservoir").unwrap_or(false);
|
||||||
let is_landuse = tags.contains_key("leisure") ||
|
let is_landuse = tags.contains_key("leisure") ||
|
||||||
@@ -442,7 +443,11 @@ async fn main() -> Result<()> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let epsilon = if is_water || is_landuse || is_highway {
|
let epsilon = if is_water || is_landuse || is_highway {
|
||||||
|
if zoom <= 4 && is_landuse {
|
||||||
|
0.0 // Disable simplification for landuse at low zoom to prevent disappearing polygons
|
||||||
|
} else {
|
||||||
base_epsilon * 0.5 // Preserve more detail for natural features AND roads
|
base_epsilon * 0.5 // Preserve more detail for natural features AND roads
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
base_epsilon
|
base_epsilon
|
||||||
};
|
};
|
||||||
@@ -454,9 +459,17 @@ async fn main() -> Result<()> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Serialize points
|
// Serialize points
|
||||||
let mut final_points = simplified_points;
|
let mut final_points = simplified_points.clone();
|
||||||
|
|
||||||
// Triangulate if it's a polygon type
|
// For highways and railways, we DON'T triangulate - they're line data
|
||||||
|
// Create the highway/railway blob BEFORE triangulation
|
||||||
|
let mut line_blob = Vec::with_capacity(simplified_points.len() * 8);
|
||||||
|
for (lat, lon) in &simplified_points {
|
||||||
|
line_blob.extend_from_slice(&(*lat as f32).to_le_bytes());
|
||||||
|
line_blob.extend_from_slice(&(*lon as f32).to_le_bytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Triangulate for polygon types (buildings, water, landuse)
|
||||||
if is_building || is_water || is_landuse {
|
if is_building || is_water || is_landuse {
|
||||||
// Close the loop if not closed
|
// Close the loop if not closed
|
||||||
if final_points.first() != final_points.last() {
|
if final_points.first() != final_points.last() {
|
||||||
@@ -465,40 +478,43 @@ async fn main() -> Result<()> {
|
|||||||
final_points = triangulate_polygon(&final_points);
|
final_points = triangulate_polygon(&final_points);
|
||||||
}
|
}
|
||||||
|
|
||||||
if final_points.len() < 2 { continue; }
|
if final_points.len() < 3 && (is_building || is_water || is_landuse) { continue; }
|
||||||
|
if simplified_points.len() < 2 && (is_highway || is_railway) { continue; }
|
||||||
|
|
||||||
let (first_lat, first_lon) = final_points[0];
|
let (first_lat, first_lon) = simplified_points[0];
|
||||||
let (x, y) = lat_lon_to_tile(first_lat, first_lon, zoom);
|
let (x, y) = lat_lon_to_tile(first_lat, first_lon, zoom);
|
||||||
let zoom_i32 = zoom as i32;
|
let zoom_i32 = zoom as i32;
|
||||||
|
|
||||||
let mut blob = Vec::with_capacity(final_points.len() * 8); // 4 bytes lat + 4 bytes lon
|
// Create polygon blob from triangulated points
|
||||||
for (lat, lon) in final_points {
|
let mut polygon_blob = Vec::with_capacity(final_points.len() * 8);
|
||||||
blob.extend_from_slice(&(lat as f32).to_le_bytes());
|
for (lat, lon) in &final_points {
|
||||||
blob.extend_from_slice(&(lon as f32).to_le_bytes());
|
polygon_blob.extend_from_slice(&(*lat as f32).to_le_bytes());
|
||||||
|
polygon_blob.extend_from_slice(&(*lon as f32).to_le_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use line_blob for highways/railways, polygon_blob for others
|
||||||
if is_highway {
|
if is_highway {
|
||||||
let task = DbTask::Way { zoom: zoom_i32, 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: line_blob.clone(), x, y };
|
||||||
let _ = tx.blocking_send(task);
|
let _ = tx.blocking_send(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_building {
|
if is_building {
|
||||||
let task = DbTask::Way { zoom: zoom_i32, 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: polygon_blob.clone(), x, y };
|
||||||
let _ = tx.blocking_send(task);
|
let _ = tx.blocking_send(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_water {
|
if is_water {
|
||||||
let task = DbTask::Way { zoom: zoom_i32, 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: polygon_blob.clone(), x, y };
|
||||||
let _ = tx.blocking_send(task);
|
let _ = tx.blocking_send(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_landuse {
|
if is_landuse {
|
||||||
let task = DbTask::Way { zoom: zoom_i32, 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: polygon_blob.clone(), x, y };
|
||||||
let _ = tx.blocking_send(task);
|
let _ = tx.blocking_send(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_railway {
|
if is_railway {
|
||||||
let task = DbTask::Way { zoom: zoom_i32, 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: line_blob.clone(), x, y };
|
||||||
let _ = tx.blocking_send(task);
|
let _ = tx.blocking_send(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user