From cb9c581365d7b9d273140e2a432bd8b456ad4b33 Mon Sep 17 00:00:00 2001 From: Jiri Drbalek Date: Wed, 11 Nov 2015 21:13:03 +0000 Subject: [PATCH 1/2] [algorithms][centroid] Fix crash when multi-geometry contains empty geometry --- .../boost/geometry/algorithms/centroid.hpp | 23 +++++++++++-------- test/algorithms/centroid_multi.cpp | 8 +++++++ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/include/boost/geometry/algorithms/centroid.hpp b/include/boost/geometry/algorithms/centroid.hpp index 1b99ab2ef..8ef017a3f 100644 --- a/include/boost/geometry/algorithms/centroid.hpp +++ b/include/boost/geometry/algorithms/centroid.hpp @@ -220,19 +220,22 @@ struct centroid_range_state iterator_type it = boost::begin(view); iterator_type end = boost::end(view); - typename PointTransformer::result_type - previous_pt = transformer.apply(*it); - - for ( ++it ; it != end ; ++it) + if (it != end) { typename PointTransformer::result_type - pt = transformer.apply(*it); + previous_pt = transformer.apply(*it); - strategy.apply(static_cast(previous_pt), - static_cast(pt), - state); - - previous_pt = pt; + for ( ++it ; it != end ; ++it) + { + typename PointTransformer::result_type + pt = transformer.apply(*it); + + strategy.apply(static_cast(previous_pt), + static_cast(pt), + state); + + previous_pt = pt; + } } } }; diff --git a/test/algorithms/centroid_multi.cpp b/test/algorithms/centroid_multi.cpp index c98b3f164..a40214f1c 100644 --- a/test/algorithms/centroid_multi.cpp +++ b/test/algorithms/centroid_multi.cpp @@ -72,6 +72,14 @@ void test_2d(bool is_integer = false) test_centroid > >( "MULTIPOLYGON(((1 1)))", 1.0, 1.0); + + test_centroid > >( + "MULTILINESTRING((0 0, 1 0), ())", + 0.5, 0.0); + + test_centroid > >( + "MULTIPOLYGON(((0 0, 1 0, 1 1, 0 1, 0 0)), (()))", + 0.5, 0.5); } From 39ef9e6e043d6874a2e2b681f90dd999f3021441 Mon Sep 17 00:00:00 2001 From: Jiri Drbalek Date: Sat, 21 Nov 2015 19:51:03 +0000 Subject: [PATCH 2/2] [test][algorithms][centroid] More centroid tests on empty geometries --- test/algorithms/centroid.cpp | 16 ++++++++ test/algorithms/centroid_multi.cpp | 63 ++++++++++++++++++++++++++---- test/algorithms/test_centroid.hpp | 16 ++++++++ 3 files changed, 87 insertions(+), 8 deletions(-) diff --git a/test/algorithms/centroid.cpp b/test/algorithms/centroid.cpp index 4ffeb45f9..8f7399230 100644 --- a/test/algorithms/centroid.cpp +++ b/test/algorithms/centroid.cpp @@ -175,6 +175,21 @@ void test_exceptions() test_centroid_exception >(); test_centroid_exception >(); test_centroid_exception >(); + + // Empty exterior ring + test_centroid_exception >( + "POLYGON((), ())"); + test_centroid_exception >( + "POLYGON((), (0 0, 1 0, 1 1, 0 1, 0 0))"); +} + +template +void test_empty() +{ + // Empty interior ring + test_centroid >( + "POLYGON((0 0, 1 0, 1 1, 0 1, 0 0), ())", + 0.5, 0.5); } void test_large_integers() @@ -255,6 +270,7 @@ int test_main(int, char* []) test_large_doubles(); test_exceptions >(); + test_empty >(); return 0; } diff --git a/test/algorithms/centroid_multi.cpp b/test/algorithms/centroid_multi.cpp index a40214f1c..5f250116e 100644 --- a/test/algorithms/centroid_multi.cpp +++ b/test/algorithms/centroid_multi.cpp @@ -72,14 +72,6 @@ void test_2d(bool is_integer = false) test_centroid > >( "MULTIPOLYGON(((1 1)))", 1.0, 1.0); - - test_centroid > >( - "MULTILINESTRING((0 0, 1 0), ())", - 0.5, 0.0); - - test_centroid > >( - "MULTIPOLYGON(((0 0, 1 0, 1 1, 0 1, 0 0)), (()))", - 0.5, 0.5); } @@ -123,6 +115,58 @@ void test_2d(bool is_integer = false) 424530.6059719588, 4527519.619367547); } +template +void test_exceptions() +{ + using namespace bg::model; + typedef multi_polygon > multi_polygon; + typedef multi_linestring > multi_linestring; + + // Empty multi-polygon + test_centroid_exception("MULTIPOLYGON()"); + test_centroid_exception("MULTIPOLYGON(())"); + test_centroid_exception("MULTIPOLYGON((), ())"); + test_centroid_exception("MULTIPOLYGON((()), ())"); + test_centroid_exception("MULTIPOLYGON(((), ()))"); + + // Empty multi-linestring + test_centroid_exception("MULTILINESTRING()"); + test_centroid_exception("MULTILINESTRING(())"); + test_centroid_exception("MULTILINESTRING((), ())"); +} + +template +void test_empty() +{ + using namespace bg::model; + typedef multi_polygon > multi_polygon; + typedef multi_linestring > multi_linestring; + + // Multi-linestring with empty linestring + test_centroid( + "MULTILINESTRING((), (0 0))", + 0.0, 0.0); + test_centroid( + "MULTILINESTRING((0 0, 1 0), ())", + 0.5, 0.0); + + // Multi-polygon with empty polygon + test_centroid( + "MULTIPOLYGON((()), ((0 0)))", + 0.0, 0.0); + test_centroid( + "MULTIPOLYGON(((0 0, 1 0, 1 1, 0 1, 0 0)), (()))", + 0.5, 0.5); + + // Multi-polygon with empty interior ring + test_centroid( + "MULTIPOLYGON(((0 0, 1 0, 1 1, 0 1, 0 0), ()))", + 0.5, 0.5); + test_centroid( + "MULTIPOLYGON((()), ((0 0, 1 0, 1 1, 0 1, 0 0), ()))", + 0.5, 0.5); +} + int test_main(int, char* []) @@ -137,5 +181,8 @@ int test_main(int, char* []) test_2d >(); #endif + test_exceptions >(); + test_empty >(); + return 0; } diff --git a/test/algorithms/test_centroid.hpp b/test/algorithms/test_centroid.hpp index cfbe01783..7e4d99483 100644 --- a/test/algorithms/test_centroid.hpp +++ b/test/algorithms/test_centroid.hpp @@ -126,5 +126,21 @@ void test_centroid_exception() BOOST_CHECK_MESSAGE(false, "A centroid_exception should have been thrown" ); } +template +void test_centroid_exception(std::string const& wkt) +{ + Geometry geometry; + bg::read_wkt(wkt, geometry); + try + { + typename bg::point_type::type c; + bg::centroid(geometry, c); + } + catch(bg::centroid_exception const& ) + { + return; + } + BOOST_CHECK_MESSAGE(false, "A centroid_exception should have been thrown" ); +} #endif