changeset 1983:f9f1babe52ae

Fix area generation from multipolygon input In case the waterway axis representing a stretch intersects distinct parts of the input area, a multipolygon has to be returned. Before, an arbitrary polygon was selected due to the used function not being set-returning. In passing, consistently name respective columns in schema.
author Tom Gottfried <tom@intevation.de>
date Wed, 23 Jan 2019 16:25:43 +0100
parents a7e47a9d890b
children 48001472e1d8 8eeb0b5eb340 29f02d0043a9
files client/src/components/Maplayer.vue pkg/imports/st.go schema/auth.sql schema/auth_tests.sql schema/gemma.sql schema/isrs_functions.sql schema/isrs_tests.sql schema/run_tests.sh schema/tap_tests_data.sql
diffstat 9 files changed, 35 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/Maplayer.vue	Wed Jan 23 16:18:36 2019 +0100
+++ b/client/src/components/Maplayer.vue	Wed Jan 23 16:25:43 2019 +0100
@@ -276,7 +276,7 @@
           featureNS: "gemma",
           featurePrefix: "gemma",
           featureTypes: ["stretches_geoserver"],
-          geometryName: "geom"
+          geometryName: "area"
         },
         "/internal/wfs",
         layer.data.getSource()
--- a/pkg/imports/st.go	Wed Jan 23 16:18:36 2019 +0100
+++ b/pkg/imports/st.go	Wed Jan 23 16:25:43 2019 +0100
@@ -97,7 +97,7 @@
 INSERT INTO waterway.stretches (
   name,
   stretch,
-  geom,
+  area,
   objnam,
   nobjnam,
   date_info,
--- a/schema/auth.sql	Wed Jan 23 16:18:36 2019 +0100
+++ b/schema/auth.sql	Wed Jan 23 16:25:43 2019 +0100
@@ -127,7 +127,7 @@
 
 CREATE POLICY responsibility_area ON waterway.stretches
     FOR ALL TO sys_admin
-    USING (utm_covers(geom));
+    USING (utm_covers(area));
 
 --
 -- RLS policies for imports and import config
--- a/schema/auth_tests.sql	Wed Jan 23 16:18:36 2019 +0100
+++ b/schema/auth_tests.sql	Wed Jan 23 16:25:43 2019 +0100
@@ -52,7 +52,7 @@
 --
 SET SESSION AUTHORIZATION test_admin_at;
 
-PREPARE bn_insert (varchar, geometry(POLYGON, 4326)) AS
+PREPARE bn_insert (varchar, geometry(MULTIPOLYGON, 4326)) AS
     INSERT INTO waterway.bottlenecks (
         bottleneck_id, fk_g_fid, stretch, area, rb, lb, responsible_country,
         revisiting_time, limiting, source_organization)
@@ -67,13 +67,13 @@
 SELECT lives_ok($$
     EXECUTE bn_insert(
         'test1',
-        ST_geomfromtext('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))', 4326))
+        ST_geomfromtext('MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))', 4326))
     $$,
     'Waterway admin can insert data within his region');
 SELECT throws_ok($$
     EXECUTE bn_insert(
         'test2',
-        ST_geomfromtext('POLYGON((1 0, 1 1, 2 1, 2 0, 1 0))', 4326))
+        ST_geomfromtext('MULTIPOLYGON(((1 0, 1 1, 2 1, 2 0, 1 0)))', 4326))
     $$,
     42501, NULL,
     'Waterway admin cannot insert data outside his region');
--- a/schema/gemma.sql	Wed Jan 23 16:18:36 2019 +0100
+++ b/schema/gemma.sql	Wed Jan 23 16:25:43 2019 +0100
@@ -351,10 +351,7 @@
         id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
         name varchar NOT NULL,
         stretch isrsrange NOT NULL,
-        -- TODO: make it a (MULTI)-LINESTRING.
-        -- POLYGON is chosen for the convinience
-        -- of re-using ISRSrange_area.
-        geom geography(POLYGON, 4326) NOT NULL,
+        area geography(MULTIPOLYGON, 4326) NOT NULL,
         objnam varchar NOT NULL,
         nobjnam varchar,
         date_info timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
@@ -376,7 +373,7 @@
         name,
         (stretch).lower::varchar as lower,
         (stretch).upper::varchar as upper,
-        geom::Geometry(POLYGON, 4326),
+        area::Geometry(MULTIPOLYGON, 4326),
         objnam,
         nobjnam,
         date_info,
@@ -442,7 +439,7 @@
         objnam varchar,
         nobjnm varchar,
         stretch isrsrange NOT NULL,
