mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-09-10 10:03:21 -04:00
109 lines
3.4 KiB
Python
Executable File
109 lines
3.4 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
from copy import deepcopy
|
|
import geojson
|
|
from pathlib import Path
|
|
import shapely.geometry as sgeom
|
|
|
|
from repo import BroadcastAreasRepository
|
|
|
|
package_path = Path(__file__).resolve().parent
|
|
|
|
|
|
def simplify_polygon(series):
|
|
polygon, *_holes = series # discard holes
|
|
|
|
approx_metres_to_degree = 111320
|
|
desired_resolution_metres = 10
|
|
simplify_degrees = desired_resolution_metres / approx_metres_to_degree
|
|
|
|
simplified_polygon = None
|
|
num_polys = len(polygon)
|
|
while True:
|
|
simplified_polygon = sgeom.LineString(polygon)
|
|
simplified_polygon = simplified_polygon.buffer(simplify_degrees)
|
|
simplified_polygon = simplified_polygon.simplify(simplify_degrees)
|
|
simplified_polygon = [[c[0], c[1]] for c in simplified_polygon.exterior.coords]
|
|
|
|
num_polys = len(simplified_polygon)
|
|
simplify_degrees *= 1.5
|
|
if num_polys <= 125:
|
|
break
|
|
|
|
return [simplified_polygon]
|
|
|
|
|
|
def simplify_geometry(feature):
|
|
if feature["type"] == "Polygon":
|
|
feature["coordinates"] = simplify_polygon(feature["coordinates"])
|
|
return feature
|
|
elif feature["type"] == "MultiPolygon":
|
|
feature["coordinates"] = [
|
|
simplify_polygon(polygon)
|
|
for polygon in feature["coordinates"]
|
|
]
|
|
return feature
|
|
else:
|
|
raise Exception("Unknown type: {}".format(feature["type"]))
|
|
|
|
|
|
repo = BroadcastAreasRepository()
|
|
|
|
repo.delete_db()
|
|
repo.create_tables()
|
|
|
|
simple_datasets = [
|
|
("Countries", "ctry19nm"),
|
|
("Regions of England", "rgn18nm"),
|
|
("Counties and Unitary Authorities in England and Wales", "ctyua16nm"),
|
|
]
|
|
for dataset_name, name_field in simple_datasets:
|
|
filepath = package_path / "{}.geojson".format(dataset_name)
|
|
dataset_geojson = geojson.loads(filepath.read_text())
|
|
|
|
repo.insert_broadcast_area_library(dataset_name)
|
|
|
|
for feature in dataset_geojson["features"]:
|
|
f_name = feature["properties"][name_field]
|
|
|
|
simple_feature = deepcopy(feature)
|
|
simple_feature["geometry"] = simplify_geometry(simple_feature["geometry"])
|
|
repo.insert_broadcast_areas([[f_name, dataset_name, feature, simple_feature]])
|
|
|
|
# https://geoportal.statistics.gov.uk/datasets/wards-may-2020-boundaries-uk-bgc
|
|
# Converted to geojson manually from SHP because of GeoJSON download limits
|
|
wards_filepath = package_path / "Electoral Wards May 2020.geojson"
|
|
|
|
# http://geoportal.statistics.gov.uk/datasets/ward-to-westminster-parliamentary-constituency-to-local-authority-district-december-2019-lookup-in-the-united-kingdom/data
|
|
las_filepath = package_path / "Electoral Wards and Local Authorities 2020.geojson"
|
|
|
|
ward_code_to_la_mapping = {
|
|
f["properties"]["WD19CD"]: f["properties"]["LAD19NM"]
|
|
for f in geojson.loads(las_filepath.read_text())["features"]
|
|
}
|
|
|
|
dataset_name = "Electoral Wards of the United Kingdom"
|
|
repo.insert_broadcast_area_library(dataset_name)
|
|
|
|
areas_to_add = []
|
|
|
|
for f in geojson.loads(wards_filepath.read_text())["features"]:
|
|
|
|
ward_code = f["properties"]["wd20cd"]
|
|
ward_name = f["properties"]["wd20nm"]
|
|
|
|
try:
|
|
la_name = ward_code_to_la_mapping[ward_code]
|
|
|
|
f_name = "{} - {}".format(la_name, ward_name)
|
|
|
|
sf = deepcopy(f)
|
|
sf["geometry"] = simplify_geometry(sf["geometry"])
|
|
|
|
areas_to_add.append([f_name, dataset_name, f, sf])
|
|
|
|
except KeyError:
|
|
print("Skipping", ward_code, ward_name) # noqa: T001
|
|
|
|
repo.insert_broadcast_areas(areas_to_add)
|