From 1e6d3082933b998925c7a364edfdc8d1f5be5fcb Mon Sep 17 00:00:00 2001 From: Ilya Zverev Date: Fri, 27 Mar 2015 18:21:48 +0300 Subject: [PATCH] find border sequence from a drawn line --- server/borders_api.py | 70 ++++++++++++++++++++++++++++++++++++------- server/config.py | 2 +- www/borders.js | 47 ++++++++++++++++++----------- www/index.html | 3 +- 4 files changed, 91 insertions(+), 31 deletions(-) diff --git a/server/borders_api.py b/server/borders_api.py index 5fe02b5..f5305d7 100755 --- a/server/borders_api.py +++ b/server/borders_api.py @@ -437,6 +437,51 @@ def make_osm(): xml = xml + '' return Response(xml, mimetype='application/x-osm+xml') +@app.route('/josmbord') +def josm_borders_along(): + name = request.args.get('name') + line = request.args.get('line') + cur = g.conn.cursor() + # select all outer osm borders inside a buffer of the given line + cur.execute(""" + with linestr as ( + select ST_Intersection(geom, ST_Buffer(ST_GeomFromText(%s, 4326), 0.1)) as line + from {table} where name = %s + ), osmborders as ( + select (ST_Dump(way)).geom as g from {osm}, linestr where ST_Intersects(line, way) + ) + select ST_AsGeoJSON((ST_Dump(ST_LineMerge(ST_Intersection(ST_Collect(ST_ExteriorRing(g)), line)))).geom) from osmborders, linestr group by line + """.format(table=config.TABLE, osm=config.OSM_TABLE), (line, name)) + + node_pool = { 'id': 1 } # 'lat_lon': id + lines = [] + for rec in cur: + geometry = json.loads(rec[0]) + if geometry['type'] == 'LineString': + nodes = parse_linestring(node_pool, geometry['coordinates']) + elif geometry['type'] == 'MultiLineString': + nodes = [] + for line in geometry['coordinates']: + nodes.extend(parse_linestring(node_pool, line)) + if len(nodes) > 0: + lines.append(nodes) + + xml = '' + for latlon, node_id in node_pool.items(): + if latlon != 'id': + (lat, lon) = latlon.split() + xml = xml + ''.format(id=node_id, lat=lat, lon=lon) + + wrid = 1 + for line in lines: + xml = xml + ''.format(id=wrid) + for nd in line: + xml = xml + ''.format(ref=nd) + xml = xml + '' + wrid = wrid + 1 + xml = xml + '' + return Response(xml, mimetype='application/x-osm+xml') + def quoteattr(value): value = value.replace('&', '&').replace('>', '>').replace('<', '<') value = value.replace('\n', ' ').replace('\r', ' ').replace('\t', ' ') @@ -450,19 +495,22 @@ def ring_hash(refs): def parse_polygon(node_pool, rings, polygon): role = 'outer' for ring in polygon: - nodes = [] - for lonlat in ring: - ref = '{} {}'.format(lonlat[1], lonlat[0]) - if ref in node_pool: - node_id = node_pool[ref] - else: - node_id = node_pool['id'] - node_pool[ref] = node_id - node_pool['id'] = node_id + 1 - nodes.append(node_id) - rings.append([role, nodes]) + rings.append([role, parse_linestring(node_pool, ring)]) role = 'inner' +def parse_linestring(node_pool, linestring): + nodes = [] + for lonlat in linestring: + ref = '{} {}'.format(lonlat[1], lonlat[0]) + if ref in node_pool: + node_id = node_pool[ref] + else: + node_id = node_pool['id'] + node_pool[ref] = node_id + node_pool['id'] = node_id + 1 + nodes.append(node_id) + return nodes + def append_way(way, way2): another = list(way2) # make copy to not modify original list if way[0] == way[-1] or another[0] == another[-1]: diff --git a/server/config.py b/server/config.py index b722a9e..b251be7 100644 --- a/server/config.py +++ b/server/config.py @@ -1,7 +1,7 @@ # postgresql connection string CONNECTION = 'dbname=borders' # passed to flask.Debug -DEBUG = True +DEBUG = False # if the main table is read-only READONLY = False # main table name diff --git a/www/borders.js b/www/borders.js index aa9fc40..0c64beb 100644 --- a/www/borders.js +++ b/www/borders.js @@ -15,6 +15,8 @@ function init() { map = L.map('map', { editable: true }).setView([30, 0], 3); var hash = new L.Hash(map); L.tileLayer('http://tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap' }).addTo(map); + L.tileLayer('http://korona.geog.uni-heidelberg.de/tiles/adminb/x={x}&y={y}&z={z}', + { attribution: '© GIScience Heidelberg' }).addTo(map); bordersLayer = L.layerGroup(); map.addLayer(bordersLayer); @@ -302,14 +304,8 @@ function bOldBorders() { } } -function bJOSM() { - var b = map.getBounds(); - var url = getServer('josm') + '?' + $.param({ - 'xmin': b.getWest(), - 'xmax': b.getEast(), - 'ymin': b.getSouth(), - 'ymax': b.getNorth() - }); +function importInJOSM(method, data ) { + var url = getServer(method) + '?' + $.param(data); $.ajax({ url: 'http://127.0.0.1:8111/import', data: { url: url, new_layer: 'true' }, @@ -320,22 +316,24 @@ function bJOSM() { }); } -function bJosmOld() { +function bJOSM() { var b = map.getBounds(); - var url = getServer('josm') + '?' + $.param({ - 'table': OLD_BORDERS_NAME, + importInJOSM('josm', { 'xmin': b.getWest(), 'xmax': b.getEast(), 'ymin': b.getSouth(), 'ymax': b.getNorth() }); - $.ajax({ - url: 'http://127.0.0.1:8111/import', - data: { url: url, new_layer: 'true' }, - complete: function(t) { - if( t.status != 200 ) - window.alert('Please enable remote_control in JOSM'); - } +} + +function bJosmOld() { + var b = map.getBounds(); + importInJOSM('josm', { + 'table': OLD_BORDERS_NAME, + 'xmin': b.getWest(), + 'xmax': b.getEast(), + 'ymin': b.getSouth(), + 'ymax': b.getNorth() }); } @@ -459,6 +457,19 @@ function bSplitDo() { bSplitCancel(); } +function bSplitJosm() { + var wkt = '', lls = splitLayer.getLatLngs(); + for( i = 0; i < lls.length; i++ ) { + if( i > 0 ) + wkt += ','; + wkt += L.Util.formatNum(lls[i].lng, 6) + ' ' + L.Util.formatNum(lls[i].lat, 6); + } + importInJOSM('josmbord', { + 'name': splitSelected, + 'line': 'LINESTRING(' + wkt + ')' + }); +} + function bSplitCancel() { map.editTools.stopDrawing(); if( splitLayer != null ) diff --git a/www/index.html b/www/index.html index ebc3473..101b7ad 100644 --- a/www/index.html +++ b/www/index.html @@ -32,7 +32,7 @@