Einführung
Willkommen in der Dokumentation für den GTASA Navigator. Diese Anwendung demonstriert fortschrittliches Routing mittels Graphentheorie in einer Next.js Umgebung.
Das Ziel ist es, den effizientesten Weg zwischen Knotenpunkten zu berechnen, wobei verschiedene Transportmittel (Auto, Boot, Fußgänger) und Kriterien (z.B. Vermeidung von Autobahnen) berücksichtigt werden.
Technologie-Stack
- Frontend: Next.js 16 (App Router), React, Tailwind CSS
- Datenbank: Neo4j (Graph Database)
- Visualisierung: HTML5 Canvas / Leaflet inkl. Custom Map Components
- Icons: Lucide React
Datenmodell
Die Daten werden in Neo4j als Knoten (Nodes) und Kanten (Relationships) gespeichert.

Node Structure
// Beispiel: Node
Node ID: 4:0a462e1b-8cda-4bcd-a3eb-faa4f7e1c95f:167935
{
area_id: 41
emergency_vehicle_only: false
flood_fill: 1
is_highway: false
link_count: 2
link_id: 713
node_id: 337
parking: false
path_width: 40
traffic_level: 2
type: "Car"
x: -1585.75
y: 1172.0
z: 6.0
}Edge Structure
// Beispiel: Edge
Edge ID: 5:0a462e1b-8cda-4bcd-a3eb-faa4f7e1c95f:113343
is_highway: false
length: 12Routing Algorithmus
Die Routenberechnung erfolgt serverseitig direkt in der Datenbank. Wir nutzen Neo4j's shortestPath Funktion.
Logik-Ablauf:
- Klick-Koordinaten (Start/Ziel) erfassen.
- Nächste verfügbare Nodes in der DB finden (Nearest Neighbor).
- Filter anwenden (z.B.
is_highway: false). - Shortest Path Algorythmus.
- Pfad als Array von Koordinaten zurückgeben.
Use Cases
Ausgewählte Anwendungsfälle:
Fußgänger RoutingVermeidet Autobahnen, nutzt Gehwege.
Auto (Schnell)Bevorzugt Highways und Hauptstraßen.
Auto (Landschaft)Vermeidet Highways, nutzt Nebenstraßen.
Use Case 1
Fußgänger Routing
MATCH (startNode:PathNode {type: 'Ped'})
WITH startNode,
(startNode.x - ORIGIN_X)^2 + (startNode.y - ORIGIN_Y)^2 AS startDistanceSq
ORDER BY startDistanceSq
LIMIT 1
MATCH (endNode:PathNode {type: 'Ped'})
WITH startNode, endNode,
(endNode.x - DESTINATION_X)^2 + (endNode.y - DESTINATION_Y)^2 AS endDistanceSq
ORDER BY endDistanceSq
LIMIT 1
MATCH p=shortestPath((startNode)-[:CONNECTS_TO*1..1000]->(endNode))
RETURN pUse Case 2
Auto Schnell
MATCH (startNode:PathNode {type: 'Car'})
WITH startNode,
(startNode.x - ORIGIN_X)^2 + (startNode.y - ORIGIN_Y)^2 AS startDistanceSq
ORDER BY startDistanceSq
LIMIT 1
MATCH (endNode:PathNode {type: 'Car'})
WITH startNode, endNode,
(endNode.x - DESTINATION_X)^2 + (endNode.y - DESTINATION_Y)^2 AS endDistanceSq
ORDER BY endDistanceSq
LIMIT 1
MATCH p=shortestPath((startNode)-[:NOT_HIGHWAY*1..1000]->(endNode))
RETURN pUse Case 3
Auto Landschaft
MATCH (startNode:PathNode {type: 'Car', is_highway: false })
WITH startNode,
(startNode.x - ORIGIN_X)^2 + (startNode.y - ORIGIN_Y)^2 AS startDistanceSq
ORDER BY startDistanceSq
LIMIT 1
MATCH (endNode:PathNode {type: 'Car', is_highway: false })
WITH startNode, endNode,
(endNode.x - DESTINATION_X)^2 + (endNode.y - DESTINATION_Y)^2 AS endDistanceSq
ORDER BY endDistanceSq
LIMIT 1
MATCH p=shortestPath((startNode)-[:NOT_HIGHWAY*1..1000]->(endNode))
RETURN pUse Case 4
Punkte im Umkreis von 200x200
MATCH (n:PathNode)
WHERE n.x >= ORIGIN_X AND n.x <= DESTINATION_X
AND n.y >= ORIGIN_Y AND n.y <= DESTINATION_Y
RETURN elementId(n) as id, n.area_id as area_id, n.node_id as node_id, n.x as x, n.y as y, n.z as z
MATCH (n1:PathNode)-[r]->(n2:PathNode)
WHERE elementId(n1) IN [NODE_IDS]
AND elementId(n2) IN [NODE_IDS]
RETURN elementId(n1) as from, elementId(n2) as to