-class MultiGeo(formencode.FancyValidator):
- "Formats multiple coordinates, even in multiple lines to [(latitude, longitude, elevation), ...] or [(latitude, longitude, None), ...] tuplets."
-
- # Valid for input_format
- FORMAT_GUESS = 0 # guesses the input format; default for input_format
- FORMAT_NONE = -1 # indicates missing formats
-
- # Valid for input_format and output_format
- FORMAT_GEOCACHING = 1 # e.g. "N 47° 13.692 E 011° 25.535"
- FORMAT_WINTERRODELN = 2 # e.g. "47.222134 N 11.467211 E"
- FORMAT_GMAPPLUGIN = 3 # e.g. "47.232922, 11.452239"
- FORMAT_GPX = 4 # e.g. "<trkpt lat="47.181289" lon="11.408827"><ele>1090.57</ele></trkpt>"
-
- input_format = FORMAT_GUESS
- output_format = FORMAT_WINTERRODELN
- last_input_format = FORMAT_NONE
-
- def __init__(self, input_format = FORMAT_GUESS, output_format = FORMAT_WINTERRODELN, **keywords):
- self.input_format = input_format
- self.output_format = output_format
- formencode.FancyValidator.__init__(self, if_empty = (None, None, None), **keywords)
-
- def to_python(self, value, state=None):
- self.assert_string(value, state)
- input_format = self.input_format
- if not input_format in [self.FORMAT_GUESS, self.FORMAT_GEOCACHING, self.FORMAT_WINTERRODELN, self.FORMAT_GMAPPLUGIN, self.FORMAT_GPX]:
- raise formencode.Invalid("input_format %d is not recognized" % input_format, value, state) # Shouldn't it be an other type of runtime error?
- lines = [line.strip() for line in value.split("\n") if len(line.strip()) > 0]
-
- result = []
- for line in lines:
- if input_format == self.FORMAT_GUESS or input_format == self.FORMAT_GEOCACHING:
- r = re.match('N ?(\d+)° ?(\d+\.\d+) +E ?(\d+)° ?(\d+\.\d+)', line)
- if not r is None:
- g = r.groups()
- result.append((float(g[0]) + float(g[1])/60, float(g[2]) + float(g[3])/60, None))
- last_input_format = self.FORMAT_WINTERRODELN
- continue
-
- if input_format == self.FORMAT_GUESS or input_format == self.FORMAT_WINTERRODELN:
- r = re.match('(\d+\.\d+) N (\d+\.\d+) E', line)
- if not r is None:
- result.append((float(r.groups()[0]), float(r.groups()[1]), None))
- last_input_format = self.FORMAT_WINTERRODELN
- continue
-
- if input_format == self.FORMAT_GUESS or input_format == self.FORMAT_GMAPPLUGIN:
- r = re.match('(\d+\.\d+), ?(\d+\.\d+)', line)
- if not r is None:
- result.append((float(r.groups()[0]), float(r.groups()[1]), None))
- last_input_format = self.FORMAT_GMAPPLUGIN
- continue
-
- if input_format == self.FORMAT_GUESS or input_format == self.FORMAT_GPX:
- try:
- xml = minidom.parseString(line)
- coord = xml.documentElement
- lat = float(coord.getAttribute('lat'))
- lon = float(coord.getAttribute('lon'))
- try: ele = float(coord.childNodes[0].childNodes[0].nodeValue)
- except (IndexError, ValueError): ele = None
- result.append((lat, lon, ele))
- last_input_format = self.FORMAT_GPX
- continue
- except (ExpatError, IndexError, ValueError): pass
-
- raise formencode.Invalid("Coordinates '%s' have no known format" % line, value, state)
-
- return result
-
- def from_python(self, value, state=None):
- output_format = self.output_format
- result = []
- for latitude, longitude, height in value:
- if output_format == self.FORMAT_GEOCACHING:
- degree = latitude
- result.append('N %02d° %02.3f E %03d° %02.3f' % (latitude, latitude % 1 * 60, longitude, longitude % 1 * 60))
-
- elif output_format == self.FORMAT_WINTERRODELN:
- result.append('%.6f N %.6f E' % (latitude, longitude))
-
- elif output_format == self.FORMAT_GMAPPLUGIN:
- result.append('%.6f, %.6f' % (latitude, longitude))
-
- elif output_format == self.FORMAT_GPX:
- if not height is None: result.append('<trkpt lat="%.6f" lon="%.6f"><ele>%.2f</ele></trkpt>' % (latitude, longitude, height))
- else: result.append('<trkpt lat="%.6f" lon="%.6f"/>' % (latitude, longitude))
-
- else:
- raise formencode.Invalid("output_format %d is not recognized" % output_format, value, state) # Shouldn't it be an other type of runtime error?
-
- return "\n".join(result)