Mój sposób na wyświetlanie na mapie danych w formacie GPX do tej pory polegał na uruchomieniu skryptu w PHP, który to skrypt pobierał nazwę pliku GPX, a następnie wypisywał stosowny plik HTML. W związku ze zmianą licencji przez Google, skypt przestał działać. Zmiana na OSM (Open Street Map) okazała się banalnie prosta:
<html> <head> <title>GPX view facility</title> <link rel="stylesheet" href="/leaflet/leaflet.css" /> <script src="/leaflet/leaflet.js"></script> <script src="/leaflet/gpx.js"></script> <style> #map { width: 960px; height:500px; } </style> </head> <body> <div id="map"></div> <script> var map = L.map('map',{ center: [54.4, 18.4], zoom: 11 }); L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' }).addTo(map); <? $trasa = $_GET['trasa']; if ($trasa != '') { print "var gpx = 'http://pinkaccordions.homelinux.org/Geo/gpx/$trasa.xml'"; } ?> new L.GPX(gpx, {async: true}).on('loaded', function(e) { map.fitBounds(e.target.getBounds()); }).addTo(map); </script> </body>
Żeby powyższe działało trzeba pobrać i skopiować do właściwych katalogów: leaflet oraz plugin leaflet-gpx. Że działa można sprawdzić tutaj.
Google wyświetla coś takiego kiedy oglądam mapę z ostatniego wyjazdu:
Jedna z funkcji Map Google używanych na tej stronie wkrótce się zmieni. Konieczne będzie przeniesienie zawartości niestandardowej mapy.
Klikam w Dowiedz się więcej:
Po lutym 2015 roku nie będzie już można wyświetlać niestandardowej zawartości plików KML w klasycznej wersji Map Google. KML to format pliku używany przez Google Earth do wymiany informacji geograficznych.
Dalej nie bardzo wiadomo w czym będzie problem, ale przynajmniej powiedzieli, że to już niedługo, jak przestanie działać. Jeszcze jeden klik i w końcu wiadomo o co chodzi (ale po angielsku):
From February 2015, maps created in the classic Google Maps --
https://maps.google.com/
-- will no longer load KML/KMZ files from
external websites. However, we know that KML files are a really useful
way to work with geographic data, so we've added KML to Google My
Maps, and continue to support this format with other Google Maps
APIs. We hope that one of these options will meet your needs.
A więc
google zmienił zdanie.
Kiedyś twierdził, że cyt:
KML upload and rendering has always
been problematic with Maps i że lepiej (jeżeli już), to nie importować KML tylko
wyświetlić go podając URL do
dokumentu KML jako wartość parametru q
, przykładowo:
https://mapy.google.pl/maps?q=http://pinkaccordions.homelinux.org/PLIK.kml
A teraz że wręcz przeciwnie: parametr q
w ogóle nie zadziała.
Wraz ze zmianą zdania trzeba przyznać poprawiono wsparcie dla KML w Google Maps -- teraz już nie jest problematic (sprawdziłem jest OK).
Google wreszcie ustalił, że można korzystać z Google Maps bez zakładania konta Google i podjął stosowne działania? Nieładnie.
Zatem trzeba będzie zmienić sposób w jakim są wyświetlane pliki KML na Google Maps (teraz to się nazywa zdaje się Moje Mapy/My Maps). Na szczęście nie jest tego w moim przypadku za dużo.
The nuisance of GoogleMaps is that it does not know GPX and only KML/GeoRSS files can be uploaded. Fortunately it is easy to convert GPX to KML with gpsbabel:
gpsbabel -i gpx -f file.gpx -x simplify,count=333 -o kml -F file.kml
If there are several files they have to be convert one-by-one and then upload to Google. It would be more comfortable to merge them first and upload it in one go rather than uploading each individually.
As I could not find how to merge serveral GPX files into one using gpsbabel (merge option in gpsbabel puts all track points from all tracks into a single track and sorts them by time stamp. Points with identical time stamps will be dropped) I worked out the following simple Perl script:
#!/usr/bin/perl # # Combine GPX files into one # usage: gpxmerge file1 file2 file3 .... # use XML::DOM; binmode(STDOUT, ":utf8"); my $parser = new XML::DOM::Parser; for my $file2parse (@ARGV) { my $doc = $parser->parsefile ($file2parse); for my $w ( $doc->getElementsByTagName ("wpt") ) { $waypoints .= $w->toString() . "\n"; } for my $r ( $doc->getElementsByTagName ("rte") ) { $routes .= $r->toString() . "\n"; } for my $t ( $doc->getElementsByTagName ("trk") ) { $tracks .= $t->toString() . "\n"; } } print "<?xml version='1.0' encoding='UTF-8' ?> <gpx version='1.1' creator='GPXmerger' xmlns='http://www.topografix.com/GPX/1/1' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd'>\n <author>tomasz przechlewski </author> <email>tprzechlewski[at]acm.org</email> <url>http://pinkaccordions.homelinux.org/Geo/gpx/</url>"; print "$waypoints\n$routes\n$tracks\n"; print "</gpx>\n";
The resulting file structure is as follows: first all waypoints, then all routes and finally all tracks. This is perfectly legal GPX file.
Now I convert GPX to KML using gpsbabel:
gpsbabel -i gpx -f file.gpx -x simplify,count=333 -o kml -F file.kml
Since gpsbabel generates pretty verbose KML files I simplify them using XSLT stylesheet (perhaps this step is superfluous):
xsltproc -o simplified.kml kml2kml.xsl file.kml
and the stylesheet looks like:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:kml="http://www.opengis.net/kml/2.2" > <xsl:output method="xml" indent='yes' /> <xsl:template match="/"> <!-- ;; http://www.jonmiles.co.uk/2007/07/using-xpaths-text-function/ ;; --> <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2"> <Document> <Folder> <name>Waypoints</name> <xsl:for-each select="//kml:Folder[kml:name/text()='Waypoints']/kml:Placemark//kml:Point"> <Placemark> <!-- <name><xsl:value-of select='../kml:name'/></name> --><!-- niepotrzebne --> <Point> <coordinates> <xsl:value-of select="kml:coordinates"/> </coordinates> </Point> </Placemark> </xsl:for-each> </Folder> <Folder> <name>Tracks</name> <xsl:for-each select="//kml:Placemark//kml:LineString"> <Placemark> <name>Path</name> <LineString> <tessellate>1</tessellate> <coordinates> <xsl:value-of select="kml:coordinates"/> </coordinates> </LineString> </Placemark> </xsl:for-each> </Folder> </Document> </kml> </xsl:template> </xsl:stylesheet>
Now KML file is ready to be imported to Google maps via Maps → My Places → Create map.
The result of example conversion can be be found here.
W bibliotece,
z której korzystam
do wizualizowania plików GPX na google maps,
do wyświetlenia
punktu (czyli elementu wpt
) wykorzystywana jest funkcja
GPXParser.prototype.CreateMarker
:
GPXParser.prototype.CreateMarker = function(point) { var lon = parseFloat(point.getAttribute("lon")); var lat = parseFloat(point.getAttribute("lat")); // ... ... ... var marker = new GMarker(new GLatLng(lat,lon)); // ... ... ... }
W powyższym
symbol // ... ... ...
oznacza pominięte fragmenty funkcji.
Wszystkie ikony
dla elementów wpt
są oznaczone standardową dużą czerwoną pinezką.
Ja chcę, żeby moja pinezka ,,reagowała'' na obecność elementu
type
, który według
schematu GXP, określa typ punktu.
Przykładowo miejsce odwiedzone będę oznaczał jako:
<wpt lat="54.071729" lon="18.446817"><ele/> <name>Skarszewy</name> <type>visited</type> <extensions><html>Skarszewy</html></extensions></wpt>
Tak oznaczone miejsca mają być wyróżniane za pomocą niebieskiej ikony. Pozostałe będą oznaczane czerwoną:
GPXParser.prototype.CreateMarker = function(point) { var lon = parseFloat(point.getAttribute("lon")); var lat = parseFloat(point.getAttribute("lat")); var wpType = point.getElementsByTagName("type")[0] ; // czy istnieje element type? var wpTypeTxt = "?"; if ( wpType ) { wpTypeTxt = wpType.firstChild.nodeValue; } // jeżeli tak przypisz wartość // ... ... ... // zmiana wyglądu, skopiowane z: http://kody.wig.pl/tag/gmarker/ var cIcon = new GIcon(); // Ikony do pobrania z http://sites.google.com/site/gmapicons/ // umieszczam w katalogu '/icons_/' if ( wpTypeTxt == "visited" ) { cIcon.image = '/icons_/mm_20_blue.png'; } else { cIcon.image = '/icons_/mm_20_red.png'; } cIcon.shadow = "/icons_/mm_20_shadow.png"; var marker = new GMarker(new GLatLng(lat,lon), cIcon ); cIcon.iconSize = new GSize(12, 20); cIcon.shadowSize = new GSize(22, 20); cIcon.iconAnchor = new GPoint(6, 20); cIcon.infoWindowAnchor = new GPoint(5, 1); // ... ... ... }
Wynik można obejrzeć tutaj.
Flickr2Map to usługa, dzięki której użytkownicy flickr.com mogą wyświetlić geotagowane zdjęcia m.in. na google maps. Przykład:
http://www.robogeo.com/Flickr2Map?referer=http://www.flickr.com/photos/tprzechlewski/3087054865/&type=map&view=satellite
Żeby za dużo nie musieć wpisywać, zrobiłem skrót do usługi.
Intensywne używanie http://www.gmap-pedometer.com/ spowodowało, iż dotarłem do granic możliwości Legenda, o których NB. do niedawna nie miałem pojęcia. Otóż Legend może przechować do 1000 punktów (waypoints), 20 śladów (tracks) oraz do 50 tras (routes), każda o długości do 250 punktów... Ponieważ punkty trasy liczą się do puli punktów, 5 tras 200 punktowych zawala pamięć ,,na amen''. Co zresztą niedawno miało miejsce...
Usunięcie wszystkich punktów i wszystkich tras z Garmina jest bardzo łatwe. Tyle, że chciałbym niektóre zachować... Można wprawdzie usuwać punkty według związanych z nimi symboli, ale to by wymagało porządku przy ich definiowaniu. A ja, póki co, mam w tym względzie bałagan. Zatem:
Zgrałem zawartość pamięci Garmina do pliku. Wywaliłem wszystkie trasy i ślady oraz związane z nimi punkty (są one łatwo rozpoznawalne po nic nie mówiącej nazwie typu Turn 233 albo GRTP-202). Pozostawiłem pozostałe punkty. (Wywalając trasy trzeba usunąć wszystkie, bo nie wiadomo jaki punkt należy do jakiej trasy -- tak jest szybciej i prościej.)
Wyczyściłem pamięć urządzenia. W tym celu w menu głównym należy wybrać ikonę Waypoints→przycisk menu/find→Delete. Teraz wybrać All Symbols i potwierdzić. Uwaga: przycisk menu/find jest po lewej na dole pod przyciskami góra/dół.
Załadowałem z powrotem plik GPX (nazwałem go LEGEND_MEM.gpx
):
gpsbabel -r -w -t -i gpx -f LEGEND_MEM.gpx -o garmin -F /dev/ttyUSB0
Plik LEGEND_MEM.gpx
zawiera moją bazę podstawowych punktów i tras (jeżeli takowe są)...
Resztę będę ładował w miarę potrzeby, a jak się znowu zapełni pamięć
Legenda, to powtórzę opisaną wyżej procedurę... Przy okazji 225 jako górny limit
punktów na trasie wygląda na zbyt dużo.
Spróbuję 100 punktów, wtedy zmieści się więcej tras....
Trasy z google maps zaimportowane do odbiornika GPS są do kitu...
Są zbyt proste
i bez Gmapy sprowadzają się do linii prostej, łamanej w kilku miejscach.
Dużo lepsze efekty daje
http://www.gmap-pedometer.com/.
Należy także zainstalować
bookmarklet
GMapToGPX, który
-- przynajmniej w Firefoksie -- pojawi się jako guzik na pasku
zakładek. Trasę należy wyklikać, a jak już jest gotowa
trzeba nacisnąć GMapToGPX
. W oddzielnym oknie zostanie
wyświetlony dokument GPX,
który metodą copy-paste wkleja się do pliku.
Teraz należy załadować
trasę -- w przypadku mojego Legenda HCx, gpsbabela i FC8, wygląda to następująco:
gpsbabel -r -i gpx -f plik.gpx -o garmin -x simplify,count=225 -F /dev/ttyUSB0
Ważny jest filtr -x simplify,count=225
, bo trasy muszą być krótsze od 250
punktów albo zostaną ucięte (co urządzenie zasygnalizuje
komunikatem Route Truncated). Dałem limit 225
mogłem 250... być może należy dać jeszcze mniej żeby Garmin nie piszczał non-stop.
Powyższe w praktyce sprawdziło się całkiem całkiem... Przykładowo moja trasa do Gdyni-Oksywia, naokoło przez las. (Na czerwono planowana na niebiesko zrealizowana.) W miejscu gdzie chciałem pojechać wzdłuż Estakady Kwiatkowskiego się okazało, że nie da rady (rura ciepłownicza); na GoogleMaps była tam zaznaczona ścieżka stąd takie nierealistyczne plany.
Jak nie zapiszę, to zapomnę. Już kiedyś znalazłem serwis pozwalający on-line na tworzenie tras (routes) w formacie GPX za pomocą klikania w GoogleMaps. Nie zapisałem i oczywiście nie mogłem go znaleźć przez dłuższą chwilę. W końcu jest: http://www.gmap-pedometer.com/. Moja przykładowa trasa: Brodnica-BachotekUMK. IMHO czasami może się okazać przydatne...