omniscale/imposm3

Invalid polygon emitted for self-intersecting way

pnorman opened this issue · 1 comments

I've found a case where imposm emits an invalid geometry for a self-intersecting polygon.
The polygon is a figure-eight shape, and the files and commands to reproduce are below.

The invalid polygon causes later operations to fail like st_pointonsurface.

Files

w120717877.osm

<?xml version="1.0" encoding="UTF-8"?>
<osm version="0.6" generator="CGImap 0.8.3 (1550984 spike-07.openstreetmap.org)" copyright="OpenStreetMap and contributors" attribution="http://www.openstreetmap.org/copyright" license="http://opendatacommons.org/licenses/odbl/1-0/">
 <node id="1352810632" visible="true" version="1" changeset="8659687" timestamp="2011-07-07T18:03:40Z" user="genyich" uid="445054" lat="48.7012054" lon="44.8461433"/>
 <node id="1352810714" visible="true" version="2" changeset="91034968" timestamp="2020-09-17T09:12:42Z" user="User4 - Lightcyphers" uid="7753484" lat="48.7005373" lon="44.8453068"/>
 <node id="1352810762" visible="true" version="1" changeset="8659687" timestamp="2011-07-07T18:03:42Z" user="genyich" uid="445054" lat="48.7009172" lon="44.8459760"/>
 <node id="1352811121" visible="true" version="1" changeset="8659687" timestamp="2011-07-07T18:03:49Z" user="genyich" uid="445054" lat="48.7006481" lon="44.8455254"/>
 <way id="120717877" visible="true" version="2" changeset="8670307" timestamp="2011-07-08T22:21:22Z" user="pankdm" uid="329833">
  <nd ref="1352810714"/>
  <nd ref="1352810762"/>
  <nd ref="1352810632"/>
  <nd ref="1352811121"/>
  <nd ref="1352810714"/>
  <tag k="natural" v="water"/>
  <tag k="water" v="river"/>
 </way>
</osm>

water.yaml

tables:
  water_polygon:
    fields:
      - {name: osm_id, type: id}
      - {name: geometry, type: validated_geometry}
    mapping:
      natural: [water]
    type: polygon

Commands to reproduce

osmium cat w120717877.osm -o w120717877.osm.pbf
./imposm-0.11.0-linux-x86-64/imposm import -read w120717877.osm.pbf \
-mapping water.yaml -write -connection 'postgis: host=/var/run/postgresql dbname=imposm' -overwritecache

psql -Xd imposm -c 'select osm_id, st_isvalid(geometry) from import.osm_water_polygon'
NOTICE:  Self-intersection at or near point 4992185.4952552263 6224225.5113198003
  osm_id   | st_isvalid
-----------+------------
 120717877 | f
(1 row)

I've found a case where imposm emits an invalid geometry for a self-intersecting polygon.

as I see - the w120717877 has 4 nodes ;
so probably your example related to this change "Skips slow GEOS IsValid calls for polygons with only 4 corners." a367850

modifying the code solves your problem.

root@2d0f4fac8032:/tools/imposm3# git diff
diff --git a/writer/ways.go b/writer/ways.go
index 6db70e7..8219523 100644
--- a/writer/ways.go
+++ b/writer/ways.go
@@ -147,7 +147,7 @@ func (ww *WayWriter) buildAndInsert(
 	if isPolygon {
 		geosgeom, err = geomp.Polygon(g, way.Nodes)
 		if err == nil {
-			if g.NumCoordinates(geosgeom) > 5 {
+			if g.NumCoordinates(geosgeom) > 4 {
 				// only check for valididty for non-simple geometries
 				geosgeom, err = g.MakeValid(geosgeom)
 			}

tested with Geos 3.8.1

osmdb=# select osm_id, st_isvalid(geometry) from import.osm_water_polygon;
+-----------+------------+
|  osm_id   | st_isvalid |
+-----------+------------+
| 120717877 | t          |
+-----------+------------+
(1 row)