BETA
Aby się zalogować, najpiew wybierz portal.
Aby się zarejestrować, najpiew wybierz portal.
Podaj słowa kluczowe
Słowa kluczowe muszą mieć co najmniej 3 sąsiadujące znaki alfanumeryczne
Pole zawiera niedozwolone znaki

Baza wiedzy











MapPoint Web Service dla początkujących

21-06-2005 11:54 | dzidol
Artykuł przedstawia podstawowy zakres użycia płatnego webserwisu Microsoftu o nazwie MapPoint. Zaprezentowane zostało generowanie i wyświetlanie map, wyszukiwanie tras pomiędzy punktami oraz lokalizacja obiektów z istniejących baz danych.

Wstęp.

Artykuł poniższy ma na celu przybliżenie czytelnikowi webserwisu MapPoint firmy Microsoft. Artykuł przeznaczony jest dla czytelnika początkującego, który chciałby dowiedzieć się, czym jest MapPoint Web Service (w dalszej części, pisząc MapPoint, będę miał na myśli MapPoint Web Service) i w jaki sposób wykorzystać jego funkcjonalność do stworzenia własnej aplikacji lub serwisu sieciowego. Artykuł nie pokazuje, jak tworzyć własne serwisy sieciowe, gdyż jest to temat całkiem odrębny.

Do artykułu dołączona jest aplikacja wyszukująca, wykorzystująca wszystkie chyba przedstawione tu funkcje, jednakże naukę lepiej zacząć od programów znajdujących się w katalogu "tutorial". Umieszczone tam zostały programiki ilustrujące kolejne przedstawiane w artykule zagadnienia. Kod programów jest skomentowany na tyle, by umożliwić czytelnikowi bezbolesne przezeń przebrnięcie.

MapPoint Web Service jest serwisem umożliwiającym dodawanie do własnych aplikacji funkcjonalności związanej z generowaniem i wyświetlaniem map, wyszukiwaniem i wizualizacją tras pomiędzy dwoma (lub więcej) zadanymi punktami, znajdowaniem znajdujących się w pobliżu zadanego punktu obiektów pewnego typu i wyszukiwaniem dróg do tych obiektów, a także innymi, podobnymi zadaniami. Obiekty mogą być obiektami już istniejącymi w bazie danych (MapPoint i NavTech), albo zostać stworzone przez użytkownika.

Przykładowe efekty użycia:


Szczypta teorii.

Poniżej przedstawiony jest zarys funkcjonalności MapPointa, ponieważ podział serwisu jest sprawą raczej nudną, a na dodatek czerpie wiele z MSDN-u, czytelnikowi chcącemu zapoznać się z bardziej przemawiającym do wyobraźni opisem, polecam przejść dalej, do części praktycznej.
Serwis MapPoint podzielony jest na 4 podserwisy. Są to CommonService, FindService, RenderService i RouteService. Funkcjonalność poszczególnych obejmuje:

CommonService: podstawowe metody MapPointa. Należą tu:
GetCountryRegionInfo -- zwraca m.in. nazwę kraju, rejonu i współrzędne geograficzne podanego obiektu;
GetDataSourceInfo -- zwraca zakres funkcjonalności i nazwę podanego źródła danych;
GetEntityTypes -- rodzaj obiektów w podanym źródle danych;
GetGreatCircleDistances -- zwraca odległości pomiędzy zadanymi punktami;
GetVersionInfo -- nazwa i numer wersji MapPointa.

FindService: to znajdowanie dowolnych obiektów w bazie danych wraz z ich lokalizacjami. Wyszukiwanie może odbywać się za pomocą rozmaitych kryteriów, jak adres, identyfikator obiektu, współrzędna geograficzna czy odległość od pewnego punktu.

