Pod tym adresem umieściłem moje ślady GPS (głównie rowerowe) z lat 2010--2012. W formacie KML bo to jedyny -- z tego co mi się wydaje -- obsługiwany przez Google Fusion Tables (GFT).
Moja procedura skopiowania danych z urządzenia GPS (zwykle jest to Garmin Legend) do GFT jest następująca:
Skryptem obsługującym program
gpsbabel
pobieram dane z urządzenia GPS do pliku w formacie GPX.
Skryptem kml2kml.sh
zamieniam plik GPX otrzymany w pierwszym kroku
na plik w formacie KML. Ponieważ plik ten jest ogromy (przykładowo z 60 kilowego pliku GPX
gpsbabel wygenerował plik o wielkości ponad 500 kb) zostaje on za pomocą
trywialnego arkusza XSLT zamieniony na znacznie mniejszą wersję uproszczoną:
#!/bin/bash # KMLSTYLE=~/share/xml/kml2kml.xsl # # Domyslna liczba punktow na sladzie COUNT=99 ## Domyslna nazwa Placemarka NAME=`date +%Y%m%d_%H`; while test $# -gt 0; do case "$1" in -name) shift; NAME="$1";; -name*) NAME="`echo :$1 | sed 's/^:-name//'`";; -max) shift; COUNT="$1";; -max*) COUNT="`echo :$1 | sed 's/^:-max//'`";; *) FILE="$1";; esac shift done ## Usun rozszerzenie z nazwy pliku wejsciowego OUT_FILE="${FILE%.*}" TMP_FILE=/tmp/${OUT_FILE}.kml.tmp echo "Converting $FILE to ${TMP_FILE}..." if [ -f $FILE ] ; then ## Konwersja GPX->KML gpsbabel -i gpx -f $FILE -x simplify,count=$COUNT -o kml -F $TMP_FILE else echo "*** ERROR *** File $FILE not found.... ***" ; exit fi ## Konwersja do uproszczonego KMLa (KML->KML) echo "Converting $TMP_FILE to ${OUT_FILE}.kml with maximum $COUNT points..." echo "KML' Placemark name is: $NAME..." xsltproc --stringparam FileName "$NAME" -o ${OUT_FILE}.kml $KMLSTYLE $TMP_FILE echo "Done..."
Zawartość arkusza XSLT zamieszczono na końcu tej notki.
Do interakcji z Fusion Tables wykorzystam zmodyfikowany skrypt (nazwany ftquery.sh
)
znaleziony na stronach
code.google.com:
#!/bin/bash # # Copyright 2011 Google Inc. All Rights Reserved. # Author: arl@google.com (Anno Langen) # http://code.google.com/intl/pl/apis/fusiontables/docs/samples/curl.html # -- Modified by TP -- MY_QUERY=$* function ClientLogin() { password='?1234567890?' email='looseheadprop1@gmail.com' local service=$1 curl -s -d Email=$email -d Passwd=$password -d \ service=$service https://www.google.com/accounts/ClientLogin | tr ' ' \n | grep Auth= | sed -e 's/Auth=//' } function FusionTableQuery() { local sql=$1 curl -L -s -H "Authorization: GoogleLogin auth=$(ClientLogin fusiontables)" \ --data-urlencode sql="$sql" https://www.google.com/fusiontables/api/query } FusionTableQuery "$MY_QUERY"
Teraz tworzę nową tabelę (wyklikowując co trzeba w przeglądarce) MyTracks
o następującej strukturze:
## Korzystamy z skryptu ftquery.sh ./ftquery.sh SHOW TABLES table id,name 2590817,MyTracks ## Tabela MyTracks ma zatem id=2590817 ./ftquery.sh DESCRIBE 2590817 column id,name,type col4,Date,string col0,Start,string col1,Stop,string col2,Location,location col3,Description,string
Kolumny zawierają odpowiednio: datę (Date
), czas
pierwszego
wpisu na śladzie GPX (Start
), czas ostatniego wpisu na
śladzie GPX (Stop
), ślad (Location
) oraz opis (Description
).
Kolumny Tabeli w Google Fusin Tables mogą być albo napisami (STRING
),
liczbami (NUMBER
), zawierać dane przestrzenne (LOCATION
) albo czas (DATETIME
).
Wstępne eksperymenty
z typem DATETIME
wskazują,
że jest z nim jakiś problem.
Primo
format czasu jest dość dziwaczny (np. gpsbabelowy zapis: 2012-01-07T09:19:47Z
nie jest rozpoznawany).
Także późniejsze filtrowanie w oparciu
o kolumnę DATETIME
też jakoś nie wychodzi, nawet jak zapisałem
datę w formacie YYY.MM.DD
,
który wg. dokumentacji
powinien być rozpoznawany.
Nie badając sprawy dogłębnie, zmieniłem po prostu
typ kolumn Date
, Start
, Stop
na STRING
.
Cytując za dokumentacją GFT: In a column of type LOCATION, the value can be a string containing an address, city name, country name, or latitude/longitude pair. The string can also use KML code to specify a point, line, or polygon... (cf. SQL API: Reference ). Zatem żeby wstawić linię śladu wystarczy przesłać napis zawierający współrzędne opakowane w następujący sposób:
<lineString><coordinates>lng,lat[,alt] lng,lat[,alt]...<coordinates></lineString>
Do tego służy następujący skrypt:
#!/bin/bash # STYLE=~/share/xml/gpxtimestamp.xsl MYTRACKS_TABLE_ID="2590817" GPX_FILE=$1 KML_FILE="${GPX_FILE%.*}".kml ## Ustal czas od--do sladu STARTTIME=`xsltproc --param Position '"First"' $STYLE $GPX_FILE` STOPTIME=`xsltproc --param Position '"Last"' $STYLE $GPX_FILE` DATE=`xsltproc --param Position '"First"' --param Mode '"Date"' $STYLE $GPX_FILE` if [ ! -f $GPX_FILE ] ; then echo "*** Error *** No GPX file: $GPX_FILE" ; exit ; fi if [ ! -f $KML_FILE ] ; then echo "*** Error *** No KML file: $KML_FILE" ; exit ; fi ## ## Wycinamy nastepujacym skryptem z uproszczonego pliku KML: TRACK=`perl -e 'undef $/; $t = <>; $t =~ m/(<coordinates>.*<\/coordinates>)/s; \ $t = $1; $t =~ s/[ \t\n]+/ /gm; print $t;' $KML_FILE` TRACK="<LineString>$TRACK</LineString>" ftquery.sh "INSERT INTO $MYTRACKS_TABLE_ID (Date, Start, Stop, Location, Description) VALUES ('$DATE', '$STARTTIME', '$STOPTIME', '$TRACK', '') "
I działa, tj. przesyła co trzeba na moje konto Google.
Google się chwali, że GFT radzi sobie z ogromnymi zbiorami danych. Mój ma -- na tem chwilem -- ponad 150 wierszy, a w każdym 99 punktów na śladzie, co daje łącznie approx 15,000 punktów do wykreślenia. Firefox/Opera coś tam wyświetla ale niewiele widać. Chrome radzi sobie najlepiej -- faktycznie da się to obejrzeć, przesuwać, powiększać... Wprawdzie nic z tych danych nie wynika, ale to już nie jest pytanie do Google.
Także filtr w połączeniu z mapą działa w Firefoksie i Operze tak sobie.
Wybieram zbiór tras,
np. za pomocą warunku Date < 20100901
(na tem chwilem jest to 7 wierszy)
następnie klikam Visualise Map i guzik -- nic nie widać.
Ale znowu w Chrome jest znacznie lepiej.
Dowód w postaci zrzutu ekranu obok.
Także wklejony poniżej link do mapy (pobrany
przez kliknięcie w guzik Get embeddable link) daje pozytywny wynik:
Przynajmniej w mojej wersji FF (8.0).
Zamiana pliku KML na uproszczony plik KML:
<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"/> <xsl:param name='FileName' select="'??????'"/> <xsl:template match="/"> <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2"> <Document> <Placemark> <name><xsl:value-of select="$FileName"/></name> <MultiGeometry><LineString> <tessellate>1</tessellate> <coordinates> <xsl:for-each select="//kml:Placemark//kml:LineString"> <xsl:value-of select="kml:coordinates"/> </xsl:for-each> </coordinates></LineString></MultiGeometry></Placemark> </Document></kml> </xsl:template> </xsl:stylesheet>
Wydrukowanie daty/czasu z pliku w formacie GPX:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:gpx="http://www.topografix.com/GPX/1/0"> <xsl:output method="text"/> <xsl:param name='Position' select="'First'"/> <xsl:param name='Mode' select="'Time'"/> <xsl:template match="/" > <xsl:for-each select='//*[local-name()="trkpt"]'> <xsl:choose> <xsl:when test="position()=1 and $Position='First' and $Mode='Time'"> <xsl:value-of select='substring(*[local-name()="time"], 12, 8)'/> <xsl:text> </xsl:text> </xsl:when> <xsl:when test="position()=1 and $Position='First' and $Mode='Date'"> <xsl:value-of select='translate(substring(*[local-name()="time"], 1, 10), "-", "")'/> <xsl:text> </xsl:text> </xsl:when> <xsl:when test="position()=last() and $Position='Last'"> <xsl:value-of select='substring(*[local-name()="time"], 12, 8)'/> <xsl:text> </xsl:text> </xsl:when> </xsl:choose> </xsl:for-each> </xsl:template> </xsl:stylesheet>