diff --git a/src/geom-from-osm.cpp b/src/geom-from-osm.cpp index 339148300..968f52d25 100644 --- a/src/geom-from-osm.cpp +++ b/src/geom-from-osm.cpp @@ -85,13 +85,15 @@ void fill_polygon(polygon_t *polygon, osmium::Area const &area, } // anonymous namespace -void create_linestring(geometry_t *geom, osmium::Way const &way) +bool create_linestring(geometry_t *geom, osmium::Way const &way) { auto &line = geom->set(); if (!fill_point_list(&line, way.nodes())) { geom->reset(); } + + return way.nodes().size() == line.size(); } geometry_t create_linestring(osmium::Way const &way) @@ -101,7 +103,7 @@ geometry_t create_linestring(osmium::Way const &way) return geom; } -void create_polygon(geometry_t *geom, osmium::Way const &way, +bool create_polygon(geometry_t *geom, osmium::Way const &way, osmium::memory::Buffer *area_buffer) { auto &polygon = geom->set(); @@ -109,20 +111,22 @@ void create_polygon(geometry_t *geom, osmium::Way const &way, // A closed way with less than 4 nodes can never be a valid polygon if (way.nodes().size() < 4U) { geom->reset(); - return; + return false; } geom::area_assembler_t assembler{area_buffer}; if (!assembler(way)) { geom->reset(); - return; + return false; } auto const &area = assembler.get_area(); auto const &ring = *area.cbegin(); fill_point_list(&polygon.outer(), ring); + + return assembler.stats().duplicate_nodes == 0; } geometry_t create_polygon(osmium::Way const &way, diff --git a/src/geom-from-osm.hpp b/src/geom-from-osm.hpp index a1068e87d..65fe6abe4 100644 --- a/src/geom-from-osm.hpp +++ b/src/geom-from-osm.hpp @@ -63,7 +63,7 @@ void create_point(geometry_t *geom, osmium::Node const &node); * \param geom Pointer to an existing geometry which will be used as output. * \param way The input way. */ -void create_linestring(geometry_t *geom, osmium::Way const &way); +bool create_linestring(geometry_t *geom, osmium::Way const &way); /** * Create a linestring geometry from a way. Nodes without location are ignored. @@ -87,7 +87,7 @@ void create_linestring(geometry_t *geom, osmium::Way const &way); * \param way The input way. * \param area_buffer Temporary buffer used to create area. */ -void create_polygon(geometry_t *geom, osmium::Way const &way, +bool create_polygon(geometry_t *geom, osmium::Way const &way, osmium::memory::Buffer *area_buffer); /** diff --git a/src/output-flex.cpp b/src/output-flex.cpp index b8a41fbed..840110544 100644 --- a/src/output-flex.cpp +++ b/src/output-flex.cpp @@ -504,9 +504,14 @@ int output_flex_t::app_as_linestring() m_way_cache.add_nodes(middle()); auto *geom = create_lua_geometry_object(lua_state()); - geom::create_linestring(geom, m_way_cache.get()); + bool const okay = geom::create_linestring(geom, m_way_cache.get()); - return 1; + if (geom->is_null()) { + return 1; + } + + lua_pushboolean(lua_state(), okay); + return 2; } int output_flex_t::app_as_polygon() @@ -517,9 +522,15 @@ int output_flex_t::app_as_polygon() m_way_cache.add_nodes(middle()); auto *geom = create_lua_geometry_object(lua_state()); - geom::create_polygon(geom, m_way_cache.get(), &m_area_buffer); + bool const okay = + geom::create_polygon(geom, m_way_cache.get(), &m_area_buffer); - return 1; + if (geom->is_null()) { + return 1; + } + + lua_pushboolean(lua_state(), okay); + return 2; } int output_flex_t::app_as_multipoint() diff --git a/tests/bdd/flex/geometry-linestring.feature b/tests/bdd/flex/geometry-linestring.feature index 6bd2f0d5e..1397aad57 100644 --- a/tests/bdd/flex/geometry-linestring.feature +++ b/tests/bdd/flex/geometry-linestring.feature @@ -66,3 +66,46 @@ Feature: Creating linestring features from way Geometry data for geometry column 'geom' has the wrong type (LINESTRING). """ + Scenario: + Given the grid + | 1 | 2 | | + | | | 3 | + And the OSM data + """ + w20 Thighway=motorway Nn1,n2,n3,n1 + w21 Thighway=motorway Nn1,n2,n2,n3,n1 + w22 Thighway=motorway Nn1,n2,n3,n1,n1 + w23 Thighway=motorway Nn1,n2,n3 + w24 Thighway=motorway Nn2,n2 + """ + And the lua style + """ + local lines = osm2pgsql.define_way_table('osm2pgsql_test_lines', { + { column = 'lgeom', type = 'linestring', projection = 4326 }, + { column = 'pgeom', type = 'polygon', projection = 4326 }, + { column = 'lclean', type = 'bool' }, + { column = 'pclean', type = 'bool' }, + }) + + function osm2pgsql.process_way(object) + lgeom, lclean = object:as_linestring() + pgeom, pclean = object:as_polygon() + lines:insert({ + lgeom = lgeom, + pgeom = pgeom, + lclean = lclean, + pclean = pclean, + }) + end + + """ + When running osm2pgsql flex + + Then table osm2pgsql_test_lines contains exactly + | way_id | lgeom!geo | lclean | pgeom!geo | pclean | + | 20 | 1, 2, 3, 1 | True | (1, 2, 3, 1) | True | + | 21 | 1, 2, 3, 1 | False | (1, 2, 3, 1) | False | + | 22 | 1, 2, 3, 1 | False | (1, 2, 3, 1) | False | + | 23 | 1, 2, 3 | True | NULL | NULL | + | 24 | NULL | NULL | NULL | NULL | +