]> ToastFreeware Gitweb - philipp/winterrodeln/wradmin.git/commitdiff
Copied wrgpx.py from http://www.winterrodeln.org/svn/gis/trunk/tools/wrgpx.py. I...
authorphilipp <philipp@7aebc617-e5e2-0310-91dc-80fb5f6d2477>
Fri, 4 Dec 2009 21:27:42 +0000 (21:27 +0000)
committerphilipp <philipp@7aebc617-e5e2-0310-91dc-80fb5f6d2477>
Fri, 4 Dec 2009 21:27:42 +0000 (21:27 +0000)
git-svn-id: http://www.winterrodeln.org/svn/servermediawiki/trunk/wradmin@536 7aebc617-e5e2-0310-91dc-80fb5f6d2477

wradmin/wradmin/lib/wrgpx.py [new file with mode: 0644]

diff --git a/wradmin/wradmin/lib/wrgpx.py b/wradmin/wradmin/lib/wrgpx.py
new file mode 100644 (file)
index 0000000..899ce64
--- /dev/null
@@ -0,0 +1,191 @@
+#!/usr/bin/python2.5
+# -*- coding: iso-8859-15 -*-
+"""Library to handle WRGPX files.
+A WRGPX file (WR stands for Winterrodeln) is a normal GPX file
+that follows several conventions so that it can be rendered to
+a map automatically."""
+
+import mapnik
+import datetime
+from xml.etree.cElementTree import parse
+
+
+class MetaData:
+       def __init__(self):
+               self.name = None           # name as string or None
+               self.desc = None           # description as string or None
+               self.author = None         # author as string or None
+               self.author_email = None   # email as string or None
+               self.copyright_year = None # year of copyright as int or None
+               self.license = None        # link to license
+               self.link = None           # link as string or None
+               self.time = None           # datetime class or None
+               self.minlat = None         # float coordinate or None
+               self.minlon = None         # float coordinate or None
+               self.maxlat = None         # float coordinate or None
+               self.maxlon = None         # float coordinate or None
+
+
+class Waypoint:
+       def __init__(self):
+               self.lat = None            # float coordinate or None
+               self.lon = None            # float coordinate or None
+               self.ele = None            # height as float value or None
+               self.name = None           # name as string or None
+               self.type = None           # type as string or None
+
+
+class Track:
+       def __init__(self):
+               self.name = None           # name as string or None
+               self.type = None           # type as string or None
+               self.points = []           # one point is a tuple (lat, lon, ele) or (lat, lon, None)
+
+
+class WrGpx:
+       def __init__(self):
+               self.metadata = MetaData()
+               self.waypoints = []
+               self.tracks = []
+
+
+class Hint:
+       def __init__(self, message, level, line_nr=None):
+               "level ... 0 informal information; 1 ... suggestion for improvement; 2 ... warning; 3 ... error"
+               self.message = message
+               self.level = level
+               self.line_nr = line_nr
+
+
+def parse_wrgpx(filename):
+       """Parses a WRGPX file and returns a tuple of a data structure representing the content of the GPX file
+       and a list of Hint classes. If the file is not well-formed, an exception is raised."""
+       hints = []
+       wrgpx = WrGpx()
+
+       ns = '{http://www.topografix.com/GPX/1/1}'
+
+       def parse_link(el):
+               if len(el.items()) == 0: hints.append(Hint("XML element link does not have an attribute 'href'.", 2))
+               elif len(el.items()) > 1: raise Exception("XML element link has more than one attribute (should only have 'href').")
+               elif el.items()[0][0] != 'href': raise Exception("XML attribute '%s' is not allowed within XML element link (only 'href' is allowed)." % el.items()[0][0])
+               else: return el.items()[0][1]
+               return None
+       
+       def parse_wpt(element):
+               waypoint = Waypoint()
+               for k, v in element.items():
+                       if k == 'lat': waypoint.lat = float(v)
+                       elif k == 'lon': waypoint.lon = float(v)
+                       else: raise Exception("Unexpected XML attribute '%s' of 'wpt'." % k)
+               for el in element:
+                       if el.tag == ns+'ele': waypoint.ele = float(el.text)
+                       elif el.tag == ns+'time': pass
+                       elif el.tag == ns+'magvar': pass
+                       elif el.tag == ns+'geoidheight': pass
+                       elif el.tag == ns+'name': waypoint.name = el.text
+                       elif el.tag == ns+'cmt': pass
+                       elif el.tag == ns+'desc': waypoint.desc = el.text
+                       elif el.tag == ns+'src': pass
+                       elif el.tag == ns+'link': waypoint.link = parse_link(el)
+                       elif el.tag == ns+'sym': pass
+                       elif el.tag == ns+'type': waypoint.type = el.text
+                       elif el.tag == ns+'fix': pass
+                       elif el.tag == ns+'sat': pass
+                       elif el.tag == ns+'hdop': pass
+                       elif el.tag == ns+'vdop': pass
+                       elif el.tag == ns+'pdop': pass
+                       elif el.tag == ns+'ageofdgpsdata': pass
+                       elif el.tag == ns+'dgpsid': pass
+                       elif el.tag == ns+'extensions': pass
+                       else: raise Exception("Unexpected XML element '%s' within '%s'." % (el.tag, element.tag))
+               return waypoint
+
+       xml = parse(open(filename, 'rb'))
+       root = xml.getroot()
+       if root.tag != ns + 'gpx':
+               raise Exception("XML root element '%s' has to be '%sgpx'!" % (root.tag, ns))
+       
+       wrgpx_has_metadata = False
+       for element in root:
+               # Metadata
+               if element.tag == ns+'metadata':
+                       wrgpx_has_metadata = True
+                       for el in element:
+                               if el.tag == ns+'name':
+                                       wrgpx.metadata.name = el.text
+                               elif el.tag == ns+'desc':
+                                       wrgpx.metadata.desc = el.text
+                               elif el.tag == ns+'author':
+                                       for e in el:
+                                               if e.tag == ns+'name': wrgpx.metadata.author = e.text
+                                               elif e.tag == ns+'email':
+                                                       mail_id = None
+                                                       mail_domain = None
+                                                       for k, v in e.items():
+                                                               if k == 'id': mail_id = v
+                                                               elif k == 'domain': mail_domain = v
+                                                               else: raise Exception("Unexpected XML attribute '%s' of email." % k)
+                                                       if mail_id is None: raise Exception("Missing XML attribute 'id' of email.")
+                                                       if mail_domain is None: raise Exception("Missing XML attribute 'domain' of email.")
+                                                       wrgpx.metadata.author_email = mail_id + '@' + mail_domain
+                                               else: raise Exception("Unexpected XML element '%s' within author." % e.tag)
+                               elif el.tag == ns+'copyright':
+                                       for e in el:
+                                               if e.tag == ns+'year': wrgpx.metadata.copyright_year = int(e.text)
+                                               elif e.tag == ns+'license': wrgpx.metadata.license = e.text
+                                               else: raise Exception("Unexpected XML element '%s' within copyright." % e.tag)
+                               elif el.tag == ns+'link': wrgpx.metadata.link = parse_link(el)
+                               elif el.tag == ns+'time':
+                                       wrgpx.metadata.time = datetime.datetime.strptime('2008-11-10T20:44:52Z', '%Y-%m-%dT%H:%M:%SZ')
+                               elif el.tag == ns+'bounds':
+                                       for k, v in el.items():
+                                               if k == 'minlat': wrgpx.metadata.minlat = float(v)
+                                               elif k == 'minlon': wrgpx.metadata.minlon = float(v)
+                                               elif k == 'maxlat': wrgpx.metadata.maxlat = float(v)
+                                               elif k == 'maxlon': wrgpx.metadata.maxlon = float(v)
+                                               else: raise Exception("Unexpected XML attribute '%s' of bounds." % k)
+                                       if wrgpx.metadata.minlat is None or wrgpx.metadata.minlon is None or wrgpx.metadata.maxlat is None or wrgpx.metadata.maxlon is None:
+                                               raise Exception("Not all of the attributes 'minlat', 'minlon', 'maxlat', 'maxlon' present in XML element 'bounds'.")
+                               elif el.tag == ns+'extensions':
+                                       hints.append(Hint("XML element extensions within XML element metadata is not used by WRGPX.", 1))
+                               else: raise Exception("Unexpected XML element '%s' within metadata." % el.tag)
+
+               # Waypoints
+               elif element.tag == ns+'wpt':
+                       waypoint = parse_wpt(element)
+                       wrgpx.waypoints.append(waypoint)
+
+               # Routes
+               elif element.tag == ns+'rte':
+                       hints.append(Hint("GPX file has a 'rte' element. This is not used in WRGPX.", 1))
+
+               # Tracks
+               elif element.tag == ns+'trk':
+                       track = Track()
+                       for el in element:
+                               if el.tag == ns+'name': track.name = el.text
+                               elif el.tag == ns+'cmt': pass
+                               elif el.tag == ns+'desc': track.desc = el.text
+                               elif el.tag == ns+'src': pass
+                               elif el.tag == ns+'link': track.link = parse_link(el)
+                               elif el.tag == ns+'number': pass
+                               elif el.tag == ns+'type': track.type = el.text
+                               elif el.tag == ns+'extensions': pass
+                               elif el.tag == ns+'trkseg': 
+                                       for e in el:
+                                               if e.tag == ns+'trkpt':
+                                                       trkpt = parse_wpt(e)
+                                                       track.points.append((trkpt.lat, trkpt.lon, trkpt.ele))
+                                               elif e.tag == ns+'extensions': pass
+                                               else: raise Exception("Unexpected XML element '%s' within 'trkseg'." % e.tag)
+                               else: raise Exception("Unexpected XML element '%s' within wpt." % el.tag)
+                       wrgpx.tracks.append(track)
+
+               # Extensions
+               elif element.tag == ns+'extensions':
+                       hints.append(Hint("GPX file has a 'extensions' element. This is not used in WRGPX.", 1))
+
+               else: raise Exception("Unexpected XML element '%s'. It has to be one of '%s', '%s' or '%s'." % (element.tag, ns+'metadata', ns+'wpt', ns+'trk'))
+       if not wrgpx_has_metadata: hints.append(Hint("GPX file has a no metadata (like author, ...).", 2))
+       return (wrgpx, hints)