Add smoothness, track type, cycleway, and bike route color modes

Four new route visualization modes extracted from BRouter WayTags:

- Smoothness: excellent (green) → impassable (dark red)
- Track Type: grade1 (green, best) → grade5 (red, worst)
- Cycleway: track/lane/shared_lane/no with direction awareness
- Bike Route: icn/ncn/rcn/lcn priority from route_bicycle_* tags

Each mode includes map polyline coloring, elevation chart coloring,
inline legend, hover label, i18n (EN+DE), and mock fixture data.

Dockerfile patched to also expose tracktype in BRouter WayTags
(smoothness, cycleway, and route_bicycle already present).

Dropdown order: plain, elevation, grade, surface, road type, speed
limit, smoothness, track type, cycleway, bike route.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ullrich Schäfer 2026-04-11 09:58:25 +02:00
parent 768fa9df44
commit 6ec95216e1
No known key found for this signature in database
GPG key ID: A32FF691A0F752D9
9 changed files with 472 additions and 15 deletions

View file

@ -377,6 +377,10 @@ export function PlannerMap({ yjs, onRouteRequest, highlightPosition, highlighted
const [surfaces, setSurfaces] = useState<string[]>([]);
const [highways, setHighways] = useState<string[]>([]);
const [maxspeeds, setMaxspeeds] = useState<string[]>([]);
const [smoothnesses, setSmoothnesses] = useState<string[]>([]);
const [tracktypes, setTracktypes] = useState<string[]>([]);
const [cycleways, setCycleways] = useState<string[]>([]);
const [bikeroutes, setBikeroutes] = useState<string[]>([]);
const [colorMode, setColorMode] = useState<ColorMode>("plain");
const [noGoDrawing, setNoGoDrawing] = useState(false);
const toggleNoGoDraw = useCallback(() => setNoGoDrawing((v) => !v), []);
@ -458,6 +462,34 @@ export function PlannerMap({ yjs, onRouteRequest, highlightPosition, highlighted
setMaxspeeds([]);
}
const smoothnessesJson = yjs.routeData.get("smoothnesses") as string | undefined;
if (smoothnessesJson) {
try { setSmoothnesses(JSON.parse(smoothnessesJson)); } catch { setSmoothnesses([]); }
} else {
setSmoothnesses([]);
}
const tracktypesJson = yjs.routeData.get("tracktypes") as string | undefined;
if (tracktypesJson) {
try { setTracktypes(JSON.parse(tracktypesJson)); } catch { setTracktypes([]); }
} else {
setTracktypes([]);
}
const cyclewaysJson = yjs.routeData.get("cycleways") as string | undefined;
if (cyclewaysJson) {
try { setCycleways(JSON.parse(cyclewaysJson)); } catch { setCycleways([]); }
} else {
setCycleways([]);
}
const bikeroutesJson = yjs.routeData.get("bikeroutes") as string | undefined;
if (bikeroutesJson) {
try { setBikeroutes(JSON.parse(bikeroutesJson)); } catch { setBikeroutes([]); }
} else {
setBikeroutes([]);
}
if (modeVal) setColorMode(modeVal);
};
@ -740,6 +772,10 @@ export function PlannerMap({ yjs, onRouteRequest, highlightPosition, highlighted
surfaces={surfaces}
highways={highways}
maxspeeds={maxspeeds}
smoothnesses={smoothnesses}
tracktypes={tracktypes}
cycleways={cycleways}
bikeroutes={bikeroutes}
/>
<RouteInteraction
coordinates={routeCoordinates}