Routenberechnung mit partitionierten Straßendaten

Ähnliche Dokumente
1 topologisches Sortieren

Konzepte der Informatik

Grundlagen der Theoretischen Informatik, SoSe 2008

Inhalt. 1 Einleitung AUTOMATISCHE DATENSICHERUNG AUF EINEN CLOUDSPEICHER

Handbuch zur Anlage von Turnieren auf der NÖEV-Homepage

4. BEZIEHUNGEN ZWISCHEN TABELLEN

Zeichen bei Zahlen entschlüsseln

Kapiteltests zum Leitprogramm Binäre Suchbäume

Datensicherung. Beschreibung der Datensicherung

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren

Mit der Maus im Menü links auf den Menüpunkt 'Seiten' gehen und auf 'Erstellen klicken.

Guide DynDNS und Portforwarding

Handbuch Fischertechnik-Einzelteiltabelle V3.7.3

Programmierkurs Java

Er musste so eingerichtet werden, dass das D-Laufwerk auf das E-Laufwerk gespiegelt

Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen

Datenbanken Kapitel 2

Zimmertypen. Zimmertypen anlegen

OP-LOG

Im Folgenden wird Ihnen an einem Beispiel erklärt, wie Sie Excel-Anlagen und Excel-Vorlagen erstellen können.

1 Mathematische Grundlagen

Das Briefträgerproblem

Dokumentation IBIS Monitor

Die Dateiablage Der Weg zur Dateiablage

Primzahlen und RSA-Verschlüsselung

Das große ElterngeldPlus 1x1. Alles über das ElterngeldPlus. Wer kann ElterngeldPlus beantragen? ElterngeldPlus verstehen ein paar einleitende Fakten

Erklärung zum Internet-Bestellschein

Jede Zahl muss dabei einzeln umgerechnet werden. Beginnen wir also ganz am Anfang mit der Zahl,192.

Dieser Ablauf soll eine Hilfe für die tägliche Arbeit mit der SMS Bestätigung im Millennium darstellen.

Erstellen einer Collage. Zuerst ein leeres Dokument erzeugen, auf dem alle anderen Bilder zusammengefügt werden sollen (über [Datei] > [Neu])

Diese Ansicht erhalten Sie nach der erfolgreichen Anmeldung bei Wordpress.

OS Anwendungsbeschreibung

etutor Benutzerhandbuch XQuery Benutzerhandbuch Georg Nitsche

Partitionieren in Vista und Windows 7/8

ecaros2 - Accountmanager

Fachdidaktik der Informatik Jörg Depner, Kathrin Gaißer

OECD Programme for International Student Assessment PISA Lösungen der Beispielaufgaben aus dem Mathematiktest. Deutschland

1. Motivation / Grundlagen 2. Sortierverfahren 3. Elementare Datenstrukturen / Anwendungen 4. Bäume / Graphen 5. Hashing 6. Algorithmische Geometrie

GeoPilot (Android) die App

Handbuch B4000+ Preset Manager

Welche Unterschiede gibt es zwischen einem CAPAund einem Audiometrie- Test?

Monitoring-Service Anleitung

Handbuch. NAFI Online-Spezial. Kunden- / Datenverwaltung. 1. Auflage. (Stand: )

Mediumwechsel - VR-NetWorld Software

How to do? Projekte - Zeiterfassung

Zahlen auf einen Blick

Outlook. sysplus.ch outlook - mail-grundlagen Seite 1/8. Mail-Grundlagen. Posteingang

Handbuch ECDL 2003 Basic Modul 5: Datenbank Grundlagen von relationalen Datenbanken

Arbeiten mit UMLed und Delphi

Software Engineering Klassendiagramme Assoziationen

mysql - Clients MySQL - Abfragen eine serverbasierenden Datenbank

Anleitung für den Euroweb-Newsletter

Dateimanagement in Moodle Eine Schritt-für

Suche schlecht beschriftete Bilder mit Eigenen Abfragen

Stellen Sie bitte den Cursor in die Spalte B2 und rufen die Funktion Sverweis auf. Es öffnet sich folgendes Dialogfenster

4. Jeder Knoten hat höchstens zwei Kinder, ein linkes und ein rechtes.

Ihre Interessentendatensätze bei inobroker. 1. Interessentendatensätze

Der vorliegende Konverter unterstützt Sie bei der Konvertierung der Datensätze zu IBAN und BIC.

WordPress. Dokumentation

PowerMover. Ein halbautomatischer Sortierer für Outlook-PowerUser. Ein Add-In für die Versionen 2007 und 2010

CALCOO Lite. Inhalt. 1. Projekt anlegen / öffnen. 2. Projekt von CALCOO App importieren

Würfelt man dabei je genau 10 - mal eine 1, 2, 3, 4, 5 und 6, so beträgt die Anzahl. der verschiedenen Reihenfolgen, in denen man dies tun kann, 60!.

Access [basics] Rechnen in Berichten. Beispieldatenbank. Datensatzweise berechnen. Berechnung im Textfeld. Reporting in Berichten Rechnen in Berichten

mobilepoi 0.91 Demo Version Anleitung Das Software Studio Christian Efinger Erstellt am 21. Oktober 2005

Dokumentation zum Spielserver der Software Challenge

Lineare Gleichungssysteme

Sie werden sehen, dass Sie für uns nur noch den direkten PDF-Export benötigen. Warum?

Datenübernahme von HKO 5.9 zur. Advolux Kanzleisoftware

Hilfe zur Urlaubsplanung und Zeiterfassung

Virtueller Seminarordner Anleitung für die Dozentinnen und Dozenten

Einrichten einer Festplatte mit FDISK unter Windows 95/98/98SE/Me

Wichtige Hinweise zu den neuen Orientierungshilfen der Architekten-/Objektplanerverträge

IBIS Professional. z Dokumentation zur Dublettenprüfung

EasyWk DAS Schwimmwettkampfprogramm

PHP - Projekt Personalverwaltung. Erstellt von James Schüpbach

Windows. Workshop Internet-Explorer: Arbeiten mit Favoriten, Teil 1

In diesem Thema lernen wir die Grundlagen der Datenbanken kennen und werden diese lernen einzusetzen. Access. Die Grundlagen der Datenbanken.

SharePoint Demonstration

Ablaufbeschreibung für das neu Aufsetzen von Firebird und Interbase Datenbanken mit der IBOConsole

WS 2009/10. Diskrete Strukturen

Funktionsbeschreibung. Lieferantenbewertung. von IT Consulting Kauka GmbH

Kurzanleitung. MEYTON Aufbau einer Internetverbindung. 1 Von 11

Der große VideoClip- Wettbewerb von Media Markt.

ICS-Addin. Benutzerhandbuch. Version: 1.0

AUF LETZTER SEITE DIESER ANLEITUNG!!!

Datenaufbereitung in SPSS. Daten zusammenfügen

Kurzanleitung fu r Clubbeauftragte zur Pflege der Mitgliederdaten im Mitgliederbereich

1 C H R I S T O P H D R Ö S S E R D E R M A T H E M A T I K V E R F Ü H R E R

3. GLIEDERUNG. Aufgabe:

Anwendungshinweise zur Anwendung der Soziometrie

geben. Die Wahrscheinlichkeit von 100% ist hier demnach nur der Gehen wir einmal davon aus, dass die von uns angenommenen

Kurzanleitung zur Übermittlung der mündlichen Prüfungsergebnisse mit DSD-Online. Stand: Dezember Schulmanagement weltweit

MORE Profile. Pass- und Lizenzverwaltungssystem. Stand: MORE Projects GmbH

OutlookExAttachments AddIn

Professionelle Seminare im Bereich MS-Office

.htaccess HOWTO. zum Schutz von Dateien und Verzeichnissen mittels Passwortabfrage

1. Einführung. 2. Die Abschlagsdefinition

FuxMedia Programm im Netzwerk einrichten am Beispiel von Windows 7

Transkript:

Fakultät für Elektrotechnik und Informatik Institut für Praktische Informatik Fachgebiet Datenbanken und Informationssysteme Routenberechnung mit partitionierten Straßendaten Bachelorarbeit im Studiengang Informatik David Bormann Matrikelnummer: 2739920 Prüfer: Prof. Dr. Udo Lipeck Zweitprüfer: Dr. Hans Hermann Brüggemann Betreuer: M. Sc. Hendrik Warneke Juli 2012

