From f298253e1d2be7c20cdec668dcd72e89ef87803c Mon Sep 17 00:00:00 2001 From: philipp Date: Sun, 30 Jul 2017 21:26:02 +0000 Subject: [PATCH] Coordinate tool works again. git-svn-id: http://www.winterrodeln.org/svn/wradmin/trunk@2692 7aebc617-e5e2-0310-91dc-80fb5f6d2477 --- wradmin/__init__.py | 8 +- wradmin/controllers/coordtool.py | 144 ++++++++++++++++++++++++------- wradmin/templates/coordtool.html | 8 +- 3 files changed, 125 insertions(+), 35 deletions(-) diff --git a/wradmin/__init__.py b/wradmin/__init__.py index 1f7850b..7804928 100644 --- a/wradmin/__init__.py +++ b/wradmin/__init__.py @@ -8,6 +8,7 @@ from wradmin.genshi import render_genshi_template from wradmin.controllers.rodelbahn import RodelbahnController from wradmin.controllers.gasthaus import GasthausController from wradmin.controllers.bericht import BerichtController +from wradmin.controllers.coordtool import CoordtoolController app = Flask(__name__) @@ -99,4 +100,9 @@ def gasthaus_update(): @app.route("/coordtool/index") def coordtool_index(): - pass + return CoordtoolController().index() + + +@app.route("/coordtool/convert", methods=['POST']) +def coordtool_convert(): + return CoordtoolController().convert() diff --git a/wradmin/controllers/coordtool.py b/wradmin/controllers/coordtool.py index 1b77e06..1aefbc9 100644 --- a/wradmin/controllers/coordtool.py +++ b/wradmin/controllers/coordtool.py @@ -1,42 +1,126 @@ #!/usr/bin/python3.4 -import logging +import re +import xml.dom.minidom as minidom +from xml.parsers.expat import ExpatError +from enum import IntEnum +from flask import request, redirect, url_for, flash +from wradmin.genshi import render_genshi_template, TemplateContext -from pylons import request, response, session, url, tmpl_context as c -from pylons.controllers.util import abort, redirect -import formencode -from wradmin.lib.base import BaseController, render -import wrpylib.wrvalidators +class MultiGeo(IntEnum): + """Formats multiple coordinates, even in multiple lines to [(latitude, longitude, elevation), ...] + or [(latitude, longitude, None), ...] tuples.""" -log = logging.getLogger(__name__) + # Valid for input_format + FORMAT_GUESS = 0 # guesses the input format; default for input_format + FORMAT_NONE = -1 # indicates missing formats -class CoordtoolController(BaseController): + # 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. "1090.57" + + +def multigeo_from_string(value, input_format): + assert input_format in [MultiGeo.FORMAT_GUESS, MultiGeo.FORMAT_GEOCACHING, MultiGeo.FORMAT_WINTERRODELN, + MultiGeo.FORMAT_GMAPPLUGIN, MultiGeo.FORMAT_GPX], "input_format %d is not recognized" + lines = [line.strip() for line in value.split("\n") if len(line.strip()) > 0] + + result = [] + for line in lines: + if input_format == MultiGeo.FORMAT_GUESS or input_format == MultiGeo.FORMAT_GEOCACHING: + r = re.match('N ?(\d+)° ?(\d+\.\d+) +E ?(\d+)° ?(\d+\.\d+)', line) + if r is not None: + g = r.groups() + result.append((float(g[0]) + float(g[1]) / 60, float(g[2]) + float(g[3]) / 60, None)) + continue + + if input_format == MultiGeo.FORMAT_GUESS or input_format == MultiGeo.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)) + continue + + if input_format == MultiGeo.FORMAT_GUESS or input_format == MultiGeo.FORMAT_GMAPPLUGIN: + r = re.match('(\d+\.\d+), ?(\d+\.\d+)', line) + if r is not None: + result.append((float(r.groups()[0]), float(r.groups()[1]), None)) + continue + + if input_format == MultiGeo.FORMAT_GUESS or input_format == MultiGeo.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)) + continue + except (ExpatError, IndexError, ValueError): + pass + + raise ValueError("Coordinates '%s' have no known format" % line, value) + return result + + +def multigeo_to_string(value, output_format): + result = [] + for latitude, longitude, height in value: + if output_format == MultiGeo.FORMAT_GEOCACHING: + result.append( + 'N %02d° %02.3f E %03d° %02.3f' % (latitude, latitude % 1 * 60, longitude, longitude % 1 * 60)) + + elif output_format == MultiGeo.FORMAT_WINTERRODELN: + result.append('%.6f N %.6f E' % (latitude, longitude)) + + elif output_format == MultiGeo.FORMAT_GMAPPLUGIN: + result.append('%.6f, %.6f' % (latitude, longitude)) + + elif output_format == MultiGeo.FORMAT_GPX: + if not height is None: + result.append( + '%.2f' % (latitude, longitude, height)) + else: + result.append('' % (latitude, longitude)) + + else: + raise ValueError("output_format %d is not recognized" % output_format, value) + + return "\n".join(result) + + +class CoordtoolController: def index(self): + c = TemplateContext() c.result = None - return render('coordtool.html') - + return render_genshi_template('coordtool.html', c=c) def convert(self): - input = request.POST['input'] - no_elevation = 'no_elevation' in request.POST - simplify = 'simplify' in request.POST - swap_latlon = 'swap_latlon' in request.POST - c.no_geoformat = 'no_geoformat' in request.POST - c.no_gpxformat = 'no_gpxformat' in request.POST - c.no_gmapsformat = 'no_gmapsformat' in request.POST - c.no_geocachingformat = 'no_geocachingformat' in request.POST + c = TemplateContext() + assert request.method == 'POST' + input = request.form['input'] + no_elevation = 'no_elevation' in request.form + simplify = 'simplify' in request.form + swap_latlon = 'swap_latlon' in request.form + c.no_geoformat = 'no_geoformat' in request.form + c.no_gpxformat = 'no_gpxformat' in request.form + c.no_gmapsformat = 'no_gmapsformat' in request.form + c.no_geocachingformat = 'no_geocachingformat' in request.form if input is None or len(input.strip()) == 0: c.result = None - return redirect(url(controller='coordtool', action='index')) + return redirect(url_for('coordtool_index')) - geo = wrpylib.wrvalidators.MultiGeo() - try: c.result = geo.to_python(input) - except formencode.Invalid as e: - session['flash'] = str(e) - session.save() - return redirect(url(controller='coordtool', action='index')) + try: + c.result = multigeo_from_string(input, MultiGeo.FORMAT_GUESS) + except ValueError as e: + flash(str(e)) + return redirect(url_for('coordtool_index')) if swap_latlon: c.result = [(latitude, longitude, elevation) for (longitude, latitude, elevation) in c.result] @@ -44,9 +128,9 @@ class CoordtoolController(BaseController): if no_elevation: c.result = [(longitude, latitude, None) for (longitude, latitude, elevation) in c.result] - c.geo_winterrodeln = wrpylib.wrvalidators.MultiGeo(output_format = geo.FORMAT_WINTERRODELN) - c.geo_gmapplugin = wrpylib.wrvalidators.MultiGeo(output_format = geo.FORMAT_GMAPPLUGIN) - c.geo_gpx = wrpylib.wrvalidators.MultiGeo(output_format = geo.FORMAT_GPX) - c.geo_geocaching = wrpylib.wrvalidators.MultiGeo(output_format = geo.FORMAT_GEOCACHING) + c.geo_winterrodeln = lambda value: multigeo_to_string(value, MultiGeo.FORMAT_WINTERRODELN) + c.geo_gmapplugin = lambda value: multigeo_to_string(value, MultiGeo.FORMAT_GMAPPLUGIN) + c.geo_gpx = lambda value: multigeo_to_string(value, MultiGeo.FORMAT_GPX) + c.geo_geocaching = lambda value: multigeo_to_string(value, MultiGeo.FORMAT_GEOCACHING) - return render('coordtool.html') + return render_genshi_template('coordtool.html', c=c) diff --git a/wradmin/templates/coordtool.html b/wradmin/templates/coordtool.html index 6d1e6ed..3e5792e 100644 --- a/wradmin/templates/coordtool.html +++ b/wradmin/templates/coordtool.html @@ -18,22 +18,22 @@

Winterrodeln-Format

- ${c.geo_winterrodeln.from_python([line])}
+ ${c.geo_winterrodeln([line])}

Google Maps Plugin Format

- ${c.geo_gmapplugin.from_python([line])}
+ ${c.geo_gmapplugin([line])}

GPX Format

- ${c.geo_gpx.from_python([line])}
+ ${c.geo_gpx([line])}

Geocaching-Format

- ${c.geo_geocaching.from_python([line])}
+ ${c.geo_geocaching([line])}

-- 2.39.5