From f689455ebbf53526c41fce037b20db9314dc4e7f Mon Sep 17 00:00:00 2001 From: Michal Migurski Date: Wed, 3 Aug 2016 17:25:48 -0700 Subject: [PATCH 1/3] By default, simplifying WoF geometries --- App/__init__.py | 19 +++++++++++++++---- requirements.txt | 2 ++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/App/__init__.py b/App/__init__.py index 5939b30..5ed9c5e 100644 --- a/App/__init__.py +++ b/App/__init__.py @@ -2,11 +2,12 @@ from operator import itemgetter from os.path import join, dirname from threading import Thread -import json, os +import json, os, math import requests import uritemplate import psycopg2 +import shapely.geometry from flask import ( Blueprint, jsonify, Response, render_template, url_for, request, session @@ -125,8 +126,18 @@ def wof_geojson(id): template = 'http://whosonfirst.mapzen.com/spelunker/id/{id}.geojson' url = uritemplate.expand(template, dict(id=id)) wof_resp = requests.get(url) + + if wof_resp.status_code != 200: + return Response('No WoF with ID {}'.format(id), status=404) + + geojson = wof_resp.json() + geom = shapely.geometry.shape(geojson.get('geometry', {})) + print('Raw {} chars of WKT with area {:.6f}'.format(len(str(geom)), geom.area)) - headers = {key: val for (key, val) in wof_resp.headers.items() - if key in ('Content-Type', 'Content-Length')} + x1, y1, x2, y2 = geom.bounds + hypot = math.hypot(x1 - x2, y1 - y2) + simple = geom.simplify(hypot/100) + print('Simplified to {} chars of WKT with tolerance {:.6f}'.format(len(str(simple)), hypot/100)) - return Response(wof_resp.content, headers=headers) + geojson['geometry'] = shapely.geometry.mapping(simple) + return jsonify(geojson) diff --git a/requirements.txt b/requirements.txt index e8a3f0a..95b1071 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,3 +18,5 @@ beautifulsoup4==4.4.1 httmock==1.2.5 psycopg2==2.6.1 mock==2.0.0 + +Shapely==1.5.16 From 52fdeecd284d392c1efaf1027ab6415d1d218d2c Mon Sep 17 00:00:00 2001 From: Michal Migurski Date: Wed, 3 Aug 2016 17:34:56 -0700 Subject: [PATCH 2/3] Added raw GeoJSON download options --- App/__init__.py | 7 ++++++- App/templates/metro.html | 2 +- App/templates/odes/extract.html | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/App/__init__.py b/App/__init__.py index 5ed9c5e..dcbde5f 100644 --- a/App/__init__.py +++ b/App/__init__.py @@ -129,7 +129,12 @@ def wof_geojson(id): if wof_resp.status_code != 200: return Response('No WoF with ID {}'.format(id), status=404) - + + if request.args.get('raw') == 'yes': + headers = {key: val for (key, val) in wof_resp.headers.items() + if key in ('Content-Type', 'Content-Length')} + return Response(wof_resp.content, headers=headers) + geojson = wof_resp.json() geom = shapely.geometry.shape(geojson.get('geometry', {})) print('Raw {} chars of WKT with area {:.6f}'.format(len(str(geom)), geom.area)) diff --git a/App/templates/metro.html b/App/templates/metro.html index 5c03ef4..0a29db8 100644 --- a/App/templates/metro.html +++ b/App/templates/metro.html @@ -31,7 +31,7 @@

{{ metro.name }}

{{ wof_name }}

To clip this extract to the {{wof_name}} boundary, use this outline:

- {{wof_name}} GEOJSON + {{wof_name}} GEOJSON
{% endif %} diff --git a/App/templates/odes/extract.html b/App/templates/odes/extract.html index a113592..d4d857d 100644 --- a/App/templates/odes/extract.html +++ b/App/templates/odes/extract.html @@ -47,7 +47,7 @@

{{extract.name or extract.wof.name or extract.id or extract.odes.id}}

{% if extract.wof.name and extract.wof.id %}

To clip this extract to the {{extract.wof.name}} boundary, use this outline:

- {{extract.wof.name}} GEOJSON + {{extract.wof.name}} GEOJSON
{% endif %}

Downloads

From 72f7d9d60718ff06b19f6886903f5c31e7e1e47d Mon Sep 17 00:00:00 2001 From: Michal Migurski Date: Wed, 3 Aug 2016 17:45:51 -0700 Subject: [PATCH 3/3] Redirecting to raw data instead of proxy --- App/__init__.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/App/__init__.py b/App/__init__.py index dcbde5f..c2c612f 100644 --- a/App/__init__.py +++ b/App/__init__.py @@ -125,17 +125,21 @@ def wof_geojson(id): ''' template = 'http://whosonfirst.mapzen.com/spelunker/id/{id}.geojson' url = uritemplate.expand(template, dict(id=id)) - wof_resp = requests.get(url) - if wof_resp.status_code != 200: + while True: + wof_head = requests.head(url) + if wof_head.status_code in (301, 302, 303): + url = wof_head.headers.get('Location') + else: + break + + if wof_head.status_code != 200: return Response('No WoF with ID {}'.format(id), status=404) if request.args.get('raw') == 'yes': - headers = {key: val for (key, val) in wof_resp.headers.items() - if key in ('Content-Type', 'Content-Length')} - return Response(wof_resp.content, headers=headers) + return Response(url, status=302, headers={'Location': url}) - geojson = wof_resp.json() + geojson = requests.get(url).json() geom = shapely.geometry.shape(geojson.get('geometry', {})) print('Raw {} chars of WKT with area {:.6f}'.format(len(str(geom)), geom.area))