Diminuire il numero di punti in un tracciato KML

Tags: 

In questa guida spiegherò come semplificare un tracciato di punti in una mappa in formato KML, allo scopo di diminuire il numero di punti (togliendo del dettaglio al tracciato), e quindi ridimensionare il file KML.

Perchè? Nel mio caso ho dovuto farlo per mostrare un tracciato salvato mediante "My Tracks" su android, esportato su Google Drive. Il visualizzatore mappe di Google Drive ha un limite sulla dimensione del file KML. Se questo è troppo grande non riesce a visualizzarlo.

Non è stato semplice a dire il vero... dopo diverse ricerche ho scoperto che esiste un tool via riga di comando, chiamato GPSBabel, che permette di manipolare in vario modo mappe e tracciati geografici, e tra le varie funzioni c'è proprio quella di semplificazione dei tracciati. Il problema è che il formato KML sarebbe si supportato, ma non nella specifica usata da Google (come da manuale, qualunque standard necessita di essere usato "fuori standard" per un motivo o per l'altro... caliamo un velo...)

Qui il link: http://www.gpsbabel.org

(Ho trovato anche altri software che sulla carta dovevano fare tutto e supportavano il KML, ma o facevano pena, o facevano tutto solo nella mente dei programmatori).

Facendo altre ricerche ho trovato un piccolo script python per convertire un tracciato KML "alla Google" in un tracciato GPX standard. Lo script lo potete trovare qui:

http://timwise.blogspot.it/2014/02/converting-kml-to-gpx-with-python.html

Riporto qui lo script, leggermente modificato per arch linux:

#!/usr/bin/python2
#@see http://timwise.blogspot.it/2014/02/converting-kml-to-gpx-with-python.html
 
import argparse
import xml.sax
 
parser = argparse.ArgumentParser(description='Convert annoying google android my tracks kml data to sensible gpx files')
parser.add_argument('input_file')
 
args = parser.parse_args()
input = args.input_file
 
class KmlParser(xml.sax.ContentHandler):
        def __init__(self):
                self.in_tag=0
                self.chars=""
                self.when=""
                self.started=0
        def startElement(self, name, attrs):
                if name == "gx:coord":
                        self.in_tag=1
                        self.chars=""
                if name == "when":
                        self.in_tag=1
                        self.chars=""
                if name == "gx:Track":
                        if self.started:
                                print '</trkseg>'
                                print '<trkseg>'
        def characters(self, char):
                if self.in_tag:
                        self.chars += char
        def endElement(self, name):
                if name == "when":
                        self.in_coord=0
                        self.when = self.chars
                        self.chars=""
                if name == "gx:coord":
                        self.in_coord=0
                        self.started=1
                        coords=self.chars
                        self.chars=""
                        coords = coords.split()
                        print '\t<trkpt lat="%s" lon="%s">' % (coords[1],coords[0])
                        if len(coords)>2:
                                print '\t\t<ele>%s</ele>' % coords[2]
                        print '\t\t<time>%s</time>' % self.when
                        print "\t</trkpt>"
 
print """<?xml version="1.0" encoding="UTF-8"?>
<gpx version="1.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        creator="tim-abell kml to gpx converter - https://gist.github.com/timabell/8791116"
        xmlns="http://www.topografix.com/GPX/1/0"
        xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
<trk><trkseg>"""
 
parser = xml.sax.make_parser()
parser.setContentHandler(KmlParser())
parser.parse(open(input,"r"))
 
print """</trkseg></trk>
</gpx>
"""

Unendo lo script all'esecuzione di gpsbabel, impostato per usare il modulo "simplify" è possibile finalmente ottenere la semplificazione del file KML.

Questi i comandi per l'esecuzione su file singolo o su un gruppo di file nella dir corrente:

kml2gpx.py INPUT.kml | gpsbabel -i gpx -f - -x simplify,count=500 -o kml,track=0,points=0,line_color=900000FF -F OUTPUT.kml
 
for i in $(ls); do kml2gpx.py $i | gpsbabel -i gpx -f - -x simplify,count=500 -o kml,track=0,points=0,line_color=900000FF -F OUTDIR/$i ; done

La parte "-x simplify,count=500" indica di eseguire la semplificazione in modo da ottenere al massimo 500 punti.

Potete provare molti altri parametri per la semplificazione, l'elenco è qui:

http://www.gpsbabel.org/htmldoc-development/filter_simplify.html

L'opzione "-o kml,track=0,points=0,line_color=900000FF" indica che occorre generare in uscita un file KML con i parametri specificati (nel caso specifico inserisce la sola linea di un colore rosso trasparente). Altre possibilità qui:

http://www.gpsbabel.org/htmldoc-development/fmt_kml.html

Aggiungi un commento