-        area geography(POLYGON, 4326) NOT NULL,
+        area geography(MULTIPOLYGON, 4326) NOT NULL,
         rb char(2) NOT NULL REFERENCES countries, -- from rb_lb in interface
         lb char(2) NOT NULL REFERENCES countries, -- from rb_lb in interface
         responsible_country char(2) NOT NULL REFERENCES countries,
--- a/schema/isrs_functions.sql	Wed Jan 23 16:18:36 2019 +0100
+++ b/schema/isrs_functions.sql	Wed Jan 23 16:25:43 2019 +0100
@@ -94,9 +94,9 @@
                         'endcap=flat'),
                     ST_Transform(area, z)))).geom
                 FROM axis_substring, utm_zone)
-        -- From the polygons returned by the last CTE, select only the one
+        -- From the polygons returned by the last CTE, select only those
         -- around the clipped axis
-        SELECT ST_Transform(range_area.geom, ST_SRID(area))
+        SELECT ST_Collect(ST_Transform(range_area.geom, ST_SRID(area)))
             FROM axis_substring, range_area
             WHERE ST_Intersects(range_area.geom, axis_substring.line)
     $$
--- a/schema/isrs_tests.sql	Wed Jan 23 16:18:36 2019 +0100
+++ b/schema/isrs_tests.sql	Wed Jan 23 16:25:43 2019 +0100
@@ -37,6 +37,7 @@
     ) IS NULL,
     'ISRSrange_area returns NULL, if given area does not intersect with axis');
 
+\set test_area 'POLYGON((-1 1, 2 1, 2 -1, -1 -1, -1 1))'
 SELECT ok(
     ST_DWithin(
         (SELECT geom FROM waterway.distance_marks_virtual
@@ -44,7 +45,7 @@
         ST_Boundary(ISRSrange_area(isrsrange(
                 ('AT', 'XXX', '00001', '00000', 0)::isrs,
                 ('AT', 'XXX', '00001', '00000', 1)::isrs),
-            ST_SetSRID('POLYGON((-1 1, 2 1, 2 -1, -1 -1, -1 1))'::geometry,
+            ST_SetSRID(:'test_area'::geometry,
                 4326)))::geography,
         1)
     AND
@@ -54,7 +55,25 @@
         ST_Boundary(ISRSrange_area(isrsrange(
                 ('AT', 'XXX', '00001', '00000', 0)::isrs,
                 ('AT', 'XXX', '00001', '00000', 1)::isrs),
-            ST_SetSRID('POLYGON((-1 1, 2 1, 2 -1, -1 -1, -1 1))'::geometry,
+            ST_SetSRID(:'test_area'::geometry,
                 4326)))::geography,
         1),
     'Resulting polygon almost ST_Touches points corresponding to stretch');
+
+SELECT ok(
+    2 = 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))/2
+                            + 0.1, 0),
+                    ST_Translate(:'test_area',
+                        -((ST_XMax(:'test_area'::geometry)
+                            - ST_XMin(:'test_area'::geometry))/2
+                            + 0.1), 0)),
+                4326))),
+    'Two intersecting polygons lead to two polygons in result');
--- a/schema/run_tests.sh	Wed Jan 23 16:18:36 2019 +0100
+++ b/schema/run_tests.sh	Wed Jan 23 16:25:43 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(55)' \
+    -c 'SELECT plan(56)' \
     -f isrs_tests.sql \
     -f auth_tests.sql \
     -f manage_users_tests.sql \
--- a/schema/tap_tests_data.sql	Wed Jan 23 16:18:36 2019 +0100
+++ b/schema/tap_tests_data.sql	Wed Jan 23 16:25:43 2019 +0100
@@ -55,7 +55,7 @@
         ('AT', 'XXX', '00001', 'G0001', 1)::isrs,
         isrsrange(('AT', 'XXX', '00001', '00000', 0)::isrs,
             ('AT', 'XXX', '00001', '00000', 2)::isrs),
-        ST_geomfromtext('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))', 4326),
+        ST_geomfromtext('MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))', 4326),
         'AT', 'AT', 'AT',
         1, 'depth', 'testorganization', false
     ), (
@@ -63,7 +63,7 @@
         ('AT', 'XXX', '00001', 'G0001', 1)::isrs,
         isrsrange(('AT', 'XXX', '00001', '00000', 0)::isrs,
             ('AT', 'XXX', '00001', '00000', 2)::isrs),
-        ST_geomfromtext('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))', 4326),
+        ST_geomfromtext('MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))', 4326),
         'AT', 'AT', 'AT',
         1, 'depth', 'testorganization', true
     );