Inhaltsverzeichnis 1 Einleitung 4 1.1 Motivation und Aufgabenstellung...................... 4 1.2 Gliederung................................... 5 2 Grundlagen 6 2.1 Die Open-Streetmap-Daten......................... 6 2.2 Das Simple-Feature-Modell.......................... 8 2.2.1 Geometrieschema........................... 8 2.2.2 Topologische Prädikate und Geometriefunktionen......... 9 2.3 Graphen.................................... 10 2.3.1 Graphentheorie............................ 10 2.3.2 Der abstrakte Datentyp Graph................... 11 2.4 Kürzeste-Wege-Algorithmen......................... 13 2.4.1 Der Bellman-Ford-Algorithmus................... 13 2.4.2 Der Dijkstra-Algorithmus...................... 14 2.4.3 Der A*-Algorithmus......................... 16 2.5 Schlussfolgerung................................ 18 3 Konzepte 19 3.1 Partitionierungsarten............................. 19 3.2 Ablauf der partitionierten Routenberechnung................ 21 3.3 Routensuche.................................. 23 3.3.1 Heuristiken zur Findung von Zielknoten.............. 23 3.3.2 Metriken zur Gewichtung der Kanten................ 24 2

INHALTSVERZEICHNIS 3 3.3.3 Vorgehen beim Misserfolg...................... 24 3.4 Komposition der Routen........................... 26 4 Implementierung 27 4.1 Anforderungen................................ 27 4.2 OpenJUMP und seine Schnittstelle..................... 27 4.3 Beschreibung der Benutzerschnittstelle................... 29 4.4 Finden von Koordinaten über Adressangabe................ 31 4.5 Umgang mit den WGS84-Koordinaten................... 31 4.6 Aufbau des Graphen............................. 32 4.6.1 Ermittlung von Kanten aus den OSM-Daten............ 32 4.6.2 Clipping der Kanten in einer Partition............... 33 4.7 Klassenbeschreibung............................. 34 4.8 Speicherverwaltung.............................. 45 5 Experimente 48 5.1 Die Experimentierumgebung......................... 48 5.2 Das Vorgehen................................. 48 5.3 A* versus Dijkstra.............................. 49 5.4 Große versus kleine Partitionen....................... 53 5.5 Unterschiede der Metriken.......................... 55 5.6 Unterschiede der Heuristiken......................... 56 5.7 Abhängige versus unabhängige Partitionierung............... 59 5.8 Fazit...................................... 62 6 Ausblick 64 A Das simple Osmosis-PostGIS-Schema 65 B PL/pgSQL-Funktionen 66 B.1 Funktionen zum Erstellen der Edges-Tabelle................ 66 B.2 Funktionen zum Finden von Start- und Zielknoten............. 69 B.3 Funktionen zum Graphaufbau........................ 72

Kapitel 1 Einleitung Dieses Kapitel dient dazu, einen Überblick über das Thema dieser Arbeit zu geben. Es wird die Aufgabenstellung beschrieben und eine Gliederung der weiteren Kapitel angegeben. 1.1 Motivation und Aufgabenstellung Die für Fahrzeug- oder Fußgängernavigation benötigten Wegenetze werden üblicherweise aus geographischen Daten gewonnen. Diese werden in einen gewichteten Graphen transformiert, in dem Kanten Wege darstellen und Knoten Kreuzungen dieser. Mit Hilfe verschiedener Algorithmen kann in diesem Graphen der kürzeste Pfad zwischen zwei Knoten ermittelt werden. Dies basiert auf einer Gewichtung der Kanten, beispielsweise aus der Entfernung zwischen zwei Knoten. Nun können diese Wegenetze allerdings sehr groß werden und den kompletten Graph zu speichern, könnte die Arbeitsspeicherkapazitäten eines Rechners sprengen, zum Beispiel die von mobilen Kommunikationsgeräten oder mobilen Servicerobotern. In diesem Fall kann der Graph, beziehungsweise dessen Ausgangsmaterial aus geographischen Daten, in kleinere Stücke zerlegt werden, um diese dann vollständig im Arbeitsspeicher abzulegen. In dieser Arbeit geht es um die Routenplanung mit Straßendaten, die vorab partitioniert worden sind. Für die Berechnung einer Route über mehrere Partitionen, werden die einzelnen Ergebnisse einer Wegfindung auf einer Partition zusammengesetzt. Durch Experimente soll bestimmt werden, inwiefern ein solches Ergebnis von der optimalen Route abweicht. Dabei sollen verschiedene Algorithmen, sowie Partitionierungsgrade und -arten getestet werden. Die erforderlichen geographischen Daten stammen aus dem Open-Streetmap-Projekt und werden in einer PostGIS-Datenbank abgelegt. 4

KAPITEL 1. EINLEITUNG 5 1.2 Gliederung In Kapitel 2 werden zuerst Open-Streetmap und die Struktur der von ihr bereitgestellten Daten skizziert. Es werden graphentheoretische Begriffe diskutiert und verschiedene Algorithmen zur Wegfindung vorgestellt. In Kapitel 3 wird der Ablauf der partitionierten Routenberechnung erläutert. Dazu gehört das Laden von Graphpartitionen, dann wird auf diesen die Wegesuche ausgeführt und anschließend werden die Routen der einzelnen Partitionen zusammengeführt. Das Kapitel 4 beschäftigt sich mit der Implementierung des Graphaufbaus, verschiedenen weiteren Implementierungsdetails und einer Beschreibung der Benutzerschnittstelle des Programms. Das nachfolgende Kapitel 5 beschreibt die ausgeführten Experimente und ihre Ergebnisse. Das Kapitel 6 bietet einen Ausblick, was man bei der partitionierten Routensuche noch ändern oder verbessern könnte. Im Anhang A ist das verwendete Datenbankschema zur Verwendung der Open-Street- Map-Daten dargestellt. Im Anhang B finden sich entwickelte PL/pgSQL-Funktionen.

Kapitel 2 Grundlagen In diesem Kapitel wird ein Überblick über das Open-Streetmap-Projekt gegeben, sowie über den Aufbau der Daten, die von Open-Streetmap zur Verfügung gestellt werden. Es folgen notwendige Begriffserklärungen der Graphentheorie und der Aufbau eines Abstrakten Datentyps eines Graphen. Anschließend werden mehrere Algorithmen vorgestellt, die kürzeste Wege von einem Startknoten aus finden. 2.1 Die Open-Streetmap-Daten Open-Streetmap (im Folgendem mit OSM abgekürzt) ist eine freie Weltkarte, an der jeder mitarbeiten kann, sie zu komplettieren. 1 Sie wurde 2004 in Großbritannien ins Leben gerufen. Mitglieder der OSM-Community zeichnen ihre Bewegung mit einem GPS- Tracker auf und fügen den geographischen Daten anschließend weitere Informationen hinzu. Dies können Straßenart und -namen und angrenzende Points of Interests, beispielsweise Gebäude oder Parkplätze, aber auch Briefkästen und Bushaltestellen sein. Eine andere Möglichkeit OSM-Karten zu erstellen, ist das Abzeichnen von Luftbildern. Weitere Information zu OSM kann man in [RT09] finden. Das Datenmodell von OSM enthält zwei für das Routing wichtige Typen Ways und Nodes. Des Weiteren gibt es noch Relations, die aus Ways und Nodes bestehen und so komplexere Zusammenhänge darstellen können, zum Beispiel den Grundriss eines Gebäudes, Straßen sind allerdings keine Relationen. Ein Node besteht aus seiner geographischen Länge und Breite und, wie die anderen Objekte auch, aus beliebig vielen Attributen, sogenannte Tags. Das sind Schlüssel-Wert-Paare, die dabei helfen, Objekte genauer zu klassifizieren und so zum Beispiel eine Autobahn und einen Fußweg auf einer Karte verschieden darzustellen. Alle Straßen erhalten den Schlüssel highway, ein Fußweg 1 http://www.openstreetmap.org, steht unter der CC-BY-SA 2.0-Lizenz 6

