#!/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)