Skip to content

Commit 76c36c6

Browse files
committed
Return linestring or multilinestring from create_multilinestring()
create_multilinestring() has a new optional parameter `force_multi` defaulted to true. If this is set to false, the function will return a linestring geometry if that's possible.
1 parent 384739d commit 76c36c6

File tree

6 files changed

+64
-22
lines changed

6 files changed

+64
-22
lines changed

src/geom-from-osm.cpp

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -96,27 +96,37 @@ geometry_t create_polygon(osmium::Way const &way)
9696
}
9797

9898
void create_multilinestring(geometry_t *geom,
99-
osmium::memory::Buffer const &ways)
99+
osmium::memory::Buffer const &ways_buffer,
100+
bool force_multi)
100101
{
101-
auto &mls = geom->set<multilinestring_t>();
102-
103-
for (auto const &way : ways.select<osmium::Way>()) {
104-
linestring_t line;
102+
auto ways = ways_buffer.select<osmium::Way>();
103+
if (ways.size() == 1 && !force_multi) {
104+
auto &line = geom->set<linestring_t>();
105+
auto &way = *ways.begin();
105106
fill_point_list(&line, way.nodes());
106-
if (line.size() >= 2U) {
107-
mls.add_geometry(std::move(line));
107+
if (line.size() < 2U) {
108+
geom->reset();
109+
}
110+
} else {
111+
auto &multiline = geom->set<multilinestring_t>();
112+
for (auto const &way : ways) {
113+
linestring_t line;
114+
fill_point_list(&line, way.nodes());
115+
if (line.size() >= 2U) {
116+
multiline.add_geometry(std::move(line));
117+
}
118+
}
119+
if (multiline.num_geometries() == 0) {
120+
geom->reset();
108121
}
109-
}
110-
111-
if (mls.num_geometries() == 0) {
112-
geom->reset();
113122
}
114123
}
115124

116-
geometry_t create_multilinestring(osmium::memory::Buffer const &ways)
125+
geometry_t create_multilinestring(osmium::memory::Buffer const &ways,
126+
bool force_multi)
117127
{
118128
geometry_t geom{};
119-
create_multilinestring(&geom, ways);
129+
create_multilinestring(&geom, ways, force_multi);
120130
return geom;
121131
}
122132

src/geom-from-osm.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ void create_polygon(geometry_t *geom, osmium::Way const &way);
101101
* \param ways Buffer containing all the input ways.
102102
*/
103103
void create_multilinestring(geometry_t *geom,
104-
osmium::memory::Buffer const &ways);
104+
osmium::memory::Buffer const &ways,
105+
bool force_multi = true);
105106

106107
/**
107108
* Create a multilinestring geometry from a bunch of ways (usually this
@@ -115,7 +116,8 @@ void create_multilinestring(geometry_t *geom,
115116
* \returns The created geometry.
116117
*/
117118
[[nodiscard]] geometry_t
118-
create_multilinestring(osmium::memory::Buffer const &ways);
119+
create_multilinestring(osmium::memory::Buffer const &ways,
120+
bool force_multi = true);
119121

120122
/**
121123
* Create a (multi)polygon geometry from a relation and member ways.

src/geom-functions.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,11 @@ static void add_nodes_to_linestring(linestring_t *linestring, ITERATOR it,
448448

449449
void line_merge(geometry_t *output, geometry_t const &input)
450450
{
451+
if (input.is_linestring()) {
452+
*output = input;
453+
return;
454+
}
455+
451456
if (!input.is_multilinestring()) {
452457
output->reset();
453458
return;

src/geom-functions.hpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,19 +159,23 @@ double area(geometry_t const &geom);
159159
std::vector<geometry_t> split_multi(geometry_t &&geom, bool split_multi = true);
160160

161161
/**
162-
* Merge lines in a multilinestring end-to-end as far as possible. Always
163-
* returns a multilinestring unless there is an error or the input geometry
164-
* is a nullgeom_t, in which case nullgeom_t is returned.
162+
* Merge lines in a multilinestring end-to-end as far as possible.
163+
*
164+
* * Returns a multilinestring if the input is a multilinestring.
165+
* * Returns a copy of the input if it is a linestring.
166+
* * Returns nullgeom_t otherwise.
165167
*
166168
* \param output Pointer to output geometry.
167169
* \param input Input geometry.
168170
*/
169171
void line_merge(geometry_t *output, geometry_t const &input);
170172

171173
/**
172-
* Merge lines in a multilinestring end-to-end as far as possible. Always
173-
* returns a multilinestring unless there is an error or the input geometry
174-
* is a nullgeom_t, in which case nullgeom_t is returned.
174+
* Merge lines in a multilinestring end-to-end as far as possible.
175+
*
176+
* * Returns a multilinestring if the input is a multilinestring.
177+
* * Returns a copy of the input if it is a linestring.
178+
* * Returns nullgeom_t otherwise.
175179
*
176180
* \param input Input geometry.
177181
* \returns Result multilinestring.

src/output-flex.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -892,7 +892,8 @@ int output_flex_t::app_as_multilinestring()
892892
m_relation_cache.add_members(middle());
893893

894894
auto *geom = create_lua_geometry_object(lua_state());
895-
geom::create_multilinestring(geom, m_relation_cache.members_buffer());
895+
geom::create_multilinestring(geom, m_relation_cache.members_buffer(),
896+
false);
896897

897898
return 1;
898899
}

tests/test-geom-multilinestrings.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,26 @@ TEST_CASE("create_multilinestring with single line", "[NoDB]")
3636
REQUIRE(ml[0] == expected);
3737
}
3838

39+
TEST_CASE("create_multilinestring with single line and no force_multi",
40+
"[NoDB]")
41+
{
42+
geom::linestring_t const expected{{1, 1}, {2, 1}};
43+
44+
test_buffer_t buffer;
45+
buffer.add_way("w20 Nn10x1y1,n11x2y1");
46+
47+
auto const geom =
48+
geom::line_merge(geom::create_multilinestring(buffer.buffer(), false));
49+
50+
REQUIRE(geom.is_linestring());
51+
REQUIRE(geometry_type(geom) == "LINESTRING");
52+
REQUIRE(num_geometries(geom) == 1);
53+
REQUIRE(area(geom) == Approx(0.0));
54+
auto const &l = geom.get<geom::linestring_t>();
55+
REQUIRE(l.num_geometries() == 1);
56+
REQUIRE(l == expected);
57+
}
58+
3959
TEST_CASE("create_multilinestring with single line forming a ring", "[NoDB]")
4060
{
4161
geom::linestring_t const expected{{1, 1}, {2, 1}, {2, 2}, {1, 1}};

0 commit comments

Comments
 (0)