KAPITEL 2. GRUNDLAGEN 7 erhält dann den Tag highway=footway, eine Autobahn highway=motorway. Es gibt aber auch Tags wie oneway=yes, an denen man Einbahnstraßen erkennen kann. Ein Way besteht zusätzlich noch aus mehreren Nodes, wobei es auf die Reihenfolge ankommt, in der die Nodes abgelegt sind. Seit 2009 darf ein Way- oder Nodeobjekt keine zwei Tags mit dem selben Schlüssel besitzen. Abbildung 2.1: EER-Diagramm zu Node, Way und deren Tags In Abbildung 2.1 sind diese Zusammenhänge als EER-Diagramm dargestellt. Für das Routing irrelevante Attribute sind nicht aufgenommen. Zum Beispiel welcher User eine Kante oder einen Knoten zu welchem Zeitpunkt hinzugefügt oder verändert hat. Die Attribute lat und lon bestimmen die geographische Lage eines Nodes, die geographische Breite lat und Länge lon. Die Koordinaten sind in der Form des WGS84 (World Geodetic System 1984) gespeichert. Die OSM-Daten von Deutschland, Stand 06.06.2012, wurden mit Hilfe von Osmosis 2, einem Bearbeitungswerkzeug für OSM-Daten, in eine PostGIS-Datenbank mit dem simplen OSM-PostGIS-Schema, siehe Anhang A überführt. Wichtig für den Aufbau des Graphen sind dabei folgende Relationen und Attribute: NODES (Id, Geom) NODE TAGS (Node Id NODES, K, V) WAYS (Id, Linestring) WAY TAGS (Way Id WAYS, K, V) WAY NODES (Way Id WAYS, Sequence Id, Node Id NODES) 2 http://wiki.openstreetmap.org/wiki/de:osmosis, Version 0.40.1

KAPITEL 2. GRUNDLAGEN 8 Die geographische Lage wird zusammengefasst in dem geographischen Attribut Geom Das Attribut Linestring stellt einen Linienzug über eine geordnete Menge von Koordinaten dar. Es gilt die Integritätsbedingung, dass die sequence id von 0 beginnend, fortlaufend für jeden Way ist. Mit Hilfe der sequence id lässt sich ein Linienzug über die Nodes eines Ways konstruieren. Die Relation bilden aus dem EER-Diagram wird durch WAY NODES umgesetzt. Dass die Karten vornehmlich von Hobbykartographen erstellt werden, bedeutet allerdings auch, dass ein OSM-Datensatz nicht unbedingt vollständig sein muss, beziehungsweise Details fehlen können, die für ein Routing benötigt würden. Dies kann der Fall sein, wenn man eine Route von einem Startpunkt, von dem nur die Adresse bekannt ist, aus sucht, diese Adresse aber nicht in den OSM-Daten verzeichnet ist. Im Normalfall sollte allerdings die Postleitzahl und der Straßenname ausreichen, um einen Start- oder Endpunkt fest zu legen. 2.2 Das Simple-Feature-Modell 2.2.1 Geometrieschema Das Modell, in dem die OSM-Daten vorliegen, ist das Simple-Feature-Modell 3. In diesem werden Datentypen und räumliche Operationen für zweidimensionale Geometrien definiert[bri08]. Die Geometrien sind deswegen simpel, da ihre Stützpunkte nur gradlinig verbunden sind. Es gibt vier Geometrieformen des Typs Geometry in dem Modell, nämlich Punkte, Linien, Flächen und Geometriesammlungen. Punkte werden durch ein Point-Objekt beschrieben, dem eine Koordinate zugeordnet ist, auf deren Werte man mittels getx(), beziehungsweisse gety() zugreifen kann. Ein OSM-Node wird so dargestellt. Linien sind Streckenzüge, die durch eine Folge von Stützpunkten definiert sind. Man kann auf den Anfangs- und Endpunkt, die Länge und den n-ten Stützpunkt zugreifen. Durch diese LineStrings werden OSM-Ways und somit unter anderem Straßen in OSM dargestellt. Flächen werden durch Polygone beschrieben. Ein Polygon besteht aus einem geschlossenen äußeren Streckenzug und beliebig vielen inneren, die Löcher beschreiben. In OSM werden Polygone durch Relationen dargestellt, zum Beispiel durch das Relationentag area und mit Verweis auf eine Menge von OSM-Ways, die den Tag outer besitzen, wird der äußere Ring eines Polygons beschrieben. 3 ISO 19125

KAPITEL 2. GRUNDLAGEN 9 Eine Geometriesammlung ist eine Sammlung verschiedener Geometrien. Man kann bei einer GeometryCollection auf die verschiedenen Geometrien zugreifen und falls alle Geometrien vom gleichen Typ sind, kann man eine der Unterklassen MultiPoint, MultiLine- String oder MultiPolygon verwenden. Abgespeichert werden die Geometrien als well-known Binary (WKB) und können für Menschen lesbar gemacht werden als well-known Text (WKT). Beispiele für WKT sind: POINT(6.2 19.90) oder LINESTRING(1 3, 3 7, 4 2). 2.2.2 Topologische Prädikate und Geometriefunktionen Topologische Eigenschaften beschreiben die räumliche Beziehung von Geometry-Objekten zueinander. Ob eine Geometrie vollständig oder nur zum Teil in einer anderen enthalten ist oder diese berührt wird, wird mit Hilfe von topologischen Prädikaten ausgedückt. contains(geometry other) - ist true, wenn die Geometrie other komplett in dieser Geometrie enthalten ist crosses(geometry other) - ist true, wenn die beiden Geometrien eine Schnittmenge haben, aber eine Geometrie nicht komplett in der anderen enthalten ist touches(geometry other) - ist true, wenn die beiden Geometrien sich nur an ihren Rändern schneiden Weitere geometrische Funktionen einer Geometrie sind: Envelope(): Geometry - Rückgabe ist das minimal umgebende Rechteck der Geometrie Boundary(): Geometry - zurück gegeben wird der Rand der Geometrie Distance(Geometry other): double - es wird der geringste Abstand zwischen zwei Punkten der Geometrie und other berechnet und zurück gegeben Intersection(Geometry other): Geometry - gibt eine Geometrie zurück, die die Schnittmenge der Geometrie und other beschreibt Difference(Geometry other): Geometry - gibt eine Geometrie zurück, die die Geometrie ohne die Schnittmenge der Geometrie und other beschreibt

KAPITEL 2. GRUNDLAGEN 10 2.3 Graphen 2.3.1 Graphentheorie Ein Graph besteht aus Knoten, die über Kanten verbunden sein können. Oder formal ausgedrückt, ein Graph G ist ein Tupel (V,E), welches aus zwei endlichen Mengen V (Vertices für die Knoten) und E (Edges für die Kanten) besteht. Die Kanten in einem gerichteten Graphen sind zweistellige Relationen der Knoten, E V V, zum Beispiel die Kante e=(a, b) verbindet die beiden Knoten a und b. Diese sind die Endpunkte von e. Die Knoten a und b sind damit adjazent und diese Knoten mit e inzident. Der Grad eines Knoten v ist die Anzahl der mit v inzidenten Kanten. Eine Schleife ist eine Kante, die einen Knoten mit sich selbst verbindet. In Abbildung 2.2 ist ein gerichteter Graph dargestellt. Ein Graph heißt dünn besetzt, wenn E = Θ( V ).[Jun94] d b e c a Abbildung 2.2: Ein gerichteter Graph Bei einem gewichteten Graphen werden alle Kanten mit einer Zahl, der Länge dieser Kante, gewichtet. Das muss nicht unbedingt der geographische Abstand zwischen zwei Knoten sein, sondern kann auch als Kosten, Zeiten oder Kapazitäten genutzt werden und darf auch negativ sein. Ein Weg besteht aus einer Menge von Knoten, die jeweils adjazent sind und ein Pfad ist ein spezieller Weg, bei dem kein Knoten doppelt auftreten darf. Ein Zyklus in einem Graph ist ein Weg, in dem ein Knoten Start- und Zielknoten zugleich darstellt. Die Länge eines Weges ist dann die Summe der Gewichte der Kanten des Weges. Der Abstand d(a,b) der Knoten a und b, oder der kürzeste Weg von a nach b, ist das Minimum der Längen aller Pfade mit Startpunkt a und Endpunkt b, b ist dann von a aus erreichbar. Falls es keinen Pfad von a nach b gibt, wird d(a,b) angenommen als. Ein Weg, der nur einen Knoten enthält, hat die triviale Länge 0. In Abbildung 2.3 ist der kürzeste Weg vom Knoten e zum Knoten d markiert. Falls es in dem Graphen einen Zyklus gibt, dessen Länge negativ ist, kann es keinen kürzesten Weg geben. Zumindest nicht, wenn man einen kürzesten Weg von a nach b sucht und man einen solchen Zyklus von a aus erreichen kann. In den folgenden Betrachtungen seien negative Kantengewichte ausgeschlossen.