RenderService: umożliwia wizualizowanie map, tras, znalezionych lokacji, znaczników na mapie (pinezek)...
GetMap -- zwraca obrazek przedstawiający mapę;
GetBestMapView -- najlepszy zakres mapy dla wyznaczonej trasy i (lub) zbioru zaznaczonych punktów cczy obiektów. Jest to mapa o największej skali, na której mieszczą się wszystkie obiekty przeznaczone do wyświetlenia;
ConvertToLatLong -- przelicza współrzędne piksela na obrazku przedstawiającym mapkę na wpółrzędne geograficzne (długość i szerokość geograficzna);
ConvertToPoint -- konwersja odwrotna do ConvertToLatLong -- współrzędne geograficzne na współrzędne obrazka.

RouteService: czyli znajdowanie tras przejazdu pomiędzy wyznaczonymi punktami. Wynik może zostać zaprezentowany na mapie, albo zostać zwrócony w postaci tekstowych wskazówek i informacji o szlaku. Posiada dwie metody, CalculateRoute (wyszukiwanie na podstawie szeregu punktów i specyfikacji) i CalculateSimpleRoute (tu wystarczą dwie współrzędne -- początku i końca trasy).

Tyle suchej teorii.

Odrobina praktyki.

Praktykę najlepiej przygotować kilka dni wcześniej... Należy zacząć od przejrzenia strony http://www.microsoft.com/mappoint/webservice -- intesujące są tam dwa odnośniki -- stworzenie 45-dniowego konta dostępowego do webserwisu i pobranie SDK. Stworzenie konta (wymaga podania dowolnych danych osobowych i ważnego adresu e-majl) jest procesem niezbędnym, gdyż zapewnia ono dostęp do serwisu MapPoint. Wg informacji na formularzu czas aktywacji konta wynosi maksymalnie 2 dni, w praktyce... Oczekiwanie na e-majl zwrotny zajęło tydzień. Potem tylko kilka zmian haseł, logowanie z jednej strony na drugą, następnie trzecią i kolejne hasło -- a, nie -- jeszcze zmiana przeglądarki... Cóż, Microsoft ufa tylko własnym przeglądarkom, Mozilla wpuszczana jest tylko na wybrane stronki... I tak, po tygodniu oczekiwań, później czasie spędzonym na surfowaniu od strony do strony, jesteśmy szczęśliwymi posiadaczami loginu i hasła. W sumie -- nie ma jak prosta procedura rejestracyjna...

Dla szczęśliwych posiadaczy 3 loginów i haseł, mała wskazówka. W wersji trialowej, login potrzebny do działania aplikacji, to ten składający się 6 cyfr, bez imienia ani nazwiska.

Po uzyskaniu danych dostępowych i zainstalowaniu SDK (to akurat przychodzi już bezproblemowo), możemy przejść do tworzenia aplikacji.

Pierwszym krokiem, po stworzeniu szkieletu, jest dodanie referencji do specyfikacji webserwisu. W Solution Explorerze dodajemy do projektu WebReference, jako url podajemy http://staging.mappoint.net/standard-30/mappoint.wsdl. W zaprezentowanych przykładach, referencja została nazwana "MapPoint".


Pierwsza aplikacja ("mapka1"), ma za zadanie wyświetlić mapę okolic Częstochowy. Zakładamy, że zaimportowano przestrzenie nazw System.Net i mapka1.MapPoint.

Garść deklaracji:

