Skip to content

Commit de145c2

Browse files
committed
Ensure that the result of geom::simplify() is a valid geom or null
The simplification function can generate a linestring with a single point in it, which wouldn't be a line any more. Return a null geometry in that case.
1 parent 69f4849 commit de145c2

File tree

2 files changed

+49
-4
lines changed

2 files changed

+49
-4
lines changed

src/geom-functions.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -582,11 +582,17 @@ void simplify(geometry_t *output, geometry_t const &geom, double tolerance)
582582
return;
583583
}
584584

585-
output->set<linestring_t>();
585+
auto &ls = output->set<linestring_t>();
586586
output->set_srid(geom.srid());
587587

588-
boost::geometry::simplify(geom.get<linestring_t>(),
589-
output->get<linestring_t>(), tolerance);
588+
boost::geometry::simplify(geom.get<linestring_t>(), ls, tolerance);
589+
590+
// Linestrings with less then 2 nodes are invalid. Older boost::geometry
591+
// versions will generate a "line" with two identical points which the
592+
// second check finds.
593+
if (ls.size() < 2 || ls[0] == ls[1]) {
594+
output->reset();
595+
}
590596
}
591597

592598
geometry_t simplify(geometry_t const &geom, double tolerance)

tests/test-geom-linestrings.cpp

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ TEST_CASE("geom::simplify", "[NoDB]")
210210

211211
SECTION("large tolerance simplifies linestring")
212212
{
213-
auto const geom = geom::simplify(input, 2.0);
213+
auto const geom = geom::simplify(input, 10.0);
214214

215215
REQUIRE(geom.is_linestring());
216216
auto const &l = geom.get<geom::linestring_t>();
@@ -219,3 +219,42 @@ TEST_CASE("geom::simplify", "[NoDB]")
219219
REQUIRE(l[1] == input.get<geom::linestring_t>()[5]);
220220
}
221221
}
222+
223+
TEST_CASE("geom::simplify of a loop", "[NoDB]")
224+
{
225+
geom::geometry_t const input{
226+
geom::linestring_t{{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0.1, 0.1}, {0, 0}}};
227+
228+
SECTION("small tolerance leaves linestring as is")
229+
{
230+
auto const geom = geom::simplify(input, 0.01);
231+
232+
REQUIRE(geom.is_linestring());
233+
auto const &l = geom.get<geom::linestring_t>();
234+
REQUIRE(l.size() == 6);
235+
REQUIRE(l == input.get<geom::linestring_t>());
236+
}
237+
238+
SECTION("medium tolerance simplifies linestring")
239+
{
240+
auto const geom = geom::simplify(input, 0.5);
241+
242+
REQUIRE(geom.is_linestring());
243+
auto const &l = geom.get<geom::linestring_t>();
244+
REQUIRE(l.size() == 5);
245+
246+
auto const &il = input.get<geom::linestring_t>();
247+
REQUIRE(l[0] == il[0]);
248+
REQUIRE(l[1] == il[1]);
249+
REQUIRE(l[2] == il[2]);
250+
REQUIRE(l[3] == il[3]);
251+
REQUIRE(l[4] == il[5]);
252+
}
253+
254+
SECTION("large tolerance breaks linestring, null geometry is returned")
255+
{
256+
auto const geom = geom::simplify(input, 10.0);
257+
258+
REQUIRE(geom.is_null());
259+
}
260+
}

0 commit comments

Comments
 (0)