# HG changeset patch # User Tom Gottfried # Date 1550054667 -3600 # Node ID 7936b46a88d4483b64d96567e007bb4851ab65e0 # Parent 97bba8b51b9c15ee70adcf0e2eeb15acdd2e5b37 Handle invalid multipolygons in area generation from stretch diff -r 97bba8b51b9c -r 7936b46a88d4 schema/isrs_functions.sql --- 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))) diff -r 97bba8b51b9c -r 7936b46a88d4 schema/isrs_tests.sql --- 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'); diff -r 97bba8b51b9c -r 7936b46a88d4 schema/run_tests.sh --- 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 \