From 59de7c5a9b2e16fdda93d3f9aac33f3b67a5bfb1 Mon Sep 17 00:00:00 2001 From: Sarah Hoffmann Date: Mon, 3 Nov 2014 22:41:12 +0100 Subject: [PATCH] fix address interpolation for self-intersecting ways --- sql/functions.sql | 14 ++++-- .../features/db/import/interpolation.feature | 46 +++++++++++++++++++ .../features/osm2pgsql/import/broken.feature | 37 +++++++++++++++ tests/steps/db_results.py | 1 + 4 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 tests/features/osm2pgsql/import/broken.feature diff --git a/sql/functions.sql b/sql/functions.sql index 48ac80b5..da9223ad 100644 --- a/sql/functions.sql +++ b/sql/functions.sql @@ -846,15 +846,13 @@ BEGIN IF search_place_id IS NOT NULL THEN select * from placex where place_id = search_place_id INTO nextnode; - IF nodeidpos < array_upper(waynodes, 1) THEN + IF nodeidpos > 1 and nodeidpos < array_upper(waynodes, 1) THEN -- Make sure that the point is actually on the line. That might -- be a bit paranoid but ensures that the algorithm still works -- should osm2pgsql attempt to repair geometries. splitline := split_line_on_node(linegeo, nextnode.geometry); sectiongeo := ST_GeometryN(splitline, 1); - IF ST_GeometryType(ST_GeometryN(splitline, 2)) = 'ST_LineString' THEN - linegeo := ST_GeometryN(splitline, 2); - END IF; + linegeo := ST_GeometryN(splitline, 2); ELSE sectiongeo = linegeo; END IF; @@ -862,7 +860,7 @@ BEGIN IF startnumber IS NOT NULL AND endnumber IS NOT NULL AND @(startnumber - endnumber) < 1000 AND startnumber != endnumber - AND ST_GeometryType(linegeo) = 'ST_LineString' THEN + AND ST_GeometryType(sectiongeo) = 'ST_LineString' THEN IF (startnumber > endnumber) THEN housenum := endnumber; @@ -897,6 +895,12 @@ BEGIN END LOOP; END IF; + -- early break if we are out of line string, + -- might happen when a line string loops back on itself + IF ST_GeometryType(linegeo) != 'ST_LineString' THEN + RETURN newpoints; + END IF; + startnumber := substring(nextnode.housenumber,'[0-9]+')::integer; prevnode := nextnode; END IF; diff --git a/tests/features/db/import/interpolation.feature b/tests/features/db/import/interpolation.feature index 9a4856f2..ad4bdf85 100644 --- a/tests/features/db/import/interpolation.feature +++ b/tests/features/db/import/interpolation.feature @@ -326,4 +326,50 @@ Feature: Import of address interpolations | housenumber | centroid | 8 | 1.001,1.001 + Scenario: Interpolation on self-intersecting way + Given the place nodes + | osm_id | class | type | housenumber | geometry + | 1 | place | house | 2 | 0 0 + | 2 | place | house | 6 | 0 0.001 + | 3 | place | house | 10 | 0 0.002 + And the place ways + | osm_id | class | type | housenumber | geometry + | 1 | place | houses | even | 0 0, 0 0.001, 0 0.002, 0 0.001 + And the ways + | id | nodes + | 1 | 1,2,3,2 + When importing + Then node 1 expands to housenumbers + | housenumber | centroid + | 2 | 0,0 + | 4 | 0,0.0005 + Then node 2 expands to housenumbers + | housenumber | centroid + | 6 | 0,0.001 + | 8 | 0,0.0015 + Then node 3 expands to housenumbers + | housenumber | centroid + | 10 | 0,0.002 + | 8 | 0,0.0015 + + Scenario: Interpolation on self-intersecting way II + Given the place nodes + | osm_id | class | type | housenumber | geometry + | 1 | place | house | 2 | 0 0 + | 2 | place | house | 6 | 0 0.001 + And the place ways + | osm_id | class | type | housenumber | geometry + | 1 | place | houses | even | 0 0, 0 0.001, 0 0.002, 0 0.001 + And the ways + | id | nodes + | 1 | 1,2,3,2 + When importing + Then node 1 expands to housenumbers + | housenumber | centroid + | 2 | 0,0 + | 4 | 0,0.0005 + Then node 2 expands to housenumbers + | housenumber | centroid + | 6 | 0,0.001 + diff --git a/tests/features/osm2pgsql/import/broken.feature b/tests/features/osm2pgsql/import/broken.feature new file mode 100644 index 00000000..58a45f91 --- /dev/null +++ b/tests/features/osm2pgsql/import/broken.feature @@ -0,0 +1,37 @@ +@DB +Feature: Import of objects with broken geometries by osm2pgsql + + @Fail + Scenario: Import way with double nodes + Given the osm nodes: + | id | geometry + | 100 | 0 0 + | 101 | 0 0.1 + | 102 | 0.1 0.2 + And the osm ways: + | id | tags | nodes + | 1 | 'highway' : 'primary' | 100 101 101 102 + When loading osm data + Then table place contains + | object | class | type | geometry + | W1 | highway | primary | (0 0, 0 0.1, 0.1 0.2) + + Scenario: Import of ballon areas + Given the osm nodes: + | id | geometry + | 1 | 0 0 + | 2 | 0 0.0001 + | 3 | 0.00001 0.0001 + | 4 | 0.00001 0 + | 5 | -0.00001 0 + And the osm ways: + | id | tags | nodes + | 1 | 'highway' : 'unclassified' | 1 2 3 4 1 5 + | 2 | 'highway' : 'unclassified' | 1 2 3 4 1 + | 3 | 'highway' : 'unclassified' | 1 2 3 4 3 + When loading osm data + Then table place contains + | object | geometrytype + | W1 | ST_LineString + | W2 | ST_Polygon + | W3 | ST_LineString diff --git a/tests/steps/db_results.py b/tests/steps/db_results.py index 2b44215e..f65e9924 100644 --- a/tests/steps/db_results.py +++ b/tests/steps/db_results.py @@ -49,6 +49,7 @@ def check_placex_content(step, tablename): q = 'SELECT *' if tablename == 'placex': q = q + ", ST_X(centroid) as clat, ST_Y(centroid) as clon" + q = q + ", ST_GeometryType(geometry) as geometrytype" q = q + ' FROM %s where osm_type = %%s and osm_id = %%s' % (tablename,) if cls is None: params = (osmtype, osmid) -- 2.39.5