From 4a3942e97126b07309725857b80bdc748b0a771b Mon Sep 17 00:00:00 2001 From: Alexey Zakharenkov <35913079+alexey-zakharenkov@users.noreply.github.com> Date: Tue, 13 Oct 2020 13:35:02 +0300 Subject: [PATCH] Exclude code about roads that cross borders: it needs 'crossing' and 'points' tables and there are no scripts/instructions how to fill them --- web/app/borders_api.py | 145 ++++++-------------------- web/app/config.py | 2 - web/app/static/borders.js | 191 +---------------------------------- web/app/templates/index.html | 14 +-- 4 files changed, 37 insertions(+), 315 deletions(-) diff --git a/web/app/borders_api.py b/web/app/borders_api.py index b725ad0..d5399d7 100755 --- a/web/app/borders_api.py +++ b/web/app/borders_api.py @@ -173,99 +173,55 @@ def query_small_in_bbox(): else: table = config.TABLE cur = g.conn.cursor() - cur.execute('''SELECT name, round(ST_Area(geography(ring))) as area, ST_X(ST_Centroid(ring)), ST_Y(ST_Centroid(ring)) + cur.execute(f""" + SELECT name, round(ST_Area(geography(ring))) as area, + ST_X(ST_Centroid(ring)), ST_Y(ST_Centroid(ring)) FROM ( SELECT name, (ST_Dump(geom)).geom as ring FROM {table} WHERE geom && ST_MakeBox2D(ST_Point(%s, %s), ST_Point(%s, %s)) ) g - WHERE ST_Area(geography(ring)) < %s;'''.format(table=table), (xmin, ymin, xmax, ymax, config.SMALL_KM2 * 1000000)) + WHERE ST_Area(geography(ring)) < %s + """, (xmin, ymin, xmax, ymax, config.SMALL_KM2 * 1000000) + ) result = [] for rec in cur: - result.append({ 'name': rec[0], 'area': rec[1], 'lon': float(rec[2]), 'lat': float(rec[3]) }) + result.append({ 'name': rec[0], 'area': rec[1], + 'lon': float(rec[2]), 'lat': float(rec[3]) }) return jsonify(features=result) -@app.route('/routing') -def query_routing_points(): - xmin = request.args.get('xmin') - xmax = request.args.get('xmax') - ymin = request.args.get('ymin') - ymax = request.args.get('ymax') - cur = g.conn.cursor() - try: - cur.execute('''SELECT ST_X(geom), ST_Y(geom), type - FROM points - WHERE geom && ST_MakeBox2D(ST_Point(%s, %s), ST_Point(%s, %s) - );''', (xmin, ymin, xmax, ymax)) - except psycopg2.Error as e: - return jsonify(features=[]) - result = [] - for rec in cur: - result.append({ 'lon': rec[0], 'lat': rec[1], 'type': rec[2] }) - return jsonify(features=result) - -@app.route('/crossing') -def query_crossing(): - xmin = request.args.get('xmin') - xmax = request.args.get('xmax') - ymin = request.args.get('ymin') - ymax = request.args.get('ymax') - region = request.args.get('region', '').encode('utf-8') - points = request.args.get('points') == '1' - rank = request.args.get('rank') or '4' - cur = g.conn.cursor() - sql = """SELECT id, ST_AsGeoJSON({line}, 7) as geometry, region, processed FROM {table} - WHERE line && ST_MakeBox2D(ST_Point(%s, %s), ST_Point(%s, %s)) and processed = 0 {reg} and rank <= %s; - """.format(table=config.CROSSING_TABLE, reg='and region = %s' if region else '', line='line' if not points else 'ST_Centroid(line)') - params = [xmin, ymin, xmax, ymax] - if region: - params.append(region) - params.append(rank) - result = [] - try: - cur.execute(sql, tuple(params)) - for rec in cur: - props = { 'id': rec[0], 'region': rec[2], 'processed': rec[3] } - feature = { 'type': 'Feature', 'geometry': json.loads(rec[1]), 'properties': props } - result.append(feature) - except psycopg2.Error as e: - pass - return jsonify(type='FeatureCollection', features=result) - @app.route('/config') def get_server_configuration(): osm = False backup = False old = [] - crossing = False try: cur = g.conn.cursor() - cur.execute('select osm_id, ST_Area(way), admin_level, name from {} limit 2;'.format(config.OSM_TABLE)) + cur.execute(f"""SELECT osm_id, ST_Area(way), admin_level, name + FROM {config.OSM_TABLE} LIMIT 2""") if cur.rowcount == 2: osm = True except psycopg2.Error as e: pass try: - cur.execute('select backup, id, name, parent_id, ST_Area(geom), modified, disabled, count_k, cmnt from {} limit 2;'.format(config.BACKUP)) + cur.execute(f"""SELECT backup, id, name, parent_id, ST_Area(geom), + modified, disabled, count_k, cmnt + FROM {config.BACKUP} LIMIT 2""") backup = True except psycopg2.Error as e: pass for t, tname in config.OTHER_TABLES.items(): try: - cur.execute('select name, ST_Area(geom), modified, disabled, count_k, cmnt from {} limit 2;'.format(tname)) + cur.execute(f"""SELECT name, ST_Area(geom), modified, disabled, + count_k, cmnt + FROM {tname} LIMIT 2""") if cur.rowcount == 2: old.append(t) except psycopg2.Error as e: pass - try: - cur = g.conn.cursor() - cur.execute('select id, ST_Length(line), region, processed from {} limit 2;'.format(config.CROSSING_TABLE)) - if cur.rowcount == 2: - crossing = True - except psycopg2.Error as e: - pass - return jsonify(osm=osm, tables=old, readonly=config.READONLY, - backup=backup, crossing=crossing, + return jsonify(osm=osm, tables=old, + readonly=config.READONLY, + backup=backup, mwm_size_thr=config.MWM_SIZE_THRESHOLD) @app.route('/search') @@ -431,7 +387,16 @@ def find_osm_borders(): lat = request.args.get('lat') lon = request.args.get('lon') cur = g.conn.cursor() - cur.execute("select osm_id, name, admin_level, (case when ST_Area(geography(way)) = 'NaN' then 0 else ST_Area(geography(way))/1000000 end) as area_km from {table} where ST_Contains(way, ST_SetSRID(ST_Point(%s, %s), 4326)) order by admin_level desc, name asc;".format(table=config.OSM_TABLE), (lon, lat)) + cur.execute(f""" + SELECT osm_id, name, admin_level, + (CASE + WHEN ST_Area(geography(way)) = 'NaN' THEN 0 + ELSE ST_Area(geography(way))/1000000 + END) AS area_km + FROM {config.OSM_TABLE} + WHERE ST_Contains(way, ST_SetSRID(ST_Point(%s, %s), 4326)) + ORDER BY admin_level DESC, name ASC + """, (lon, lat)) result = [] for rec in cur: b = { 'id': rec[0], 'name': rec[1], 'admin_level': rec[2], 'area': rec[3] } @@ -483,7 +448,7 @@ def delete_border(): abort(405) region_id = int(request.args.get('id')) cur = g.conn.cursor() - cur.execute('delete from {} where id = %s;'.format(config.TABLE), (region_id,)) + cur.execute(f"DELETE FROM {config.TABLE} WHERE id = %s", (region_id,)) g.conn.commit() return jsonify(status='ok') @@ -883,56 +848,6 @@ def draw_hull(): g.conn.commit() return jsonify(status='ok') -@app.route('/fixcrossing') -def fix_crossing(): - if config.READONLY: - abort(405) - preview = request.args.get('preview') == '1' - region = request.args.get('region').encode('utf-8') - if region is None: - return jsonify(status='Please specify a region') - ids = request.args.get('ids') - if ids is None or len(ids) == 0: - return jsonify(status='Please specify a list of line ids') - ids = tuple(ids.split(',')) - cur = g.conn.cursor() - if preview: - cur.execute(""" - WITH lines as (SELECT ST_Buffer(ST_Collect(line), 0.002, 1) as g FROM {cross} WHERE id IN %s) - SELECT ST_AsGeoJSON(ST_Collect(ST_MakePolygon(er.ring))) FROM - ( - SELECT ST_ExteriorRing((ST_Dump(ST_Union(ST_Buffer(geom, 0.0), lines.g))).geom) as ring FROM {table}, lines WHERE name = %s - ) as er - """.format(table=config.TABLE, cross=config.CROSSING_TABLE), (ids, region)) - res = cur.fetchone() - if not res: - return jsonify(status='Failed to extend geometry') - f = { "type": "Feature", "properties": {}, "geometry": json.loads(res[0]) } - #return jsonify(type="FeatureCollection", features=[f]) - return jsonify(type="Feature", properties={}, geometry=json.loads(res[0])) - else: - cur.execute(""" - WITH lines as (SELECT ST_Buffer(ST_Collect(line), 0.002, 1) as g FROM {cross} WHERE id IN %s) - UPDATE {table} SET geom = res.g FROM - ( - SELECT ST_Collect(ST_MakePolygon(er.ring)) as g FROM - ( - SELECT ST_ExteriorRing((ST_Dump(ST_Union(ST_Buffer(geom, 0.0), lines.g))).geom) as ring FROM {table}, lines WHERE name = %s - ) as er - ) as res - WHERE name = %s - """.format(table=config.TABLE, cross=config.CROSSING_TABLE), (ids, region, region)) - cur.execute(""" - UPDATE {table} b SET geom = ST_Difference(b.geom, o.geom) - FROM {table} o - WHERE ST_Overlaps(b.geom, o.geom) - AND o.name = %s - """.format(table=config.TABLE), (region,)) - cur.execute("UPDATE {cross} SET processed = 1 WHERE id IN %s".format(cross=config.CROSSING_TABLE), (ids,)) - g.conn.commit() - return jsonify(status='ok') - - @app.route('/backup') def backup_do(): if config.READONLY: diff --git a/web/app/config.py b/web/app/config.py index a6b04d2..f9fb7e0 100644 --- a/web/app/config.py +++ b/web/app/config.py @@ -18,8 +18,6 @@ OTHER_TABLES = { } # backup table BACKUP = 'borders_backup' -## table with crossing lines -CROSSING_TABLE = 'crossing' # area of an island for it to be considered small SMALL_KM2 = 10 # force multipolygons in JOSM output diff --git a/web/app/static/borders.js b/web/app/static/borders.js index b0329e5..bd0d950 100644 --- a/web/app/static/borders.js +++ b/web/app/static/borders.js @@ -14,25 +14,15 @@ var size_good, size_bad; var maxRank = 1; var tooSmallLayer = null; var oldBordersLayer = null; -var routingGroup = null; -var crossingLayer = null; function init() { map = L.map('map', { editable: true }).setView([30, 0], 3); var hash = new L.Hash(map); L.tileLayer('https://tile.openstreetmap.de/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap' }).addTo(map); //L.tileLayer('https://b.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap' }).addTo(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); -// L.tileLayer('https://tile.cyclestreets.net/boundaries/{z}/{x}/{y}.png', -// { attribution: '© CycleStreets.net' }).addTo(map); + //L.tileLayer('http://tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap' }).addTo(map); bordersLayer = L.layerGroup(); map.addLayer(bordersLayer); - routingGroup = L.layerGroup(); - map.addLayer(routingGroup); - crossingLayer = L.layerGroup(); - map.addLayer(crossingLayer); map.on('moveend', function() { if( map.getZoom() >= 5 ) @@ -85,8 +75,6 @@ function getServerConfiguration() { $('#old_action').css('display', 'block'); $('#josm_old').css('display', 'inline'); } - if( res.crossing ) - $('#cross_actions').css('display', 'block'); if( res.backup ) { $('#backups').show(); } @@ -128,34 +116,6 @@ function updateBorders() { simplified: simplified }); - /*$.ajax(getServer('routing'), { - data: { - 'xmin': b.getWest(), - 'xmax': b.getEast(), - 'ymin': b.getSouth(), - 'ymax': b.getNorth() - }, - success: processRouting, - dataType: 'json' - }); - - if (map.getZoom() >= 4) { - $.ajax(getServer('crossing'), { - data: { - 'xmin': b.getWest(), - 'xmax': b.getEast(), - 'ymin': b.getSouth(), - 'ymax': b.getNorth(), - 'points': (map.getZoom() < 10 ? 1 : 0), - 'rank': maxRank - }, - success: processCrossing, - dataType: 'json' - }); - } else { - crossingLayer.clearLayers(); - } - if( oldBordersLayer != null && config.OLD_BORDERS_NAME ) { oldBordersLayer.clearLayers(); $.ajax(getServer('bbox'), { @@ -167,10 +127,10 @@ function updateBorders() { 'ymin': b.getSouth(), 'ymax': b.getNorth() }, - success: processOldBorders, + success: makeAnswerHandler(processOldBorders), dataType: 'json' }); - } */ + } } function makeAnswerHandler(on_ok_func) { @@ -182,18 +142,6 @@ function makeAnswerHandler(on_ok_func) { }; } -routingTypes = {1: "Border and feature are intersecting several times.", - 2: "Unknown outgoing feature."}; - -function processRouting(data) { - routingGroup.clearLayers(); - for( var f = 0; f < data.features.length; f++ ) { - marker = L.marker([data.features[f]["lat"], data.features[f]["lon"]]); - marker.bindPopup(routingTypes[data.features[f]["type"]], {showOnMouseOver: true}); - routingGroup.addLayer(marker); - } -} - function processBorders(data) { data = data.geojson; for( var id in borders ) { @@ -240,8 +188,8 @@ function processBorders(data) { } function processOldBorders(data) { - var layer = L.geoJson(data, { - style: { fill: false, color: 'purple', weight: 3, clickable: false } + var layer = L.geoJson(data.geojosn, { + style: { fill: false, color: 'purple', weight: 5, clickable: false } }); oldBordersLayer.addLayer(layer); } @@ -1064,9 +1012,6 @@ function bDivideCancel() { $('#actions').show(); } - - - function bLargest() { if( !selectedId || !(selectedId in borders) ) return; @@ -1172,131 +1117,6 @@ function getPolyDownloadLink(use_bbox) { return downloadLink; } -var crossSelected = null, fcPreview = null; -var selectedCrossings = {}; - -function crossingUpdateColor(layer) { - if( 'setStyle' in layer ) - layer.setStyle({ color: selectedCrossings[layer.crossId] ? 'red' : 'blue' }); -} - -function crossingClicked(e) { - if( !crossSelected ) - return; - var layer = e.target; - if( 'crossId' in layer ) { - var id = layer.crossId; - if( selectedCrossings[id] ) - delete selectedCrossings[id]; - else - selectedCrossings[id] = true; - crossingUpdateColor(layer); - } -} - -function setBordersSelectable(selectable) { - crossingLayer.eachLayer(function(l) { - l.bringToFront(); - }); -} - -function processCrossing(data) { - crossingLayer.clearLayers(); - for( var f = 0; f < data.features.length; f++ ) { - var layer = L.GeoJSON.geometryToLayer(data.features[f].geometry), - props = data.features[f].properties; - layer.crossId = '' + props.id; - layer.crossRegion = props.region; - crossingUpdateColor(layer); - layer.on('click', crossingClicked); - crossingLayer.addLayer(layer); - } -} - -function selectCrossingByRegion(region) { - if( region ) { - crossingLayer.eachLayer(function(l) { - if( l.crossId && l.crossRegion == region ) { - selectedCrossings[l.crossId] = true; - crossingUpdateColor(l); - } - }); - } else { - crossingLayer.eachLayer(function(l) { - if( l.crossId ) { - delete selectedCrossings[l.crossId]; - crossingUpdateColor(l); - } - }); - } -} - -function bFixCross() { - if( !selectedId || !(selectedId in borders) ) - return; - setBordersSelectable(false); - crossSelected = selectedId; - fcPreview = null; - $('#actions').css('display', 'none'); - $('#fc_sel').text(crossSelected); - $('#fc_do').css('display', 'none'); - $('#fixcross').css('display', 'block'); - selectCrossingByRegion(crossSelected); -} - -function bFixCrossPreview() { - if( fcPreview != null ) { - map.removeLayer(fcPreview); - fcPreview = null; - } - $('#fc_do').css('display', 'none'); - $.ajax(getServer('fixcrossing'), { - data: { - 'preview': 1, - 'region': crossSelected, - 'ids': Object.keys(selectedCrossings).join(',') - }, - success: bFixCrossDrawPreview - }); -} - -function bFixCrossDrawPreview(geojson) { - if( !('geometry' in geojson) ) { - return; - } - fcPreview = L.geoJson(geojson, { - style: function(f) { - return { color: 'red', weight: 1, fill: false }; - } - }); - map.addLayer(fcPreview); - $('#fc_do').css('display', 'block'); -} - -function bFixCrossDo() { - $.ajax(getServer('fixcrossing'), { - data: { - 'region': crossSelected, - 'ids': Object.keys(selectedCrossings).join(',') - }, - success: updateBorders - }); - bFixCrossCancel(); -} - -function bFixCrossCancel() { - if( fcPreview != null ) { - map.removeLayer(fcPreview); - fcPreview = null; - } - crossSelected = null; - selectCrossingByRegion(false); - selectedCrossings = {}; - updateBorders(); - $('#actions').css('display', 'block'); - $('#fixcross').css('display', 'none'); -} - function startOver() { if (confirm('Вы уверены, что хотите начать разбиение сначала?')) { finishChooseParent(); @@ -1306,7 +1126,6 @@ function startOver() { bPointCancel(); bDivideCancel(); bBackupCancel(); - bFixCrossCancel(); selectLayer(null); $('#wait_start_over').show(); $.ajax(getServer('start_over'), { diff --git a/web/app/templates/index.html b/web/app/templates/index.html index 7cfff93..2e55ab3 100644 --- a/web/app/templates/index.html +++ b/web/app/templates/index.html @@ -23,12 +23,12 @@ #info { margin-top: 1em; } #b_delete, #b_clear, .back_del { font-size: 8pt; } #split, #join, #join_to_parent, #point, - #divide, #backup, #fixcross { display: none; } + #divide, #backup { display: none; } .actions input[type='text'], #search input[type='text'] { width: 150px; } #header { border-bottom: 1px solid gray; margin-bottom: 1em; padding-bottom: 1em; } #f_topo, #f_chars, #f_comments, #links { font-size: 10pt; } #backup_saving, #backup_restoring { margin-bottom: 1em; } - #filefm, #old_action, #josm_old, #cross_actions { display: none; } + #filefm, #old_action, #josm_old { display: none; } #h_iframe { display: block; width: 100%; height: 80px; } a, a:hover, a:visited { color: blue; } #start_over, #start_over:hover, #start_over:visited { color: red; } @@ -226,16 +226,6 @@
-
- Границы региона будут поправлены, чтобы включать в себя подсвеченные красным линии. - Кликайте на линии, чтобы изменять их статус.
-
-
-
- -
- -