Google sorgte vor kurzem mit zwei Nachrichten für Überraschung: Die erste ist die Integration von Satellitenbildern in Google Maps, die zweite die Veröffentlichung eines API mit freiem Zugriff auf Bilder und Kartenmaterial für die Entwicklung von eigenen Webanwendungen.
Die Entwickler von Google haben eine Programmierschnittstelle (API) auf Basis von Javascript (respektive ECMA-Script, [1]) vorbereitet. Sie erleichtert es, Programme zu schreiben, die auf Satellitenbilder und Karten von Google Maps zugreifen. Die Anwendungen lassen sich einfach und direkt in eigene Webseiten einbinden und per Browser ausführen. Mit anderen Worten: Der eigene Browser (Firefox, Opera, Safari oder Internet Explorer) ist für die Ausführung der selbst geschriebenen Applikationen zuständig, eine spezielle Infrastruktur auf der Server-Seite ist nicht nötig.
Erste Schritte
Der Artikel stellt das Interface anhand eines Beispielprogramms vor, das über Mausklicks einen Weg auf Satellitenfotos oder Karten zeichnet, die zurückgelegte Strecke in Kilometern misst und anzeigt. Es kann zum Beispiel die Basis für einen digitalen Schrittmesser bilden.
Um das API verwenden zu dürfen, müssen sich Programmierer an folgende Richtlinien von Google halten [2]:
- Eigene Entwicklungen müssen für jedermann frei
zugänglich sein. - Die Anfragen pro Tag dürfen ein bestimmtes Maß nicht
überschreiten. - Das Google-Logo muss auf der Seite sichtbar sein.
Den nötigen Zuggriff auf das API bekommen Entwickler unter [3]. Hier müssen sie sich mit einem bestehenden Google-Account anmelden. Dazu reicht ein Gmail-Konto. Wer keins hat, kann sich unter der genannten Adresse ein Konto einrichten.
Jeder Zugang ist mit einem User und einer Zugangs-URL verknüpft. Wer keine Webadresse hat, um seine Entwicklungen zu speichern, meldet sich mit der Adresse [http://localhost] an, um das Testprogramm lokal auszuführen. Dazu muss natürlich ein Apache-Server laufen. Bei der Angabe der Zugangs-URL ist darauf zu achten, die gesamte Adresse inklusive Ports und Ordner anzugeben, da sonst ein Zugriff auf das API-Angebot nicht möglich ist.
Das Beispiel geht davon aus, dass Apache über Port 8080 erreichbar ist und sich die Site im Ordner »maps« befindet. Die Zugangsadresse lautet somit:
http://localhost:8080/maps/
Pro Benutzer lassen sich beliebig viele Zugänge anmelden. Nach dem Akzeptieren der Vertragsbedingungen sendet Google Interessierten einen langen alphanumerischen Schlüssel zu. Es lohnt sich, ihn für den späteren Gebrauch in einer Datei zu speichern.
Der Flug des Phoenix
Als erstes Beispiel dient die in Listing 1 gezeigte HTML-Seite. Die offizielle API-Dokumentation [4] empfiehlt XHTML statt HTML. Die Gründe dafür liegen in der besseren Portierbarkeit, die der neue Standard bietet. XHTML-Dokumente deklariert der »DOCTYPE«-Eintrag in der ersten Zeile. Es ist empfehlenswert, die Zeilen 2 sowie 5 bis 9 des Listings so beizubehalten, damit auch der Internet Explorer einige der Effekte richtig anzeigen kann, die die Javascript-Bibliothek von Google Maps zur Verfügung stellt, vor allem die Streckenlinien, die das Beispiel später benötigt.
Zeile 10 in Listing 1 bindet die Javascript-Datei mit dem API-Code ein. Hier ist »XXXXX« durch den von Google erzeugten Schlüssel zu ersetzen. Nur so ist es möglich, bei Google angemeldet zu bleiben und die Funktionen des Google-Servers aufzurufen. Interessanterweise beschränkt sich das ganze XHTML des ersten Beispiels auf die Zeilen 24 und 25. Hier bestimmt der Code, dass der Browser nach dem Laden der HTML-Seite die Javascript-Funktion »onLoad« (definiert ab Zeile 13) ausführen soll. In Zeile 25 findet sich die Formulierung »<div>« mit 500 mal 500 Pixeln und dem Identifier »map«. Wozu dieser dient, erklärt der Artikel weiter unten.
Browser-Check
Die Funktion »onLoad« initialisiert die Landkarte. Wie bereits erwähnt ist das gesamte API von Google in Javascript geschrieben und läuft im eigenen Browser. Da nicht alle Programme die gleiche Javascript-Version respektive die gleichen Funktionen verwenden, gibt es gewisse Inkompatibilitäten zwischen den Browsern. Um sicherzustellen, dass das Programm unter den vom Google-API unterstützten Browsern läuft, führt die Funktion »GBrowserIsCompatible()« in Zeile 14 einen Browser-Check durch. Mit Firefox, Safari, Opera und dem Internet Explorer ab Version 5.5 dürfte es dann keine Probleme geben.
Die nächste Zeile erzeugt ein Objekt vom Typ »GMap« und übergibt dieses »div«-Objekt mit dem Identifier »map« an den Konstruktor. Dieses HTML-Objekt verwendet »GMap«, um eine Karte in der Größe einzufügen, die mit dem Identifier verknüpft ist. »GMap« bietet eine Schnittstelle, die in der offiziellen Dokumentation [3] erklärt wird (für das Objekt existieren auch weitere Konstruktoren). Um das Objekt (die Landkarte) bewegen zu können, bietet das API verschiedene Steuerelemente an.

Abbildung 1: Das lange Steuerelement links entspricht dem »GLargeMapControl«, oben rechts »GSmallMapControl« und rechts in der Mitte »GSmallZoomControl«.
Kontrollelemente
Das Beispiel benutzt in Zeile 16 die Methode »addControl()«. Sie baut verschiedene Steuerelemente in die Karte ein, die bei gedrücktem linken Mauszeiger die Landkarte verschieben. Eine weitere Möglichkeit besteht darin, dass eine mit der Karte verknüpfte Komponente das Zoom-Niveau verändert.
Ein solches Steuerelement fügt Zeile 16 des Listings 1 ein. Es entspricht dem Kontrollwerkzeug oben rechts in Abbildung 1. Alternativ bietet sich folgende Schreibweise an, um getrennte Steuerelemente für Position und Zoom zu verwenden:
map.addControl(new GLargeMapControl());
Das API verfügt über zwei weitere Bausteine zur Navigation: Schalter für die verschiedenen Kartentypen und eine Anzeige für den Maßstab in Kilometern und Meilen. Der wichtigere von beiden ist für die Auswahl der Ansicht zuständig (Zeile 17). Google unterscheidet dabei drei Typen: Karte, Satellitenfoto und die Kombination beider. Je ein Beispiel zeigen die Abbildungen 2 bis 4. Gegenwärtig gibt es klassisches Kartenmaterial mit Straßennamen und Adressen allerdings nur für die USA, Großbritannien und Japan, sodass der Nutzen für Deutschland gering ist.
Zeile 19 zentriert das Bild, indem sie die geografische Breite, Länge und das Zoom-Niveau spezifiziert. Das Beispiel benutzt dazu die Koordinaten von Palo Alto in Kalifornien. Bei der Eingabe der Koordinaten des Punktes, an dem sich die Karte ausrichten soll, muss man zuerst die Länge und dann die Breite angeben. Normalerweise erfolgen Koordinatenangaben in umgekehrter Reihenfolge: Breite, Länge.
Die Sphäre
Neben diesem Hauptdokument soll ein zweites Dokument die Distanzen zwischen Kontrollpunkten berechnen. Dabei kommen anspruchsvollere Konzepte wie Ereignisse und Markierungen zum Einsatz. Die Grundstruktur entspricht aber weitgehend dem in Listing 1 abgedruckten »test1.html«. Das komplette Programm zeigt Listing 2.
Jeder Punkt der Erdoberfläche lässt sich über zwei Zahlen eindeutig bestimmen: Breite und Länge. Beide werden in Grad angegeben, da es sich um Winkel handelt. Die Breite gibt den Winkel zwischen dem Punkt und dem Äquator an und die Länge den Winkel zwischen Punkt und Nullmeridian. Anhand der Koordinaten zweier Punkte der Oberfläche einer Kugel lässt sich aber nicht deren Abstand berechnen, dazu ist noch eine weitere Zahl erforderlich: der Radius der Kugel. Nimmt man für die Erde einen durchschnittlichen Radius von 6378,7 Kilometern an (die Erde ist keine perfekte Kugel), lassen sich die Abstände mit Hilfe der Kugelgeometrie ausrechnen.
Für diese Berechnung existieren unter [5] mehrere Lösungen. Der am häufigsten benutzte Weg erfordert zuerst die Umwandlung der Breiten- und Längengrade in Bogenmaße, um dann folgende Formel anzuwenden:
d = 6378.7 * acos(sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(lon2 - lon1))
Die konkrete Anwendung der Gleichung erfolgt in der Funktion »calcDistance()« in Listing 2 ab Zeile 69. Diese und gleichwertige Gleichungen lassen sich mit den bekannten trigometrischen Formeln leicht herleiten.

Abbildung 4: Das HTML-File blendet auch die Karte ins Satellitenbild ein. Die Namen der Straßen erscheinen über deren Abbildern.

Abbildung 5: Hier ist eine Strecke von 776 Metern in die Karte eingezeichnet. Für Strecken lassen sich so viele rote Markierungen einzeichnen wie gewünscht.
|
Listing 1: |
|---|
01 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
02 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
03 <head>
04 <title>Beispiel 1 - test1.html</title>
05 <style type="text/css">
06 v:* {
07 behavior:url(#default#VML);
08 }
09 </style>
10 <script src="http://maps.google.com/maps?file=api&v=1&key=XXXXX" type="text/javascript"></script>
11 <script type="text/javascript">
12 //<![CDATA[
13 function onLoad() {
14 if (GBrowserIsCompatible()) {
15 var map = new GMap(document.getElementById("map"));
16 map.addControl(new GSmallMapControl());
17 map.addControl(new GMapTypeControl());
18 map.addControl(new GScaleControl());
19 map.centerAndZoom(new GPoint(-122.1419, 37.4419), 4);
20 }
21 }
22 //]]>
23 </script>
24 <body onload="onLoad()">
25 <div id="map" style="width: 500px; height: 500px"></div>
26 </body>
27 </html>
|
Entfernungen messen
Im Vergleich zum ersten Beispiel benutzt »Distanz.html« in Zeile 21 beim Aufruf des Konstruktors »GMap« einen zusätzlichen Parameter, ein Array aus nur einem Element. Es legt fest, dass dieses Dokument nur den Satellitenmodus anzeigt. Die Schalter für die Auswahl der Ansicht dürfen entfallen, da Google Maps für Deutschland zurzeit kein Kartenmaterial bereitstellt.
Das Google-API erlaubt es, den Funktionen eine Reihe vorgefertigter Ereignisse zuzuordnen. Der Benutzer kann damit das Verhalten bei Mausklicks über bestimmten Bereichen verändern, um zum Beispiel bei einem Ortswechsel automatisch zu zoomen oder eine Markierung zu setzen. Die vollständige Liste der unterstützten Ereignisse findet sich in der Google-Dokumentation.
Das Testprogramm soll auf zwei Ereignisse reagieren: zum einen nach einem Ortswechsel, um die neuen Koordinaten des Kartenmittelpunkts aufzunehmen und sie anzuzeigen. Zum anderen bei einem Mausklick über der Karte. Hier soll es die Markierungen für die zu messende Strecke hinzufügen oder entfernen.
Das Google-API bietet mehrere Möglichkeiten, Ereignisse aufzufangen. Das Beispiel verwendet folgende:
GEvent.addListener(map, 'click', function(overlay,point) {
map.recenterOrPanToLatLng (point);
});
Die Methode »addListener()« der Klasse »GEvent« muss wissen, welches Ereignis sie auffangen und mit welcher Funktion sie es behandeln soll. Das Beispieldokument fängt einen Mausklick über der Karte ab (»click«-Event in Zeile 27). Die Funktion dieses Ereignisses verarbeitet zwei Parameter: Das »overlay«, also die Markierung, auf die geklickt wurde, und einen Punkt, der die exakten Koordinaten des Mausklicks enthält. In Zeile 22 erfolgt mit dem Event »movend« der abgeschlossene Ortswechsel.
Markierungen setzen
Das entscheidende Ereignis beschreibt aber Zeile 35 des Listings 2: Durch einen eigenen Verwalter für Mausklicks kann der User mehrere Markierungen setzen, die das Programm in einem Array speichert. Klickt der Benutzer ein zweites Mal auf eine der Markierungen, soll das Programm sie aus der Karte und aus dem Array entfernen. Auf diese Art und Weise lässt sich leicht eine Strecke definieren, die die Javascript-Anwendung als blaue Linie zeichnet.
Sowohl die Markierungen als auch die Streckenlinien sind in der offiziellen Dokumentation unter »overlays« detailliert beschrieben. Jedes Overlay ist ein in die Karte eingeblendetes Objekt. Obwohl sich auch eigene Symbole für die Markierungen definieren lassen, verwendet dieses Beispiel der Einfachheit halber direkt die Standards aus dem API. Folgende Zeilen erzeugen eine Markierung für eine bestimmte Koordinate:
var m = new GMarker(new GPoint(lon1, lat1)); map.addOverlay(m);
Diese Markierung setzt dann die Methode »addOverlay()« der Klasse »GMap« auf die Landkarte. Die gleiche Methode zeichnet die zurückgelegte Strecke. Statt »GMarker« kommt hier aber ein »GPolyline«-Objekt zum Einsatz:
var p = new Array; p.push(new GPoint(lon1, lat1)); p.push(new GPoint(lon2, lat2)); map.addOverlay(new GPolyline(p));
Im Beispielprogramm erfüllen die Funktionen »addOverlay()« und »drawLine()« die gleiche Funktion. Abbildung 5 zeigt die fertig gezeichnete Strecke. Ist sie (oder ein Teil davon) festgelegt, lässt sich die zurückgelegte Distanz mit den oben genannten Formeln berechnen.
Ausblick
Mit lediglich vier Objekten und acht Methoden schreiben Entwickler eine Anwendung, die Distanzen für interaktiv gezeichnete Strecken berechnet. Das ist nur dank der guten Qualität des Google-Maps-API möglich. Es hilft dabei, mit einfachen Mitteln innovative und interessante Webanwendungen zu entwickeln, die eigentlich tiefe Kenntnisse in Mathematik, Geometrie und Navigation voraussetzen.
Die Programmierschnittstelle stellt auch noch eine Gruppe von Objekten für den asynchronen Zugang zu XML-Daten über Javascript bereit (AJAX, [6]). Damit lassen sich große Mengen an Koordinaten in einer Datenbank speichern und effizient mit dem eigenen Browser darstellen. Einige Programmierer haben schon damit begonnen, AJAX-Anwendungen mit den gezeigten und weiteren Funktionen zu entwickeln ([8], [9], [10]).
Zusätzlich kennt das API Objekte, die kleine Symbole erzeugen, die sich bei einem Klickereignis oder einem beliebig definierten Event öffnen. Sie eignen sich etwa als Tooltipp oder als Onlinehilfe, zum Beispiel zu einem Denkmal, auf das der Benutzer klickt.
Das API befindet sich allerdings noch in der Betaphase, sodass Änderungen möglich sind. Google behält sich zudem das Recht vor, auf der Seite Werbung einzublenden. Mit Ausnahme des eigenen Logos macht der Suchspezialist davon derzeit aber keinen Gebrauch. Informationen zu Weiterentwicklungen, neuen Funktionalitäten oder dem Austausch von Applikationen liefert das Diskussionsforum von Google Maps [7]. Hier lassen sich auch selbst entwickelte Anwendungen veröffentlichen, ganz im Sinne von Open Source. (mhi)
|
Listing 2: |
|---|
01 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
02 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
03 <head>
04 <title>Distanzen berechnen</title>
05 <style type="text/css">
06 v:* {
07 behavior:url(#default#VML);
08 }
09 </style>
10 <script src="http://maps.google.com/maps?file=api&v=1&key=XXXXX" type="text/javascript"></script>
11 <script type="text/javascript">
12 //<![CDATA[
13 // Punkte der Strecke (GMaker)
14 var points = new Array;
15 // Letzte gezeichnete Linie
16 var polyLine;
17 function onLoad() {
18 if (GBrowserIsCompatible()) {
19 var map = new GMap(document.getElementById("map"), [G_SATELLITE_TYPE]);
20 map.addControl(new GSmallMapControl());
21 map.addControl(new GScaleControl());
22 GEvent.addListener(map, 'moveend', function() {
23 var center = map.getCenterLatLng();
24 var latLngStr = '(' + center.y + ', ' + center.x + ')';
25 document.getElementById("latlong").innerHTML = latLngStr;
26 });
27 GEvent.addListener(map, 'click', function(overlay, point) {
28 if (overlay) {
29 removeOverlay(map, points, overlay);
30 } else if (point) {
31 addOverlay(map, points, new GMarker(point));
32 }
33 polyLine = drawLine(map, points, polyLine);
34 var distance = calcDistance(points);
35 document.getElementById("distance").innerHTML = distance + " Km"; 42. });
36
37 map.centerAndZoom(new GPoint(-4.48333, 36.66667), 4);
38 }
39
40 function drawLine(map, points, lastLine) {
41 var p = new Array();
42 for (var i = 0; i < points.length; i++) {
43 p.push(new GPoint(points[i].point.x, points[i].point.y));
44 }
45 var newLine = new GPolyline(p);
46
47 if (lastLine) {
48 map.removeOverlay(lastLine);
49 }
50 map.addOverlay(newLine);
51
52 return newLine;
53 }
54 function addOverlay(map, points, overlay) {
55 map.addOverlay(overlay);
56 points.push(overlay);
57 }
58 function removeOverlay(map, points, overlay) {
59 map.removeOverlay(overlay);
60 var oi = -1;
61 for (var i = 0; i < points.length; i++) {
62 if (points[i] == overlay) {
63 oi = i;
64 break;
65 }
66 }
67 points.splice(oi, 1);
68 }
69 function calcDistance(points) {
70 var distance = 0.0;
71 var p1 = points[0];
72 for (var i = 1; i < points.length; i++) {
73 var p2 = points[i];
74 var lat1 = p1.point.y * Math.PI / 180.0;
75 var lon1 = p1.point.x * Math.PI / 180.0;
76 var lat2 = p2.point.y * Math.PI / 180.0;
77 var lon2 = p2.point.x * Math.PI / 180.0;
78 distance += 6378.7 * Math.acos(Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1));
79 p1 = p2;
80 }
81 return distance;
82 }
83 }
84 //]]>
85 </script>
86 <body onload="onLoad()">
87 <div id="map" style="width: 500px; height: 500px"></div>
88 <div id="latlong"></div>
89 <div id="distance"></div>
90 </body>
91 </html>
|
|
Infos |
|---|
|
[1] ECMA-262: [http://www.ecma-international.org/publications/standards/Ecma-262.htm] [2] Terms of use: [http://www.google.com/apis/maps/terms.html] [3] Google-Maps-API: [http://www.google.com/apis/maps/] [4] API-Dokumentation: [http://www.google.com/apis/maps/documentation/] [5] Distanzen: [http://www.meridianworlddata.com/Distance-Calculation.asp] [6] AJAX: [http://en.wikipedia.org/wiki/AJAX] [7] Diskussionsforum: [http://groups-beta.google.com/group/Google-Maps-API] [8] Denkmäler in Paris: [http://www.kahunablog.de/gmaps.php?map=paris] [9] Wikimap: [http://www.wikyblog.com/Map/Guest/Home] [10] Verkehr in Großbritannien: [http://www.gtraffic.info] |