KAPITEL 2. GRUNDLAGEN 11 1 d 2 c 1 b 1 0.5 3 a 4 e Abbildung 2.3: Ein kürzester Weg zwischen zwei Knoten 2.3.2 Der abstrakte Datentyp Graph Der abstrakte Datentyp, kurz ADT, Graph benutzt die ADTs Vertex und Edge. Diese dienen lediglich dazu die Knoten und Kanten darzustellen und stellen, außer einem Konstruktor, nur Anfrage- und Änderungsmethoden bereit, die für die Bestimmung des kürzesten Weges hilfreich sind. Der ADT Edge stellt folgende Methode bereit: getid(): String - liefert die OSM-Id dieser Kante getweight(): double - liefert das Gewicht einer Kante getlinestring(): LineString - gibt den Streckenzug der Kante als Geometrie zurück Im ADT Vertex wird vermerkt, welchen Abstand ein Knoten zu einem Startknoten hat, beziehungsweise welcher Abstand bisher geschätzt wurde und welcher Knoten in einem kürzesten Weg sein Vorgänger ist: getid(): String - liefert die OSM-Id dieses Knotens setpred(vertex v) - setzt den Vorgänger von diesem Knoten auf v getpred(): Vertex - gibt den Vorgänger dieses Knotens zurück setd(double distance) - setzt den Abstand von dem Startknoten zu diesem auf distance getd(): double - gibt den Abstand zum Startknoten zurück getpoint(): Point - gibt die geometrische Lage diese Knotens als Geometrie zurück markastarget(): - markiert den Knoten als Ziel einer Wegesuche istarget(): boolean - gibt true zurück, falls der Knoten ein Zielknoten ist

KAPITEL 2. GRUNDLAGEN 12 Der ADT Graph besitzt folgende Methoden. Eine Sequence ist eine verkettete Liste mit Indexzugriff. Ein Großteil der Methoden entstammt [Lip12]; size(): int - liefert die Anzahl der Knoten dieses Graphen vertices(): Sequence - liefert die Knoten dieses Graphen insertvertex(vertex v) - fügt den Knoten v in den Graphen ein removevertex(vertex v) - entfernt den Knoten v und seine inzidenten Kanten aus dem Graph edges(): Sequence - liefert die Kanten dieses Graphen insertedge(vertex v, Vertex w, Edge e) - fügt die gerichtete Kante e zwischen den Knoten v und w ein removeedge(edge e) - entfernt die Kante e aus dem Graphen indegree(vertex v): int - liefert die Anzahl der eingehenden Kanten von v inincidentedges(vertex v): Sequence - liefert die eingehenden Kanten vom Knoten v inadjacentvertices(vertex v): Sequence - liefert die Knoten, die über eine eingehende Kante zum Knoten v adjazent sind areadjacent(vertex v, Vertex w): boolean - gibt true zurück, falls v über eine Kante mit w verbunden ist origin(edge e): Vertex - liefert den Knoten, von dem die Kante e ausgeht destination(edge e): Vertex - liefert den Knoten, wohin die Kante e führt findedge(vertex v, Vertex w): Edge - liefert die Kante, über die die Knoten v und w verbunden sind getvertexwithid(string id): Vertex - liefert die Knoten mit der übergebenen id, sofern vorhanden containsvertexwithid(string id): boolean - liefert true, falls ein Knoten mit der dieser id im Graphen existiert Die Methoden outdegree(), outincidentedges() und outadjacentvertices() werden analog definiert. Die Methode findedge() hat für beliebige Graphen eine Laufzeit von O( E ). Da ein Straßennetz in der Regel dünn besetzt ist, Knoten höchstens den Grad 4 haben und ein- und ausgehende Kanten eines Knoten mit Indizenzlisten für jeden Knoten festgehalten werden können, beträgt die Laufzeit in diesem Fall O(1).

KAPITEL 2. GRUNDLAGEN 13 2.4 Kürzeste-Wege-Algorithmen Man unterscheidet zwischen einer kürzesten Wegfindung von einem Startknoten aus und zwischen allen Knoten. Manche Algorithmen kann man abbrechen, falls man einen kürzesten Weg zu einem gesuchten Zielknoten gefunden hat. Die Initalisierung ist bei allen Algorithmen gleich. Man benötigt einen Graph G und einen Startknoten, Vertex s, siehe Algorithmus 1. Dieser ist aus [CLRS10] entnommen, wie auch die Algorithmen 2 und 3. Die Distanz zum Startknoten wird für alle Knoten auf Algorithm 1 1: procedure Init-Single-Source(Graph G, Vertex s) 2: for all Vertex v G.vertices() do 3: v.setd( ); 4: v.setpred(null); 5: end for 6: s.setd(0); 7: end procedure den maximal zulässigen Wert gesetzt, bis auf die triviale Distanz vom Startknoten s zu s auf 0. Da jeder Knoten so initalisiert wird, hat die Methode die Laufzeit O( V ). Wird die Routensuche nur einmal auf einen Graphen angewandt, kann schon bei der Initalisierung der Knoten die Distanz auf gesetzt werden, wodurch die Laufzeit konstant wäre. Die folgenden Algorithmen berechnen alle kürzesten Wege von einem Knoten zu prinzipiell allen anderen. 2.4.1 Der Bellman-Ford-Algorithmus Der Bellman-Ford-Algorithmus würde auch ein Ergebnis bei negativen Kanten liefern, hat aber eine Laufzeit von O( E V ). Er wird im Algorithmus 2 beschrieben. Da es nur positve Kanten gibt, wird auf die Darstellung des Programmcodes, der prüft, ob der Graph einen Zyklus mit negativer Länge enthält, verzichtet. Die Zeilen 6-9 sind bei allen Algorithmen ähnlich und beschreiben die Relaxation einer Kante. Dabei wird geprüft, ob sich der geschätzte Abstand vom Startpunkt zum Endknoten einer Kante verringert, falls man diese Kante in den kürzesten Weg mit aufnehmen würde. Wenn dies der Fall ist, wird der neue Schätzwert vermerkt und der Startknoten der Kante wird zu dem Vorgänger des Endknotens in diesem geschätzten kürzesten Weg. Dies wird für alle Kanten V -1 mal gemacht Der Algorithmus arbeitet korrekt, falls der Graph keinen Zyklus mit negativer Länge enthält. Denn dann kann ein kürzester Weg höchstens aus V -1 Kanten bestehen, da

KAPITEL 2. GRUNDLAGEN 14 Algorithm 2 1: procedure Bellman-Ford(Graph G, Vertex s) 2: Init-Single-Source(G,s); 3: int newdist=0; 4: for i=1 to G.size()-1 do 5: for all Edge e G.edges() do 6: newdist=g.origin(e).getd()+e.getweight(); 7: if G.destination(e).getD()>newDist then 8: G.destination(e).setD(newDist); 9: G.destination(e).setPred(G.origin(e)); 10: end if 11: end for 12: end for 13: end procedure ein Zyklus mit positiver Länge einen Weg nur verlängert. Wenn es einen kürzesten Weg von s zu einem Knoten gibt, dann kann man diesen erhalten, indem man die Kanten in der Reihenfolge dieses Weges sukzessiv relaxiert. Pro äußeren Schleifendurchlauf, werden alle Kanten relaxiert. Da dies V -1 mal passiert, relaxiert man unter anderem auch die Kanten eines kürzesten Weges mit V -1 Kanten. Daher die Laufzeit O( E V ). 2.4.2 Der Dijkstra-Algorithmus Djikstras Algorithmus, der Algorithmus 3, kann nur auf einen Graphen mit positiven Kantengewichten ausgeführt werden, läuft dafür aber auch schneller, bei geeigneter Implementierung der PriorityQueue Q, in O(( V + E )log V ). Die Idee hinter Djkstras Algorithmus ist, dass in einer Menge von Knoten, der cloud, vermerkt wird zu welchen Knoten kürzeste Wege schon bekannt sind. Dies wird erreicht, in dem der Knoten mit der kürzesten Länge zur cloud in eben diese aufgenommen wird, siehe die Zeilen 8 und 9. Dann werden alle Kanten, die von diesem Knoten ausgehen, relaxiert. Das funktioniert, da es nur positive Kantengewichte gibt und so ein aktuelles Minimum einer Distanz zur cloud nicht nachträglich unterschritten werden kann. Insgesammt wird jede Kante nur genau einmal relaxiert. In Q werden die noch nicht in die cloud aufgenommenen Knoten nach ihrer bisher berechneten Länge des kürzesten Weges aufsteigend geordnet. Dabei muss ein Knoten nach einer erfolgreichen Relaxation einer eingehenden Kante eventuell neu positioniert werden, siehe Zeile 15 replacekeyat(). Q.poll() gibt den Knoten mit kleinster Distanz zurück und löscht diesen aus Q. Die Implementierung dieser Methoden, beeinflusst die Laufzeit des Dijkstra-Algorithmus. Wird die Priorityqueue mit einem Min-Heap realisiert, erhält man eine Laufzeit von O( E log V ). Ein Knoten mit der geringsten Distanz zur cloud,

