From 953507125c3371fa3244f18da97bf88b80da4e45 Mon Sep 17 00:00:00 2001 From: Karsten Prehn Date: Wed, 24 Jul 2024 03:18:17 +0000 Subject: [PATCH 1/3] Added check for multi-point geometry to make sure a double-bracketed wkt of that geometry is sent to geoserver --- boranga/components/spatial/utils.py | 50 ++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/boranga/components/spatial/utils.py b/boranga/components/spatial/utils.py index 2c5ef773..00a09e5c 100644 --- a/boranga/components/spatial/utils.py +++ b/boranga/components/spatial/utils.py @@ -50,6 +50,8 @@ def invert_xy_coordinates(geometries): def intersect_geometry_with_layer(geometry, intersect_layer, geometry_name="SHAPE"): + """Query a geoserver WFS layer with a geometry and return the intersecting features as JSON.""" + geoserver_url = intersect_layer.geoserver_url intersect_layer_name = intersect_layer.layer_name invert_xy = intersect_layer.invert_xy @@ -58,6 +60,22 @@ def intersect_geometry_with_layer(geometry, intersect_layer, geometry_name="SHAP if invert_xy: test_geom = invert_xy_coordinates([geometry])[0] + if test_geom.geom_type in ["MultiPoint"]: + # For some unknown silly reason, geoserver's jts cannot handle valid single-bracketed multipoint geometries, + # e.g. MULTIPOINT (3 1, 4 1, 5 2), and rather throws unintelligible java class exceptions at me, so we + # have to convert them to a double-bracket notation in the form of MULTIPOINT ((3 1), (4 1), (5 2)). Even + # though both forms are (topologically) valid by OGC definition, the jts (java topology suite) library only + # seems to except singleton lists (https://www.tsusiatsoftware.net/jts/javadoc/com/vividsolutions/jts/io/WKTReader.html) + logger.warn( + f"Converting MultiPoint geometry {test_geom} to double-bracket notation" + ) + test_geom_wkt = ( + f'MULTIPOINT ({", ".join([f"({c[0]} {c[1]})" for c in test_geom.coords])})' + ) + else: + test_geom_wkt = test_geom.wkt + + wkt.loads(test_geom.wkt) params = { "service": "WFS", "version": "2.0.0", @@ -67,7 +85,7 @@ def intersect_geometry_with_layer(geometry, intersect_layer, geometry_name="SHAP "srsName": "EPSG:4326", # using the default projection for open layers and geodjango "outputFormat": "application/json", "propertyName": f"{geometry_name},CAD_OWNER_NAME,CAD_OWNER_COUNT", - "CQL_FILTER": f"INTERSECTS({geometry_name}, {test_geom.wkt})", + "CQL_FILTER": f"INTERSECTS({geometry_name}, {test_geom_wkt})", } request_path = ( @@ -142,16 +160,15 @@ def populate_occurrence_tenure_data(geometry_instance, features, request): else: occurrence_tenures = OccurrenceTenure.objects.filter( tenure_area_id=feature_id - ).exclude(occurrence_geometry=None,tenure_area_id=None) + ).exclude(occurrence_geometry=None, tenure_area_id=None) occurrence_tenures_current = occurrence_tenures.filter( - occurrence_geometry=geometry_instance, - status="current" + occurrence_geometry=geometry_instance, status="current" ) occurrence_tenures_historical = occurrence_tenures.filter( historical_occurrence=geometry_instance.occurrence.id, - status="historical" + status="historical", ) if occurrence_tenures_current.exists(): @@ -298,7 +315,7 @@ def save_geometry( InstanceCopiedFrom ) - opacity = feature.get("properties", {}).get("opacity", .5) + opacity = feature.get("properties", {}).get("opacity", 0.5) geom_4326 = feature_json_to_geosgeometry(feature) @@ -454,9 +471,20 @@ def save_geometry( # or have been drawn by another user geometry_ids = list(geometry_id_intersect_data.keys()) if instance_fk_field_name == "occurrence": - affected_tenure_ids = list(OccurrenceTenure.objects.filter(occurrence_geometry__in=(InstanceGeometry.objects.filter(**{instance_fk_field_name: instance}) - .exclude(Q(id__in=geometry_ids) | Q(locked=True) | ~Q(drawn_by=request.user.id)))).values_list("id",flat=True)) - + affected_tenure_ids = list( + OccurrenceTenure.objects.filter( + occurrence_geometry__in=( + InstanceGeometry.objects.filter( + **{instance_fk_field_name: instance} + ).exclude( + Q(id__in=geometry_ids) + | Q(locked=True) + | ~Q(drawn_by=request.user.id) + ) + ) + ).values_list("id", flat=True) + ) + deleted_geometries = ( InstanceGeometry.objects.filter(**{instance_fk_field_name: instance}) .exclude(Q(id__in=geometry_ids) | Q(locked=True) | ~Q(drawn_by=request.user.id)) @@ -466,9 +494,9 @@ def save_geometry( logger.info( f"Deleted {instance_model_name} geometries: {deleted_geometries} for {instance}" ) - + if instance_fk_field_name == "occurrence": - #we save affected tenures to record the historical change + # we save affected tenures to record the historical change affected_tenures = OccurrenceTenure.objects.filter(id__in=affected_tenure_ids) for i in affected_tenures: i.save(version_user=request.user) From bde36776b466a678842a0442aeb5496d5325af89 Mon Sep 17 00:00:00 2001 From: Karsten Prehn Date: Wed, 24 Jul 2024 03:18:51 +0000 Subject: [PATCH 2/3] Added svg for multi-polygons in the list of geometries --- .../src/components/common/component_map.vue | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/boranga/frontend/boranga/src/components/common/component_map.vue b/boranga/frontend/boranga/src/components/common/component_map.vue index 1b03702d..2e48a221 100644 --- a/boranga/frontend/boranga/src/components/common/component_map.vue +++ b/boranga/frontend/boranga/src/components/common/component_map.vue @@ -364,6 +364,53 @@ stroke-width="2" /> + + + + + Date: Wed, 24 Jul 2024 04:28:43 +0000 Subject: [PATCH 3/3] Updated sql queries to support multi polygons --- docs/sql-scripts/OccurrenceCommunity.sql | 1 + docs/sql-scripts/OccurrenceFauna.sql | 1 + docs/sql-scripts/OccurrenceFlora.sql | 1 + docs/sql-scripts/OccurrenceReportCommunity.sql | 1 + docs/sql-scripts/OccurrenceReportFauna.sql | 1 + docs/sql-scripts/OccurrenceReportFlora.sql | 1 + 6 files changed, 6 insertions(+) diff --git a/docs/sql-scripts/OccurrenceCommunity.sql b/docs/sql-scripts/OccurrenceCommunity.sql index e87b807a..41c475f7 100644 --- a/docs/sql-scripts/OccurrenceCommunity.sql +++ b/docs/sql-scripts/OccurrenceCommunity.sql @@ -131,6 +131,7 @@ geom AS ( CASE ST_GeometryType(geometry) WHEN 'ST_Point' THEN ST_Buffer(geometry, 0.00001) + WHEN 'ST_MultiPoint' THEN ST_Buffer(geometry, 0.00001) ELSE geometry END AS geometry, ST_GeometryType(geometry) AS geometry_type, diff --git a/docs/sql-scripts/OccurrenceFauna.sql b/docs/sql-scripts/OccurrenceFauna.sql index 97bc52c5..87511cc0 100644 --- a/docs/sql-scripts/OccurrenceFauna.sql +++ b/docs/sql-scripts/OccurrenceFauna.sql @@ -131,6 +131,7 @@ geom AS ( CASE ST_GeometryType(geometry) WHEN 'ST_Point' THEN ST_Buffer(geometry, 0.00001) + WHEN 'ST_MultiPoint' THEN ST_Buffer(geometry, 0.00001) ELSE geometry END AS geometry, ST_GeometryType(geometry) AS geometry_type, diff --git a/docs/sql-scripts/OccurrenceFlora.sql b/docs/sql-scripts/OccurrenceFlora.sql index a174f121..14145939 100644 --- a/docs/sql-scripts/OccurrenceFlora.sql +++ b/docs/sql-scripts/OccurrenceFlora.sql @@ -131,6 +131,7 @@ geom AS ( CASE ST_GeometryType(geometry) WHEN 'ST_Point' THEN ST_Buffer(geometry, 0.00001) + WHEN 'ST_MultiPoint' THEN ST_Buffer(geometry, 0.00001) ELSE geometry END AS geometry, ST_GeometryType(geometry) AS geometry_type, diff --git a/docs/sql-scripts/OccurrenceReportCommunity.sql b/docs/sql-scripts/OccurrenceReportCommunity.sql index a4079111..5ede4226 100644 --- a/docs/sql-scripts/OccurrenceReportCommunity.sql +++ b/docs/sql-scripts/OccurrenceReportCommunity.sql @@ -72,6 +72,7 @@ geom AS ( CASE ST_GeometryType(geometry) WHEN 'ST_Point' THEN ST_Buffer(geometry, 0.00001) + WHEN 'ST_MultiPoint' THEN ST_Buffer(geometry, 0.00001) ELSE geometry END AS geometry, ST_GeometryType(geometry) AS geometry_type, diff --git a/docs/sql-scripts/OccurrenceReportFauna.sql b/docs/sql-scripts/OccurrenceReportFauna.sql index d170abfd..1d4ae8cb 100644 --- a/docs/sql-scripts/OccurrenceReportFauna.sql +++ b/docs/sql-scripts/OccurrenceReportFauna.sql @@ -72,6 +72,7 @@ geom AS ( CASE ST_GeometryType(geometry) WHEN 'ST_Point' THEN ST_Buffer(geometry, 0.00001) + WHEN 'ST_MultiPoint' THEN ST_Buffer(geometry, 0.00001) ELSE geometry END AS geometry, ST_GeometryType(geometry) AS geometry_type, diff --git a/docs/sql-scripts/OccurrenceReportFlora.sql b/docs/sql-scripts/OccurrenceReportFlora.sql index 2b50ce25..45c8f9f6 100644 --- a/docs/sql-scripts/OccurrenceReportFlora.sql +++ b/docs/sql-scripts/OccurrenceReportFlora.sql @@ -72,6 +72,7 @@ geom AS ( CASE ST_GeometryType(geometry) WHEN 'ST_Point' THEN ST_Buffer(geometry, 0.00001) + WHEN 'ST_MultiPoint' THEN ST_Buffer(geometry, 0.00001) ELSE geometry END AS geometry, ST_GeometryType(geometry) AS geometry_type,