Skip to content

Commit e39c56b

Browse files
authored
Merge pull request #1791 from joto/fix-multi-with-single
Fix: Handle special single-geom case for multipoint/linestring
2 parents 7fa2e73 + 886fdf9 commit e39c56b

File tree

3 files changed

+79
-3
lines changed

3 files changed

+79
-3
lines changed

src/geom-from-osm.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,16 +112,24 @@ void create_multipoint(geometry_t *geom, osmium::memory::Buffer const &buffer)
112112
geom->reset();
113113
}
114114
} else {
115-
auto &multiline = geom->set<multipoint_t>();
115+
auto &multipoint = geom->set<multipoint_t>();
116116
for (auto const &node : nodes) {
117117
auto const location = node.location();
118118
if (location.valid()) {
119-
multiline.add_geometry(point_t{location});
119+
multipoint.add_geometry(point_t{location});
120120
}
121121
}
122-
if (multiline.num_geometries() == 0) {
122+
if (multipoint.num_geometries() == 0) {
123123
geom->reset();
124124
}
125+
126+
// In the (unlikely) event that this multipoint geometry only contains
127+
// a single point because locations for all others were not available
128+
// turn it into a point geometry retroactively.
129+
if (multipoint.num_geometries() == 1) {
130+
auto const p = multipoint[0];
131+
geom->set<point_t>() = p;
132+
}
125133
}
126134
}
127135

@@ -154,6 +162,15 @@ void create_multilinestring(geometry_t *geom,
154162
if (multiline.num_geometries() == 0) {
155163
geom->reset();
156164
}
165+
166+
// In the (unlikely) event that this multilinestring geometry only
167+
// contains a single linestring because ways or locations for all
168+
// others were not available turn it into a linestring geometry
169+
// retroactively.
170+
if (multiline.num_geometries() == 1 && !force_multi) {
171+
auto p = std::move(multiline[0]);
172+
geom->set<linestring_t>() = std::move(p);
173+
}
157174
}
158175
}
159176

tests/test-geom-multilinestrings.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,39 @@ TEST_CASE("create_multilinestring with single line and no force_multi",
6565
REQUIRE(l == expected);
6666
}
6767

68+
TEST_CASE(
69+
"create_multilinestring with multiple incomplete lines and no force_multi",
70+
"[NoDB]")
71+
{
72+
geom::linestring_t const expected{{1, 1}, {2, 1}};
73+
74+
test_buffer_t buffer;
75+
76+
SECTION("with second invalid line")
77+
{
78+
buffer.add_way("w20 Nn10x1y1,n11x2y1");
79+
buffer.add_way("w21 Nn12x2y2");
80+
}
81+
82+
SECTION("with second line with missing location")
83+
{
84+
buffer.add_way("w20 Nn10x1y1,n11x2y1");
85+
buffer.add_way("w21 Nn12x2y2,n13");
86+
}
87+
88+
auto const geom =
89+
geom::line_merge(geom::create_multilinestring(buffer.buffer(), false));
90+
91+
REQUIRE(geom.is_linestring());
92+
REQUIRE(geometry_type(geom) == "LINESTRING");
93+
REQUIRE(num_geometries(geom) == 1);
94+
REQUIRE(area(geom) == Approx(0.0));
95+
REQUIRE(length(geom) == Approx(1.0));
96+
auto const &l = geom.get<geom::linestring_t>();
97+
REQUIRE(l.num_geometries() == 1);
98+
REQUIRE(l == expected);
99+
}
100+
68101
TEST_CASE("create_multilinestring with single line forming a ring", "[NoDB]")
69102
{
70103
geom::linestring_t const expected{{1, 1}, {2, 1}, {2, 2}, {1, 1}};

tests/test-geom-multipoints.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,29 @@ TEST_CASE("create_multipoint from OSM data", "[NoDB]")
9595
REQUIRE(length(geom) == Approx(0.0));
9696
REQUIRE(centroid(geom) == geom::geometry_t{geom::point_t{2, 1}});
9797
}
98+
99+
TEST_CASE("create_multipoint from OSM data with only a single point", "[NoDB]")
100+
{
101+
test_buffer_t buffer;
102+
103+
SECTION("only single node in relation")
104+
{
105+
buffer.add_node("n10 x1 y0");
106+
}
107+
108+
SECTION("two nodes in relation, but one with missing location")
109+
{
110+
buffer.add_node("n10 x1 y0");
111+
buffer.add_node("n11");
112+
}
113+
114+
auto const geom = geom::create_multipoint(buffer.buffer());
115+
116+
REQUIRE(geometry_type(geom) == "POINT");
117+
REQUIRE(dimension(geom) == 0);
118+
REQUIRE(num_geometries(geom) == 1);
119+
REQUIRE(geom.get<geom::point_t>() == geom::point_t{1, 0});
120+
REQUIRE(area(geom) == Approx(0.0));
121+
REQUIRE(length(geom) == Approx(0.0));
122+
REQUIRE(centroid(geom) == geom::geometry_t{geom::point_t{1, 0}});
123+
}

0 commit comments

Comments
 (0)