KAPITEL 2. GRUNDLAGEN 15 Algorithm 3 1: procedure Dijkstra(Graph G, Vertex s) 2: Init-Single-Source(G,s); 3: int newdist=0; 4: Vertex u=null; 5: Set cloud= ; 6: PriorityQueue Q=G.vertices(); Der Schlüssel ist getd() 7: while Q do 8: u=q.poll(); 9: cloud.add(u); 10: for all Vertex v G.outAdjacentVertices(u) do 11: newdist=u.getd()+g.findedge(u,v).getweight(); 12: if v.getd()>newdist then 13: v.setd(newdist); 14: v.setpred(u); 15: Q.replaceKeyAt(v, newdist); 16: end if 17: end for 18: end while 19: end procedure also der Aufruf Q.poll(), wird maximal V -mal aus Q benötigt. Die Umstrukturierung nach dem Entfernen des Minimums läuft, bei maximal V Knoten im Heap, in einer Laufzeit von O(log V ), also insgesammt O( V log V ). Die nach der Relaxation nötige Umstrukturierung des Heaps, kann in O(log V ) geschehen, durch schrittweises Vertauschen des betreffenden Heapknotens mit seinen Elternknoten, bis die Heapeigenschaft wieder erfüllt ist 4. Da dies höchstens E -mal passieren kann ergibt sich eine Laufzeit von O( E log V ). Die Laufzeiten von replacekeyat() und Q.poll() ergeben also insgesammt O(( V + E )log V ). Falls man die Route zu einem bestimmten Zielknoten sucht, kann der Algorithmus abgebrochen werden, wenn der Zielknoten in die cloud aufgenommen wurde oder man nicht alle Knoten erreichen kann und sich in Q nur noch Knoten mit einer unendlichen Distanz zum Startknoten befinden. 4 Da die Java-Implementierung der PriorityQueue die replacekeyat()-methde nicht anbietet, wird der Knoten aus dem Heap entfernt und neu einsortiert. Durch das Entfernen eines Nicht-Wurzel-Knotens verschlechtert sich die Laufzeit auf O( V )

KAPITEL 2. GRUNDLAGEN 16 2.4.3 Der A*-Algorithmus Die bisher vorgestellten Algorithmen bedienen sich nur Eigenschaften eines abstrakten Graphen. Sind zusätzlich noch andere Informationen bekannt, wie zum Beispiel die geographische Lage der Knoten, lässt sich eine Heuristik bestimmen, mit deren Hilfe man gezielter nach einem kürzesten Weg suchen lassen kann. Im Falle des A*-Algorithmus, siehe Algorithmus 4, wird es vermieden, Kanten zu relaxieren, die wahrscheinlich nicht zu dem kürzesten Weg gehören. Dazu müssen aber auch eine Menge von Zielknoten T bekannt sein. Um zu entscheiden, welche Kante als nächstes relaxiert wird, wird eine Schätzfunktion ˆf benutzt,[hnr68]. Die Länge des kürzesten Weges von einem Start- zu einem Zielpunkt über einen Knoten n wird beschrieben durch f(n) = g(n) + h(n). g(n) ist die Länge des kürzesten Weges zum Knoten n, während h(n) die Länge des kürzesten Weges von n zum Zielpunkt bestimmt, beziehungsweise zu einem Zielpunkt t T, zum Beispiel zum Weitentferntesten vom Startpunkt aus. Die Schätzfunktion für die Länge eines kürzesten Weges ist dann ˆf(n) = ĝ(n) + ĥ(n). ĝ(n) ist eine Schätzung der Länge des Weges zum Knoten n, ĥ(n) dementsprechend analog. Für ĝ(n) kann also die Länge des bisher berechneten kürzesten Weges genutzt werden. Wird ĥ für alle Knoten auf 0 gesetzt, erhält man dadurch Dijkstra s Algorithmus und es gilt sogar ˆf(n) = f(n), da durch die Aufnahme des Knotens mit dem kürzesten Abstand zur cloud, ĝ(n) = g(n) gilt. ĥ(n) darf die wirkliche Länge nicht überschätzen, dann bestimmt der Algorithmus auch den kürzesten Weg. Eine mögliche Schätzung für die Länge des Restwegs ist der Luftlinienabstand, da kein Weg kürzer sein kann, als der direkte. Die Schätzfunktion ĥ ist konsistent, genau dann wenn für jeden Knoten n und jeden seiner Nachfolger m die Dreiecksungleichung h(n, m)+ĥ(m) ĥ(n) gilt, wobei h(n, m) die wirkliche Länge zwischen n und m ist. Die Luftlinie ist eine konsistente Schätzfunktion, da die Dreiecksungleichung der euklidischen Distanz in der Ebene gilt. Die Berechnung der Schätzfunktion unter Verwendung des euklidischen Abstandes für einen Knoten v sähe folgendermaßen aus, wobei t ein Point sei, der die geographische Lage des Zielpunktes besitzt und t x für die X-Koordinate von t steht. ˆf(v) = v.getd() + (v x t x ) 2 + (v y t y ) 2 Der Algorithmus 4 zeigt den allgemeinen Fall, in dem ĥ(n) nicht konsistent ist. Es werden wie bei Dijkstra zwei Mengen von Knoten benutzt, die zwar disjunkt sind, aber vereinigt nicht die Menge aller Knoten ergeben müssen. Es wird eine PriorityQueue, hier open, benutzt, um zu ermitteln welcher Knoten als nächstes in die Liste closed kommt. Der Schlüssel, nach dem die Priorityqueue sortiert ist, ist der Wert von ˆf für den jeweiligen Knoten. Sobald ein Weg zum Startknoten bekannt ist, wird der Knoten inopen aufgenommen, Zeile 14 f. Wenn der geschätzte kürzeste Weg zu einem Knoten bekannt ist, wird er in closed aufgenommen. Falls der Knoten zu T gehört, kann der Algorithmus abgebrochen werden. Wenn ein Knoten in closed aufgenommen wird, werden alle aus-

KAPITEL 2. GRUNDLAGEN 17 Algorithm 4 1: procedure A*(Graph G, Vertex s) 2: Init-Single-Source(G, s); 3: int newdist=0; 4: Vertex u=null; 5: Sequence closed= ; Hier ist der Schlüssel ˆf(n), Pendant zu Dijkstra s cloud 6: PriorityQueue open.add(s); enhält Knoten, zu denen ein Weg bekannt ist 7: while open do 8: u=open.poll(); 9: closed.add(u); 10: if u.istarget() then 11: break 12: end if 13: for all Vertex v G.outAdjacentVertices(u) do 14: if v / closed v / open then 15: open.add(v); 16: end if 17: newdist=u.getd()+g.findedge(u,v).getweight(); 18: if v.getd()>newdist then 19: v.setd(newdist); 20: v.setpred(u); 21: if v closed then 22: closed.remove(v); 23: open.add(v) 24: else 25: open.replacekeyat(v, ˆf(v)); 26: end if 27: end if 28: end for 29: end while 30: end procedure

