diff --git a/notifications_utils/broadcast_areas/create-broadcast-areas-db.py b/notifications_utils/broadcast_areas/create-broadcast-areas-db.py index c42226cdb..d0bc2e9f0 100755 --- a/notifications_utils/broadcast_areas/create-broadcast-areas-db.py +++ b/notifications_utils/broadcast_areas/create-broadcast-areas-db.py @@ -1,15 +1,26 @@ #!/usr/bin/env python from copy import deepcopy +import sqlite3 import geojson from pathlib import Path import shapely.geometry as sgeom +from notifications_utils.safe_string import make_string_safe_for_id + from repo import BroadcastAreasRepository package_path = Path(__file__).resolve().parent +def convert_shape_to_feature(shape): + return { + "type": "Feature", + "properties": {}, + "geometry": sgeom.mapping(shape), + } + + def simplify_polygon(series): polygon, *_holes = series # discard holes @@ -26,7 +37,7 @@ def simplify_polygon(series): simplified_polygon = [[c[0], c[1]] for c in simplified_polygon.exterior.coords] num_polys = len(simplified_polygon) - simplify_degrees *= 1.5 + simplify_degrees *= 1.75 if num_polys <= 125: break @@ -53,22 +64,30 @@ repo.delete_db() repo.create_tables() simple_datasets = [ - ("Countries", "ctry19nm"), - ("Regions of England", "rgn18nm"), - ("Counties and Unitary Authorities in England and Wales", "ctyua16nm"), + ("Countries", "ctry19cd", "ctry19nm"), + ("Regions of England", "rgn18cd", "rgn18nm"), + ("Counties and Unitary Authorities in England and Wales", "ctyua16cd", "ctyua16nm"), ] -for dataset_name, name_field in simple_datasets: +for dataset_name, id_field, name_field in simple_datasets: filepath = package_path / "{}.geojson".format(dataset_name) + + dataset_id = make_string_safe_for_id(dataset_name) dataset_geojson = geojson.loads(filepath.read_text()) - repo.insert_broadcast_area_library(dataset_name) + repo.insert_broadcast_area_library(dataset_id, dataset_name, False) for feature in dataset_geojson["features"]: + f_id = dataset_id + "-" + feature["properties"][id_field] 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]]) + + repo.insert_broadcast_areas([[ + f_id, f_name, + dataset_id, None, + 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 @@ -81,28 +100,73 @@ ward_code_to_la_mapping = { f["properties"]["WD19CD"]: f["properties"]["LAD19NM"] for f in geojson.loads(las_filepath.read_text())["features"] } +ward_code_to_la_id_mapping = { + f["properties"]["WD19CD"]: f["properties"]["LAD19CD"] + 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) +dataset_id = make_string_safe_for_id(dataset_name) +repo.insert_broadcast_area_library(dataset_id, dataset_name, True) + +for f in geojson.loads(las_filepath.read_text())["features"]: + group_id = dataset_id + "-" + f["properties"]["LAD19CD"] + group_name = f["properties"]["LAD19NM"] + + try: + repo.insert_broadcast_area_library_group(group_id, group_name, dataset_id) + except sqlite3.IntegrityError: + # Already exists + pass areas_to_add = [] for f in geojson.loads(wards_filepath.read_text())["features"]: - ward_code = f["properties"]["wd20cd"] ward_name = f["properties"]["wd20nm"] + ward_id = dataset_id + "-" + ward_code try: + la_id = dataset_id + "-" + ward_code_to_la_id_mapping[ward_code] 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]) + areas_to_add.append([ + ward_id, ward_name, + dataset_id, la_id, + f, sf + ]) except KeyError: print("Skipping", ward_code, ward_name) # noqa: T001 repo.insert_broadcast_areas(areas_to_add) +areas_to_add = [] + +for group_id, group_name in repo.get_all_groups_for_library(dataset_id): + areas = repo.get_all_areas_for_group(group_id) + + features = [geojson.loads(f) for _, _, f, _ in areas] + shapes = [sgeom.shape(f["geometry"]) for f in features] + + if len(shapes) == 0: + continue + + print(group_id, group_name, "union") + shape = shapes[0] + for other in shapes[1:]: + shape = shape.buffer(0).union(other.buffer(0)) + + feature = convert_shape_to_feature(shape) + simple_feature = deepcopy(feature) + simple_feature["geometry"] = simplify_geometry(simple_feature["geometry"]) + + areas_to_add.append([ + group_id, group_name, + dataset_id, None, + feature, simple_feature + ]) + +repo.insert_broadcast_areas(areas_to_add)