diff --git a/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp b/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp index ccaf089b6..8bb6e3bce 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp @@ -126,8 +126,11 @@ struct has_spikes while (next != boost::end(view)) { - if ( geometry::detail::is_spike_or_equal(*prev, *cur, *next, - strategy) ) + // Verify spike. TODO: this is a reverse order from expected + // in is_spike_or_equal, but this order calls the side + // strategy in the way to correctly detect the spikes, + // also in geographic cases going over the pole + if (detail::is_spike_or_equal(*next, *cur, *prev, strategy)) { return ! visitor.template apply(is_linear, *cur); @@ -147,7 +150,7 @@ struct has_spikes boost::rend(view)); iterator next = find_different_from_first(cur, boost::end(view)); - if (detail::is_spike_or_equal(*prev, *cur, *next, strategy)) + if (detail::is_spike_or_equal(*next, *cur, *prev, strategy)) { return ! visitor.template apply(is_linear, *cur); diff --git a/test/algorithms/is_simple_geo.cpp b/test/algorithms/is_simple_geo.cpp index 4a81cb170..28405c030 100644 --- a/test/algorithms/is_simple_geo.cpp +++ b/test/algorithms/is_simple_geo.cpp @@ -60,7 +60,21 @@ BOOST_AUTO_TEST_CASE( test_is_simple_geo_linestring ) bg::strategy::intersection::geographic_segments<> s_4053(sph_4053); bg::strategy::intersection::geographic_segments<> s_near_4053(sph_near_4053); + // Two cases which in Cartesian would be a spike, but in Geographic + // they go over the equator (first segment) and then over the pole + // (second segment) test_simple_s(from_wkt("LINESTRING(0 0, -90 0, 90 0)"), s, true); + test_simple_s(from_wkt("LINESTRING(0 0, 90 0, -90 0)"), s, true); + + // Two similar cases, but these do not go over the pole back, but + // over the equator, and therefore make a spike + test_simple_s(from_wkt("LINESTRING(0 0, -80 0, 80 0)"), s, false); + test_simple_s(from_wkt("LINESTRING(0 0, 80 0, -80 0)"), s, false); + + // Going over the equator in a normal way, eastwards and westwards + test_simple_s(from_wkt("LINESTRING(-90 0, 0 0, 90 0)"), s, true); + test_simple_s(from_wkt("LINESTRING(90 0, 0 0, -90 0)"), s, true); + test_simple_s(from_wkt("LINESTRING(0 90, -90 0, 90 0)"), s, false); test_simple_s(from_wkt("LINESTRING(0 90, -90 50, 90 0)"), s, false); test_simple_s(from_wkt("LINESTRING(0 90, -90 -50, 90 0)"), s, true); diff --git a/test/algorithms/is_valid.cpp b/test/algorithms/is_valid.cpp index e6b84ff4d..8efd1ef41 100644 --- a/test/algorithms/is_valid.cpp +++ b/test/algorithms/is_valid.cpp @@ -345,6 +345,11 @@ inline void test_open_rings() // wrong orientation test::apply("r33", "POLYGON((0 0,0 1,1 1))", false); + + // Normal case, plus spikes formed in two different ways + test::apply("r34", "POLYGON((0 0,4 0,4 4,0 4,0 0))", true); + test::apply("r35", "POLYGON((0 0,5 0,4 0,4 4,0 4,0 0))", false); + test::apply("r36", "POLYGON((0 0,4 0,4 -1,4 4,0 4,0 0))", false); }