KAPITEL 2. GRUNDLAGEN 18 gehenden Kanten relaxiert. Ist ĥ konsistent, dann entspricht die Laufzeit im worst-case der des Dijkstra Algorithmus. Denn dann wird kein Knoten mehr nachträglich aus closed entfernt, beziehungsweise muss die Schätzung für die Länge des kürzesten Weges nicht mehr nachträglich korrgiert werden. Ist ĥ(n) konsistent, kann Dijkstras Algorithmus übernommen werden, nur der Schlüssel, der zum Einordnen in die PriorityQueue benutzt wird, muss ˆf(n) sein.[bri08] Aber unter Anwendung der gleichen Heuristik, relaxiert kein Algorithmus weniger Kanten als der A*-Algorithmus, bis er mit einer geeigneten Heuristik einen Zielknoten gefunden hat. 2.5 Schlussfolgerung Die OSM-Daten sind schon als Graph organisiert, weshalb es nicht schwer ist, aus diesen einen Graphen aufzubauen. Die OSM-Nodes werden zu Knoten in dem Graphen und die Kanten entstehen aus den Teilabschnitten der Ways, die zwei Nodes verbinden. Da es Einbahnstraßen gibt, bietet sich ein gerichteter Graph an. Gewichtete Kanten werden vorausgesetzt, bleibt also nur noch die Frage offen, wie man die Kanten gewichtet. Zusätzlich zu der Länge des Weges, den eine Kante darstellt, könnten auch andere Faktoren, wie die Art der Straße, das Gewicht einer Kante bestimmen. Die vorgestellten Algorithmen bestimmen kürzeste Wege von einem Knoten zu allen anderen. Das wird nicht nötig sein und der Dijkstra- und A*Algorithmus können abgebrochen werden, wenn ein kürzester Weg zum Zielknoten gefunden oder ein Zielknoten aus einer Menge von Knoten erreicht wurde. Dies ist beim Bellman-Ford-Algorithmus nicht der Fall, daher wird auf die Implementierung verzichtet, da er die gleiche kürzeste Route wie Dijkstra liefert. Der A*-Algorithmus ist der einzige Algorithmus, der die geographische Lage der Knoten beachtet, dadurch wird er durch das zielgerichtete Suchen wahrscheinlich am Schnellsten ein Ergebnis liefern.

Kapitel 3 Konzepte In diesem Kapitel wird der Ablauf der partitionierten Routenberechnung erläutert. Dazu gehört zunächst das Laden von Graphpartitionen, dann wird auf diesen die Wegesuche ausgeführt und anschließend werden die Routen der einzelnen Partitionen zusammengeführt. 3.1 Partitionierungsarten Bevor die Routensuche beginnen kann, müssen die geographischen Daten partitioniert werden. Es werden nun zwei Arten der Partitionierung vorgestellt. Die Straßendaten werden partitioniert, indem sie in Gitterzellen zerlegt werden. Diese Gitterzellen sind alle gleich breit und gleich lang und sind lückenlos aneinander gereiht. Die geometrischen Daten in Punktform sind so disjunkt aufgeteilt. Bei Linienzügen wird durch sogenanntes Clipping der Teil, der außerhalb einer Gitterzelle liegt, abgeschnitten, so dass auch die Straßen disjunkt aufgeteilt sind. Einzig die Knoten auf dem Gitter sind in den jeweiligen Graphen mehrmals vorhanden. Im Folgenden unterscheiden wir zwischen Partitionierungsarten, die abhänig oder unabhängig von der gesuchten Route sind. Eine unabhängige Partitionierung kann für verschiedene Routensuchen genutzt werden, nur die Wahl der relevanten Partitionen wäre unterschiedlich. Ein Beispiel für eine unabhängige Partitionierung ist in Abbildung 3.1(a) dargestellt. Die Gitterlinien sind horizontal und vertikal angeordnet. Alle geographischen Daten liegen innerhalb der schwarzen Umrandung. Zusätzlich ist ein Weg von einem Punkt s zu einem Punkt t eingezeichnet. In 3.1(b) ist eine abhängige Partitionierung dargestellt. Die Gitterlinien sind parallel und orthogonal zur Luftlinie zwischen Start- und Endpunkt ausgerichtet. Der Start- und Endpunkt befinden sich im Zentrum einer Partition. 19

KAPITEL 3. KONZEPTE 20 t t s s (a) Eine unabhängige Partitionierung (b) Eine abhängige Partitionierung Abbildung 3.1: Zwei Partitionierungsarten Dadurch soll verhindert werden, dass Straßen nicht vollends berücksichtigt werden können, falls bei der unabhängigen Partitionierung der Start- oder Endpunkt der gesuchten Route am Rand zu einer nicht weiter betrachteten Partition liegt. Das soll die Wahrscheinlichkeit erhöhen, dass Straßen, die zu dem optimalen kürzesten Weg gehören, nicht an einem Rand abgeschnitten werden und nicht weiter untersucht werden können. Durch die Ausrichtung entlang der Luftlinie, kann sich die Anzahl der relevanten Partitionen verringern, vergleiche Abbildung 3.1. Wir nehmen an, dass eine Vorgabe existiert, wie breit und wie lang eine Gitterzelle sein soll. Das abhängige Gitter soll also in zwei Kriterien von der gesuchten Route abghängig sein. Start- und Zielpunkt sollen mittig in ihrer Partition liegen Die Gitterlinien sollen parallel, beziehungsweise orthogonal zur Luftlinie ausgerichtet sein. Anders als bei der unabhängien Partitionierung muss die vorgegebene Breite oder Höhe, die eine Partitionsgitterzelle besitzen soll, wahrscheinlich noch angepasst werden, damit die Partitionierung dem ersten Kriterium gerecht wird. Die Vorgaben der Länge und Höhe werden dabei als Mindestlänge und -höhe interpretiert und werden gegebenenfalls noch angepasst. Um das zweite Kriterium zu erfüllen, müssen nun die Partitionen in Richtung der Luftlinie vom Startpunkt aus rotiert werden.

KAPITEL 3. KONZEPTE 21 Beispiel zur Erstellung einer abhängigen Partitionierung Gegeben sei der Startpunkt s bei (0,0) und ein Endpunkt t bei (2.5,5). Die Höhe und Breite einer Gitterpartition soll 1 betragen. Eine unabhängige Partitionierung sähe wie im Bild von Abbildung 3.2(a) aus. Um aus ihr eine abhängige Partitionierung zu machen, wird zuerst beispielsweise die Höhe einer Partition neu angepasst. Der Abstand zwischen s und t beträgt 5,59. Das bedeutet, dass bei der Höhe von 1 nach sechs Partitionen der Zielpunkt erreicht wird. Damit beide Punkte jeweils mittig liegen, wird der Nachkommateil der Differenz auf die Partitionshöhe von fünf Partitionen aufgeteilt. Das macht 1+(0,59/5) also etwa 1,18. Nachdem man das Gitter um die Hälfte der neuen Höhe und der Breite verschoben hat, erhält man eine Partitionierung, wie sie im Bild 3.2(b) dargestellt ist. Nun muss noch das gesammte Gitter um den Winkel, der zwischen der Y-Achse und der Luftlinie liegt, im Startpunkt gedreht werden, in diesem Beispiel sind das 26,565. In diesem Beispiel wurde die Y-Achse genommen, da der Startpunkt im Ursprung liegt und so um den kleinsten Winkel gedreht werden konnte. Die fertige abhängige Partitionierung ist in Bild 3.2(c) zu sehen. t t t s s s (a) Erster Schritt (b) Zweiter Schritt (c) Dritter Schritt Abbildung 3.2: Beispiel zur Erstellung einer abhängigen Partitionierung 3.2 Ablauf der partitionierten Routenberechnung Ziel einer partitionierten Routenberechnung ist es, den kürzesten Weg von einem Startpunkt in einer Partition zu einem Endpunkt in einer anderen Partition über beliebig viele Partitionen zu finden. Es ergibt sich grob der folgende Programmablauf aus Algorithmus 5.

KAPITEL 3. KONZEPTE 22 Algorithm 5 1: procedure PartitionStreetRouting() 2: Erstelle Partitionen und 3: Bestimme Start- und Zielpartition benötigt Start- und Zielpunkt 4: Beginne in der Startpartition 5: while aktuelle Partition ist nicht die Zielpartition do 6: Baue den Graph auf benötigt Partitionspolygon 7: Ermittle den Rand, zu dem geroutet werden soll 8: Markiere den oder die Zielknoten nach gewählter Heuristik 9: Suche einen Weg vom aktuellen Startknoten aus 10: if Kein weiterer Rand erreichbar then siehe Algorithmus 7 11: Breche Routensuche komplett ab 12: end if 13: Setze neuen Startknoten auf Zielknoten dieser Route 14: Verarbeite das Routingergebnis 15: Verwerfe den Graphen 16: Wechsel in die nächste Partition 17: end while 18: Baue Graph auf und markiere Zielknoten 19: Finde Route zum Endpunkt 20: Gib das Ergebnis der Gesamroute zurück 21: end procedure

