feat: Enhance track model and import functionality

- Added new fields to TrackModel: status, is_bidirectional, and coordinates.
- Updated network service to handle new track attributes and geometry extraction.
- Introduced CLI scripts for importing and loading tracks from OpenStreetMap.
- Implemented normalization of track elements to ensure valid geometries.
- Enhanced tests for track model, network service, and import/load scripts.
- Updated frontend to accommodate new track attributes and improve route computation.
- Documented OSM ingestion process in architecture and runtime views.
This commit is contained in:
2025-10-11 19:54:10 +02:00
parent 090dca29c2
commit c2927f2f60
18 changed files with 968 additions and 52 deletions

View File

@@ -68,21 +68,22 @@ function App(): JSX.Element {
[data]
);
const routeComputation = useMemo(() => {
const core = computeRoute({
startId: routeSelection.startId,
endId: routeSelection.endId,
stationById,
adjacency: trackAdjacency,
});
const routeComputation = useMemo(
() =>
computeRoute({
startId: routeSelection.startId,
endId: routeSelection.endId,
stationById,
adjacency: trackAdjacency,
}),
[routeSelection, stationById, trackAdjacency]
);
const segments = core.stations ? buildSegmentsFromStations(core.stations) : [];
return {
...core,
segments,
};
}, [routeSelection, stationById, trackAdjacency]);
const routeSegments = useMemo<LatLngExpression[][]>(() => {
return routeComputation.segments.map((segment) =>
segment.map((pair) => [pair[0], pair[1]] as LatLngExpression)
);
}, [routeComputation.segments]);
const focusedStation = useMemo(() => {
if (!data || !focusedStationId) {
@@ -144,7 +145,7 @@ function App(): JSX.Element {
focusedStationId={focusedStationId}
startStationId={routeSelection.startId}
endStationId={routeSelection.endId}
routeSegments={routeComputation.segments}
routeSegments={routeSegments}
onStationClick={handleStationSelection}
/>
</div>
@@ -267,7 +268,9 @@ function App(): JSX.Element {
{data.tracks.map((track) => (
<li key={track.id}>
{track.startStationId} {track.endStationId} ·{' '}
{(track.lengthMeters / 1000).toFixed(1)} km
{track.lengthMeters > 0
? `${(track.lengthMeters / 1000).toFixed(1)} km`
: 'N/A'}
</li>
))}
</ul>
@@ -329,16 +332,3 @@ export default App;
function hasStation(stations: Station[], id: string): boolean {
return stations.some((station) => station.id === id);
}
function buildSegmentsFromStations(stations: Station[]): LatLngExpression[][] {
const segments: LatLngExpression[][] = [];
for (let index = 0; index < stations.length - 1; index += 1) {
const current = stations[index];
const next = stations[index + 1];
segments.push([
[current.latitude, current.longitude],
[next.latitude, next.longitude],
]);
}
return segments;
}