Laboratorium Systemów Informacji Przestrzennej Korzystanie z zewnętrznych usług geokodowania i nawigacji w środowisku OpenLayers ZADANIA DO WYKONANIA: 1. W oparciu o dostępny kod źródłowy stworzyć funkcję addmarker. 0,5 pkt. 2. Dodać kod obsługi kliknięcia na mapie. 0,5 pkt. 3. Zaimplementować funkcję getlocationdata i z jej wykorzystaniem dodawać markery do mapy. 1,5 pkt. 4. Zaimplementować funkcję getroutepolyline i z jej wykorzystaniem tworzyć trasę przejazdu pomiędzy dwoma stworzonymi markerami. 2,5 pkt. WSKAZÓWKI: Biblioteka OpenLayers jest darmowym narzędziem pozwalającym na tworzenie sieciowych systemów informacji przestrzennej które pod względem funkcjonalności mogą rywalizować np. z Google Maps. Ponieważ biblioteka ta jest rozwiązaniem typu Open Source, możliwe jest rozszerzanie jej istniejących możliwości o nowe elementy jak również całkowita zmiana sposobu jej działania. W ramach niniejszego ćwiczenia zapoznamy się z możliwościami współpracy pomiędzy OpenLayers a usługami geokodowania oraz nawigacji udostępnianymi przez firmę Google. Z podanego przez prowadzącego adresu należy pobrać plik BaseOpenLayersMap.html i zapisać w nowym katalogu na dysku, a następnie otworzyć np. w Notatniku. Domyślnie mapa ta zawiera dwie warstwy, OpenStreetMap i Google Streets, oraz marker umieszczony w okolicach Krakowa. Pierwszym istotnym elementem kodu jest lista importowanych skryptów, znajdująca się zaraz za znacznikiem </title>. Ponieważ OpenLayers jest biblioteką języka Javascript, można w stosunkowo łatwy sposób integrować ją z innymi bibliotekami w tym języku poprzez zaimportowanie odpowiedniego skryptu (kod tego ćwiczenia importuje skrypt Google Maps API). Kolejnymi elementami skryptu strony są deklaracje zmiennych globalnych. Zmienna map reprezentuje obiekt mapy, zmienne mercator i geographic symbolizują wykorzystywane w programie układy współrzędnych, zmienna directionsservice zawiera referencję na usługę Google Directions, markers reprezentuje obiekt warstwy markerów, zaś pozostałe zmienne można wykorzystać podczas realizacji niniejszego ćwiczenia. Tablica line_style zawiera definicję stylu, jakim będą rysowane trasy w dalszej części ćwiczenia. Za utworzenie mapy oraz elementów interfejsu użytkownika w OpenLayers odpowiada funkcja init(). Konstruktor OpenLayers.Map( 'map', options ) tworzy nowy obiekt typu Map wewnątrz podanego kontenera HTML (w tym przypadku obiektu div o nazwie map) i z wykorzystaniem ustawień zawartych w tabeli options. Metody addlayer i addlayers służą do dodawania warstw do mapy (odpowiednio: pojedynczej warstwy oraz listy warstw), addcontrol służy do dodawania narzędzi i kontrolek, zaś metoda map.setcenter(new OpenLayers.LonLat(lon, lat), zoom) powoduje wycentrowanie utworzonej mapy na punkcie o podanych współrzędnych 1
geograficznych (lon,lat), oraz odpowiednio przybliża obraz (w tym wypadku jest to 5 poziom przybliżenia obrazu). Pomiędzy liniami "// Marker:" a "// End Marker" znajduje się kod tworzący na mapie marker. Na jego podstawie należy stworzyć funkcję addmarker(lonlat, popupcontenthtml) która po pobraniu parametrów (w postaci współrzędnych punktu podanych w układzie Mercatora oraz tekstu mającego pojawić się w dymku) stworzy nowy marker i doda go do mapy. następnie należy usunąć kod tworzenia markera z funkcji init() i odkomentować linię pod segmentem "// End Marker", która stanowi przykład wykorzystania nowo stworzonej funkcji. Następnie poniżej kodu funkcji addmarker należy umieścić kod narzędzia obsługującego wydarzenie kliknięcia przez użytkownika na mapie: OpenLayers.Control.Click = OpenLayers.Class(OpenLayers.Control, defaulthandleroptions: 'single': true, 'double': false, 'pixeltolerance': 0, 'stopsingle': false, 'stopdouble': false, initialize: function(options) this.handleroptions = OpenLayers.Util.extend(, this.defaulthandleroptions OpenLayers.Control.prototype.initialize.apply( this, arguments, this.handler = new OpenLayers.Handler.Click( this, 'click': this.trigger, this.handleroptions trigger: function(e) var lonlat = map.getlonlatfromviewportpx(e.xy numclicks++; alert("kliknąłeś "+numclicks+" razy" następnie należy w ciele funkcji init() (pod wołaniem metody addmarker) utworzyć nowy obiekt kontrolki OpenLayers.Control.Click, dodać go do mapy oraz aktywować. Pod ciałem klasy OpenLayers.Control.Click należy dodać funkcję 2
getlocationdata, wykorzystującą usługę geokodującą Google w celu pobrania fizycznego adresu (w postaci ulica, miasto, kraj ) punktu wskazanego kliknięciem przez użytkownika. Usługa gekodująca Google korzysta ze współrzędnych w postaci długości oraz szerokości geograficznej, które mają być przekazywane do funkcji getlocationdata w postaci zmiennych glon i glat. function getlocationdata(glon, glat) geocoder = new google.maps.geocoder( latlng = new google.maps.latlng(glat, glon, true geocoder.geocode('latlng': latlng, function(results, status) if (status == google.maps.geocoderstatus.ok) /* Obsługa */ else alert('geocode failure because of ' + status W miejscu wskazanym przez komentarz /* Obsługa */ należy wydobyć z obiektu results adres wskazanego kliknięciem punktu. Pełen adres znajduje się w obiekcie results[1].formatted_address. Po jego wydobyciu należy dodać do mapy nowy marker który będzie wskazywał klikniętą lokalizację i podawał jej dokładny adres. W ciele kontrolki obsługi kliknięcia (funkcja trigger) zamiast alert("kliknąłeś "+numclicks+"razy") należy wstawić odwołanie do funkcji getlocationdata(lonlat.lon, lonlat.lat). Należy zwrócić uwagę, że usługa gekodująca Google korzysta ze współrzędnych geograficznych, zaś funkcja getlonlatfromviewportpx zwraca współrzędne Mercatora. Z tego powodu przed przekazaniem współrzędnych należy dokonać ich transformacji (np. przy pomocy metody transform obiektu lonlat). Po wykonaniu powyższych czynności na mapie powinien już działać mechanizm geokodowania, sprawiając że po kliknięciu na mapę w wybranym punkcie pojawiać się tam będzie marker podający pełen adres wskazanej lokalizacji. Aby zrealizować mechanizm wyszukiwania i wskazywania tras pomiędzy wybranymi punktami, w pierwszej kolejności należy umożliwić rysowanie na mapie polilinii. W tym celu należy w ciele funkcji init() stworzyć nową warstwę wektorową o nazwie Routes (konstruktor OpenLayers.Layer.Vector("nazwa")) i dodać ją do mapy. Ważne: należy zwrócić uwagę, aby warstwę wektorową dodać do mapy PRZED warstwą markerów (tak, aby warstwa markerów była ostatnią w kolejności warstwę dodaną do mapy). Następnie należy zaimplementować obsługę połączenia z serwisem nawigacyjnym Google i 3
w odpowiedni sposób przetworzyć otrzymane wyniki. W tym celu należy zaimplementować funkcję getroutepolyline, której celem będzie rysowanie na mapie polilinii wskazującej znalezioną przez usługę Google trasę pomiędzy dwoma podanymi punktami. function getroutepolyline(result) var pointlist = []; var vectorlayer=map.getlayersbyname("routes")[0]; vectorlayer.removeallfeatures( /* Konstrukcja polilinii */ linefeature = new OpenLayers.Feature.Vector( new OpenLayers.Geometry.LineString(pointList), null, line_style vectorlayer.addfeatures(linefeature Funkcja getroutepolyline będzie wołana po odebraniu przez aplikację odpowiedzi na zapytanie wysłane do usługi nawigacyjnej Google. W miejscu komentarza /* Konstrukcja polilinii */ należy z obiektu result (reprezentującego trasę odebraną z serwisu Google) pobrać znaleziona polilinię. Znajduje się ona w obiekcie result.routes[0].legs[0].steps (routes[0] zawiera najkrótszą trasę; w pozostałych komórkach tabeli można znaleźć trasy alternatywne). Pobraną polilinię należy zapisać do nowego obiektu, po czym należy w pętli pobrać jej elementy i stworzyć z nich nową linię wektorową. Ilość wierzchołków polilinii (rozmiar tablicy steps) można uzyskać poprzez pole length obiektu steps. Współrzędne każdego wierzchołka polilinii znajdują się w jego polu end_point. W celu utworzenia nowej linii pobrane punkty należy zapisać w tablicy pointlist (np. przy pomocy metody push). Należy pamiętać iż z powodu niekompatybilności obiektów wykorzystywanych przez API Google Maps oraz OpenLayers, z punktów Google należy pobrać współrzędne (zwracane przez metody lng() i lat() punktu), na ich podstawie stworzyć nowy obiekt typu OpenLayers.Geometry.Point i dokonać jego transformacji do układu współrzędnych Mercatora. Po zaimplementowaniu funkcji getroutepolyline należy powiązać ją z obsługą wyników otrzymanych z serwisu nawigacyjnego Google. W tym celu należy rozszerzyć zakres działania funkcji getlocationdata. Mianowicie, zamiast kodu dodającego marker w miejscu kliknięcia należy wstawić następujący segment: if (numclicks==1) /* Marker startowy */ else if (numclicks==2) /* Marker końcowy */ numclicks=0; else numclicks=0; 4
W miejscu komentarza /* Marker startowy */ należy umieścić kod czyszczący warstwę markerów, np. z wykorzystaniem jej metody clearmarkers(). Następnie należy do obiektu fromaddress przypisać adres wskazanego kursorem punktu i dodać do mapy nowy marker wskazujący tę pozycję oraz podający jej adres i informujący iż jest to początek trasy. W miejscu komentarza /* Marker końcowy */ należy do obiektu toaddress przypisać adres wskazanego kursorem punktu i dodać do mapy nowy marker wskazujący tę pozycję oraz podający jej adres i informujący iż jest to koniec trasy. Następnie należy wywołać metodę route obiektu directionsservice, jako pierwszy parametr podając następujący obiekt: var request = ; origin: fromaddress, destination: toaddress,, zaś jako drugi parametr następującą funkcję: travelmode: google.maps.travelmode.driving function(response, status) if (status == google.maps.directionsstatus.ok) getroutepolyline(response Po wykonaniu powyższych czynności aplikacja powinna wyszukiwać i rysować trasę pomiędzy dwoma zadanymi markerami na mapie. 5