]> ToastFreeware Gitweb - philipp/winterrodeln/wradmin.git/blob - wradmin/controllers/coordtool.py
rodelbahn_list.html now uses jinja2.
[philipp/winterrodeln/wradmin.git] / wradmin / controllers / coordtool.py
1 #!/usr/bin/python3.4
2 import re
3 import xml.dom.minidom as minidom
4 from xml.parsers.expat import ExpatError
5 from enum import IntEnum
6 from flask import request, redirect, url_for, flash
7 from wradmin.genshi import render_genshi_template, TemplateContext
8
9
10 class MultiGeo(IntEnum):
11     """Formats multiple coordinates, even in multiple lines to [(latitude, longitude, elevation), ...] 
12     or [(latitude, longitude, None), ...] tuples."""
13
14     # Valid for input_format
15     FORMAT_GUESS = 0  # guesses the input format; default for input_format
16     FORMAT_NONE = -1  # indicates missing formats
17
18     # Valid for input_format and output_format
19     FORMAT_GEOCACHING = 1  # e.g. "N 47° 13.692 E 011° 25.535"
20     FORMAT_WINTERRODELN = 2  # e.g. "47.222134 N 11.467211 E"
21     FORMAT_GMAPPLUGIN = 3  # e.g. "47.232922, 11.452239"
22     FORMAT_GPX = 4  # e.g. "<trkpt lat="47.181289" lon="11.408827"><ele>1090.57</ele></trkpt>"
23
24
25 def multigeo_from_string(value, input_format):
26     assert input_format in [MultiGeo.FORMAT_GUESS, MultiGeo.FORMAT_GEOCACHING, MultiGeo.FORMAT_WINTERRODELN,
27                             MultiGeo.FORMAT_GMAPPLUGIN, MultiGeo.FORMAT_GPX], "input_format %d is not recognized"
28     lines = [line.strip() for line in value.split("\n") if len(line.strip()) > 0]
29
30     result = []
31     for line in lines:
32         if input_format == MultiGeo.FORMAT_GUESS or input_format == MultiGeo.FORMAT_GEOCACHING:
33             r = re.match('N ?(\d+)° ?(\d+\.\d+) +E ?(\d+)° ?(\d+\.\d+)', line)
34             if r is not None:
35                 g = r.groups()
36                 result.append((float(g[0]) + float(g[1]) / 60, float(g[2]) + float(g[3]) / 60, None))
37                 continue
38
39         if input_format == MultiGeo.FORMAT_GUESS or input_format == MultiGeo.FORMAT_WINTERRODELN:
40             r = re.match('(\d+\.\d+) N (\d+\.\d+) E', line)
41             if not r is None:
42                 result.append((float(r.groups()[0]), float(r.groups()[1]), None))
43                 continue
44
45         if input_format == MultiGeo.FORMAT_GUESS or input_format == MultiGeo.FORMAT_GMAPPLUGIN:
46             r = re.match('(\d+\.\d+), ?(\d+\.\d+)', line)
47             if r is not None:
48                 result.append((float(r.groups()[0]), float(r.groups()[1]), None))
49                 continue
50
51         if input_format == MultiGeo.FORMAT_GUESS or input_format == MultiGeo.FORMAT_GPX:
52             try:
53                 xml = minidom.parseString(line)
54                 coord = xml.documentElement
55                 lat = float(coord.getAttribute('lat'))
56                 lon = float(coord.getAttribute('lon'))
57                 try:
58                     ele = float(coord.childNodes[0].childNodes[0].nodeValue)
59                 except (IndexError, ValueError):
60                     ele = None
61                 result.append((lat, lon, ele))
62                 continue
63             except (ExpatError, IndexError, ValueError):
64                 pass
65
66         raise ValueError("Coordinates '%s' have no known format" % line, value)
67     return result
68
69
70 def multigeo_to_string(value, output_format):
71     result = []
72     for latitude, longitude, height in value:
73         if output_format == MultiGeo.FORMAT_GEOCACHING:
74             result.append(
75                 'N %02d° %02.3f E %03d° %02.3f' % (latitude, latitude % 1 * 60, longitude, longitude % 1 * 60))
76
77         elif output_format == MultiGeo.FORMAT_WINTERRODELN:
78             result.append('%.6f N %.6f E' % (latitude, longitude))
79
80         elif output_format == MultiGeo.FORMAT_GMAPPLUGIN:
81             result.append('%.6f, %.6f' % (latitude, longitude))
82
83         elif output_format == MultiGeo.FORMAT_GPX:
84             if not height is None:
85                 result.append(
86                     '<trkpt lat="%.6f" lon="%.6f"><ele>%.2f</ele></trkpt>' % (latitude, longitude, height))
87             else:
88                 result.append('<trkpt lat="%.6f" lon="%.6f"/>' % (latitude, longitude))
89
90         else:
91             raise ValueError("output_format %d is not recognized" % output_format, value)
92
93     return "\n".join(result)
94
95
96 class CoordtoolController:
97
98     def index(self):
99         c = TemplateContext()
100         c.result = None
101         return render_genshi_template('coordtool.html', c=c)
102
103     def convert(self):
104         c = TemplateContext()
105         assert request.method == 'POST'
106         input = request.form['input']
107         no_elevation = 'no_elevation' in request.form
108         simplify = 'simplify' in request.form
109         swap_latlon = 'swap_latlon' in request.form
110         c.no_geoformat = 'no_geoformat' in request.form
111         c.no_gpxformat = 'no_gpxformat' in request.form
112         c.no_gmapsformat = 'no_gmapsformat' in request.form
113         c.no_geocachingformat = 'no_geocachingformat' in request.form
114         
115         if input is None or len(input.strip()) == 0: 
116             c.result = None
117             return redirect(url_for('coordtool_index'))
118         
119         try:
120             c.result = multigeo_from_string(input, MultiGeo.FORMAT_GUESS)
121         except ValueError as e:
122             flash(str(e))
123             return redirect(url_for('coordtool_index'))
124         
125         if swap_latlon:
126             c.result = [(latitude, longitude, elevation) for (longitude, latitude, elevation) in c.result]
127         
128         if no_elevation:
129             c.result = [(longitude, latitude, None) for (longitude, latitude, elevation) in c.result]
130         
131         c.geo_winterrodeln = lambda value: multigeo_to_string(value, MultiGeo.FORMAT_WINTERRODELN)
132         c.geo_gmapplugin = lambda value: multigeo_to_string(value, MultiGeo.FORMAT_GMAPPLUGIN)
133         c.geo_gpx = lambda value: multigeo_to_string(value, MultiGeo.FORMAT_GPX)
134         c.geo_geocaching = lambda value: multigeo_to_string(value, MultiGeo.FORMAT_GEOCACHING)
135         
136         return render_genshi_template('coordtool.html', c=c)