Mit GPS-Geräten schreiten Freiwillige die Straßen ihrer Heimatorte ab und erfassen Daten für die freie Weltkarte Openstreetmap. Ganz pedantische kartografieren gar die Parkzonen ihres Viertels.
(Notiz: Bitte "Ways" und "Nodes" nicht übersetzen).
Ein Blick auf die aktuelle Openstreetmap-Karte der Münchner Innenstadt (Abbildung 1) offenbart, dass genügend Freiwillige in akribischer Kleinstarbeit Kartendaten per GPS sammeln und auf dem neuesten Stand halten. Dabei glänzt das Projekt nicht nur mit Straßenverläufen und -namen, sondern auch mit Bushaltestellen, Bahnlinien und Radwegen. Bei Geschäften und Restaurants, die ihre Namen oft von einem Monat auf den anderen ändern ist Openstreetmap (OSM) mit seinem sogenannten Crowdsource-Verfahren mittlerweile aktueller als manch professioneller Anbieter.
Abbildung 1: Das Openstreetmap-Projekt zeigt die freie Karte der Münchner Innenstadt. |
Ebenfalls ein Vorteil gegenüber kommerziellen Anbietern ist der freie Datenexport. Per Knopfdruck auf der Webseite oder programmatisch per API auf api.openstreetmap.org darf jedermann die XML-Daten herunterladen, auf der die Karten basieren. Damit öffnet sich die Tür für kreative Basteleien. Das Datenmodell ist denkbar simpel: Sogenannte "Nodes" bezeichnen Wegpunkte, die ihren Standort in der realen Welt mittels Koordinaten in geographischer Breite und Länge angeben. Nodes werden meist mit einem tragbaren GPS an markanten Punkten wie Straßenkreuzungen erfasst.
Abbildung 2: Straßen bestehen aus Wegpunkten (Nodes), die durch Strecken (Ways) verbunden sind. |
Der Verlauf einer Straße ergibt sich dann durch das Verbinden dieser Nodes mit Wegstrecken, sogenannten "Ways". Eine Straße setzt sich oft aus mehreren Ways zusammen, und jeder Way kann dutzende von Nodes beinhalten, zum Beispiel weil eine Straße nicht gerade verläuft oder über Kreuzungen führt. Dort teilt sich der Way einer Straße oft einen Node mit einem Way der Querstraße (Abbildung 2).
Abbildung 4 zeigt die XML-Darstellung der OSM-Daten der Sonnenstraße am
Stachus in München. Ein Klick auf den Reiter "Export" in der
Kartendarstellung bringt den Dialog in Abbildung 3 hoch und nach dem
Auswählen der Option "XML" und dem Drücken des Submit-Buttons lädt der
Web-Browser eine XML-Datei des angezeigten Bereiches herunter.
Die Way-Definition im unteren Bereich von Abbildung 4
enthält Referenzen auf insgesamt elf Nodes.
Die letzten beiden, 1156387191 und 361792, sind im oberen Teil der Datei
als Node-Definitionen sichtbar.
Neben den geographischen Koordinaten lat
und lon
für die
geographische Breite und Länge im Digitalformat listet ein Node auch noch
auf wer (user
) ihn wann (timestamp
) erfasst hat, und in welchem
changeset
die Daten an den OSM-Server hochgeladen wurden. Letztere
Bündelung erlaubt es den OSM-Verwaltern, oft tausende von kleinen
Änderungen in einem Rutsch zu überprüfen oder rückgängig zu machen,
falls sich nach dem Hochladen herausstellt, dass die Daten falsch sind oder mit
unlauteren Methoden kopiert wurden.
Abbildung 3: Die hinter der Karte stehenden XML-Daten darf jedermann herunterladen und weiterverwenden. |
Abbildung 4: Der Openstreetmap-Server exportiert die Kartendaten auf Wunsch als XML unter einer freien Lizenz. |
Wie genau stimmen die OSM-Daten mit der Realität überein? Als Test lassen sich die Lat/Lon-Geodaten einfach in Google-Maps eingeben, und, wie Abbildung 4 zeigt, liegen die von Freiwilligen per GPS ermittelten Koordinaten der zwei Nodes des Ways mit dem Tag "Sonnenstraße" genau im erwarteten Bereich des kommerziellen Anbieters, von dem Google die Daten kauft.
Abbildung 5: Realitäts-Check: Die Lat/Long-Koordinaten aus der Openstreetmap-Datei bezeichnen auf Google Maps einen Teil der Sonnenstraße in München. |
Eine Straße setzt sich im XML der OSM-Datenbank aus einem oder mehreren
Ways zusammen. Den Namen der Straße, zu dem ein Way gehört, führt dieser
als Tag unter dem Attribut name
. Die drittletzte Zeile in Abbildung
4 weist deshalb im XML-Tag <tag>
des Ways dem Schlüssel
k="name"
den Wert v="Sonnenstraße"
zu.
Zu beachten ist, dass der
dort gezeigte Way mit der ID 3654453 keineswegs den gesamten Verlauf der
Sonnenstraße in München zeigt, sondern nur einen kleinen Abschnitt.
Besonders bei längeren Straßen ist es üblich, dass mehrere Ways mit dem
gleichen Tag name
den Gesamtverlauf festlegen. Oft lassen sich diese
Einzelabschnitte auf höherer Ebene zu etwas Sinnvollem bündeln, um etwa
den Verlauf einer Trambahnlinie zu modellieren.
Es ist auch nicht ungewöhnlich, dass ein
Helfer im OSM-Projekt einen Way in mehrere Teile aufspalten muss, um die
gewünschte Strukturierung zu ermöglichen, falls zum Beispiel zwei
Teilstrecken eines Ways unterschiedlichen Geschwindigkeitsbeschränkungen
unterliegen.
Die im XML in Abbildung 4 sichtbaren Ways-Tags highway
(Straßenart), lanes
(Anzahl der Spuren), name
(Straßenname) und
oneway
(Einbahnstraße) hat das Projekt über die Jahre standardisiert,
doch es erlaubt praktisch beliebige Erweiterungen. Das Design wurde
bewusst so flexibel ausgelegt, damit freiwillige Helfer schnell und
unbürokratisch neue Funktionen hinzufügen können, ohne sich in langwierigen
Gremiendiskussionen zur Erweiterung von Standards aufzureiben.
Der Nachteil dieses flexiblen Ansatzes ist ein gewisser Wildwuchs, der Anhängern normalisierter Datenbankschemata das Wasser in die Augen treibt. Damit Applikationen neu erfasste Daten weltweit verarbeiten können, müssen sich die Helfer aber irgendendwie zusammenraufen, und das geschieht üblicherweise auf dem OSM-Wiki und dessen Talk-Seiten ([7]). Schlägt dort zum Beispiel jemand ein neues Schema für Briefkästen oder Geschäftsöffnungszeiten vor, entwickelt sich nach reger Diskussion oft ein neuer Standard.
Damit Mapper selbst Änderungen in der OSM-Datenbank vornehmen können, helfen eine Reihe von Tools, allen voran die Online-Editoren JOSM ([9]) und Potlatch ([10]). JOSM ist schon etwas in die Jahre gekommen und seine im Cross-Plattform-Java-Look erscheinende Bedienoberfläche stößt Ästheten ab, doch er bietet alle notwendigen Funktionen. Betritt man exotisches Neuland mit bislang unbekannten Tags, ist JSOM sogar oft der einzige Editor mit der geforderten Funktion. Potlatch hingegen ist eine direkt im Browser laufende Flash-Applikation, die poliert daherkommt und sich mittlerweile zum Standard fürs Editieren der Karte gemausert hat.
Abbildung 6: Der JSOM-Editor lädt die Kartendaten eines ausgewählten Bereiches in den Arbeitsspeicher. |
Die heute vorgestellten Änderungen, Straßensäuberungsdaten in meiner Wahlheimat San Francisco, fallen in die Kategorie "exotisch" und deswegen kommt JOSM zum Einsatz. Die in den Repositories aktueller Distributionen lungernden JSOM-Versionen sind meist veraltet, es empfiehlt sich daher, die aktuelle "josm-tested" Jar-Datei direkt von der Projektseite [9] zu laden und mit
java -jar josm-tested.jar
zu starten (Java 1.6 erforderlich). Ein Klick auf das Icon mit dem grünen nach unten weisenden Pfeil in der Kopfleiste des Applikationsfensters (oberer Rand in Abbildung 6) öffnet ein Dialogfenster, in dem der Hobbykartograph mit der Maus einen rechteckigen Bereich auswählen kann. Drückt der User auf den weiter unten liegenden "Download"-Button, holt JSOM die selektierten Kartendaten vom OSM-Server und lädt sie in den Arbeitsspeicher des Editors. Der Mapper sieht anschließend im "Data-Layer" bereits definierte städtische Strukturen und kann Änderungen vornehmen oder neue Daten hinzufügen. Einen angezeigten Way klickt man mit der Maus an, bis er hell aufleuchtet. Im Fenster "Properties" auf der rechten Seite in Abbildung 7 erscheinen dann alle auf dem Way definierten Tags (z.B. "name", das in Abbildung 7 auf "23rd Street" gesetzt ist), und ein Klick auf den "Add"-Button öffnet ein Dialogfenster, in dem der User neue Tagnamen und die zugehörigen Werte eintragen kann.
Abbildung 7: Mit JSOM trägt der Openstreetmap-Helfer die 2-Stunden-Parkzone auf der 23sten Straße ein. |
Passt alles, lädt ein Klick auf das Icon mit dem grünen Pfeil nach oben (Kopfleiste in Abbildung 6) die Daten hoch auf den OSM-Server. Hierzu registriert sich der Mapper mit seiner Email-Addresse und legt einen Useraccount mit Passwort an. Die Daten sind, ähnlich wie bei Wikipedia, ohne Prüfschritt sofort auf dem Live-Server sichtbar.
San Francisco ist wie alle größeren Städte der Welt vollständig auf OpenStreetMap erfasst. Allerdings stellt es mit seinen komplizierten Parkregeln einige Herausforderungen an touristische Autofahrer, und diese bürokratischen Vorschriften in die freie Weltkarte einzubinden schien mir als lohnendes Projekt.
Wer meint, geparkt würde hier nach Wildwestmanier, irrt sich. Auf der 23sten Straße bei mir um die Ecke dürfen Autos ohne Anwohnerplakette montags bis freitags von 8 bis 18 Uhr nur 2 Stunden lang parken. Anwohner mit der Parkmarke "Z" sind davon ausgenommen. Außerdem fährt in San Francisco auf den meisten Straßen an bestimmten Tagen das Kehrauto ([6]) durch und während der 2-stündigen Zeitspanne darf auf der betroffenen Straßenseite niemand parken. Wer's dennoch tut bekommt einen Strafzettel über 55 Dollar ausgestellt. Das Straßenschild in Abbildung 8 zeigt die Parkbedingungen im Detail. Sie variieren oft von Kreuzung zu Kreuzung und folgen einem geheimen Plan, den nur der Kehrautofahrer kennt.
Abbildung 8: Anwohnerparken mit zweiwöchentlicher Straßenreinigung |
Bis San Franciscos Parkregeln stadtweit in der OSM-Datenbank stehen, wird aber noch einige Zeit ins Land ziehen. In deutschen Landen ist man da wesentlich weiter: Aus Abbildung 9 geht hervor, dass Mapper die Parkzonen der bayrischen Stadt Bamberg praktisch vollständig erfasst haben und der extra für Parkplatzinformationen aufgestellte Server parking.openstreetmap.org blendet Parkscheiben an den entsprechenden Stellen ein. Das Wiki mit dem Vorschlag für ein Straßenparktag-Format ([8]) listet noch weitere führende Städte auf.
Abbildung 9: Die Parkzonen der Bamberger Innenstadt sind schon relativ vollständig erfasst (parking.openstreetmap.org). |
Nach langwieriger Diskussion auf dem Park-Wiki auf OSM ([7]) kristallierten sich die Tags in Abbildung 10 für Straßenparkregeln auf der ganzen Welt heraus. Die ersten drei Tags beschreiben das Anwohnerparken, der zweite Block die Straßenreinigungszeit für die linke und der dritte Block für die rechte Straßenseite.
Abbildung 10: Nach dem Hochladen der Daten zum OSM-Server weiß die ganze Welt, wann man auf der 23rd Street in San Francisco parken darf. |
Doch wo ist "left" und wo "right"? Ways in OSM weisen immer in eine
Richtung, denn sie zeigen von einer Node zur anderen. Dies ist für die
erfasste Straße oft irrelevant (mit Ausnahme von Einbahnstraßen)
und spiegelt lediglich die oft willkürliche Wahl des Mappers wider. Im Fall
der Parkregeln in San Francisco legt die Richtung bei einseitig definierten
Reinigungszeiten jedoch genau fest, wann das Kehrauto auf welcher Seite
fährt. Abbildung 7 zeigt den Editor JOSM beim Einfügen eines neuen Tags mit dem Namen
parking:condition:left:maxstay
in einen Way, der Abschnitte der
23th Street mit einer Maximalparkdauer von 2 Stunden für Autos
ohne Anwohnerparkmarke auszeichnet.
Noch eine Komplikation: Die Regel, dass das Kehrauto nur jeden zweiten Dienstag im Monat kommt, lässt sich ebenfalls über einen bereits verabschiedeten OSM-Standard ausdrücken. Öffnungszeiten von Geschäften gehorchen ähnlichen Regeln und deswegen schlugen die OSM-Mapper kurzum vor, die existierende Syntax auch für Parkregeln zu verwenden ([11]) gibt Auskunft darüber, wer dafür verantwortlich zeichnet und wann es passiert ist. Der Ausdruck "Fr[2,4]" steht so für den zweiten und den vierten Freitag im Monat.
Abbildung 11: Hinter dem Reiter "History" verbirgt sich ein Log mit den neuesten Änderungen, die auch rechts in der Karte hell aufleuchten. |
Nach dem Hochladen sieht die ganze Welt sofort die Änderung und im Reiter "History" (Abbildung 11). Doch der eigentliche Clou der Geschichte ist nun, dass beliebige Applikationen die neu erfassten Daten frei nutzen können. Wie wäre es mit einem Skript, das mir Bescheid gibt, wann das Kehrauto kommt, wenn ich ihm mitteile, dass ich auf der Chattanooga Street auf der rechten Seite zwischen 23. und 24. Straße geparkt habe? Listing 1 lädt sich hierzu die XML-Daten vom OSM-Server und spuckt nach nur Sekunden die richtige Antwort aus:
$ ./street-cleaning "Chattanooga Street" "23rd Street" "24th Street" right Street Cleaning: We[2,4] 08:00-10:00
Listing 1 lädt sich hierzu zunächst eine XML-Datei des Stadteils Noe Valley in San Francisco vom OSM-Server. Nach Abbildung 3 liegt das Viertel zwischen -122.43738 und -122.42098 Grad geographischer (und wegen der negativen Werte westlicher) Länge und zwischen 37.74754 und 37.7589 Grad nördlicher Breite auf dem Globus. Zeile 9 formt daraus einen URL für die API des OSM-Servers und Zeile 23 spiegelt die komprimierte XML-Datei unter map.osm.gz auf der lokalen Festplatte. Die if-Bedingungen in Zeile 22 prüfen, ob die Datei schon existiert und nicht älter als eine Woche ist, und unterbindet eine erneute Übertragung relativ neuer Daten. Der Zusatzheader "Accept-Encoding" in Zeile 20 signalisiert dem Server, dass der Client eine gzip-komprimierte Datei wünscht.
Die XML-Daten durchforstet das Modul Geo::Parse::OSM vom CPAN, dessen
Methode parse()
einen Callback entgegen nimmt, den sie jedes Mal anspringt,
wenn sie ein gesuchtes Element findet. Zu beachten ist, dass parse()
nichts mehr findet, falls es schon einmal durchgelaufen ist, und nur ein
seek_to(0)
den Parser wieder auf den Anfang der Datei setzt, damit
eine neue Suche stattfindet.
001 #!/usr/local/bin/perl -w 002 use strict; 003 use Geo::Parse::OSM; 004 use Graph::Directed; 005 use LWP::UserAgent; 006 007 my @bbox = qw( -122.4374 37.74754 008 -122.42096 37.75894 ); 009 my $url = "http://api.openstreetmap.org/" . 010 "api/0.6/map?bbox=" . join ',', @bbox; 011 012 my $mapfile = "map.osm.gz"; 013 014 my( $street_on, $street_cross1, 015 $street_cross2, $side ) = @ARGV; 016 die "usage: $0 street cross1 cross2 side" 017 if !defined $side; 018 019 my $ua = LWP::UserAgent->new(); 020 $ua->default_header("Accept-Encoding", 021 "gzip"); 022 if( ! -f $mapfile or -M $mapfile > 7 ) { 023 my $rsp = $ua->mirror( $url, $mapfile ); 024 $rsp->is_success or die $rsp->message(); 025 } 026 027 my $osm = Geo::Parse::OSM->new( $mapfile ); 028 029 my %on_nodes = (); 030 031 street_nodes( $osm, $street_on, sub { 032 $on_nodes{ $_[0] } = 1; 033 } ); 034 035 my $cross1_node = cross_find( $osm, 036 \%on_nodes, $street_cross1 ); 037 my $cross2_node = cross_find( $osm, 038 \%on_nodes, $street_cross2 ); 039 040 my( $nodes, $flip_order) = 041 find_path_on_way( $osm, $street_on, 042 $cross1_node, $cross2_node ); 043 044 $side = flipside( $side, $flip_order ); 045 046 my $parking = parking($osm, $nodes, $side); 047 048 print "Street Cleaning: ", 049 street_cleaning( $parking ), "\n"; 050 051 ########################################### 052 sub street_nodes { 053 ########################################### 054 my( $osm, $name, $cb ) = @_; 055 056 $osm->seek_to( 0 ); 057 $osm->parse( sub { 058 my($n) = @_; 059 if( exists $n->{tag}->{name} and 060 $n->{tag}->{name} eq $name ) { 061 for my $n ( @{ $n->{chain} } ) { 062 $cb->( $n ) or last; 063 } 064 } 065 }, only => "way"); 066 } 067 068 ########################################### 069 sub cross_find { 070 ########################################### 071 my($osm, $on_nodes, $cross_street) = @_; 072 073 my $found; 074 street_nodes( $osm, $cross_street, sub { 075 my($n) = @_; 076 if( exists $on_nodes->{ $n } ) { 077 $found = $n; 078 return 0; # stop iteration 079 } 080 return 1; # continue iteration 081 }); 082 083 return $found; 084 } 085 086 ########################################### 087 sub find_path_on_way { 088 ########################################### 089 my( $osm, $way_name, @nodes ) = @_; 090 091 my $g = Graph::Directed->new(); 092 093 $osm->seek_to(0); 094 $osm->parse(sub { 095 my($n) = @_; 096 if( exists $n->{tag}->{name} and 097 $n->{tag}->{name} eq $way_name ) { 098 $g->add_path( @{ $n->{chain} } ); 099 } 100 }, only => "way" ); 101 102 my $flip_order = 0; 103 104 my @path = $g->SP_Dijkstra( @nodes ); 105 106 if( !@path ) { 107 @nodes = reverse @nodes; 108 @path = $g->SP_Dijkstra( @nodes ); 109 $flip_order = 1; 110 } 111 112 return( \@path, $flip_order ); 113 } 114 115 ########################################### 116 sub parking { 117 ########################################### 118 my( $osm, $nodes, $side ) = @_; 119 120 my %to_match = map { $_ => 1 } @$nodes; 121 my %results = (); 122 123 $osm->seek_to( 0 ); 124 $osm->parse( sub { 125 my($w) = @_; 126 127 my @matches = 128 grep { exists $to_match{$_} } 129 @{ $w->{chain} }; 130 131 return if @matches < 2; 132 133 for my $tag ( keys %{ $w->{tag} } ) { 134 if( $tag =~ 135 /parking:condition:$side:.*/ ) { 136 $results{$tag} = $w->{tag}->{$tag}; 137 } 138 } 139 }, only => "way"); 140 141 return \%results; 142 } 143 144 ########################################### 145 sub street_cleaning { 146 ########################################### 147 my( $parking ) = @_; 148 149 for my $key ( keys %$parking ) { 150 if( $key =~ /(.*)\:reason/ ) { 151 if( $parking->{ $key } eq 152 "street_cleaning" ) { 153 return $parking->{ $1 . 154 ":time_interval" }; 155 } 156 } 157 } 158 159 return undef; 160 } 161 162 ########################################### 163 sub flipside { 164 ########################################### 165 my($side, $flip_order) = @_; 166 167 if( $flip_order ) { 168 if( $side eq "left" ) { 169 $side = "right"; 170 } else { 171 $side = "left"; 172 } 173 } 174 175 return $side; 176 }
Um nun im Straßenlabyrinth einen oder mehrere OSM-Ways zu finden, die sich
zwischen zwei Querstraßen auf einer Hauptstraße befinden, legt der
Aufruf von street_nodes
in Zeile 31 erst einmal alle Node-Nummern der
Hauptstraße als Schlüssel im Hash %on_street
ab. Die Funktion
street_nodes
ist ab Zeile 52 definiert und klappert mit der
Einschränkung only => "way"
alle Ways der XML-Datei ab, sucht
nach einem, der im name
-Tag den Wert der Hauptstraße führt, und
springt mit seiner Referenznummer den hereingereichten Callback an.
Gewappnet mit den Nodes der Hauptstraße bestimmen nun die Aufrufe
von cross_find()
(definiert ab Zeile 69) in den Zeilen 35 und 37
diejenigen Nodes, auf denen die auf der Kommandozeile angegebenen
Querstraßen sich mit der Hauptstraße schneiden. Nun stehen etwa in
Abbildung 12 die Nodes N2 und N5 fest. Allerdings kommt es vor, dass
sich die Verbindungsstrecke zwischen zwei Kreuzungen aus mehreren
Ways zusammensetzt, wie in der Abbildung 12 aus way2, way3 und way4.
Von N2 ausgehend muss der Algorithmus sich nun in eine Richtung in
Bewegung setzen, hoffend, dass er bei N5 ankommt und nicht in der
Sackgasse bei N1 endet. Zum Glück hat Algorithmus-Urgestein
Edsger W. Dijkstra dieses Problem schon 1959 gelöst ([13]) und das Modul
Graph vom CPAN bietet das Verfahren mit der Methode SP_Dijkstra()
an.
Letztere nimmt nur die zwei zu verbindenden Nodes entgegen und berechnet
auf der Basis des bislang definierten gerichteten Grafen
("Directed Acyclic Graph", DAG) den kürzesten Weg von N2 nach N5.
Abbildung 12: Die Nodes zwischen zwei Querstraßen ermittelt der "Shortes-Path"-Algorithmus von Edsger W. Dijkstra. |
Die ab Zeile 87 definierte Funktion find_path_on_way()
implementiert
das Verfahren. Erst erzeugt sie ein neues Objekt vom Typ Graph::Directed
und legt über den von parse()
angesprungenen Callback für alle
gefundenen Ways mit dem Straßennamen mit jeweils allen in der
Datenstruktur chain
enthaltenen Nodes einen Pfad im DAG an.
Findet die Methode SP_Dijkstra()
keinen Weg von A nach B, zeigen
die willkürlich gewählten Richtungspfeile zwischen den Nodes
wohl in die verkehrte Richtung und Zeile 107 dreht die Reihenfolge der
Nodes um. In der Variablen flip_order
merkt sich die Funktion
diese Tatsache und später weiß das Hauptprogramm, dass "links" in diesem
Fall nicht "links" in Richtung der Ways-Richtung meint, sondern "rechts".
Die Funktion parking()
stöbert durch den aus Nodes bestehenden Pfad
und speichert das letzte auf den dabei durchschrittenen Ways gefundene
Park-Tag. In der Annahme, dass sich die Parkzone nicht innerhalb eines
Straßenblocks ändert, was für Straßenreinigungszeiten der Fall ist aber
bei anderen Parkinformationen in die Hose ginge.
Fand eine Richtungsumkehr statt, ändert die Funktion flipside()
, definiert
ab Zeile 163 und aufgerufen in Zeile 44, den Sting "left" in "right" um
und umgekehrt. Die Funktion street_cleaning()
ab Zeile 145 braucht
dann nur noch eventuell vorhandene Parking-Tags wie in Abbildung 10
aufzuspüren, die richtige Straßenseite ("left"/"right") zu extrahieren
und auszugeben, und schon weiß der parkende Tourist
wann die Kehrmaschine kommt.
Das Erstlingswerk "OpenStreetMap" [2] führt anschaulich in die Materie ein und stellt eine Reihe von Tools und Verfahren für den ambitionierten Streetmapper vor. Das gleichnamige Werk aus dem Packt-Verlag [3] ist sogar noch aktueller, bietet eine ausgezeichnete Einführung in die Community, zeigt viele praktische GPS-Tipps und erläutert anschaulich die OSM-Datenstrukuren und API-Funktionen.
Ich werde in den nächsten Wochen in meinem Viertel "Noe Valley" in San Francisco jedenfalls fleißig weiter Parkdaten sammeln und auf den OSM-Server hochladen. Mir schwebt eine Webapplikation vor, auf der ich den aktuellen Stellplatz meines Zweitautos Perly Perlman eintragen kann und die mich per Email warnt, falls am nächsten Tag das Kehrauto mit der Strafzettelwespe [12] im Schlepptau kommt. Das könnte sich bezahlt machen.
Listings zu diesem Artikel: ftp://www.linux-magazin.de/pub/listings/magazin/2011/02/Perl
Frederik Ramm, Jochen Topf, "OpenStreetMap: Die freie Weltkarte nutzen und mitgestalten", Lehmanns Media; 3. Auflage, http://www.amazon.de/dp/3865413757
Jonathan Bennett, "OpenStreetMap", Packt Publishing (September 22, 2010), ISBN: 1847197507
Garmin GPSMAP 60CSx Handheld GPS Navigator, http://www.amazon.com/dp/B000CSOXTO
Michael Schilli, "Hinterm Horizont", GPS-Daten eines Garmin eTrex mit Perl auswerten und online in Karten einblenden, Linux-Magazin 07/2006
"Street Cleaning in San Francisco", http://www.youtube.com/watch?v=kLR0uxooEf8
Diskussion im Wiki um die neuen Park-Tags auf dem Openstreetmap-Wiki: http://wiki.openstreetmap.org/wiki/Talk:Proposed_features/parking:lane
Wiki mit dem Vorschlag für die neuen Park-Tags: http://wiki.openstreetmap.org/wiki/Proposed_features/parking:lane
Projektseite des OSM-Editors JOSM: http://josm.openstreetmap.de
Projektseite des OSM-Editors Potlatch: http://wiki.openstreetmap.org/wiki/Potlatch_2
Standards für Öffnungszeiten auf dem Openstreetmap-Wiki: http://wiki.openstreetmap.org/wiki/Key:opening_hours
Die Strafzettelwespe in San Francisco, die während der Straßenreinigungszeiten 55-Dollar-Knöllchen verteilt.
"Dijkstra-Algorithmus", http://de.wikipedia.org/wiki/Dijkstra-Algorithmus