KAPITEL 3. KONZEPTE 23 Ein Graph wird dabei für eine Partition höchstens ein Mal aufgebaut, man kann also nicht zweimal die gleiche Partition untersuchen. In den nachfolgenden Abschnitten werden ein Großteil der Zeilen erläutert. In Abschnitt 3.2 werden zwei Partitionierungsarten vorgestellt. Die while-schleife und was genau mit Heuristik gemeint ist, wird in Abschnitt 3.3 geklärt. 3.3 Routensuche Nachdem die Art der Partitionierung gewählt wurde, kann man mit der Routensuche in der Partition mit dem Startpunkt beginnen.die nachfolgenden Abschnitten beziehen sich auf die Schleife in Algorithmus 6. Der Zwischenzielpunkt der Routensuche in einer Partition ist ein Randpunkt zu einer anderen Partition. Dieser Rand wird vor jeder Routensuche durch die geringste Distanz eines Randes zum Zielpunkt bestimmt. 3.3.1 Heuristiken zur Findung von Zielknoten Zu Beginn der Routensuche in einer Partition hat man genau einen Startknoten. Das ist entweder der Startpunkt der gesuchten Route in der ersten Partition oder ein Knoten, der die gleiche geographische Lage besitzt, wie der Zielknoten, der in der vorherigen Partition berechnet wurde. Den Zielknoten auf dem Zielrand einer Partition kann man über folgende Heuristiken bestimmen. a) Kürzeste Distanz zum Start: Der Randknoten mit dem berechneten kürzesten Weg zum Startpunkt wird ausgewählt b) Kürzeste Distanz zum Ziel: Der Randknoten mit dem geschätztesten geringsten Abstand zum Zielpunkt wird ausgewählt c) Gewichtung der Straßenart: Ein Randknoten einer Autobahn wird dem einer Landstraße vorgezogen Wird die Heuristik a) gewählt, hat man eine Menge von Zielknoten, nämlich alle die auf dem Rand zur nächsten relevanten Partition liegen. Verwendet man b), kann man vor dem Starten der Routensuche den Knoten auf dem Zielrand berechnen, der den geringsten Abstand zum Zielknoten der gesamten Route besitzt, und nur diesen als Ziel markieren. Man sollte jedoch sicher stellen, dass dieser Knoten auch erreichbar ist und man nicht die Spur einer Autobahn wählt, die in die

KAPITEL 3. KONZEPTE 24 Partition hineinführt. Denn dann kann dieser Zielknoten nicht erreicht werden und es werden solange Kanten relaxiert, bis zu allen erreichbaren Knoten ein kürzester Weg bestimmt worden ist. Jedoch kann man dies nicht nur über das Ausschließen von bestimmten Einbahnstraßen lösen und diese Gefahr besteht immer bei einer ungeschickten Partitionierung. Die Heuristik c), die die Art der Straße berücksichtigt, muss entweder mit a) oder b) kombiniert werden. Im Falle von a) werden zum Beispiel nur Autobahnknoten und von b) nur der Autobahnknoten mit dem geringsten Abstand zum Ziel markiert. 3.3.2 Metriken zur Gewichtung der Kanten Zur Gewichtung der Kanten haben wir zwei verschiedene Metriken gewählt. i) Die kürzeste Route: Das Maß ist die Länge des LineStrings einer Kante ii) Die schnellste Route: Das Maß ist die Länge des LineStrings Durchschnittsgeschwindigkeit, bestimmt durch die Art der Straße In der Tabelle 3.1 sind die highwaytags, ihre Bedeutung und die Wahl der Durchschnittsgeschwindigkeit dieser Straßenart in der Reihenfolge notiert, in der sie von der Heuristik c) bevorzugt werden. Die Geschwindigkeiten entsprechen denen von OpenRouteService 1, ein Webservice, das eine Routensuche mit OSM-Daten anbietet. 3.3.3 Vorgehen beim Misserfolg Stellt man während des Routings fest, dass man in einer Partition nicht den Zielknoten oder Zielgrenzknoten erreichen kann, muss die Auswahl des Zielrandes korrigiert werden. Wir gehen aber davon aus, dass man die Partitionen so groß wählt und das Straßennetz von Deutschland so ausgebaut ist, dass man von einem Rand einen Weg zu jedem anderen Rand finden kann. Erreicht man trotzdem keine anderen Randknoten, weil man zum Beispiel durch eine ungeschickte Partitionierung auf einer Halbinsel angekommen ist, wird die Routensuche ohne Ergebnis abgebrochen. Auch falls man bereits in der Endpartition angelangt ist und man den Zielpunkt nicht erreichen kann, wird abgebrochen, da kein Partitionsgraph mehrfach berechnet werden soll. Dieses Vorgehen ist im Algorithmus 6 dargestellt. Das Rand erreichbar aus Zeile 7 soll einerseits ausdrücken, dass es einen Knoten auf diesem Rand gibt, der bei der Routensuche erreicht wurde, als auch dass man die Partition 1 http://www.openrouteservice.org

KAPITEL 3. KONZEPTE 25 Highway-Tag Bedeutung Ø Geschwindigkeit (km/h) motorway Autobahn 110 motorway link Autobahnauffahrt 90 trunk Kraftfahrstraße 90 trunk link Kraftfahrstraßenauffahrt 70 primary Bundesstraße 70 primary link Bundesstraßenauffahrt 60 secondary Landesstraße 60 tertiary Kreisstraße 55 unclassified Nebenstraße 50 residential Straße in einem Wohngebiet 40 service Zugangsweg 30 living street Wohn- oder Spielstraße 10 track Feld- oder Waldweg 10 Tabelle 3.1: Die Straßenarten und ihre Gewichtungen noch untersuchen darf. Wurde der Zielrand nicht erreicht gibt es somit nur noch zwei mögliche Ränder, da man auch nicht mehr die Partition untersuchen kann, aus der man in diese Partition gelangt ist.

KAPITEL 3. KONZEPTE 26 Algorithm 6 1: function Kein weiterer Rand erreichbar() 2: if mindestens ein Knoten auf dem Zielrand erreichbar then 3: Bestimme Zielknoten 4: return false; 5: else 6: for all Ränder dieser Partition do sortiert nach Entfernung zum Ziel 7: if Rand erreichbar then 8: Bestimme Zielknoten 9: return false; 10: end if 11: end for 12: Bestimme Teilergebnis der Routensuche 13: return true; Suche muss endgültig abgebrochen werden 14: end if 15: end function 3.4 Komposition der Routen Die Ergebnisse der Routensuche in einer Partition bestehen aus dem berechneten Weg und dem Gewicht dieses Kantenzugs. Um Speicherplatz zu sparen wird lediglich der LineString gespeichert, der aus den Kanten des kürzesten Weges bestimmt wird, sowie das Gewicht. Dadurch gehen zwar Informationen verloren, die in dieser Arbeit aber auch keine Rolle spielen, wie eine detailierte Beschreibung des Weges, beispielsweise nach zwanzig Kilometern auf der A2, rechts abbiegen. Die Gewichte der einzelnen Partitionen auf dem Gesamtweg werden aufsummiert und die Linestring-Geometrien vereinigt.

Kapitel 4 Implementierung Dieses Kapitel beschäftigt sich mit der Implementierung des Graphaufbaus, verschiedenen Implementierungsdetails, einer Beschreibung der Klassen und einer Beschreibung der Benutzerschnittstelle. 4.1 Anforderungen Das Programm soll einen Weg durch verschiedene Partitionen berechnen können. Dabei sollen die Faktoren Partitionsgröße, Metrik zur Gewichtung der Kanten, Heuristik zur Auswahl der Randknoten und Wahl des Kürzeste-Wege-Algorithmus, entweder Dijkstra oder A*, beliebig kombinierbar sein. Da das alleinige Gesamtgewicht der Route wenig Aussagekraft hat, soll die Route noch visuell dargestellt werden können. Dies geschieht durch die Umsetzung als PlugIn für das Open-Source-Programm OpenJUMP 1. Der Benutzer soll Ziel- und Endpunkt entweder als WGS84-Koordinaten oder als Adressen angeben können. Da die Straßendaten partitioniert werden sollen, um den Arbeitsspeicher zu entlasten, sollte der Speicherplatz des Graphen, der in einer Partition berechnet wurde, wieder freigegeben werden, wenn man eine andere Partition betrachtet. 4.2 OpenJUMP und seine Schnittstelle OpenJUMP ist ein Open-Source-Programm, das in Java geschrieben ist und unter der GNU-Lizenz steht. Es ist ein geographisches Informationssystem und bietet die Anzeige und Bearbeitung von Geometrien. Die Geometrien können zum Beispiel aus einer 1 http://www.openjump.org/ 27

