diff --git a/src/geom-from-osm.cpp b/src/geom-from-osm.cpp index 684ed4d4f..9064976fe 100644 --- a/src/geom-from-osm.cpp +++ b/src/geom-from-osm.cpp @@ -112,16 +112,24 @@ void create_multipoint(geometry_t *geom, osmium::memory::Buffer const &buffer) geom->reset(); } } else { - auto &multiline = geom->set(); + auto &multipoint = geom->set(); for (auto const &node : nodes) { auto const location = node.location(); if (location.valid()) { - multiline.add_geometry(point_t{location}); + multipoint.add_geometry(point_t{location}); } } - if (multiline.num_geometries() == 0) { + if (multipoint.num_geometries() == 0) { geom->reset(); } + + // In the (unlikely) event that this multipoint geometry only contains + // a single point because locations for all others were not available + // turn it into a point geometry retroactively. + if (multipoint.num_geometries() == 1) { + auto const p = multipoint[0]; + geom->set() = p; + } } } @@ -154,6 +162,15 @@ void create_multilinestring(geometry_t *geom, if (multiline.num_geometries() == 0) { geom->reset(); } + + // In the (unlikely) event that this multilinestring geometry only + // contains a single linestring because ways or locations for all + // others were not available turn it into a linestring geometry + // retroactively. + if (multiline.num_geometries() == 1 && !force_multi) { + auto p = std::move(multiline[0]); + geom->set() = std::move(p); + } } } diff --git a/tests/test-geom-multilinestrings.cpp b/tests/test-geom-multilinestrings.cpp index db26436de..27c68fcc4 100644 --- a/tests/test-geom-multilinestrings.cpp +++ b/tests/test-geom-multilinestrings.cpp @@ -65,6 +65,39 @@ TEST_CASE("create_multilinestring with single line and no force_multi", REQUIRE(l == expected); } +TEST_CASE( + "create_multilinestring with multiple incomplete lines and no force_multi", + "[NoDB]") +{ + geom::linestring_t const expected{{1, 1}, {2, 1}}; + + test_buffer_t buffer; + + SECTION("with second invalid line") + { + buffer.add_way("w20 Nn10x1y1,n11x2y1"); + buffer.add_way("w21 Nn12x2y2"); + } + + SECTION("with second line with missing location") + { + buffer.add_way("w20 Nn10x1y1,n11x2y1"); + buffer.add_way("w21 Nn12x2y2,n13"); + } + + auto const geom = + geom::line_merge(geom::create_multilinestring(buffer.buffer(), false)); + + REQUIRE(geom.is_linestring()); + REQUIRE(geometry_type(geom) == "LINESTRING"); + REQUIRE(num_geometries(geom) == 1); + REQUIRE(area(geom) == Approx(0.0)); + REQUIRE(length(geom) == Approx(1.0)); + auto const &l = geom.get(); + REQUIRE(l.num_geometries() == 1); + REQUIRE(l == expected); +} + TEST_CASE("create_multilinestring with single line forming a ring", "[NoDB]") { geom::linestring_t const expected{{1, 1}, {2, 1}, {2, 2}, {1, 1}}; diff --git a/tests/test-geom-multipoints.cpp b/tests/test-geom-multipoints.cpp index 1fc8bee50..f0a9d8d5b 100644 --- a/tests/test-geom-multipoints.cpp +++ b/tests/test-geom-multipoints.cpp @@ -95,3 +95,29 @@ TEST_CASE("create_multipoint from OSM data", "[NoDB]") REQUIRE(length(geom) == Approx(0.0)); REQUIRE(centroid(geom) == geom::geometry_t{geom::point_t{2, 1}}); } + +TEST_CASE("create_multipoint from OSM data with only a single point", "[NoDB]") +{ + test_buffer_t buffer; + + SECTION("only single node in relation") + { + buffer.add_node("n10 x1 y0"); + } + + SECTION("two nodes in relation, but one with missing location") + { + buffer.add_node("n10 x1 y0"); + buffer.add_node("n11"); + } + + auto const geom = geom::create_multipoint(buffer.buffer()); + + REQUIRE(geometry_type(geom) == "POINT"); + REQUIRE(dimension(geom) == 0); + REQUIRE(num_geometries(geom) == 1); + REQUIRE(geom.get() == geom::point_t{1, 0}); + REQUIRE(area(geom) == Approx(0.0)); + REQUIRE(length(geom) == Approx(0.0)); + REQUIRE(centroid(geom) == geom::geometry_t{geom::point_t{1, 0}}); +}