[Kod C#]

// tu będzie przechowywana mapka
MapImage currentMapImage;
// zawiera metody do odpytywania serwisu generowania map
RenderServiceSoap renderService = new RenderServiceSoap();


Następnie, należy się zalogować do serwisu. Tworzymy wierzytelność i przydzielamy ją wykorzystywanym serwisom.

[Kod C#]

NetworkCredential myCredentials = new NetworkCredential("userID", "passwd");

// przydzielenie wierzytelnosci dla serwisow
renderService.Credentials = myCredentials;
renderService.PreAuthenticate = true;


Teraz trzeba ustalić, jakie opcje mają zostać zastosowane do generacji mapki. Służy do tego klasa MapOptions. Ustawić możemy wielkość obrazka (pole Format typu ImageFormat), rozmiar fontów (FontSize typu MapFontSize), rodzaj mapy (Style typu MapStyle) i inne parametry.

[Kod C#]

// wielkość dopasowana do obrazka na formie
ImageFormat myImageFormat = new ImageFormat();
myImageFormat.Width = pictureBox1.Size.Width;
myImageFormat.Height = pictureBox1.Size.Height;
 
MapOptions myMapOptions = new MapOptions();
myMapOptions.Format = myImageFormat;


Kolejną sprawą jest ustalenie obszaru, który chcemy zwizualizować, czyli MapView. MapView jest klasą abstrakcyjną, posiadającą m.in. następujące specjalizacje:
ViewByBoundingRectangle -- obszar ustalamy podając prostokąt, który musi zostać wyświetlony;
ViewByScale -- punkt środkowy i skala mapy;
ViewByHeightWidth -- punkt środkowy i wielkość obrzaru do wizualizacji.

[Kod C#]

// współrzędne geograficzne centrum wyświetlanej mapy
LatLong myLatLong = new LatLong();
myLatLong.Latitude = 50.8119560660701;
myLatLong.Longitude = 19.1211504399438;

ViewByHeightWidth[] myMapViews = new ViewByHeightWidth[1];
myMapViews[0] = new  ViewByHeightWidth();
// srodek
myMapView.CenterPoint = myLatLong;
// rozmiar wizualizowanego prostokata
// w kilometrach
myMapView.Height = 300;
myMapView.Width = 400;


Zebranie wszystkiego razem i wywołanie (zdalnej) procedury generowania mapki:

[Kod C#]

// specyfikacja żądania
MapSpecification mapSpec = new MapSpecification();

// wyżej ustalone dane
mapSpec.Views = myMapViews;
mapSpec.Options = myMapOptions;
// skąd pobierać dane dla mapy
mapSpec.DataSourceName = "MapPoint.EU";

// właściwe pobranie obrazka
MapImage[] myMapImages = renderService.GetMap(mapSpec);
// i wyświetlenie go na formie
pictureBox1.Image = new Bitmap(new System.IO.MemoryStream(myMapImages[0].MimeData.Bits));


Uff... Jest obrazek, tylko taki... Nieruchawy... po dodaniu guziczków do przewijania i suwaka powiększenia, okienko aplikacji wygląda tak:


Jest suwak, więc należy go użyć. Wywołanie powiększenia może wyglądac następująco:

[Kod C#]

double zoomFactor = 0.5F; // dwukrotne powiększenie.
mapSpec.Options.Zoom = zoomFactor;
MapImage[] myMapImages = renderService.GetMap(mapSpec);
pictureBox1.Image = new Bitmap(new System.IO.MemoryStream(myMapImages[0].MimeData.Bits));


Powiązanie tego z suwakiem nie powinno nikomu sprawiać trudności. Przesuwanie mapy odbywać się może przez zmianę jej środka na punkt znajdujący się w połowie drogi między obecnym centrum, a krawędzią, w której kierunku przesuwamy, co jest pretekstem do zaprezentowania funkcji ConvertToLatLong. Przykładowe przesunięcie:

[Kod C#]

MapImage myMapImage = currentMapImage;

// wspolrzedne piksela na obrazku
PixelCoord[] myPixelCoords = new PixelCoord[1];
myPixelCoords[0] = new PixelCoord();

myPixelCoords[0].X = pictureBox1.Size.Width / 4;
myPixelCoords[0].Y = pictureBox1.Size.Height / 2;

// Zwraca współrzędne geogr. punktu pobranego z obrazka
LatLong[] myLatLongs = renderService.ConvertToLatLong(myPixelCoords, myMapImage.View.ByHeightWidth, pictureBox1.Size.Width, pictureBox1.Size.Height);

MapImage[] myMapImages = renderService.GetMap(mapSpec);
pictureBox1.Image = new Bitmap(new System.IO.MemoryStream(myMapImages[0].MimeData.Bits));


Kolejna aplikacja (mapka3, mapka5) pokazuje przykład wyszukania trasy z Paryża do Grenoble. Dlaczego? Do Paryża latają tanie samoloty, a w Grenoble i uczelnia przyzwoita (pozdrowienie dla INPG!), i górki niedaleko...

[Kod C#]

// ----- przydzielenie wierzytelnosci dla serwisow
routeService.Credentials =  = new NetworkCredential(uzyszkodnik, haslo);
routeService.PreAuthenticate = true;

// Wspolrzedne punktu poczatkowego i docelowego
LatLong[] latLongs = new LatLong[2];
// Paryz
latLongs[0] = new LatLong();
latLongs[0].Latitude = 48.8569441897482;
latLongs[0].Longitude =  2.34125843355591;
// Grenoble
latLongs[1] = new LatLong();
latLongs[1].Latitude = 45.1940059454241;
latLongs[1].Longitude = 5.73204928450467;

// wyznaczanie trasy
Route myRoute;
myRoute = routeService.CalculateSimpleRoute(latLongs, "MapPoint.EU", SegmentPreference.Quickest);


Wyniki można przedstawić w postaci tekstowej:

[Kod C#]

// wskazówki, jak dojechać
for(int i = 0; i < myRoute.Itinerary.Segments[0].Directions.Length ; i++) {
   textBox1.AppendText(myRoute.Itinerary.Segments[0].Directions[i].Instruction);
   textBox1.AppendText(System.Environment.NewLine);
}
textBox1.AppendText(System.Environment.NewLine);
// długość trasy
textBox1.AppendText("Distance: ");
textBox1.AppendText((myRoute.Itinerary.Segments[0].Distance).ToString());
textBox1.AppendText(" km");
textBox1.AppendText(System.Environment.NewLine);
// czas podróży
// może obejmujować czas spędzony na np. podróż promem itd;
// "czysty" czas jazdy: DrivingTime
textBox1.AppendText("Trip time: ");
textBox1.AppendText((myRoute.Itinerary.Segments[0].TripTime / (60 * 60)).ToString());
textBox1.AppendText(" h");


Wynik:

  Depart Start on Pont Neuf [Place du Pont-Neuf] (North)
  Turn RIGHT (East) onto Quai de la Megisserie
  Merge onto Place du Chatelet [Quai de la Megisserie]
  Keep STRAIGHT onto Quai de Gesvres
  Turn RIGHT (South) onto Pont Notre-Dame
  Road name changes to Rue de la Cite
  Road name changes to Petit Pont...

Domyślnie wskazówki wyświetlane są w języku angielskim, ale nie jest problemem zmiana na inny język, ze zbioru dostępnych.

[Kod C#]

CultureInfo myCultureInfo = new CultureInfo();
myCultureInfo.Name = "fr";
UserInfoRouteHeader myUserInfoRouteHeader = new UserInfoRouteHeader();
myUserInfoRouteHeader.Culture = myCultureInfo;
routeService.UserInfoRouteHeaderValue = myUserInfoRouteHeader;
myRoute = routeService.CalculateSimpleRoute(latLongs, "MapPoint.EU", SegmentPreference.Quickest);


I teraz, wskazówki wyglądają tak (wycięte akcenty):

  Depart de Debut sur Pont Neuf [Place du Pont-Neuf] (nord)
  Tourner a DROITE (est), prendre Quai de la Megisserie
  Deboucher sur Place du Chatelet [Quai de la Megisserie]
  Continuer TOUT DROIT sur Quai de Gesvres
  Tourner a DROITE (sud), prendre Pont Notre-Dame
  Le nom de la route devient Rue de la Cite
  Le nom de la route devient Petit Pont...

Wizualizacja trasy może zostać zrealizowana tak:

[Kod C#]

// zostało zrealizowane:
// myRoute = routeService.CalculateSimpleRoute(latLongs, "MapPoint.EU", SegmentPreference.Quickest);
// wyświetlanie wskazówek można pominąć.

// pobierz mapę opisującą znalezioną trasę
ViewByHeightWidth[] myRouteView = new ViewByHeightWidth[1];
myRouteView[0] = myRoute.Itinerary.View.ByHeightWidth;

// zdefiniuj mapę -- tym razem obszar do wyrysowania
// wyznaczony jest położeniem wyszukanej trasy
// oraz (ewentualnie) zoomem.
MapSpecification mapSpec  = new MapSpecification();
mapSpec.DataSourceName = "MapPoint.EU";
mapSpec.Route = myRoute;
mapSpec.Views = myRouteView;
mapSpec.Options = myMapOptions;

// generuj mapkę
MapImage[] myMaps = renderService.GetMap(mapSpec);
pictureBox1.Image = new Bitmap(new System.IO.MemoryStream(myMaps[0].MimeData.Bits));


Efekt?

Aplikacja mapka7 przedstawia przykład użycia serwisu Find. Wyszukanie Grenoble wygląda następująco:

[Kod C#]

// jak zawsze -- uwierzytenienie
findService.Credentials = credential;
findService.PreAuthenticate = true;

// specyfikacja zapytania:
// znajdź Grenoble w bazie MapPoint.EU
FindSpecification findSpec  = new FindSpecification();
findSpec.DataSourceName = "MapPoint.EU";
findSpec.InputPlace = "Grenoble";

// wywołanie zapytania
FindResults foundResults;
foundResults = findService.Find(findSpec);

// pobranie pierwszego wyniku ze zbioru odpowiedzi
LatLong coord = foundResults.Results[0].FoundLocation.LatLong;


Możliwa jest operacja odwrotna -- uzyskanie informacji, co znajduje się we wskazanym miejscu:

[Kod C#]

Location[] returnedLocations;
returnedLocations = findService.GetLocationInfo(coord, "MapPoint.EU", null);

for(int i = 0; i < returnedLocations.Length; i++) {
   textBox1.AppendText(returnedLocations[i].Entity.DisplayName);
   textBox1.AppendText(System.Environment.NewLine);
}


Znalezienie obiektu dowolnego typu w (określonym) otoczeniu punktu:

[Kod C#]

FindNearbySpecification findNearbySpec  = new FindNearbySpecification();
findNearbySpec.DataSourceName = "NavTech.EU";

// otoczenie w km
findService.UserInfoFindHeaderValue = new UserInfoFindHeader();
findService.UserInfoFindHeaderValue.DefaultDistanceUnit = DistanceUnit.Kilometer;

// w promieniu 5 km (bo dalej isc sie nie chce,
// a tramwajarze akurat strajkuja (Francja!)...
findNearbySpec.Distance = 5;
// od naszej lokalizacji...
findNearbySpec.LatLong = coord;
// szukaj kin -- TypeName trzeba znaleźć w dokumentacji
findNearbySpec.Filter = new FindFilter();
findNearbySpec.Filter.EntityTypeName = "SIC7832";

foundResults = findService.FindNearby(findNearbySpec);

// wyswietl kina
textBox2.AppendText("Znalezione kina:");
textBox2.AppendText(System.Environment.NewLine);
foreach(FindResult fr in foundResults.Results) {
   textBox2.AppendText(fr.FoundLocation.Address.AddressLine + ": " + fr.FoundLocation.Entity.Name);
   textBox2.AppendText(System.Environment.NewLine);
}


Znalezione wyniki można zwizualizować. Kod aplikacji, pokazuje wyszukane... Hmm... Ciekawi sprawdzą sami ;)

Mapa zwracana jest jako URL obrazka na zdalnym serwerze -- co jest przydatne podczas tworzenie własnych webserwisów. Obrazek pozostaje na serwerze ok. 5 minut, co jest czasem wystarczającym na wczytanie go przez przeglądarkę.

[Kod C#]

// tworzenie pinezek
Pushpin[] myPushpins = new Pushpin[foundResults.Results.Length];
for (int i = 0; i < foundResults.Results.Length; ++i) {
   myPushpins[i] = new Pushpin();
   myPushpins[i].IconDataSource = "MapPoint.Icons";
   myPushpins[i].IconName = i.ToString();
   myPushpins[i].LatLong = foundResults.Results[i].FoundLocation.LatLong;
   myPushpins[i].Label = foundResults.Results[i].FoundLocation.Entity.DisplayName;
   myPushpins[i].ReturnsHotArea = false;
}

mapSpec.DataSourceName = "MapPoint.NA";
mapSpec.Pushpins = myPushpins;
mapSpec.Options.Style = MapStyle.Terrain;

// pobierz mapę w postaci URL-a
mapSpec.Options.ReturnType = MapReturnType.ReturnUrl;

mapImages = renderService.GetMap(mapSpec);
textBox1.AppendText(mapImages[0].Url);


Podsumowanie.

Powyższy artykuł miał pokazać, jak stworzyć prostą aplikację wykorzystując MapPoint Web Service. Przeznaczony jest dla osób nie znających owego webserwisu. Trudniejsze zagadnienia, jak wstawianie np. własnych danych czy zaawansowane wyszukiwanie, integracja ze środowiskiem nie .NETowym (Java lub standardowe, przenośne C++) -- są tematami na dalsze artykuły, jeśli będzie na takowe zapotrzebowanie.
MapPoint Web Serwice jest przyzwoitym narzędziem, ilość zgromadzonych obiektów typu sklepy, placówki kulturalne czy nawet epicentra trzęsień ziemi jest powalająca. Niestety, jak każde, także i to narzędzie ma swoje wady. Najpoważniejszą jest brak danych dla Polski -- nie działa nawet wyszukiwanie dróg pomiędzy miastami. Brakuje także polskiej lokalizacji. Ogranicza to poważnie pole zastosowań na rodzimym rynku. Choć do przedstawienia sklepów w najbliższej lokalizacji klienta (z dokładnością co do miejscowości) z pewnością ta usługa będzie przydatna. Stwarza także pole do popisu osobom, które pracują poza Polską -- szczególnie w Ameryce Północnej.

Załączniki:

tagi: web

Komentarze 2

dzidol
dzidol
2 pkt.
Nowicjusz
21-01-2010
oceń pozytywnie 0
W artykule jest kilka błędów -- brak przyimka "z", literówka, z której wyszedł ortograf (jeden z "obszarów" stał się "obrzarem"), brakuje kilku enterków i formatowania długich linii kodu. Te dwa pierwsze, z przeoczenia (brak też opcji edit -- a przydałaby się bardzo), zaś formatowanie -- cóż... Pięć razy mnie serwis wyrzucał albo gubił dane, przy szóstym podejściu miałem troszeczkę już mniej entuzjazmu...
dzidol
dzidol
2 pkt.
Nowicjusz
21-01-2010
oceń pozytywnie 0
Koledzy zwrócili mi uwagę, że nie wspominam w artykule o konieczności zmiany wartości "userId" i "passwd" w plikach .config (ew. w samym kodzie) na te uzyskane w procesie rejestracji... Po zmianie parametrów na poprawne, program połączy się poprawnie z serwisem (czyli nie pojawi się "Error 401...").
Za pominięcie przepraszam. Jeśli są jeszcze jakieś niejasności -- proszę o komentarz...
pkt.

Zaloguj się lub Zarejestruj się aby wykonać tę czynność.