KAPITEL 4. IMPLEMENTIERUNG 28 PostGIS-Datenbank geladen und in Features, die aus einer Geometrie und beliebig vielen anderen Attributen bestehen, überführt werden. Die Geometrien werden mit Datentypen von der Java Topology Suite, kurz JTS, dargestellt, ein Framework, das das Simple Feature Format unterstützt. Diese Features können in der Workbench dargestellt werden, dem Arbeitsbereich in OpenJUMP. Die Features befinden sich in Layern, die in ihrer Darstellung in Farbe, Transparenz oder Linienbreite angepasst werden können. Außer Geometrien, können auch Bilder dargestellt werden und auch Karten, zum Beispiel mittels einem sogenannten Web-Map-Service, kurz WMS. In Abbildung 4.1 ist die Oberfläche mit einem Ausschnitt eines WMS-Layers von Deutschland dargestellt. Abbildung 4.1: Die OpenJump-Oberfläche OpenJUMP unterstützt das PlugIn Framework. Damit OpenJUMP ein PlugIn benutzen kann, muss es sich entweder im Extension-Ordner, der von OpenJUMP spezifiziert wird, befinden oder man teilt OpenJUMP über eine workbench-property.xml-datei mit, an welchem Ort im Dateisystem sich ein zu ladenes PlugIn befindet. Ein PlugIn bekommt dann ein PluginContext übergeben, über das es auf die Workbench zugreifen und neue Layer oder Menüpunkte anlegen kann. Das Programm wird also als PlugIn für OpenJUMP realisiert.

KAPITEL 4. IMPLEMENTIERUNG 29 Abbildung 4.2: Das Einstellungsfenster 4.3 Beschreibung der Benutzerschnittstelle Wurde das PlugIn in OpenJUMP geladen, erscheint ein Menue-Punkt, der PRS lautet. Betätigt man diesen kann man das Partitionierte Routensuche-PlugIn auswählen. Es erscheint ein Fenster in dem man verschiedene Einstellungen bezüglich der Routensuche treffen kann. In Abbildung 4.2 ist dieses Fenster zu sehen. Man kann zwischen folgenden Einstellungen wählen. Start/Ziel Es kann gewählt werden zwischen der Eingabe des Start- und Zielpunktes als Adresse, bestehend aus Postleitzahl und Straßenname oder als Koordinaten im dezimalen Gradsystem. In das jeweils linke Textfeld wird die Postleitzahl oder der Breitengrad angegeben. Routingalgorithmus Man kann zwischen Dijkstra und A* als Algorithmus für die Routensuche wählen. Heuristik Es kann zwischen den vier Heuristiken eine ausgewählt werden, die der kürzesten Distanz zum Startknoten, zum Zielknoten oder jeweils unter Berücksichti-

KAPITEL 4. IMPLEMENTIERUNG 30 gung der Straßenart. Metrik Hier muss man die Entscheidung treffen, ob man die kürzeste oder die schnellste Route suchen möchte. Partitionierung In diesem Bereich müssen die Höhe und die Breite einer Gitterzelle gesetzt werden. Wird als Einteilung ausgewählt, wird die Fläche Deutschlands in ein Gitter der Form Breite mal Höhe aufgeteilt. Wird in km gewählt werden die Angaben im Textfeld als Breite- und Längeangaben einer Partition in km interpretiert. Zudem kann zwischen einer abhängigen und einer unabhängigen Partitionierung gewählt werden. Damit die Verbindung zu einer PostGIS-Datenbank hergestellt werden kann, muss sich im OpenJUMP-Ordner einer Datei namens db.con befinden. In ihr müssen folgende Verbindungseinstellungen befinden, wobei es nicht auf die Reihenfolge ankommt: Host, Port, Datenbank, Benutzer, Passwort. host:<host> port:<port> database:<datenbank> user:<benutzer> password:<passwort> Bestätigt man die Eingabe, wierden die Partitionen aufgebaut. Liegen bei der abhängigen Partitionierung die eingegebenen Punkte zu nah beieinander, sodass nicht beide mittig in einer Partition liegen können, wird der Benutzer aufgefordert die Partitionsgrößen anzupassen. Ansonsten beginnt die Routensuche und es werden erst die Startund Zielpunkte angezeigt. Für jede Partition erscheint das Partitionspolygon und nach dem Aufbau des Graphen und der Routensuche wird der Ergebnis-LineString dargestellt. Dahinter wird ein WMS-Layer aus OSM-Daten 2 angezeigt. Am Ende erscheint ein Fenster, in dem die Länge des kürzesten Weges oder die Information, dass abgebrochen werden musste, steht. Nach der Berechnung einer Route kann man das PlugIn erneut starten und die neue Route wird gezeichnet, während die bisherige Route in der Workbench verbleibt. Man kann die Berechnung des PlugIns auch abbrechen, allerdings sollte dann vor einem erneuten Durchlauf, OpenJUMP neu gestartet werden. 2 http://ows.terrestris.de/dienste.html#openstreetmap-deutschland

KAPITEL 4. IMPLEMENTIERUNG 31 4.4 Finden von Koordinaten über Adressangabe Da sowieso nicht alle Straßennummern in den OSM-Daten verzeichnet sind, werden Koordinaten nur über eine Postleitzahl und eine Straße gesucht. Es gibt zwei Modellierungsmöglichkeiten für Postleitzahlen. Entweder werden OSM- Nodes mit Schlüssel-Wert-Paaren der Form addr:postcode und addr:street angelegt oder es gibt Polygone, die über eine Relation mit einer Postleitzahl verknüpft sind. Diese Polygone sind weit verbreitet, decken aber nicht ganz Deutschland ab. Es wird zuerst geprüft, ob es ein passendes Polygon zu der gegebenen Postleitzahl gibt. Falls kein Polygon existiert werden alle Edges und Nodes aus den OSM-Daten überprüft, ob sie einen Tag-key besitzten mit addr:postcode und der value gleich der gesuchten Postleitzahl ist. Um diese Geometrien wird eine BoundingBox gelegt und als Polygonersatz genutzt. Wurde ein Polygon oder eine BoundingBox gefunden, wird in dieser Geometrie nach der Straße mit dem angegebenen Straßennamen gesucht und die Node Id und Point- Geometrie, eines Knotens zurückgegeben. Dies führt die Funktion getnodeidforadress(text,text) aus, die im Anhang B.2 zu finden ist. 4.5 Umgang mit den WGS84-Koordinaten Die OSM-Daten liegen in zweidimensionalen Koordinaten bezogen auf den WGS84- Referenzellipsoiden in dezimaler Schreibweise vor. Das bedeutet unter anderem, dass die Entfernung zwischen zwei beliebigen Koordinaten nicht über den euklidischen Abstand der Ebene bestimmt werden kann. Zumindest nicht, wenn man den realen Abstand zweier Punkte auf der Erde in beispielsweise Kilometern wissen möchte. Dazu müsste man den kürzesten Weg auf einer Kugel oder besser noch auf dem WGS84-Referenzellipsoiden bestimmen. PostGIS hat für geographische Daten und Geometrien mit geographischen Koordinaten ab der Version 1.5 einen eigenen Typen, Geography, der bestimmte Geometrieberechnungen auf dem WGS84-Referenzellipsoiden anbietet. So kann die Distanz zwischen zwei Koordinaten mit ST Distance(Geography,Geography) bestimmt werden und auch die Länge eines LineStrings kann mit ST Length(Geography) in Metern ausgedrückt werden. Die Linestrings liegen zwar als Geometry vor, können jedoch automatisch zu Geography gecastet werden, wenn eindeutig ist, dass eine Geography benötigt wird. Den Abstand zwischen zwei Koordinaten kann man mit dem Verfahren nach Andoyer aus [Mee91], Seite 81, bestimmen. Alternativ, da sowieso nur Distanzen innerhalb Deutschlands bestimmt werden sollen, könnte auf trigonometrische, spärischen Berechnungen verzichtet und angenommen werden, dass die Krümmung der Erde keine Rolle spielt. Es