Compare commits

...

2 Commits

Author SHA1 Message Date
Chris Hill-Scott
3b11fc76d7 Pass polygons through if they’re small already
If a polygon is smaller than the largest polygon in our dataset of
simplified polygons then we’re only throwing away useful detail by
simplifying it.

We should still simplify larger polygons as a fallback, to avoid sending
anything to the CBC that we’re not sure it will like.

The thresholds here are low: we can raise them as we test and experiment
more.

Here’s some data about the Flood Warning Service polygons

Percentile | 80% | 90%   | 95%    | 98%     | 99%     | 99.9%
-----------|-----|-------|--------|---------|---------|---------
Point count| 226 | 401.9 | 640.45 | 1015.38 | 1389.07 | 3008.609

Percentile    | 80% | 90%   | 95%    | 98%     | 99%     | 99.9%
--------------|-----|-------|--------|---------|---------|---------
Polygon count |2----|3------|5-------|8--------|10-------|40.469
2021-11-18 13:54:56 +00:00
Chris Hill-Scott
fc905d21f5 Bump utils
This new version of utils implements the transformation of our polygons
to a Cartesian plane. In other words, it converts them from being
defined in spherical degrees to metres.

For the API this means our simplification will be slightly more
accurate.
2021-11-18 13:54:21 +00:00
5 changed files with 79 additions and 8 deletions

View File

@@ -29,5 +29,5 @@ def cap_xml_polygon_to_list(polygon_string):
[
float(coordinate) for coordinate in pair.split(',')
]
for pair in polygon_string.split(' ')
for pair in polygon_string.strip().split(' ')
]

View File

@@ -44,9 +44,17 @@ def create_broadcast():
_validate_template(broadcast_json)
polygons = Polygons(list(chain.from_iterable((
area['polygons'] for area in broadcast_json['areas']
[
[[y, x] for x, y in polygon]
for polygon in area['polygons']
] for area in broadcast_json['areas']
))))
if len(polygons) > 12 or polygons.point_count > 250:
simple_polygons = polygons.smooth.simplify
else:
simple_polygons = polygons
broadcast_message = BroadcastMessage(
service_id=authenticated_service.id,
content=broadcast_json['content'],
@@ -56,7 +64,7 @@ def create_broadcast():
'names': [
area['name'] for area in broadcast_json['areas']
],
'simple_polygons': polygons.smooth.simplify.as_coordinate_pairs_long_lat,
'simple_polygons': simple_polygons.as_coordinate_pairs_lat_long,
},
status=BroadcastStatusType.PENDING_APPROVAL,
api_key_id=api_user.id,

View File

@@ -36,7 +36,7 @@ notifications-python-client==6.0.2
# PaaS
awscli-cwlogs==1.4.6
git+https://github.com/alphagov/notifications-utils.git@48.1.0#egg=notifications-utils==48.1.0
git+https://github.com/alphagov/notifications-utils.git@48.0.0#egg=notifications-utils==49.0.0
# gds-metrics requires prometheseus 0.2.0, override that requirement as 0.7.1 brings significant performance gains
prometheus-client==0.10.1

File diff suppressed because one or more lines are too long

View File

@@ -104,10 +104,10 @@ def test_valid_post_cap_xml_broadcast_returns_201(
assert response_json['personalisation'] is None
assert response_json['service_id'] == str(sample_broadcast_service.id)
assert len(response_json['areas']['simple_polygons']) == 1
assert len(response_json['areas']['simple_polygons'][0]) == 22
assert response_json['areas']['simple_polygons'][0][0] == [53.10562, 0.244127]
assert response_json['areas']['simple_polygons'][0][-1] == [53.10562, 0.244127]
assert len(response_json['simple_polygons']) == 1
assert len(response_json['simple_polygons'][0]) == 29
assert response_json['simple_polygons'][0][0] == [53.10569, 0.24453]
assert response_json['simple_polygons'][0][-1] == [53.10569, 0.24453]
assert response_json['areas']['names'] == ['River Steeping in Wainfleet All Saints']
assert 'ids' not in response_json['areas'] # only for broadcasts created in Admin
@@ -119,6 +119,27 @@ def test_valid_post_cap_xml_broadcast_returns_201(
assert response_json['updated_at'] is None
def test_large_polygon_is_simplified(
client,
sample_broadcast_service,
):
auth_header = create_service_authorization_header(service_id=sample_broadcast_service.id)
response = client.post(
path='/v2/broadcast',
data=sample_cap_xml_documents.WINDEMERE,
headers=[('Content-Type', 'application/cap+xml'), auth_header],
)
assert response.status_code == 201
response_json = json.loads(response.get_data(as_text=True))
assert len(response_json['simple_polygons']) == 1
assert len(response_json['simple_polygons'][0]) == 110
assert response_json['simple_polygons'][0][0] == [54.419546, -2.988521]
assert response_json['simple_polygons'][0][-1] == [54.419546, -2.988521]
@pytest.mark.parametrize("training_mode_service", [True, False])
def test_valid_post_cap_xml_broadcast_sets_stubbed_to_true_for_training_mode_services(
client,