changeset 2232:7936b46a88d4

Handle invalid multipolygons in area generation from stretch
author Tom Gottfried <tom@intevation.de>
date Wed, 13 Feb 2019 11:44:27 +0100
parents 97bba8b51b9c
children 137addc77b1b
files schema/isrs_functions.sql schema/isrs_tests.sql schema/run_tests.sh
diffstat 3 files changed, 34 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/schema/isrs_functions.sql	Wed Feb 13 11:13:06 2019 +0100
+++ b/schema/isrs_functions.sql	Wed Feb 13 11:44:27 2019 +0100
@@ -19,6 +19,8 @@
 -- Distance marks are assumed to be near the axis and the area passed as
 -- argument is assumed to intersect with the axis
 -- (use e.g. waterway area or fairway dimensions).
+-- If a multipolygon is passed, the union of the polygons intersecting with the
+-- relevant part of the axis is used for clipping.
 CREATE OR REPLACE FUNCTION ISRSrange_area(
     stretch isrsrange,
     area geometry
@@ -79,6 +81,15 @@
                     ST_LineLocatePoint(axis_segment.line, to_point.geom)
                 ), 0.0001) AS line
             FROM axis_segment, from_point, to_point),
+        area_subset AS (
+            -- In case area is a multipolygon, process the union of those
+            -- polygons, which intersect with the axis. The union is to avoid
+            -- problems with invalid/self-intersecting multipolygons
+            SELECT ST_Union(a_dmp.geom) AS area
+                FROM axis_substring, utm_zone,
+                    ST_Dump(ST_Transform(area, z)) AS a_dmp
+                WHERE ST_Intersects(a_dmp.geom, axis_substring.line)
+            ),
         range_area AS (
             -- Create a buffer around the clipped axis, as large as it could
             -- potentially be intersecting with the area polygon that
@@ -90,10 +101,10 @@
                         axis_substring.line,
                         ST_MaxDistance(
                             axis_substring.line,
-                            ST_Transform(area, z)),
+                            area_subset.area),
                         'endcap=flat'),
-                    ST_Transform(area, z)))).geom
-                FROM axis_substring, utm_zone)
+                    area_subset.area))).geom
+                FROM axis_substring, area_subset)
         -- From the polygons returned by the last CTE, select only those
         -- around the clipped axis
         SELECT ST_Collect(ST_Transform(range_area.geom, ST_SRID(area)))
--- a/schema/isrs_tests.sql	Wed Feb 13 11:13:06 2019 +0100
+++ b/schema/isrs_tests.sql	Wed Feb 13 11:44:27 2019 +0100
@@ -81,4 +81,22 @@
                             - ST_XMin(:'test_area'::geometry))/2
                             + 0.1), 0)),
                 4326))),
-    'Two intersecting polygons lead to two polygons in result');
+    'Two polygons intersecting the axis lead to two polygons in result');
+
+SELECT ok(
+    1 = ST_NumGeometries(
+        ISRSrange_area(
+            isrsrange(
+                ('AT', 'XXX', '00001', '00000', 0)::isrs,
+                ('AT', 'XXX', '00001', '00000', 1)::isrs),
+            ST_SetSRID(ST_Collect(
+                    ST_Translate(:'test_area',
+                        (ST_XMax(:'test_area'::geometry)
+                            - ST_XMin(:'test_area'::geometry))/3,
+                            0),
+                    ST_Translate(:'test_area',
+                        -((ST_XMax(:'test_area'::geometry)
+                            - ST_XMin(:'test_area'::geometry))/3),
+                            0)),
+                4326))),
+    'Self-intersecting multipolygon leads to one polygon in result');
--- a/schema/run_tests.sh	Wed Feb 13 11:13:06 2019 +0100
+++ b/schema/run_tests.sh	Wed Feb 13 11:44:27 2019 +0100
@@ -28,7 +28,7 @@
     -c 'SET client_min_messages TO WARNING' \
     -c "DROP ROLE IF EXISTS $TEST_ROLES" \
     -f tap_tests_data.sql \
-    -c 'SELECT plan(56)' \
+    -c 'SELECT plan(57)' \
     -f isrs_tests.sql \
     -f auth_tests.sql \
     -f manage_users_tests.sql \