Skip to content

Commit c735ff0

Browse files
committed
Add geom::simplify() function
For linestrings only. For polygons we'll need something else.
1 parent 8859bc4 commit c735ff0

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

src/geom-functions.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,4 +562,25 @@ geometry_t centroid(geometry_t const &geom)
562562
return output;
563563
}
564564

565+
void simplify(geometry_t *output, geometry_t const &geom, double tolerance)
566+
{
567+
if (!geom.is_linestring()) {
568+
output->reset();
569+
return;
570+
}
571+
572+
output->set<linestring_t>();
573+
output->set_srid(geom.srid());
574+
575+
boost::geometry::simplify(geom.get<linestring_t>(),
576+
output->get<linestring_t>(), tolerance);
577+
}
578+
579+
geometry_t simplify(geometry_t const &geom, double tolerance)
580+
{
581+
geom::geometry_t output{linestring_t{}, geom.srid()};
582+
simplify(&output, geom, tolerance);
583+
return output;
584+
}
585+
565586
} // namespace geom

src/geom-functions.hpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,36 @@ geometry_t line_merge(geometry_t geom);
126126
*/
127127
geometry_t centroid(geometry_t const &geom);
128128

129+
/**
130+
* Simplify a linestring geometry using Douglas-Peucker algorithm.
131+
*
132+
* Geometries might become invalid by using simplify. The simplification
133+
* process might create self-intersections.
134+
*
135+
* Returns null geometry for anything but linestring geometries!
136+
*
137+
* \param output Pointer to output geometry.
138+
* \param geom Input geometry.
139+
* \param tolerance Max distance (in units of input coordinates) of a point
140+
* to other segments to be removed.
141+
*/
142+
void simplify(geometry_t *output, geometry_t const &geom, double tolerance);
143+
144+
/**
145+
* Simplify a linestring geometry using Douglas-Peucker algorithm.
146+
*
147+
* Geometries might become invalid by using simplify. The simplification
148+
* process might create self-intersections.
149+
*
150+
* Returns null geometry for anything but linestring geometries!
151+
*
152+
* \param geom Input geometry.
153+
* \param tolerance Max distance (in units of input coordinates) of a point
154+
* to other segments to be removed.
155+
* \returns Simplified geometry.
156+
*/
157+
geometry_t simplify(geometry_t const &geom, double tolerance);
158+
129159
} // namespace geom
130160

131161
#endif // OSM2PGSQL_GEOM_FUNCTIONS_HPP

tests/test-geom-linestrings.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,30 @@ TEST_CASE("geom::segmentize with split 1.0 at end", "[NoDB]")
192192
REQUIRE(ml[2] == expected[2]);
193193
REQUIRE(ml[3] == expected[3]);
194194
}
195+
196+
TEST_CASE("geom::simplify", "[NoDB]")
197+
{
198+
geom::geometry_t const input{
199+
geom::linestring_t{{0, 0}, {1, 1}, {2, 0}, {3, 1}, {4, 0}, {5, 1}}};
200+
201+
SECTION("small tolerance leaves linestring as is")
202+
{
203+
auto const geom = geom::simplify(input, 0.5);
204+
205+
REQUIRE(geom.is_linestring());
206+
auto const &l = geom.get<geom::linestring_t>();
207+
REQUIRE(l.size() == 6);
208+
REQUIRE(l == input.get<geom::linestring_t>());
209+
}
210+
211+
SECTION("large tolerance simplifies linestring")
212+
{
213+
auto const geom = geom::simplify(input, 2.0);
214+
215+
REQUIRE(geom.is_linestring());
216+
auto const &l = geom.get<geom::linestring_t>();
217+
REQUIRE(l.size() == 2);
218+
REQUIRE(l[0] == input.get<geom::linestring_t>()[0]);
219+
REQUIRE(l[1] == input.get<geom::linestring_t>()[5]);
220+
}
221+
}

0 commit comments

Comments
 (0)