#!/usr/bin/python # # convert gpspoint files to GPX # # TODO: finish symbol normalization # TODO: more complete conversion of fields # import os import sys import re import string import time class Metadata: inputFilename = None outputFilename = None inputFile = None outputFile = None creator = "gp2gpx" normalize = 1 #========================================================================= # UnixToIso8601 #========================================================================= def UnixToIso8601(unixtime): return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(unixtime)) #========================================================================= # Usage #========================================================================= def Usage(): sys.stderr.write("gp2gpx [gp_file] [-o gpx_file] [-c creator] [-n]\n\n") sys.stderr.write(" -o output file name\n") sys.stderr.write(" -n do not normalize waypoint symbols\n") sys.exit(1) #========================================================================= # ParseCommandLine #========================================================================= def ParseCommandline(md): sys.argv.pop(0) # throw away the script name while len(sys.argv) > 0: if sys.argv[0] == "-h" or sys.argv[0] == "-?" or \ sys.argv[0] == "--help" or sys.argv[0] == "-H": Usage() elif sys.argv[0] == "-o": if len(sys.argv) == 1: Usage() sys.argv.pop(0) md.outputFilename = sys.argv[0] elif sys.argv[0] == "-c": if len(sys.argv) == 1: Usage() sys.argv.pop(0) md.creator = sys.argv[0] elif sys.argv[0] == "-n": md.normalize = 0 else: if md.inputFilename == None: md.inputFilename = sys.argv[0] else: Usage() sys.argv.pop(0) if md.inputFilename == None: md.inputFilename = "-" if md.outputFilename == None: md.outputFilename = "-" return md #========================================================================= # OpenFiles #========================================================================= def OpenFiles(md): if md.inputFilename == None or md.inputFilename == "-": md.inputFile = sys.stdin else: try: md.inputFile = open(md.inputFilename, "r") except IOError, (errno, strerror): sys.stderr.write("gp2gpx: %s: %s\n" % (md.inputFilename, strerror)) sys.exit(2) if md.outputFilename == None or md.outputFilename == "-": md.outputFile = sys.stdout else: try: md.outputFile = open(md.outputFilename, "w") except IOError, (errno, strerror): sys.stderr.write("gp2gpx: %s: %s\n" % (md.outputFilename, strerror)) sys.exit(3) #========================================================================= # FindGPField #========================================================================= def FindGPField(field, str): r = re.match((".*%s=\"([^\"]*)\"" % field), str); if r != None: val = r.group(1) else: val = None return val #========================================================================= # NormalizeSymbol #========================================================================= def NormalizeSymbol(sym): if sym == "wpt_dot": return "Dot" elif sym == "amuse_pk": return "Amusement Park" elif sym == "ball": return "Ball Park" elif sym == "dollar": return "Bank" elif sym == "mug": return "Bar" elif sym == "camp": return "Campground" elif sym == "lrg_cty": return "Large City" elif sym == "med_cty": return "Medium City" elif sym == "sml_cty": return "Small City" elif sym == "gas_plus": return "Convenience Store" elif sym == "skull": return "Danger Area" elif sym == "danger": return "Dangerous Area" elif sym == "store": return "Department Store" elif sym == "drinking_wtr": return "Drinking Water" elif sym == "fastfood": return "Fast Food" elif sym == "fish": return "Fishing Area" elif sym == "fitness": return "Fitness Center" elif sym == "fuel": return "Gas Station" elif sym == "glider": return "Glider Area" else: sym2 = sym sym2 = string.upper(sym2[0]) + sym2[1:] re.sub("_", " ", sym2) i = str.find(sym2, " ", 0) while i != -1: sym2 = sym2[0:i+1] + str.upper(sym2[i+1]) + sym2[i+2:] i = str.find(s, " ", i+1) return sym2 #========================================================================= # WriteGPXHeader #========================================================================= def WriteGPXHeader(md): fout = md.outputFile fout.write("\n") fout.write("\n\n" % (md.creator)) #========================================================================= # WriteGPXFooter #========================================================================= def WriteGPXFooter(md): fout = md.outputFile fout.write("\n\n") #========================================================================= # WriteGPXBody #========================================================================= def WriteGPXBody(md): # modes: # 0 - nostate # 1 - processing waypoint # 2 - processing routes lineNum = 0 mode = 0 trackname = "" fin = md.inputFile fout = md.outputFile for line in fin: lineNum += 1 type = FindGPField("type", line); if type == None: continue if mode == 0: if type == "waypointlist": mode = 1 elif type == "track": trackname = FindGPField("name", line) startedNewTrack = True insegment = False if trackname == None: trackname = "track" fout.write("\n") fout.write(" %s\n" % trackname) #sys.stderr.write("gp2gpx: warning: tracks not implemented yet--ignoring\n") mode = 2 else: sys.stderr.write("%s: unexpected type \"%s\" (line %d)\n" % (md.inputFilename, type, lineNum)) sys.exit(4) elif mode == 1: if type == "waypoint": lat = FindGPField("latitude", line) lon = FindGPField("longitude", line) name = FindGPField("name", line) sym = FindGPField("symbol", line) ele = FindGPField("altitude", line) if sym != None and md.normalize: sym = NormalizeSymbol(sym) if lat == None or lon == None: sys.stderr.write("%s: missing latitude or longitude (line %d)\n" % (md.inputFilename, lineNum)) sys.exit(4) lat = lat.strip() lon = lon.strip() fout.write("\n\n"); if name != None: fout.write(" %s\n" % (name)) if sym != None: fout.write(" %s\n" % (sym)) if ele != None: fout.write(" %s\n" % (ele)) fout.write("\n") else: fout.write("/>\n") elif type == "waypointlistend": mode = 0 else: sys.stderr.write("%s: unexpected type \"%s\" (line %d)\n" % (md.inputFilename, type, lineNum)) sys.exit(4) elif mode == 2: if type == "trackpoint": lat = FindGPField("latitude", line) lon = FindGPField("longitude", line) ele = FindGPField("altitude", line) unixtime = FindGPField("unixtime", line) newsegment = FindGPField("newsegment", line) if newsegment == "yes" or startedNewTrack: if insegment: fout.write(" \n") insegment = True fout.write(" \n") startedNewTrack = False if not insegment: sys.stderr.write("%s: warning: ignoring track data outside segment (line %d)\n" % (md.inputFilename, lineNum)) continue if lat == None or lon == None: sys.stderr.write("%s: missing latitude or longitude (line %d)\n" % (md.inputFilename, lineNum)) sys.exit(4) lat = lat.strip() lon = lon.strip() if ele == None: ele = "0" fout.write(" \n" % (lat, lon)) fout.write(" %s\n" % (ele)) if unixtime != None: fout.write(" \n" % (UnixToIso8601(float(unixtime)))) fout.write(" \n") elif type == "trackend": if insegment: fout.write(" \n") else: sys.stderr.write("%s: warning: track data has 0 segments (line %d)\n" % (md.inputFilename, lineNum)) fout.write("\n") mode = 0 else: sys.stderr.write("%s: unexpected type \"%s\" (line %d)\n" % (md.inputFilename, type, lineNum)) sys.exit(4) #========================================================================= # main #========================================================================= md = Metadata() ParseCommandline(md) OpenFiles(md) WriteGPXHeader(md) WriteGPXBody(md) WriteGPXFooter(md)