From 641ee182572e9c261d1b84da994b3e6d5625c132 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 6 Oct 2017 09:18:10 +0200 Subject: [PATCH 01/16] [dissolve] fix call to traverse which needs extra argument now (which is not (yet) used for dissolve) --- .../boost/geometry/algorithms/detail/overlay/traverse.hpp | 2 +- include/boost/geometry/extensions/algorithms/dissolve.hpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/traverse.hpp b/include/boost/geometry/algorithms/detail/overlay/traverse.hpp index 2ec71850b..b9cbea312 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traverse.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traverse.hpp @@ -62,7 +62,7 @@ public : typename RobustPolicy, typename Turns, typename Rings, - typename TurnInfoMap, + typename TurnInfoMap, typename Clusters, typename Visitor > diff --git a/include/boost/geometry/extensions/algorithms/dissolve.hpp b/include/boost/geometry/extensions/algorithms/dissolve.hpp index 8ffb7cdfc..78e288f49 100644 --- a/include/boost/geometry/extensions/algorithms/dissolve.hpp +++ b/include/boost/geometry/extensions/algorithms/dissolve.hpp @@ -196,6 +196,8 @@ struct dissolve_ring_or_polygon clusters, geometry, geometry, rescale_policy, side_strategy); + std::map turn_info_per_ring; + detail::overlay::traverse < false, false, @@ -204,7 +206,7 @@ struct dissolve_ring_or_polygon backtrack_for_dissolve >::apply(geometry, geometry, strategy, rescale_policy, - turns, rings, clusters, visitor); + turns, rings, turn_info_per_ring, clusters, visitor); clear_visit_info(turns); @@ -221,7 +223,7 @@ struct dissolve_ring_or_polygon backtrack_for_dissolve >::apply(geometry, geometry, strategy, rescale_policy, - turns, rings, clusters, visitor); + turns, rings, turn_info_per_ring, clusters, visitor); std::map map; detail::overlay::get_ring_turn_info(map, turns, clusters); From 1d23e0b5115e808b1f5d8ff881bac0d627b8a110 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 6 Oct 2017 09:18:56 +0200 Subject: [PATCH 02/16] [dissolve][test] fix test environment, exclude now failing cases --- extensions/test/algorithms/dissolve.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/extensions/test/algorithms/dissolve.cpp b/extensions/test/algorithms/dissolve.cpp index 46163e0c4..c62876d37 100644 --- a/extensions/test/algorithms/dissolve.cpp +++ b/extensions/test/algorithms/dissolve.cpp @@ -225,13 +225,12 @@ void test_all() test_one("5", "POLYGON((0 0,0 4,4 4,4 0,0 4,2 0,0 0))", 0, 8, 12.0); -#endif - // With spike test_one("6", "POLYGON((0 0,0 4,4 4,4 2,6 2,4 2,4 0,0 0))", 0, 6, 16); +#endif // Non intersection, but with duplicate @@ -248,7 +247,7 @@ void test_all() // Hole: interior tangent to exterior test_one("h1", "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 2,2 4,3 2,1 2))", - 0, 6, 16); + 0, 5, 16); // Hole: interior intersecting exterior test_one("h2", @@ -338,9 +337,12 @@ void test_all() test_one("ggl_list_20110307_javier_01_a", "MULTIPOLYGON(((560 -400, 600 -400, 600 -440, 560 -440, 560 -400)), ((480 -400, 520 -400, 520 -440, 480 -440, 480 -400)), ((600 -320, 640 -320, 640 -360, 600 -360, 600 -320)), ((520 -400, 560 -400, 560 -440, 520 -440, 520 -400)))", 1, 14, 6400); + +#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS test_one("ggl_list_20110307_javier_01_b", "POLYGON((0 0, 2000 0, 2000 -2000, 0 -2000, 0 0), (560 -400, 560 -440, 600 -440, 600 -400, 560 -400), (480 -400, 480 -440, 520 -440, 520 -400, 480 -400), (600 -320, 600 -360, 640 -360, 640 -320, 600 -320), (520 -400, 520 -440, 560 -440, 560 -400, 520 -400))", 1, 19, 3993600); +#endif } From aaf2a5f4d6d3ee4ca5e0f2b90afd32c18c429dc4 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 6 Oct 2017 10:00:36 +0200 Subject: [PATCH 03/16] [dissolve] use the map, which is now passed, instead of the old one which was created explicitly --- extensions/test/algorithms/dissolve.cpp | 2 +- include/boost/geometry/extensions/algorithms/dissolve.hpp | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/extensions/test/algorithms/dissolve.cpp b/extensions/test/algorithms/dissolve.cpp index c62876d37..b6b6c158c 100644 --- a/extensions/test/algorithms/dissolve.cpp +++ b/extensions/test/algorithms/dissolve.cpp @@ -247,7 +247,7 @@ void test_all() // Hole: interior tangent to exterior test_one("h1", "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 2,2 4,3 2,1 2))", - 0, 5, 16); + 0, 6, 16); // Hole: interior intersecting exterior test_one("h2", diff --git a/include/boost/geometry/extensions/algorithms/dissolve.hpp b/include/boost/geometry/extensions/algorithms/dissolve.hpp index 78e288f49..7e15e107d 100644 --- a/include/boost/geometry/extensions/algorithms/dissolve.hpp +++ b/include/boost/geometry/extensions/algorithms/dissolve.hpp @@ -225,8 +225,7 @@ struct dissolve_ring_or_polygon strategy, rescale_policy, turns, rings, turn_info_per_ring, clusters, visitor); - std::map map; - detail::overlay::get_ring_turn_info(map, turns, clusters); + detail::overlay::get_ring_turn_info(turn_info_per_ring, turns, clusters); typedef typename geometry::point_type::type point_type; typedef typename Strategy::template area_strategy @@ -238,7 +237,7 @@ struct dissolve_ring_or_polygon std::map selected; - detail::overlay::select_rings(geometry, map, selected, strategy); + detail::overlay::select_rings(geometry, turn_info_per_ring, selected, strategy); // Add intersected rings { From 2ece2f2fca2cb5bb595df2d9a2dc59faf8d12a3f Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 6 Oct 2017 10:01:46 +0200 Subject: [PATCH 04/16] [dissolve] pass visitor, this makes dissolve_overlay_visitor redundant --- .../extensions/algorithms/dissolve.hpp | 54 +++++-------------- .../extensions/multi/algorithms/dissolve.hpp | 14 +++-- 2 files changed, 23 insertions(+), 45 deletions(-) diff --git a/include/boost/geometry/extensions/algorithms/dissolve.hpp b/include/boost/geometry/extensions/algorithms/dissolve.hpp index 7e15e107d..e7441f01d 100644 --- a/include/boost/geometry/extensions/algorithms/dissolve.hpp +++ b/include/boost/geometry/extensions/algorithms/dissolve.hpp @@ -110,50 +110,19 @@ public : } }; -struct dissolve_overlay_visitor -{ -public : - void print(char const* /*header*/) - { - } - - template - void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/) - { - } - - template - void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/, int /*op_index*/) - { - } - - template - void visit_turns(int , Turns const& ) {} - - template - void visit_clusters(Clusters const& , Turns const& ) {} - - template - void visit_traverse(Turns const& /*turns*/, Turn const& /*turn*/, Operation const& /*op*/, const char* /*header*/) - { - } - - template - void visit_traverse_reject(Turns const& , Turn const& , Operation const& , - detail::overlay::traverse_error_type ) - {} -}; - - - template struct dissolve_ring_or_polygon { - template + template + < + typename RescalePolicy, typename OutputIterator, + typename Strategy, typename Visitor + > static inline OutputIterator apply(Geometry const& geometry, RescalePolicy const& rescale_policy, OutputIterator out, - Strategy const& strategy) + Strategy const& strategy, + Visitor& visitor) { typedef typename point_type::type point_type; @@ -186,7 +155,6 @@ struct dissolve_ring_or_polygon > cluster_type; cluster_type clusters; - dissolve_overlay_visitor visitor; // Enrich/traverse the polygons twice: once for union... typename Strategy::side_strategy_type const @@ -344,13 +312,15 @@ inline OutputIterator dissolve_inserter(Geometry const& geometry, rescale_policy_type robust_policy = geometry::get_rescale_policy(geometry); + detail::overlay::overlay_null_visitor visitor; + return dispatch::dissolve < typename tag::type, typename tag::type, Geometry, GeometryOut - >::apply(geometry, robust_policy, out, strategy); + >::apply(geometry, robust_policy, out, strategy, visitor); } /*! @@ -397,6 +367,8 @@ inline void dissolve(Geometry const& geometry, Collection& output_collection, St concepts::check(); + detail::overlay::overlay_null_visitor visitor; + dispatch::dissolve < typename tag::type, @@ -405,7 +377,7 @@ inline void dissolve(Geometry const& geometry, Collection& output_collection, St geometry_out >::apply(geometry, detail::no_rescale_policy(), std::back_inserter(output_collection), - strategy); + strategy, visitor); } template diff --git a/include/boost/geometry/extensions/multi/algorithms/dissolve.hpp b/include/boost/geometry/extensions/multi/algorithms/dissolve.hpp index 2abb05e0e..bedc995ff 100644 --- a/include/boost/geometry/extensions/multi/algorithms/dissolve.hpp +++ b/include/boost/geometry/extensions/multi/algorithms/dissolve.hpp @@ -38,9 +38,14 @@ namespace detail { namespace dissolve template struct dissolve_multi { - template - static inline OutputIterator apply(Multi const& multi, RescalePolicy const& rescale_policy, - OutputIterator out, Strategy const& strategy) + template + < + typename RescalePolicy, typename OutputIterator, + typename Strategy, typename Visitor + > + static inline OutputIterator apply(Multi const& multi, + RescalePolicy const& rescale_policy, OutputIterator out, + Strategy const& strategy, Visitor& visitor) { typedef typename boost::range_value::type polygon_type; typedef typename boost::range_iterator::type iterator_type; @@ -55,7 +60,8 @@ struct dissolve_multi < polygon_type, GeometryOut - >::apply(*it, rescale_policy, std::back_inserter(step1), strategy); + >::apply(*it, rescale_policy, std::back_inserter(step1), + strategy, visitor); } // Step 2: remove mutual overlap From 0bb0e7fcae45cfa0c67db55ed462fad58db86ef0 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 6 Oct 2017 10:23:08 +0200 Subject: [PATCH 05/16] [dissolve][test] enhance test information, check different outputs, prepare svg-debug-info --- extensions/test/algorithms/dissolve.cpp | 88 +++++++++++++++++++++---- 1 file changed, 74 insertions(+), 14 deletions(-) diff --git a/extensions/test/algorithms/dissolve.cpp b/extensions/test/algorithms/dissolve.cpp index b6b6c158c..f5f1be21c 100644 --- a/extensions/test/algorithms/dissolve.cpp +++ b/extensions/test/algorithms/dissolve.cpp @@ -68,6 +68,14 @@ struct map_segment }; +template +std::string as_wkt(Geometry const& geometry) +{ + std::ostringstream out; + out << bg::wkt(geometry); + return out.str(); +} + template void test_dissolve(std::string const& caseid, Geometry const& geometry, std::size_t /*expected_hole_count*/, std::size_t expected_point_count, @@ -79,17 +87,65 @@ void test_dissolve(std::string const& caseid, Geometry const& geometry, //std::cout << bg::area(geometry) << std::endl; - std::vector dissolved_vector; - bg::dissolve_inserter(geometry, std::back_inserter(dissolved_vector)); + std::vector dissolved1; + + // Check dispatch::dissolve + { + typedef typename bg::strategy::intersection::services::default_strategy + < + typename bg::cs_tag::type + >::type strategy_type; + + typedef typename bg::rescale_policy_type + < + typename bg::point_type::type + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = bg::get_rescale_policy(geometry); + + // This will optionally also create SVG with turn-debug information + strategy_type strategy; + bg::detail::overlay::overlay_null_visitor visitor; + + bg::dispatch::dissolve + < + typename bg::tag::type, + typename bg::tag::type, + Geometry, + GeometryOut + >::apply(geometry, robust_policy, std::back_inserter(dissolved1), + strategy, visitor); + } + + // Check dissolve_inserter + std::vector dissolved2; + bg::dissolve_inserter(geometry, std::back_inserter(dissolved2)); + + // Check dissolve and difference dissolve/dissolve_inserter + std::vector dissolved3; + bg::dissolve(geometry, dissolved3); + + // Make output unique (TODO: this should probably be moved to dissolve itself) + BOOST_FOREACH(GeometryOut& dissolved, dissolved1) + { + bg::unique(dissolved); + } + BOOST_FOREACH(GeometryOut& dissolved, dissolved2) + { + bg::unique(dissolved); + } + BOOST_FOREACH(GeometryOut& dissolved, dissolved3) + { + bg::unique(dissolved); + } typename bg::default_area_result::type length_or_area = 0; //std::size_t holes = 0; std::size_t count = 0; - BOOST_FOREACH(GeometryOut& dissolved, dissolved_vector) + BOOST_FOREACH(GeometryOut& dissolved, dissolved2) { - bg::unique(dissolved); - length_or_area += is_line ? bg::length(dissolved) : bg::area(dissolved); @@ -108,10 +164,19 @@ void test_dissolve(std::string const& caseid, Geometry const& geometry, //BOOST_CHECK_EQUAL(holes, expected_hole_count); BOOST_CHECK_CLOSE(length_or_area, expected_length_or_area, percentage); - // Compile check, it should also compile inplace, outputting to the same geometry + BOOST_CHECK_EQUAL(dissolved1.size(), dissolved2.size()); + BOOST_CHECK_EQUAL(dissolved1.size(), dissolved3.size()); + if (dissolved1.size() == dissolved2.size() + && dissolved1.size() == dissolved3.size()) { - std::vector dissolved; - bg::dissolve(geometry, dissolved); + for (std::size_t i = 0; i < dissolved1.size(); i++) + { + std::string const wkt1 = as_wkt(dissolved1[i]); + std::string const wkt2 = as_wkt(dissolved2[i]); + std::string const wkt3 = as_wkt(dissolved3[i]); + BOOST_CHECK_MESSAGE(wkt1 == wkt2, caseid << " : output differs: " << wkt1 << " VERSUS " << wkt2); + BOOST_CHECK_MESSAGE(wkt1 == wkt3, caseid << " : output differs: " << wkt1 << " VERSUS " << wkt3); + } } @@ -138,8 +203,7 @@ void test_dissolve(std::string const& caseid, Geometry const& geometry, bg::for_each_segment(geometry, map_segment(mapper)); - - BOOST_FOREACH(GeometryOut& dissolved, dissolved_vector) + BOOST_FOREACH(GeometryOut& dissolved, dissolved1) { mapper.map(dissolved, "opacity:0.6;fill:none;stroke:rgb(255,0,0);stroke-width:5"); } @@ -191,8 +255,6 @@ void test_one(std::string const& caseid, std::string const& wkt, } - - template void test_all() { @@ -232,13 +294,11 @@ void test_all() 0, 6, 16); #endif - // Non intersection, but with duplicate test_one("d1", "POLYGON((0 0,0 4,4 0,4 0,0 0))", 0, 4, 8); - // With many duplicates test_one("d2", "POLYGON((0 0,0 1,0 1,0 1,0 2,0 2,0 3,0 3,0 3,0 3,0 4,2 4,2 4,4 4,4 0,4 0,3 0,3 0,3 0,3 0,3 0,0 0))", From 6e02971a66e724590e3a47d9bec409e41d5e8a87 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 6 Oct 2017 10:52:42 +0200 Subject: [PATCH 06/16] [test] enhance dissolve SVG with information from visitor --- extensions/test/algorithms/dissolve.cpp | 122 +++++++++++------- .../extensions/algorithms/dissolve.hpp | 13 +- 2 files changed, 89 insertions(+), 46 deletions(-) diff --git a/extensions/test/algorithms/dissolve.cpp b/extensions/test/algorithms/dissolve.cpp index f5f1be21c..6d2621dd2 100644 --- a/extensions/test/algorithms/dissolve.cpp +++ b/extensions/test/algorithms/dissolve.cpp @@ -40,33 +40,64 @@ # include #endif +#if defined(TEST_WITH_SVG) template -struct map_segment +struct map_visitor { - map_segment(Mapper& m) - : m_mapper(&m) + map_visitor(Mapper& mapper) + : m_mapper(mapper) {} - map_segment& operator=(map_segment const& other) + void print(char const* header) + {} + + template + void print(char const* header, Turns const& turns, int turn_index) { - if(this != &other) + std::string style = "fill:rgb(0,0,0);font-family:Arial;font-size:6px"; + stream(turns, turns[turn_index], turns[turn_index].operations[0], header, style); + } + + template + void print(char const* header, Turns const& turns, int turn_index, int op_index) + { + std::string style = "fill:rgb(0,0,0);font-family:Arial;font-size:6px"; + stream(turns, turns[turn_index], turns[turn_index].operations[op_index], header, style); + } + + template + void visit_turns(int phase, Turns const& turns) + { + typedef typename boost::range_value::type turn_type; + BOOST_FOREACH(turn_type const& turn, turns) { - this->m_mapper = other.m_mapper; + switch (phase) + { + case 1 : // after self_turns + m_mapper.map(turn.point, "fill:rgb(255,128,0);" + "stroke:rgb(0,0,0);stroke-width:1", 4); + break; + // TODO: add enriched information as label + } } - return *this; } + template + void visit_clusters(Clusters const& , Turns const& ) {} - template - inline void operator()(Segment const& s) - { - // create a little offset - m_mapper->map(s, "opacity:0.6;fill:none;stroke:rgb(0,0,0);stroke-width:2"); - } + template + void visit_traverse(Turns const& , Turn const& , Operation const& , char const*) + {} - Mapper* m_mapper; + template + void visit_traverse_reject(Turns const& , Turn const& , Operation const& , + bg::detail::overlay::traverse_error_type ) + {} + + Mapper& m_mapper; }; +#endif template std::string as_wkt(Geometry const& geometry) @@ -106,7 +137,31 @@ void test_dissolve(std::string const& caseid, Geometry const& geometry, // This will optionally also create SVG with turn-debug information strategy_type strategy; + + +#if ! defined(TEST_WITH_SVG) bg::detail::overlay::overlay_null_visitor visitor; +#else + std::ostringstream filename; + filename << "dissolve_" << caseid << "_" + << string_from_type::name() + << ".svg"; + + std::ofstream svg(filename.str().c_str()); + + typedef bg::svg_mapper + < + typename bg::point_type::type + > mapper_type; + + mapper_type mapper(svg, 500, 500); + mapper.add(geometry); + + mapper.map(geometry, "fill-opacity:0.5;fill:rgb(153,204,0);" + "stroke:rgb(153,204,0);stroke-width:3;fill-rule:nonzero"); + + map_visitor visitor(mapper); +#endif bg::dispatch::dissolve < @@ -116,6 +171,14 @@ void test_dissolve(std::string const& caseid, Geometry const& geometry, GeometryOut >::apply(geometry, robust_policy, std::back_inserter(dissolved1), strategy, visitor); + +#if defined(TEST_WITH_SVG) + BOOST_FOREACH(GeometryOut& dissolved, dissolved1) + { + mapper.map(dissolved, "fill:none;stroke-opacity:0.4;stroke:rgb(255,0,255);stroke-width:8;"); + } +#endif + } // Check dissolve_inserter @@ -178,37 +241,6 @@ void test_dissolve(std::string const& caseid, Geometry const& geometry, BOOST_CHECK_MESSAGE(wkt1 == wkt3, caseid << " : output differs: " << wkt1 << " VERSUS " << wkt3); } } - - -#if defined(TEST_WITH_SVG) - { - std::ostringstream filename; - filename << "dissolve_" - << caseid << "_" - << string_from_type::name() - << ".svg"; - - std::ofstream svg(filename.str().c_str()); - - typedef - bg::svg_mapper - < - typename bg::point_type::type - > mapper_type; - - mapper_type mapper(svg, 500, 500); - mapper.add(geometry); - - mapper.map(geometry, "opacity:0.6;fill:rgb(0,0,255);stroke:rgb(0,0,0);stroke-width:1;fill-rule:nonzero"); - - bg::for_each_segment(geometry, map_segment(mapper)); - - BOOST_FOREACH(GeometryOut& dissolved, dissolved1) - { - mapper.map(dissolved, "opacity:0.6;fill:none;stroke:rgb(255,0,0);stroke-width:5"); - } - } -#endif } diff --git a/include/boost/geometry/extensions/algorithms/dissolve.hpp b/include/boost/geometry/extensions/algorithms/dissolve.hpp index e7441f01d..838d36f67 100644 --- a/include/boost/geometry/extensions/algorithms/dissolve.hpp +++ b/include/boost/geometry/extensions/algorithms/dissolve.hpp @@ -140,6 +140,8 @@ struct dissolve_ring_or_polygon detail::overlay::assign_null_policy >(geometry, strategy, rescale_policy, turns, policy); + visitor.visit_turns(1, turns); + // The dissolve process is not necessary if there are no turns at all if (boost::size(turns) > 0) @@ -164,6 +166,10 @@ struct dissolve_ring_or_polygon clusters, geometry, geometry, rescale_policy, side_strategy); + visitor.visit_turns(2, turns); + + visitor.visit_clusters(clusters, turns); + std::map turn_info_per_ring; detail::overlay::traverse @@ -176,13 +182,16 @@ struct dissolve_ring_or_polygon strategy, rescale_policy, turns, rings, turn_info_per_ring, clusters, visitor); - clear_visit_info(turns); + visitor.visit_turns(3, turns); // ... and for intersection + clear_visit_info(turns); enrich_intersection_points(turns, clusters, geometry, geometry, rescale_policy, side_strategy); + visitor.visit_turns(4, turns); + detail::overlay::traverse < false, false, @@ -193,6 +202,8 @@ struct dissolve_ring_or_polygon strategy, rescale_policy, turns, rings, turn_info_per_ring, clusters, visitor); + visitor.visit_turns(5, turns); + detail::overlay::get_ring_turn_info(turn_info_per_ring, turns, clusters); typedef typename geometry::point_type::type point_type; From f73abdab1b846142d6fd363a94b0d2bf39a91063 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 6 Oct 2017 11:20:37 +0200 Subject: [PATCH 07/16] [test] add labels for dissolve-svg --- extensions/test/algorithms/dissolve.cpp | 82 ++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 2 deletions(-) diff --git a/extensions/test/algorithms/dissolve.cpp b/extensions/test/algorithms/dissolve.cpp index 6d2621dd2..47189aae6 100644 --- a/extensions/test/algorithms/dissolve.cpp +++ b/extensions/test/algorithms/dissolve.cpp @@ -1,7 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2010-2017 Barend Gehrels, Amsterdam, the Netherlands. // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -38,6 +38,7 @@ #if defined(TEST_WITH_SVG) # include # include +# include #endif #if defined(TEST_WITH_SVG) @@ -69,6 +70,7 @@ struct map_visitor void visit_turns(int phase, Turns const& turns) { typedef typename boost::range_value::type turn_type; + std:size_t index = 0; BOOST_FOREACH(turn_type const& turn, turns) { switch (phase) @@ -77,8 +79,14 @@ struct map_visitor m_mapper.map(turn.point, "fill:rgb(255,128,0);" "stroke:rgb(0,0,0);stroke-width:1", 4); break; - // TODO: add enriched information as label + case 3 : // after enrich/traverse for union + label_turn(index, turn, -5, "fill:rgb(0,0,128);"); + break; + case 5 : // after enrich/traverse for intersection + label_turn(index, turn, 5, "fill:rgb(0,0,0);"); + break; } + index++; } } @@ -94,6 +102,76 @@ struct map_visitor bg::detail::overlay::traverse_error_type ) {} +private : + + template + bool label_operation(Turn const& turn, std::size_t index, std::ostream& os) + { + os << bg::operation_char(turn.operations[index].operation); + bool result = false; + if (! turn.discarded) + { + if (turn.operations[index].enriched.next_ip_index != -1) + { + os << "->" << turn.operations[index].enriched.next_ip_index; + if (turn.operations[index].enriched.next_ip_index != -1) + { + result = true; + } + } + else + { + os << "->" << turn.operations[index].enriched.travels_to_ip_index; + if (turn.operations[index].enriched.travels_to_ip_index != -1) + { + result = true; + } + } + } + + return result; + } + + template + void label_turn(std::size_t index, Turn const& turn, int y_offset, std::string const& color) + { + std::ostringstream out; + out << index << " "; + if (turn.cluster_id != -1) + { + out << " c=" << turn.cluster_id << " "; + } + bool lab1 = label_operation(turn, 0, out); + out << " / "; + bool lab2 = label_operation(turn, 1, out); + if (turn.switch_source) + { + out << "#"; + } + if (turn.discarded) + { + out << "!"; + } + + std::string font8 = "font-family:Arial;font-size:6px"; + std::string font6 = "font-family:Arial;font-size:4px"; + std::string style = color + ";" + font8; + if (turn.discarded) + { + style = "fill:rgb(92,92,92);" + font6; + } + else if (turn.cluster_id != -1) + { + style = color + ";" + font8; + } + else if (! lab1 || ! lab2) + { + style = color + ";" + font6; + } + + m_mapper.text(turn.point, out.str(), style, 5, y_offset, 6); + } + Mapper& m_mapper; }; From 5eed687af3c5eb45d7a7d01566617fdf2d0f1ad0 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 6 Oct 2017 11:21:50 +0200 Subject: [PATCH 08/16] [dissolve] clear turns between the two phases of enrich/traverse --- .../extensions/algorithms/dissolve.hpp | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/include/boost/geometry/extensions/algorithms/dissolve.hpp b/include/boost/geometry/extensions/algorithms/dissolve.hpp index 838d36f67..40bcf3fb3 100644 --- a/include/boost/geometry/extensions/algorithms/dissolve.hpp +++ b/include/boost/geometry/extensions/algorithms/dissolve.hpp @@ -113,6 +113,28 @@ public : template struct dissolve_ring_or_polygon { + template + static inline void clear(Turns& turns) + { + typedef typename boost::range_value::type turn_type; + + for (typename boost::range_iterator::type + it = boost::begin(turns); + it != boost::end(turns); + ++it) + { + turn_type& turn = *it; + turn.discarded = false; + turn.cluster_id = -1; + turn.has_colocated_both = false; + turn.switch_source = false; + turn.touch_only = false; + } + + clear_visit_info(turns); + } + + template < typename RescalePolicy, typename OutputIterator, @@ -158,7 +180,7 @@ struct dissolve_ring_or_polygon cluster_type clusters; - // Enrich/traverse the polygons twice: once for union... + // Enrich/traverse the polygons twice: first for union... typename Strategy::side_strategy_type const side_strategy = strategy.get_side_strategy(); @@ -184,8 +206,8 @@ struct dissolve_ring_or_polygon visitor.visit_turns(3, turns); - // ... and for intersection - clear_visit_info(turns); + // ... and then for intersection + clear(turns); enrich_intersection_points(turns, clusters, geometry, geometry, rescale_policy, side_strategy); From 7783eb6a240fff753b5fe62c152840e2193f8bdc Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 6 Oct 2017 12:30:48 +0200 Subject: [PATCH 09/16] [overlay] distinguish dissolve intersection/union to be able to avoid self-turn being true for dissolve (otherwise all is true), to avoid having those turns discarded. This fixes some (but not all) of the regressions detected earlier --- extensions/test/algorithms/dissolve.cpp | 9 +++---- .../detail/overlay/is_self_turn.hpp | 11 +++++++- .../detail/overlay/overlay_type.hpp | 27 ++++++++++++++++++- .../extensions/algorithms/dissolve.hpp | 12 ++++----- 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/extensions/test/algorithms/dissolve.cpp b/extensions/test/algorithms/dissolve.cpp index 47189aae6..1b5f852a4 100644 --- a/extensions/test/algorithms/dissolve.cpp +++ b/extensions/test/algorithms/dissolve.cpp @@ -386,23 +386,22 @@ void test_all() test_one("3", "POLYGON((0 2,2 4,2 0,4 2,0 2))", 0, 8, 4.0); +#endif // Self tangent - polygons are now included twice test_one("4", "POLYGON((0 0,0 4,4 4,4 0,2 4,0 0))", - 0, 8, 8.0); - + 0, 7, 8.0); // Self tangent in corner - polygons are now included twice test_one("5", "POLYGON((0 0,0 4,4 4,4 0,0 4,2 0,0 0))", - 0, 8, 12.0); + 0, 7, 12.0); // With spike test_one("6", "POLYGON((0 0,0 4,4 4,4 2,6 2,4 2,4 0,0 0))", 0, 6, 16); -#endif // Non intersection, but with duplicate test_one("d1", @@ -508,11 +507,9 @@ void test_all() "MULTIPOLYGON(((560 -400, 600 -400, 600 -440, 560 -440, 560 -400)), ((480 -400, 520 -400, 520 -440, 480 -440, 480 -400)), ((600 -320, 640 -320, 640 -360, 600 -360, 600 -320)), ((520 -400, 560 -400, 560 -440, 520 -440, 520 -400)))", 1, 14, 6400); -#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS test_one("ggl_list_20110307_javier_01_b", "POLYGON((0 0, 2000 0, 2000 -2000, 0 -2000, 0 0), (560 -400, 560 -440, 600 -440, 600 -400, 560 -400), (480 -400, 480 -440, 520 -440, 520 -400, 480 -400), (600 -320, 600 -360, 640 -360, 640 -320, 600 -320), (520 -400, 520 -440, 560 -440, 560 -400, 520 -400))", 1, 19, 3993600); -#endif } diff --git a/include/boost/geometry/algorithms/detail/overlay/is_self_turn.hpp b/include/boost/geometry/algorithms/detail/overlay/is_self_turn.hpp index 9cb7a0fca..9423a24b3 100644 --- a/include/boost/geometry/algorithms/detail/overlay/is_self_turn.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/is_self_turn.hpp @@ -41,7 +41,7 @@ struct is_self_turn_check }; template <> -struct is_self_turn_check +struct is_self_turn_check { template static inline bool apply(Turn const& turn) @@ -50,6 +50,15 @@ struct is_self_turn_check } }; +template <> +struct is_self_turn_check +{ + template + static inline bool apply(Turn const& turn) + { + return false; + } +}; template bool is_self_turn(Turn const& turn) diff --git a/include/boost/geometry/algorithms/detail/overlay/overlay_type.hpp b/include/boost/geometry/algorithms/detail/overlay/overlay_type.hpp index 0f6084097..f3ec9eaa6 100644 --- a/include/boost/geometry/algorithms/detail/overlay/overlay_type.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/overlay_type.hpp @@ -21,7 +21,8 @@ enum overlay_type overlay_intersection, overlay_difference, overlay_buffer, - overlay_dissolve + overlay_dissolve_union, + overlay_dissolve_intersection }; #ifndef DOXYGEN_NO_DETAIL @@ -41,6 +42,17 @@ enum operation_type template struct operation_from_overlay +{ +}; + +template <> +struct operation_from_overlay +{ + static const operation_type value = operation_union; +}; + +template <> +struct operation_from_overlay { static const operation_type value = operation_union; }; @@ -57,6 +69,19 @@ struct operation_from_overlay static const operation_type value = operation_intersection; }; +template <> +struct operation_from_overlay +{ + static const operation_type value = operation_union; +}; + +template <> +struct operation_from_overlay +{ + static const operation_type value = operation_intersection; +}; + + }} // namespace detail::overlay #endif //DOXYGEN_NO_DETAIL diff --git a/include/boost/geometry/extensions/algorithms/dissolve.hpp b/include/boost/geometry/extensions/algorithms/dissolve.hpp index 40bcf3fb3..ac0bc5a84 100644 --- a/include/boost/geometry/extensions/algorithms/dissolve.hpp +++ b/include/boost/geometry/extensions/algorithms/dissolve.hpp @@ -184,7 +184,7 @@ struct dissolve_ring_or_polygon typename Strategy::side_strategy_type const side_strategy = strategy.get_side_strategy(); - enrich_intersection_points(turns, + enrich_intersection_points(turns, clusters, geometry, geometry, rescale_policy, side_strategy); @@ -198,7 +198,7 @@ struct dissolve_ring_or_polygon < false, false, Geometry, Geometry, - overlay_dissolve, + overlay_dissolve_union, backtrack_for_dissolve >::apply(geometry, geometry, strategy, rescale_policy, @@ -208,7 +208,7 @@ struct dissolve_ring_or_polygon // ... and then for intersection clear(turns); - enrich_intersection_points(turns, + enrich_intersection_points(turns, clusters, geometry, geometry, rescale_policy, side_strategy); @@ -218,7 +218,7 @@ struct dissolve_ring_or_polygon < false, false, Geometry, Geometry, - overlay_intersection, + overlay_dissolve_intersection, backtrack_for_dissolve >::apply(geometry, geometry, strategy, rescale_policy, @@ -226,7 +226,7 @@ struct dissolve_ring_or_polygon visitor.visit_turns(5, turns); - detail::overlay::get_ring_turn_info(turn_info_per_ring, turns, clusters); + detail::overlay::get_ring_turn_info(turn_info_per_ring, turns, clusters); typedef typename geometry::point_type::type point_type; typedef typename Strategy::template area_strategy @@ -238,7 +238,7 @@ struct dissolve_ring_or_polygon std::map selected; - detail::overlay::select_rings(geometry, turn_info_per_ring, selected, strategy); + detail::overlay::select_rings(geometry, turn_info_per_ring, selected, strategy); // Add intersected rings { From ee02d25a42fc2dd7195ca518fa7d2082ebe93c7c Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 6 Oct 2017 13:02:14 +0200 Subject: [PATCH 10/16] [test] add Johan's testcases for dissolve --- extensions/test/algorithms/dissolve.cpp | 29 +++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/extensions/test/algorithms/dissolve.cpp b/extensions/test/algorithms/dissolve.cpp index 1b5f852a4..305f70bae 100644 --- a/extensions/test/algorithms/dissolve.cpp +++ b/extensions/test/algorithms/dissolve.cpp @@ -41,6 +41,21 @@ # include #endif + +// Testcases send by Johan Doré at September 24, 2017: +static std::string dissolve_mail_2017_09_24_a = "POLYGON((0 1, 1 0, 1 1, 0 0, 0 1))"; // two triangles +static std::string dissolve_mail_2017_09_24_b = "POLYGON((1 0, 0 0, 0 4, 4 4, 4 0))"; // input is not closed +static std::string dissolve_mail_2017_09_24_c = "POLYGON((0 0, 1 0, 0 -1, 0.0001 1))"; // spike and not closed +static std::string dissolve_mail_2017_09_24_d = "POLYGON((0 0, 1 0, 0 -1, 0 1))"; // spike and not closed + +// Large polygon with self-intersections +static std::string dissolve_mail_2017_09_24_e = "POLYGON((25.21475410461420 -1.19600892066955, 25.36818313598630 -1.20732820034027, 25.36953926086420 -1.20868659019470, 25.37180328369140 -1.20959210395812, 25.37451934814450 -1.21049761772155, 25.37632942199700 -1.21185600757598, 25.37904357910150 -1.21276152133941, 25.38085556030270 -1.21321427822113, 25.38221168518060 -1.21366703510284, 25.38311767578120 -1.21411991119384, 25.38447570800780 -1.21411991119384, 25.38447570800780 -1.21185600757598, 25.38492774963370 -1.21140325069427, 25.38492774963370 -1.21095049381256, 25.38945388793940 -1.21095049381256, 25.38990592956540 -1.21049761772155, 25.39035987854000 -1.21004486083984, 25.39081192016600 -1.21004486083984, 25.39081192016600 -1.20959210395812, 25.39126396179190 -1.20913934707641, 25.39171600341790 -1.20913934707641, 25.39262199401850 -1.20868659019470, 25.39262199401850 -1.20823383331298, 25.39352798461910 -1.20823383331298, 25.39398002624510 -1.20778107643127, 25.39443206787100 -1.20778107643127, 25.39443206787100 -1.20732820034027, 25.39488410949700 -1.20687544345855, 25.39443206787100 -1.20642268657684, 25.39420700073240 -1.20596992969512, 25.39386749267570 -1.20551717281341, 25.39352798461910 -1.20551717281341, 25.39352798461910 -1.20506441593170, 25.39386749267570 -1.20551717281341, 25.39398002624510 -1.20551717281341, 25.39420700073240 -1.20596992969512, 25.39488410949700 -1.20687544345855, 25.39533805847160 -1.20778107643127, 25.39579010009760 -1.20823383331298, 25.39579010009760 -1.20868659019470, 25.39624214172360 -1.20913934707641, 25.39669609069820 -1.20959210395812, 25.39669609069820 -1.21049761772155, 25.39714813232420 -1.21095049381256, 25.39760017395010 -1.21185600757598, 25.39805221557610 -1.21321427822113, 25.39850616455070 -1.21411991119384, 25.39895820617670 -1.21547818183898, 25.39895820617670 -1.21638369560241, 25.39986419677730 -1.21819484233856, 25.40031623840330 -1.21955311298370, 25.40076828002920 -1.22045862674713, 25.40076828002920 -1.22181701660156, 25.40122032165520 -1.22226977348327, 25.40122032165520 -1.22408080101013, 25.40212631225580 -1.22498643398284, 25.40212631225580 -1.22634470462799, 25.40257835388180 -1.22725021839141, 25.40257835388180 -1.22770309448242, 25.40303230285640 -1.22860860824584, 25.40303230285640 -1.23041963577270, 25.40348434448240 -1.23041963577270, 25.21475410461420 -1.19600892066955))"; + +// Idem but moving closing point eastwards to view self-intersections better +static std::string dissolve_mail_2017_09_24_f = "POLYGON((25.35475410461420 -1.20600892066955, 25.36818313598630 -1.20732820034027, 25.36953926086420 -1.20868659019470, 25.37180328369140 -1.20959210395812, 25.37451934814450 -1.21049761772155, 25.37632942199700 -1.21185600757598, 25.37904357910150 -1.21276152133941, 25.38085556030270 -1.21321427822113, 25.38221168518060 -1.21366703510284, 25.38311767578120 -1.21411991119384, 25.38447570800780 -1.21411991119384, 25.38447570800780 -1.21185600757598, 25.38492774963370 -1.21140325069427, 25.38492774963370 -1.21095049381256, 25.38945388793940 -1.21095049381256, 25.38990592956540 -1.21049761772155, 25.39035987854000 -1.21004486083984, 25.39081192016600 -1.21004486083984, 25.39081192016600 -1.20959210395812, 25.39126396179190 -1.20913934707641, 25.39171600341790 -1.20913934707641, 25.39262199401850 -1.20868659019470, 25.39262199401850 -1.20823383331298, 25.39352798461910 -1.20823383331298, 25.39398002624510 -1.20778107643127, 25.39443206787100 -1.20778107643127, 25.39443206787100 -1.20732820034027, 25.39488410949700 -1.20687544345855, 25.39443206787100 -1.20642268657684, 25.39420700073240 -1.20596992969512, 25.39386749267570 -1.20551717281341, 25.39352798461910 -1.20551717281341, 25.39352798461910 -1.20506441593170, 25.39386749267570 -1.20551717281341, 25.39398002624510 -1.20551717281341, 25.39420700073240 -1.20596992969512, 25.39488410949700 -1.20687544345855, 25.39533805847160 -1.20778107643127, 25.39579010009760 -1.20823383331298, 25.39579010009760 -1.20868659019470, 25.39624214172360 -1.20913934707641, 25.39669609069820 -1.20959210395812, 25.39669609069820 -1.21049761772155, 25.39714813232420 -1.21095049381256, 25.39760017395010 -1.21185600757598, 25.39805221557610 -1.21321427822113, 25.39850616455070 -1.21411991119384, 25.39895820617670 -1.21547818183898, 25.39895820617670 -1.21638369560241, 25.39986419677730 -1.21819484233856, 25.40031623840330 -1.21955311298370, 25.40076828002920 -1.22045862674713, 25.40076828002920 -1.22181701660156, 25.40122032165520 -1.22226977348327, 25.40122032165520 -1.22408080101013, 25.40212631225580 -1.22498643398284, 25.40212631225580 -1.22634470462799, 25.40257835388180 -1.22725021839141, 25.40257835388180 -1.22770309448242, 25.40303230285640 -1.22860860824584, 25.40303230285640 -1.23041963577270, 25.40348434448240 -1.23041963577270, 25.35475410461420 -1.20600892066955))"; + + + #if defined(TEST_WITH_SVG) template struct map_visitor @@ -364,6 +379,9 @@ void test_one(std::string const& caseid, std::string const& wkt, } +#define TEST_DISSOLVE(caseid, area, clips, holes, points) \ + (test_one) ( #caseid, caseid, holes, points, area) + template void test_all() @@ -443,6 +461,17 @@ void test_all() "POLYGON((5 0,2.5 9,9.5 3.5,0.5 3.5,7.5 9,5 0))", 0, 11, 25.6158412); +#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS + TEST_DISSOLVE(dissolve_mail_2017_09_24_a, 99.99, 2, 0, 6); +#endif + + // These are not all complete yet + TEST_DISSOLVE(dissolve_mail_2017_09_24_b, 16.0, 1, 0, 5); + TEST_DISSOLVE(dissolve_mail_2017_09_24_c, 0.4999, 1, 0, 4); + TEST_DISSOLVE(dissolve_mail_2017_09_24_d, 0.5, 1, 0, 4); + TEST_DISSOLVE(dissolve_mail_2017_09_24_e, 0.0018011, 1, 0, 64); + TEST_DISSOLVE(dissolve_mail_2017_09_24_f, 0.0003612064, 2, 0, 64); + #ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS test_one("pentagram_rev", "POLYGON((5 0,7.5 9,0.5 3.5,9.5 3.5,2.5 9,5 0))", From a73246bbd23a91c42a367f635560e712150188fb Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 6 Oct 2017 13:46:01 +0200 Subject: [PATCH 11/16] [dissolve] change in order of algorithm / comment --- .../detail/overlay/assign_parents.hpp | 2 +- .../extensions/algorithms/dissolve.hpp | 188 +++++++++--------- 2 files changed, 93 insertions(+), 97 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp index 78160f520..7cc91f726 100644 --- a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp @@ -372,7 +372,7 @@ inline void assign_parents(Geometry1 const& geometry1, } -// Version for one geometry (called by buffer) +// Version for one geometry (called by buffer/dissolve) template < typename Geometry, diff --git a/include/boost/geometry/extensions/algorithms/dissolve.hpp b/include/boost/geometry/extensions/algorithms/dissolve.hpp index ac0bc5a84..6fef44a64 100644 --- a/include/boost/geometry/extensions/algorithms/dissolve.hpp +++ b/include/boost/geometry/extensions/algorithms/dissolve.hpp @@ -164,108 +164,104 @@ struct dissolve_ring_or_polygon visitor.visit_turns(1, turns); - // The dissolve process is not necessary if there are no turns at all - - if (boost::size(turns) > 0) - { - typedef typename ring_type::type ring_type; - typedef std::vector out_vector; - out_vector rings; - - typedef std::map - < - signed_size_type, - detail::overlay::cluster_info - > cluster_type; - - cluster_type clusters; - - // Enrich/traverse the polygons twice: first for union... - typename Strategy::side_strategy_type const - side_strategy = strategy.get_side_strategy(); - - enrich_intersection_points(turns, - clusters, geometry, geometry, rescale_policy, - side_strategy); - - visitor.visit_turns(2, turns); - - visitor.visit_clusters(clusters, turns); - - std::map turn_info_per_ring; - - detail::overlay::traverse - < - false, false, - Geometry, Geometry, - overlay_dissolve_union, - backtrack_for_dissolve - >::apply(geometry, geometry, - strategy, rescale_policy, - turns, rings, turn_info_per_ring, clusters, visitor); - - visitor.visit_turns(3, turns); - - // ... and then for intersection - clear(turns); - enrich_intersection_points(turns, - clusters, geometry, geometry, rescale_policy, - side_strategy); - - visitor.visit_turns(4, turns); - - detail::overlay::traverse - < - false, false, - Geometry, Geometry, - overlay_dissolve_intersection, - backtrack_for_dissolve - >::apply(geometry, geometry, - strategy, rescale_policy, - turns, rings, turn_info_per_ring, clusters, visitor); - - visitor.visit_turns(5, turns); - - detail::overlay::get_ring_turn_info(turn_info_per_ring, turns, clusters); - - typedef typename geometry::point_type::type point_type; - typedef typename Strategy::template area_strategy - < - point_type - >::type area_strategy_type; - typedef typename area_strategy_type::return_type area_result_type; - typedef detail::overlay::ring_properties properties; - - std::map selected; - - detail::overlay::select_rings(geometry, turn_info_per_ring, selected, strategy); - - // Add intersected rings - { - area_strategy_type const area_strategy = strategy.template get_area_strategy(); - - ring_identifier id(2, 0, -1); - for (typename boost::range_iterator const>::type - it = boost::begin(rings); - it != boost::end(rings); - ++it) - { - selected[id] = properties(*it, area_strategy); - id.multi_index++; - } - } - - detail::overlay::assign_parents(geometry, rings, selected, strategy, true); - return detail::overlay::add_rings(selected, geometry, rings, out); - - } - else + if (boost::size(turns) == 0) { + // No self-turns, then add original geometry GeometryOut g; geometry::convert(geometry, g); *out++ = g; return out; } + + typedef typename ring_type::type ring_type; + typedef std::vector out_vector; + out_vector rings; + + typedef std::map + < + signed_size_type, + detail::overlay::cluster_info + > cluster_type; + + cluster_type clusters; + + // Enrich/traverse the polygons twice: first for union... + typename Strategy::side_strategy_type const + side_strategy = strategy.get_side_strategy(); + + enrich_intersection_points(turns, + clusters, geometry, geometry, rescale_policy, + side_strategy); + + visitor.visit_turns(2, turns); + + visitor.visit_clusters(clusters, turns); + + std::map turn_info_per_ring; + + detail::overlay::traverse + < + false, false, + Geometry, Geometry, + overlay_dissolve_union, + backtrack_for_dissolve + >::apply(geometry, geometry, + strategy, rescale_policy, + turns, rings, turn_info_per_ring, clusters, visitor); + + visitor.visit_turns(3, turns); + + // ... and then for intersection + clear(turns); + enrich_intersection_points(turns, + clusters, geometry, geometry, rescale_policy, + side_strategy); + + visitor.visit_turns(4, turns); + + detail::overlay::traverse + < + false, false, + Geometry, Geometry, + overlay_dissolve_intersection, + backtrack_for_dissolve + >::apply(geometry, geometry, + strategy, rescale_policy, + turns, rings, turn_info_per_ring, clusters, visitor); + + visitor.visit_turns(5, turns); + + detail::overlay::get_ring_turn_info(turn_info_per_ring, turns, clusters); + + typedef typename geometry::point_type::type point_type; + typedef typename Strategy::template area_strategy + < + point_type + >::type area_strategy_type; + typedef typename area_strategy_type::return_type area_result_type; + typedef detail::overlay::ring_properties properties; + + std::map selected; + + detail::overlay::select_rings(geometry, turn_info_per_ring, selected, strategy); + + // Add intersected rings + { + area_strategy_type const area_strategy = strategy.template get_area_strategy(); + + ring_identifier id(2, 0, -1); + for (typename boost::range_iterator const>::type + it = boost::begin(rings); + it != boost::end(rings); + ++it) + { + selected[id] = properties(*it, area_strategy); + id.multi_index++; + } + } + + detail::overlay::assign_parents(geometry, rings, selected, strategy, true); + return detail::overlay::add_rings(selected, geometry, rings, out); } }; From 1187e1e8058779c95b989c955ef736875faa0726 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 6 Oct 2017 15:46:20 +0200 Subject: [PATCH 12/16] [dissolve] fix case with two triangles which needs to be corrected w.r.t. next turn if there is only one turn --- extensions/test/algorithms/dissolve.cpp | 18 +++++++++--------- .../algorithms/detail/overlay/traversal.hpp | 7 ++++++- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/extensions/test/algorithms/dissolve.cpp b/extensions/test/algorithms/dissolve.cpp index 305f70bae..e9b6a4587 100644 --- a/extensions/test/algorithms/dissolve.cpp +++ b/extensions/test/algorithms/dissolve.cpp @@ -399,22 +399,20 @@ void test_all() "POLYGON((1 2,1 1,2 1,2 2.25,3 2.25,3 0,0 0,0 3,3 3,2.75 2,1 2))", 1, 12, 7.9296875); -#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS // Self intersecting in last segment test_one("3", "POLYGON((0 2,2 4,2 0,4 2,0 2))", 0, 8, 4.0); -#endif // Self tangent - polygons are now included twice test_one("4", "POLYGON((0 0,0 4,4 4,4 0,2 4,0 0))", - 0, 7, 8.0); + 0, 8, 8.0); // Self tangent in corner - polygons are now included twice test_one("5", "POLYGON((0 0,0 4,4 4,4 0,0 4,2 0,0 0))", - 0, 7, 12.0); + 0, 8, 12.0); // With spike test_one("6", @@ -461,16 +459,14 @@ void test_all() "POLYGON((5 0,2.5 9,9.5 3.5,0.5 3.5,7.5 9,5 0))", 0, 11, 25.6158412); -#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS - TEST_DISSOLVE(dissolve_mail_2017_09_24_a, 99.99, 2, 0, 6); -#endif + TEST_DISSOLVE(dissolve_mail_2017_09_24_a, 0.5, 2, 0, 8); // These are not all complete yet TEST_DISSOLVE(dissolve_mail_2017_09_24_b, 16.0, 1, 0, 5); TEST_DISSOLVE(dissolve_mail_2017_09_24_c, 0.4999, 1, 0, 4); TEST_DISSOLVE(dissolve_mail_2017_09_24_d, 0.5, 1, 0, 4); - TEST_DISSOLVE(dissolve_mail_2017_09_24_e, 0.0018011, 1, 0, 64); - TEST_DISSOLVE(dissolve_mail_2017_09_24_f, 0.0003612064, 2, 0, 64); + TEST_DISSOLVE(dissolve_mail_2017_09_24_e, 0.001801138128, 1, 0, 69); + TEST_DISSOLVE(dissolve_mail_2017_09_24_f, 0.000361308800, 2, 0, 69); #ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS test_one("pentagram_rev", @@ -478,20 +474,24 @@ void test_all() 0, 11, 25.6158412); // Poygons contain too many polygons +#endif // CCW polygons should turn CW after dissolve test_one("cw", "POLYGON((2 8,8 8,8 0,0 0,0 6,4 6,4 4,2 4,2 8))", 0, 7, 60); +#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS test_one("ccw", "POLYGON((2 8,2 4,4 4,4 6,0 6,0 0,8 0,8 8,2 8))", 0, 12, 64); // TODO: should have the same, 7, 60. The polygon is dissolved (splitted) but the extra polygon is still on top of the other +#endif // https://svn.boost.org/trac/boost/ticket/10713 test_one("ticket_10713", "POLYGON((-0.7189743518829346 4.1308121681213379, 0.0831791982054710 4.1034231185913086, 0.1004156470298767 4.1107301712036133, 0.1044322624802589 4.1026973724365234, 0.0831791982054710 4.1034231185913086, -0.7711903452873230 3.7412264347076416, -0.7189743518829346 4.1308121681213379))", 0, 8, 0.157052766); +#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS // Reported by Artem Pavlenko at gitter // https://gitter.im/boostorg/geometry?at=58ef46408e4b63533dc49b48 test_one("artem1", diff --git a/include/boost/geometry/algorithms/detail/overlay/traversal.hpp b/include/boost/geometry/algorithms/detail/overlay/traversal.hpp index 73b2b53c3..735ca82cb 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traversal.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traversal.hpp @@ -661,7 +661,9 @@ struct traversal turn_operation_type const& start_op, int start_op_index) const { - if (OverlayType != overlay_buffer) + if (OverlayType != overlay_buffer + && OverlayType != overlay_dissolve_union + && OverlayType != overlay_dissolve_intersection) { return; } @@ -689,6 +691,9 @@ struct traversal bool const correct = ! start_turn.both(operation_union) + && start_op.seg_id.source_index == other_op.seg_id.source_index + && start_op.seg_id.multi_index == other_op.seg_id.multi_index + && start_op.seg_id.ring_index == other_op.seg_id.ring_index && start_op.seg_id.segment_index == to_vertex_index; #if defined(BOOST_GEOMETRY_DEBUG_TRAVERSE) From 5f865f79f254f90f0429e0a50937f12dd846a3db Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 6 Oct 2017 16:01:40 +0200 Subject: [PATCH 13/16] [test] dissolve: start testing #clips and #holes too --- extensions/test/algorithms/dissolve.cpp | 140 +++++++++++++----------- 1 file changed, 76 insertions(+), 64 deletions(-) diff --git a/extensions/test/algorithms/dissolve.cpp b/extensions/test/algorithms/dissolve.cpp index e9b6a4587..7b8fcbf46 100644 --- a/extensions/test/algorithms/dissolve.cpp +++ b/extensions/test/algorithms/dissolve.cpp @@ -42,18 +42,53 @@ #endif -// Testcases send by Johan Doré at September 24, 2017: -static std::string dissolve_mail_2017_09_24_a = "POLYGON((0 1, 1 0, 1 1, 0 0, 0 1))"; // two triangles -static std::string dissolve_mail_2017_09_24_b = "POLYGON((1 0, 0 0, 0 4, 4 4, 4 0))"; // input is not closed -static std::string dissolve_mail_2017_09_24_c = "POLYGON((0 0, 1 0, 0 -1, 0.0001 1))"; // spike and not closed -static std::string dissolve_mail_2017_09_24_d = "POLYGON((0 0, 1 0, 0 -1, 0 1))"; // spike and not closed +namespace +{ + // Simplex + std::string const dissolve_1 = "POLYGON((0 0,0 4,1.5 2.5,2.5 1.5,4 0,0 0))"; -// Large polygon with self-intersections -static std::string dissolve_mail_2017_09_24_e = "POLYGON((25.21475410461420 -1.19600892066955, 25.36818313598630 -1.20732820034027, 25.36953926086420 -1.20868659019470, 25.37180328369140 -1.20959210395812, 25.37451934814450 -1.21049761772155, 25.37632942199700 -1.21185600757598, 25.37904357910150 -1.21276152133941, 25.38085556030270 -1.21321427822113, 25.38221168518060 -1.21366703510284, 25.38311767578120 -1.21411991119384, 25.38447570800780 -1.21411991119384, 25.38447570800780 -1.21185600757598, 25.38492774963370 -1.21140325069427, 25.38492774963370 -1.21095049381256, 25.38945388793940 -1.21095049381256, 25.38990592956540 -1.21049761772155, 25.39035987854000 -1.21004486083984, 25.39081192016600 -1.21004486083984, 25.39081192016600 -1.20959210395812, 25.39126396179190 -1.20913934707641, 25.39171600341790 -1.20913934707641, 25.39262199401850 -1.20868659019470, 25.39262199401850 -1.20823383331298, 25.39352798461910 -1.20823383331298, 25.39398002624510 -1.20778107643127, 25.39443206787100 -1.20778107643127, 25.39443206787100 -1.20732820034027, 25.39488410949700 -1.20687544345855, 25.39443206787100 -1.20642268657684, 25.39420700073240 -1.20596992969512, 25.39386749267570 -1.20551717281341, 25.39352798461910 -1.20551717281341, 25.39352798461910 -1.20506441593170, 25.39386749267570 -1.20551717281341, 25.39398002624510 -1.20551717281341, 25.39420700073240 -1.20596992969512, 25.39488410949700 -1.20687544345855, 25.39533805847160 -1.20778107643127, 25.39579010009760 -1.20823383331298, 25.39579010009760 -1.20868659019470, 25.39624214172360 -1.20913934707641, 25.39669609069820 -1.20959210395812, 25.39669609069820 -1.21049761772155, 25.39714813232420 -1.21095049381256, 25.39760017395010 -1.21185600757598, 25.39805221557610 -1.21321427822113, 25.39850616455070 -1.21411991119384, 25.39895820617670 -1.21547818183898, 25.39895820617670 -1.21638369560241, 25.39986419677730 -1.21819484233856, 25.40031623840330 -1.21955311298370, 25.40076828002920 -1.22045862674713, 25.40076828002920 -1.22181701660156, 25.40122032165520 -1.22226977348327, 25.40122032165520 -1.22408080101013, 25.40212631225580 -1.22498643398284, 25.40212631225580 -1.22634470462799, 25.40257835388180 -1.22725021839141, 25.40257835388180 -1.22770309448242, 25.40303230285640 -1.22860860824584, 25.40303230285640 -1.23041963577270, 25.40348434448240 -1.23041963577270, 25.21475410461420 -1.19600892066955))"; + // Self intersecting + std::string const dissolve_2 = "POLYGON((1 2,1 1,2 1,2 2.25,3 2.25,3 0,0 0,0 3,3 3,2.75 2,1 2))"; -// Idem but moving closing point eastwards to view self-intersections better -static std::string dissolve_mail_2017_09_24_f = "POLYGON((25.35475410461420 -1.20600892066955, 25.36818313598630 -1.20732820034027, 25.36953926086420 -1.20868659019470, 25.37180328369140 -1.20959210395812, 25.37451934814450 -1.21049761772155, 25.37632942199700 -1.21185600757598, 25.37904357910150 -1.21276152133941, 25.38085556030270 -1.21321427822113, 25.38221168518060 -1.21366703510284, 25.38311767578120 -1.21411991119384, 25.38447570800780 -1.21411991119384, 25.38447570800780 -1.21185600757598, 25.38492774963370 -1.21140325069427, 25.38492774963370 -1.21095049381256, 25.38945388793940 -1.21095049381256, 25.38990592956540 -1.21049761772155, 25.39035987854000 -1.21004486083984, 25.39081192016600 -1.21004486083984, 25.39081192016600 -1.20959210395812, 25.39126396179190 -1.20913934707641, 25.39171600341790 -1.20913934707641, 25.39262199401850 -1.20868659019470, 25.39262199401850 -1.20823383331298, 25.39352798461910 -1.20823383331298, 25.39398002624510 -1.20778107643127, 25.39443206787100 -1.20778107643127, 25.39443206787100 -1.20732820034027, 25.39488410949700 -1.20687544345855, 25.39443206787100 -1.20642268657684, 25.39420700073240 -1.20596992969512, 25.39386749267570 -1.20551717281341, 25.39352798461910 -1.20551717281341, 25.39352798461910 -1.20506441593170, 25.39386749267570 -1.20551717281341, 25.39398002624510 -1.20551717281341, 25.39420700073240 -1.20596992969512, 25.39488410949700 -1.20687544345855, 25.39533805847160 -1.20778107643127, 25.39579010009760 -1.20823383331298, 25.39579010009760 -1.20868659019470, 25.39624214172360 -1.20913934707641, 25.39669609069820 -1.20959210395812, 25.39669609069820 -1.21049761772155, 25.39714813232420 -1.21095049381256, 25.39760017395010 -1.21185600757598, 25.39805221557610 -1.21321427822113, 25.39850616455070 -1.21411991119384, 25.39895820617670 -1.21547818183898, 25.39895820617670 -1.21638369560241, 25.39986419677730 -1.21819484233856, 25.40031623840330 -1.21955311298370, 25.40076828002920 -1.22045862674713, 25.40076828002920 -1.22181701660156, 25.40122032165520 -1.22226977348327, 25.40122032165520 -1.22408080101013, 25.40212631225580 -1.22498643398284, 25.40212631225580 -1.22634470462799, 25.40257835388180 -1.22725021839141, 25.40257835388180 -1.22770309448242, 25.40303230285640 -1.22860860824584, 25.40303230285640 -1.23041963577270, 25.40348434448240 -1.23041963577270, 25.35475410461420 -1.20600892066955))"; + // Self intersecting in last segment + std::string const dissolve_3 = "POLYGON((0 2,2 4,2 0,4 2,0 2))"; + // Self tangent - polygons are now included twice + std::string const dissolve_4 = "POLYGON((0 0,0 4,4 4,4 0,2 4,0 0))"; + + // Self tangent in corner - polygons are now included twice + std::string const dissolve_5 = "POLYGON((0 0,0 4,4 4,4 0,0 4,2 0,0 0))"; + + // With spike + std::string const dissolve_6 = "POLYGON((0 0,0 4,4 4,4 2,6 2,4 2,4 0,0 0))"; + + // Non intersection, but with duplicate + std::string const dissolve_d1 = "POLYGON((0 0,0 4,4 0,4 0,0 0))"; + + // With many duplicate points + std::string const dissolve_d2 = "POLYGON((0 0,0 1,0 1,0 1,0 2,0 2,0 3,0 3,0 3,0 3,0 4,2 4,2 4,4 4,4 0,4 0,3 0,3 0,3 0,3 0,3 0,0 0))"; + + // Case with touching reversed interior ring inside, which should be removed + std::string const dissolve_h1_a = "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 2,2 4,3 2,1 2))"; + + // Case with correct interior ring inside, which should be stay + std::string const dissolve_h1_b = "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 2,3 2,2 4,1 2))"; + + // Testcases send by Johan Doré at September 24, 2017: + std::string const dissolve_mail_2017_09_24_a = "POLYGON((0 1, 1 0, 1 1, 0 0, 0 1))"; // two triangles + std::string const dissolve_mail_2017_09_24_b = "POLYGON((1 0, 0 0, 0 4, 4 4, 4 0))"; // input is not closed + std::string const dissolve_mail_2017_09_24_c = "POLYGON((0 0, 1 0, 0 -1, 0.0001 1))"; // spike and not closed + std::string const dissolve_mail_2017_09_24_d = "POLYGON((0 0, 1 0, 0 -1, 0 1))"; // spike and not closed + + // Large polygon with self-intersections + std::string const dissolve_mail_2017_09_24_e = "POLYGON((25.21475410461420 -1.19600892066955, 25.36818313598630 -1.20732820034027, 25.36953926086420 -1.20868659019470, 25.37180328369140 -1.20959210395812, 25.37451934814450 -1.21049761772155, 25.37632942199700 -1.21185600757598, 25.37904357910150 -1.21276152133941, 25.38085556030270 -1.21321427822113, 25.38221168518060 -1.21366703510284, 25.38311767578120 -1.21411991119384, 25.38447570800780 -1.21411991119384, 25.38447570800780 -1.21185600757598, 25.38492774963370 -1.21140325069427, 25.38492774963370 -1.21095049381256, 25.38945388793940 -1.21095049381256, 25.38990592956540 -1.21049761772155, 25.39035987854000 -1.21004486083984, 25.39081192016600 -1.21004486083984, 25.39081192016600 -1.20959210395812, 25.39126396179190 -1.20913934707641, 25.39171600341790 -1.20913934707641, 25.39262199401850 -1.20868659019470, 25.39262199401850 -1.20823383331298, 25.39352798461910 -1.20823383331298, 25.39398002624510 -1.20778107643127, 25.39443206787100 -1.20778107643127, 25.39443206787100 -1.20732820034027, 25.39488410949700 -1.20687544345855, 25.39443206787100 -1.20642268657684, 25.39420700073240 -1.20596992969512, 25.39386749267570 -1.20551717281341, 25.39352798461910 -1.20551717281341, 25.39352798461910 -1.20506441593170, 25.39386749267570 -1.20551717281341, 25.39398002624510 -1.20551717281341, 25.39420700073240 -1.20596992969512, 25.39488410949700 -1.20687544345855, 25.39533805847160 -1.20778107643127, 25.39579010009760 -1.20823383331298, 25.39579010009760 -1.20868659019470, 25.39624214172360 -1.20913934707641, 25.39669609069820 -1.20959210395812, 25.39669609069820 -1.21049761772155, 25.39714813232420 -1.21095049381256, 25.39760017395010 -1.21185600757598, 25.39805221557610 -1.21321427822113, 25.39850616455070 -1.21411991119384, 25.39895820617670 -1.21547818183898, 25.39895820617670 -1.21638369560241, 25.39986419677730 -1.21819484233856, 25.40031623840330 -1.21955311298370, 25.40076828002920 -1.22045862674713, 25.40076828002920 -1.22181701660156, 25.40122032165520 -1.22226977348327, 25.40122032165520 -1.22408080101013, 25.40212631225580 -1.22498643398284, 25.40212631225580 -1.22634470462799, 25.40257835388180 -1.22725021839141, 25.40257835388180 -1.22770309448242, 25.40303230285640 -1.22860860824584, 25.40303230285640 -1.23041963577270, 25.40348434448240 -1.23041963577270, 25.21475410461420 -1.19600892066955))"; + + // Idem but moving closing point eastwards to view self-intersections better + std::string const dissolve_mail_2017_09_24_f = "POLYGON((25.35475410461420 -1.20600892066955, 25.36818313598630 -1.20732820034027, 25.36953926086420 -1.20868659019470, 25.37180328369140 -1.20959210395812, 25.37451934814450 -1.21049761772155, 25.37632942199700 -1.21185600757598, 25.37904357910150 -1.21276152133941, 25.38085556030270 -1.21321427822113, 25.38221168518060 -1.21366703510284, 25.38311767578120 -1.21411991119384, 25.38447570800780 -1.21411991119384, 25.38447570800780 -1.21185600757598, 25.38492774963370 -1.21140325069427, 25.38492774963370 -1.21095049381256, 25.38945388793940 -1.21095049381256, 25.38990592956540 -1.21049761772155, 25.39035987854000 -1.21004486083984, 25.39081192016600 -1.21004486083984, 25.39081192016600 -1.20959210395812, 25.39126396179190 -1.20913934707641, 25.39171600341790 -1.20913934707641, 25.39262199401850 -1.20868659019470, 25.39262199401850 -1.20823383331298, 25.39352798461910 -1.20823383331298, 25.39398002624510 -1.20778107643127, 25.39443206787100 -1.20778107643127, 25.39443206787100 -1.20732820034027, 25.39488410949700 -1.20687544345855, 25.39443206787100 -1.20642268657684, 25.39420700073240 -1.20596992969512, 25.39386749267570 -1.20551717281341, 25.39352798461910 -1.20551717281341, 25.39352798461910 -1.20506441593170, 25.39386749267570 -1.20551717281341, 25.39398002624510 -1.20551717281341, 25.39420700073240 -1.20596992969512, 25.39488410949700 -1.20687544345855, 25.39533805847160 -1.20778107643127, 25.39579010009760 -1.20823383331298, 25.39579010009760 -1.20868659019470, 25.39624214172360 -1.20913934707641, 25.39669609069820 -1.20959210395812, 25.39669609069820 -1.21049761772155, 25.39714813232420 -1.21095049381256, 25.39760017395010 -1.21185600757598, 25.39805221557610 -1.21321427822113, 25.39850616455070 -1.21411991119384, 25.39895820617670 -1.21547818183898, 25.39895820617670 -1.21638369560241, 25.39986419677730 -1.21819484233856, 25.40031623840330 -1.21955311298370, 25.40076828002920 -1.22045862674713, 25.40076828002920 -1.22181701660156, 25.40122032165520 -1.22226977348327, 25.40122032165520 -1.22408080101013, 25.40212631225580 -1.22498643398284, 25.40212631225580 -1.22634470462799, 25.40257835388180 -1.22725021839141, 25.40257835388180 -1.22770309448242, 25.40303230285640 -1.22860860824584, 25.40303230285640 -1.23041963577270, 25.40348434448240 -1.23041963577270, 25.35475410461420 -1.20600892066955))"; + + std::string const ticket17 = "POLYGON ((-122.28139163 37.37319149,-122.28100699 37.37273669,-122.28002186 37.37303123,-122.27979681 37.37290072,-122.28007349 37.37240493,-122.27977334 37.37220360,-122.27819720 37.37288580,-122.27714184 37.37275161,-122.27678628 37.37253167,-122.27766437 37.37180973,-122.27804382 37.37121453,-122.27687664 37.37101354,-122.27645829 37.37203386,-122.27604423 37.37249110,-122.27632234 37.37343339,-122.27760980 37.37391082,-122.27812478 37.37800320,-122.26117222 37.39121007,-122.25572289 37.39566631,-122.25547269 37.39564971,-122.25366304 37.39552993,-122.24919976 37.39580268,-122.24417933 37.39366907,-122.24051443 37.39094143,-122.23246277 37.38100418,-122.23606766 37.38141338,-122.24001587 37.37738940,-122.23666848 37.37609347,-122.23057450 37.37882170,-122.22679803 37.37807143,-122.22525727 37.37448817,-122.22523229 37.37443000,-122.23083199 37.37609347,-122.23033486 37.37777891,-122.23169030 37.37732117,-122.23229178 37.37709687,-122.23237761 37.37631249,-122.23297776 37.37438834,-122.23872850 37.37165986,-122.24044511 37.36934068,-122.24671067 37.36865847,-122.24825570 37.36981819,-122.25151719 37.36947713,-122.25357721 37.36756706,-122.26001451 37.36579354,-122.25615213 37.36545239,-122.25486458 37.36245083,-122.25357721 37.36108651,-122.25194642 37.36013139,-122.24885652 37.35958557,-122.24911401 37.35849399,-122.25357721 37.35808470,-122.25675286 37.35897159,-122.25855539 37.35753887,-122.26181687 37.35828939,-122.26713837 37.35897159,-122.26782510 37.36108651,-122.26662339 37.36456559,-122.27288911 37.36722601,-122.27366159 37.36531602,-122.27168740 37.36470213,-122.27391900 37.36374701,-122.27074326 37.36245083,-122.27134408 37.35951742,-122.27426240 37.36135926,-122.27709482 37.36115474,-122.27966974 37.36231438,-122.27958391 37.36463382,-122.27572152 37.36463382,-122.27563569 37.36524779,-122.27700899 37.36593000,-122.27709482 37.36763529,-122.27554978 37.36838573,-122.27667254 37.36931478,-122.27677932 37.36932073,-122.27769362 37.36853987,-122.27942490 37.36830803,-122.28178776 37.36677917,-122.28509559 37.36443500,-122.28845129 37.36413744,-122.29194403 37.36695946,-122.29382577 37.36726817,-122.29600414 37.36898512,-122.29733083 37.36995398,-122.29593239 37.37141436,-122.29416649 37.37075898,-122.29325026 37.37108436,-122.29652910 37.37311697,-122.29584237 37.37374461,-122.29537583 37.37573372,-122.29487677 37.37752502,-122.30923212 37.37593011,-122.31122484 37.38230086,-122.31467994 37.38092472,-122.31715663 37.38252181,-122.32307970 37.38166978,-122.31985618 37.37667694,-122.32210304 37.37580220,-122.32581446 37.37589532,-122.32401730 37.37331839,-122.32960417 37.37189020,-122.33465527 37.37331906,-122.33425328 37.37623680,-122.33620676 37.37726132,-122.33397986 37.37822382,-122.33358918 37.38036590,-122.33202637 37.37986918,-122.33147954 37.38101784,-122.33394080 37.38198017,-122.33545239 37.38587943,-122.33478058 37.38785697,-122.33386050 37.38723721,-122.33350041 37.38571137,-122.33122003 37.38548891,-122.33140008 37.38650606,-122.33366042 37.38817490,-122.33244019 37.39157602,-122.33298157 37.39419201,-122.33164013 37.39477028,-122.33202017 37.39518351,-122.33358038 37.39499282,-122.33376050 37.39597811,-122.33550067 37.39734478,-122.33556069 37.39481797,-122.33344040 37.39292676,-122.33638094 37.38892189,-122.34240644 37.38852719,-122.34906293 37.38726898,-122.35072321 37.39338769,-122.34910291 37.39445252,-122.34796272 37.39410291,-122.34449043 37.39640534,-122.34500223 37.39729709,-122.34936291 37.39670910,-122.35098322 37.39531066,-122.35364623 37.39554510,-122.35434369 37.39612111,-122.35798429 37.39600988,-122.35768430 37.39478621,-122.36334519 37.39206871,-122.36604726 37.39203267,-122.36778592 37.39335592,-122.36518870 37.40022011,-122.36554552 37.40247752,-122.36370519 37.40331974,-122.36270506 37.40530591,-122.36320512 37.40670418,-122.36149849 37.40851392,-122.36730580 37.41054938,-122.37263720 37.41378932,-122.37161871 37.42076600,-122.36566153 37.42006292,-122.36520547 37.42742106,-122.37165953 37.43661157,-122.35943972 37.44459022,-122.35356359 37.44600810,-122.33792254 37.45796329,-122.35228518 37.47478091,-122.35127080 37.48181199,-122.34867342 37.48487322,-122.34359717 37.48801082,-122.33388431 37.48677650,-122.33142321 37.48429747,-122.32929580 37.48473149,-122.32609609 37.48291144,-122.32344850 37.48228229,-122.31924364 37.48410234,-122.31677299 37.48114051,-122.31431751 37.47848973,-122.31259201 37.47682190,-122.31515972 37.47568196,-122.31691389 37.47360309,-122.31292494 37.46960081,-122.31130153 37.46937743,-122.30889894 37.47124987,-122.30612839 37.47011613,-122.30149630 37.46568378,-122.30064277 37.46363784,-122.29283821 37.45922376,-122.28630141 37.45415497,-122.28883099 37.44629920,-122.28316717 37.44197138,-122.27554148 37.42297597,-122.25597410 37.40553692,-122.25196579 37.40129593,-122.25012043 37.40049143,-122.24823207 37.39897758,-122.24754551 37.39740941,-122.24778582 37.39621607,-122.24934787 37.39599102,-122.25005170 37.39871849,-122.25222328 37.39863668,-122.25342491 37.39737529,-122.25520162 37.39667289,-122.25528737 37.39522726,-122.27747460 37.37809616,-122.27977493 37.37858717,-122.28157729 37.37920106,-122.28322534 37.37952846,-122.28416939 37.38092656,-122.28621223 37.37984219,-122.28638389 37.37613857,-122.28382607 37.37843722,-122.27930278 37.37718220,-122.28196361 37.37652740,-122.28295058 37.37568167,-122.28216101 37.37523148,-122.28114822 37.37543608,-122.27934569 37.37528613,-122.27996369 37.37448121,-122.28104521 37.37454944,-122.28185197 37.37422883,-122.28290767 37.37474038,-122.28376597 37.37467224,-122.28428104 37.37399012,-122.28402346 37.37338989,-122.28610922 37.37364914,-122.28651264 37.37327388,-122.28672722 37.37207343,-122.28628398 37.37205448,-122.28574460 37.37166682,-122.28479711 37.37200981,-122.28327731 37.37137228,-122.28285511 37.37100700,-122.28279409 37.37125669,-122.28315527 37.37173756,-122.28321872 37.37220569,-122.28187007 37.37231918,-122.28193109 37.37294908,-122.28139163 37.37319149))"; + std::string const toolkit = "POLYGON((170718 605997,170718 605997,170776 606016,170773 606015,170786 606020,170778 606016,170787 606021,170781 606017,170795 606028,170795 606028,170829 606055,170939 606140,170933 605968,170933 605968,170932 605908,170929 605834,170920 605866,170961 605803,170739 605684,170699 605749,170691 605766,170693 605762,170686 605775,170688 605771,170673 605794,170676 605790,170668 605800,170672 605796,170651 605818,170653 605816,170639 605829,170568 605899,170662 605943,170633 605875,170603 605961,170718 605997))"; +} #if defined(TEST_WITH_SVG) @@ -202,7 +237,9 @@ std::string as_wkt(Geometry const& geometry) template void test_dissolve(std::string const& caseid, Geometry const& geometry, - std::size_t /*expected_hole_count*/, std::size_t expected_point_count, + std::size_t expected_clip_count, + std::size_t expected_hole_count, + std::size_t expected_point_count, double expected_length_or_area, double percentage) { typedef typename bg::coordinate_type::type coordinate_type; @@ -297,7 +334,7 @@ void test_dissolve(std::string const& caseid, Geometry const& geometry, } typename bg::default_area_result::type length_or_area = 0; - //std::size_t holes = 0; + std::size_t holes = 0; std::size_t count = 0; BOOST_FOREACH(GeometryOut& dissolved, dissolved2) @@ -305,7 +342,7 @@ void test_dissolve(std::string const& caseid, Geometry const& geometry, length_or_area += is_line ? bg::length(dissolved) : bg::area(dissolved); - //holes += bg::num_interior_rings(dissolved); + holes += bg::num_interior_rings(dissolved); count += bg::num_points(dissolved); } @@ -316,6 +353,16 @@ void test_dissolve(std::string const& caseid, Geometry const& geometry, << " type: " << string_from_type::name() ); + if (expected_clip_count > 0) + { + BOOST_CHECK_MESSAGE(dissolved1.size() == expected_clip_count, + "dissolve: " << caseid + << " #clips expected: " << expected_clip_count + << " detected: " << dissolved1.size() + << " type: " << string_from_type::name() + ); + } + //BOOST_CHECK_EQUAL(holes, expected_hole_count); BOOST_CHECK_CLOSE(length_or_area, expected_length_or_area, percentage); @@ -340,13 +387,15 @@ void test_dissolve(std::string const& caseid, Geometry const& geometry, template void test_one(std::string const& caseid, std::string const& wkt, std::size_t expected_hole_count, std::size_t expected_point_count, - double expected_length_or_area, double percentage = 0.001) + double expected_length_or_area, + std::size_t expected_clip_count = 0, // to be moved later + double percentage = 0.001) { Geometry geometry; bg::read_wkt(wkt, geometry); test_dissolve(caseid, geometry, - expected_hole_count, expected_point_count, + expected_clip_count, expected_hole_count, expected_point_count, expected_length_or_area, percentage); #ifdef BOOST_GEOMETRY_TEST_MULTI_PERMUTATIONS @@ -380,7 +429,7 @@ void test_one(std::string const& caseid, std::string const& wkt, } #define TEST_DISSOLVE(caseid, area, clips, holes, points) \ - (test_one) ( #caseid, caseid, holes, points, area) + (test_one) ( #caseid, caseid, holes, points, area, clips) template @@ -389,50 +438,17 @@ void test_all() typedef bg::model::ring

ring; typedef bg::model::polygon

polygon; - // Simplex - test_one("1", - "POLYGON((0 0,0 4,1.5 2.5,2.5 1.5,4 0,0 0))", - 0, 6, 8); + TEST_DISSOLVE(dissolve_1, 8.0, 1, 0, 6); + TEST_DISSOLVE(dissolve_2, 7.9296875, 1, 1, 12); + TEST_DISSOLVE(dissolve_3, 4.0, 2, 0, 8); + TEST_DISSOLVE(dissolve_4, 8.0, 2, 0, 8); + TEST_DISSOLVE(dissolve_5, 12.0, 2, 0, 8); + TEST_DISSOLVE(dissolve_6, 16.0, 1, 0, 6); + TEST_DISSOLVE(dissolve_d1, 8.0, 1, 0, 4); + TEST_DISSOLVE(dissolve_d2, 16.0, 1, 0, 10); - // Self intersecting - test_one("2", - "POLYGON((1 2,1 1,2 1,2 2.25,3 2.25,3 0,0 0,0 3,3 3,2.75 2,1 2))", - 1, 12, 7.9296875); - - // Self intersecting in last segment - test_one("3", - "POLYGON((0 2,2 4,2 0,4 2,0 2))", - 0, 8, 4.0); - - // Self tangent - polygons are now included twice - test_one("4", - "POLYGON((0 0,0 4,4 4,4 0,2 4,0 0))", - 0, 8, 8.0); - - // Self tangent in corner - polygons are now included twice - test_one("5", - "POLYGON((0 0,0 4,4 4,4 0,0 4,2 0,0 0))", - 0, 8, 12.0); - - // With spike - test_one("6", - "POLYGON((0 0,0 4,4 4,4 2,6 2,4 2,4 0,0 0))", - 0, 6, 16); - - // Non intersection, but with duplicate - test_one("d1", - "POLYGON((0 0,0 4,4 0,4 0,0 0))", - 0, 4, 8); - - // With many duplicates - test_one("d2", - "POLYGON((0 0,0 1,0 1,0 1,0 2,0 2,0 3,0 3,0 3,0 3,0 4,2 4,2 4,4 4,4 0,4 0,3 0,3 0,3 0,3 0,3 0,0 0))", - 0, 10, 16); - - // Hole: interior tangent to exterior - test_one("h1", - "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 2,2 4,3 2,1 2))", - 0, 6, 16); + TEST_DISSOLVE(dissolve_h1_a, 16.0, 1, 0, 6); + TEST_DISSOLVE(dissolve_h1_b, 14.0, 1, 1, 10); // Hole: interior intersecting exterior test_one("h2", @@ -465,15 +481,13 @@ void test_all() TEST_DISSOLVE(dissolve_mail_2017_09_24_b, 16.0, 1, 0, 5); TEST_DISSOLVE(dissolve_mail_2017_09_24_c, 0.4999, 1, 0, 4); TEST_DISSOLVE(dissolve_mail_2017_09_24_d, 0.5, 1, 0, 4); - TEST_DISSOLVE(dissolve_mail_2017_09_24_e, 0.001801138128, 1, 0, 69); - TEST_DISSOLVE(dissolve_mail_2017_09_24_f, 0.000361308800, 2, 0, 69); + TEST_DISSOLVE(dissolve_mail_2017_09_24_e, 0.001801138128, 5, 0, 69); + TEST_DISSOLVE(dissolve_mail_2017_09_24_f, 0.000361308800, 5, 0, 69); #ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS test_one("pentagram_rev", "POLYGON((5 0,7.5 9,0.5 3.5,9.5 3.5,2.5 9,5 0))", 0, 11, 25.6158412); - - // Poygons contain too many polygons #endif // CCW polygons should turn CW after dissolve @@ -561,12 +575,10 @@ void test_all() */ - std::string const ticket17 = "POLYGON ((-122.28139163 37.37319149,-122.28100699 37.37273669,-122.28002186 37.37303123,-122.27979681 37.37290072,-122.28007349 37.37240493,-122.27977334 37.37220360,-122.27819720 37.37288580,-122.27714184 37.37275161,-122.27678628 37.37253167,-122.27766437 37.37180973,-122.27804382 37.37121453,-122.27687664 37.37101354,-122.27645829 37.37203386,-122.27604423 37.37249110,-122.27632234 37.37343339,-122.27760980 37.37391082,-122.27812478 37.37800320,-122.26117222 37.39121007,-122.25572289 37.39566631,-122.25547269 37.39564971,-122.25366304 37.39552993,-122.24919976 37.39580268,-122.24417933 37.39366907,-122.24051443 37.39094143,-122.23246277 37.38100418,-122.23606766 37.38141338,-122.24001587 37.37738940,-122.23666848 37.37609347,-122.23057450 37.37882170,-122.22679803 37.37807143,-122.22525727 37.37448817,-122.22523229 37.37443000,-122.23083199 37.37609347,-122.23033486 37.37777891,-122.23169030 37.37732117,-122.23229178 37.37709687,-122.23237761 37.37631249,-122.23297776 37.37438834,-122.23872850 37.37165986,-122.24044511 37.36934068,-122.24671067 37.36865847,-122.24825570 37.36981819,-122.25151719 37.36947713,-122.25357721 37.36756706,-122.26001451 37.36579354,-122.25615213 37.36545239,-122.25486458 37.36245083,-122.25357721 37.36108651,-122.25194642 37.36013139,-122.24885652 37.35958557,-122.24911401 37.35849399,-122.25357721 37.35808470,-122.25675286 37.35897159,-122.25855539 37.35753887,-122.26181687 37.35828939,-122.26713837 37.35897159,-122.26782510 37.36108651,-122.26662339 37.36456559,-122.27288911 37.36722601,-122.27366159 37.36531602,-122.27168740 37.36470213,-122.27391900 37.36374701,-122.27074326 37.36245083,-122.27134408 37.35951742,-122.27426240 37.36135926,-122.27709482 37.36115474,-122.27966974 37.36231438,-122.27958391 37.36463382,-122.27572152 37.36463382,-122.27563569 37.36524779,-122.27700899 37.36593000,-122.27709482 37.36763529,-122.27554978 37.36838573,-122.27667254 37.36931478,-122.27677932 37.36932073,-122.27769362 37.36853987,-122.27942490 37.36830803,-122.28178776 37.36677917,-122.28509559 37.36443500,-122.28845129 37.36413744,-122.29194403 37.36695946,-122.29382577 37.36726817,-122.29600414 37.36898512,-122.29733083 37.36995398,-122.29593239 37.37141436,-122.29416649 37.37075898,-122.29325026 37.37108436,-122.29652910 37.37311697,-122.29584237 37.37374461,-122.29537583 37.37573372,-122.29487677 37.37752502,-122.30923212 37.37593011,-122.31122484 37.38230086,-122.31467994 37.38092472,-122.31715663 37.38252181,-122.32307970 37.38166978,-122.31985618 37.37667694,-122.32210304 37.37580220,-122.32581446 37.37589532,-122.32401730 37.37331839,-122.32960417 37.37189020,-122.33465527 37.37331906,-122.33425328 37.37623680,-122.33620676 37.37726132,-122.33397986 37.37822382,-122.33358918 37.38036590,-122.33202637 37.37986918,-122.33147954 37.38101784,-122.33394080 37.38198017,-122.33545239 37.38587943,-122.33478058 37.38785697,-122.33386050 37.38723721,-122.33350041 37.38571137,-122.33122003 37.38548891,-122.33140008 37.38650606,-122.33366042 37.38817490,-122.33244019 37.39157602,-122.33298157 37.39419201,-122.33164013 37.39477028,-122.33202017 37.39518351,-122.33358038 37.39499282,-122.33376050 37.39597811,-122.33550067 37.39734478,-122.33556069 37.39481797,-122.33344040 37.39292676,-122.33638094 37.38892189,-122.34240644 37.38852719,-122.34906293 37.38726898,-122.35072321 37.39338769,-122.34910291 37.39445252,-122.34796272 37.39410291,-122.34449043 37.39640534,-122.34500223 37.39729709,-122.34936291 37.39670910,-122.35098322 37.39531066,-122.35364623 37.39554510,-122.35434369 37.39612111,-122.35798429 37.39600988,-122.35768430 37.39478621,-122.36334519 37.39206871,-122.36604726 37.39203267,-122.36778592 37.39335592,-122.36518870 37.40022011,-122.36554552 37.40247752,-122.36370519 37.40331974,-122.36270506 37.40530591,-122.36320512 37.40670418,-122.36149849 37.40851392,-122.36730580 37.41054938,-122.37263720 37.41378932,-122.37161871 37.42076600,-122.36566153 37.42006292,-122.36520547 37.42742106,-122.37165953 37.43661157,-122.35943972 37.44459022,-122.35356359 37.44600810,-122.33792254 37.45796329,-122.35228518 37.47478091,-122.35127080 37.48181199,-122.34867342 37.48487322,-122.34359717 37.48801082,-122.33388431 37.48677650,-122.33142321 37.48429747,-122.32929580 37.48473149,-122.32609609 37.48291144,-122.32344850 37.48228229,-122.31924364 37.48410234,-122.31677299 37.48114051,-122.31431751 37.47848973,-122.31259201 37.47682190,-122.31515972 37.47568196,-122.31691389 37.47360309,-122.31292494 37.46960081,-122.31130153 37.46937743,-122.30889894 37.47124987,-122.30612839 37.47011613,-122.30149630 37.46568378,-122.30064277 37.46363784,-122.29283821 37.45922376,-122.28630141 37.45415497,-122.28883099 37.44629920,-122.28316717 37.44197138,-122.27554148 37.42297597,-122.25597410 37.40553692,-122.25196579 37.40129593,-122.25012043 37.40049143,-122.24823207 37.39897758,-122.24754551 37.39740941,-122.24778582 37.39621607,-122.24934787 37.39599102,-122.25005170 37.39871849,-122.25222328 37.39863668,-122.25342491 37.39737529,-122.25520162 37.39667289,-122.25528737 37.39522726,-122.27747460 37.37809616,-122.27977493 37.37858717,-122.28157729 37.37920106,-122.28322534 37.37952846,-122.28416939 37.38092656,-122.28621223 37.37984219,-122.28638389 37.37613857,-122.28382607 37.37843722,-122.27930278 37.37718220,-122.28196361 37.37652740,-122.28295058 37.37568167,-122.28216101 37.37523148,-122.28114822 37.37543608,-122.27934569 37.37528613,-122.27996369 37.37448121,-122.28104521 37.37454944,-122.28185197 37.37422883,-122.28290767 37.37474038,-122.28376597 37.37467224,-122.28428104 37.37399012,-122.28402346 37.37338989,-122.28610922 37.37364914,-122.28651264 37.37327388,-122.28672722 37.37207343,-122.28628398 37.37205448,-122.28574460 37.37166682,-122.28479711 37.37200981,-122.28327731 37.37137228,-122.28285511 37.37100700,-122.28279409 37.37125669,-122.28315527 37.37173756,-122.28321872 37.37220569,-122.28187007 37.37231918,-122.28193109 37.37294908,-122.28139163 37.37319149))"; test_one("ticket17", ticket17, 1, 228, 0.00920834633689); // Real-life - std::string const toolkit = "POLYGON((170718 605997,170718 605997,170776 606016,170773 606015,170786 606020,170778 606016,170787 606021,170781 606017,170795 606028,170795 606028,170829 606055,170939 606140,170933 605968,170933 605968,170932 605908,170929 605834,170920 605866,170961 605803,170739 605684,170699 605749,170691 605766,170693 605762,170686 605775,170688 605771,170673 605794,170676 605790,170668 605800,170672 605796,170651 605818,170653 605816,170639 605829,170568 605899,170662 605943,170633 605875,170603 605961,170718 605997))"; test_one("toolkit", toolkit, 0, 25, 91756.916526794434); From c77f1c99abcbc0e170d885429b42910eaa99faea Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 6 Oct 2017 16:26:28 +0200 Subject: [PATCH 14/16] [test] improve test, phase 2, now always check for clips/holes --- extensions/test/algorithms/dissolve.cpp | 126 +++++++++++------------- 1 file changed, 56 insertions(+), 70 deletions(-) diff --git a/extensions/test/algorithms/dissolve.cpp b/extensions/test/algorithms/dissolve.cpp index 7b8fcbf46..24c7f5855 100644 --- a/extensions/test/algorithms/dissolve.cpp +++ b/extensions/test/algorithms/dissolve.cpp @@ -62,6 +62,18 @@ namespace // With spike std::string const dissolve_6 = "POLYGON((0 0,0 4,4 4,4 2,6 2,4 2,4 0,0 0))"; + // Many intersections + std::string const dissolve_7 = "POLYGON((1 3,0 9,9 5,1 7,9 8,2 5,10 10,9 2,1 3))"; + + // Pentagram + std::string const dissolve_8 = "POLYGON((5 0,2.5 9,9.5 3.5,0.5 3.5,7.5 9,5 0))"; + // CCW pentagram + std::string const dissolve_9 = "POLYGON((5 0,7.5 9,0.5 3.5,9.5 3.5,2.5 9,5 0))"; + // CW, one keyhole + std::string const dissolve_10 = "POLYGON((2 8,8 8,8 0,0 0,0 6,4 6,4 4,2 4,2 8))"; + // CCW, one keyhole + std::string const dissolve_11 = "POLYGON((2 8,2 4,4 4,4 6,0 6,0 0,8 0,8 8,2 8))"; + // Non intersection, but with duplicate std::string const dissolve_d1 = "POLYGON((0 0,0 4,4 0,4 0,0 0))"; @@ -74,6 +86,15 @@ namespace // Case with correct interior ring inside, which should be stay std::string const dissolve_h1_b = "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 2,3 2,2 4,1 2))"; + // Hole: interior intersecting exterior + std::string const dissolve_h2 = "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 3,5 4,1 1))"; + + // Hole: two intersecting holes + std::string const dissolve_h3 = "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 3,3 3,3 1,1 1),(2 2,2 3.5,3.5 3.5,3.5 2,2 2))"; + + // Hole: self-intersecting hole + std::string const dissolve_h4 = "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,3 3,3 2.5,1 3.5,1.5 3.5,1 1))"; + // Testcases send by Johan Doré at September 24, 2017: std::string const dissolve_mail_2017_09_24_a = "POLYGON((0 1, 1 0, 1 1, 0 0, 0 1))"; // two triangles std::string const dissolve_mail_2017_09_24_b = "POLYGON((1 0, 0 0, 0 4, 4 4, 4 0))"; // input is not closed @@ -86,8 +107,11 @@ namespace // Idem but moving closing point eastwards to view self-intersections better std::string const dissolve_mail_2017_09_24_f = "POLYGON((25.35475410461420 -1.20600892066955, 25.36818313598630 -1.20732820034027, 25.36953926086420 -1.20868659019470, 25.37180328369140 -1.20959210395812, 25.37451934814450 -1.21049761772155, 25.37632942199700 -1.21185600757598, 25.37904357910150 -1.21276152133941, 25.38085556030270 -1.21321427822113, 25.38221168518060 -1.21366703510284, 25.38311767578120 -1.21411991119384, 25.38447570800780 -1.21411991119384, 25.38447570800780 -1.21185600757598, 25.38492774963370 -1.21140325069427, 25.38492774963370 -1.21095049381256, 25.38945388793940 -1.21095049381256, 25.38990592956540 -1.21049761772155, 25.39035987854000 -1.21004486083984, 25.39081192016600 -1.21004486083984, 25.39081192016600 -1.20959210395812, 25.39126396179190 -1.20913934707641, 25.39171600341790 -1.20913934707641, 25.39262199401850 -1.20868659019470, 25.39262199401850 -1.20823383331298, 25.39352798461910 -1.20823383331298, 25.39398002624510 -1.20778107643127, 25.39443206787100 -1.20778107643127, 25.39443206787100 -1.20732820034027, 25.39488410949700 -1.20687544345855, 25.39443206787100 -1.20642268657684, 25.39420700073240 -1.20596992969512, 25.39386749267570 -1.20551717281341, 25.39352798461910 -1.20551717281341, 25.39352798461910 -1.20506441593170, 25.39386749267570 -1.20551717281341, 25.39398002624510 -1.20551717281341, 25.39420700073240 -1.20596992969512, 25.39488410949700 -1.20687544345855, 25.39533805847160 -1.20778107643127, 25.39579010009760 -1.20823383331298, 25.39579010009760 -1.20868659019470, 25.39624214172360 -1.20913934707641, 25.39669609069820 -1.20959210395812, 25.39669609069820 -1.21049761772155, 25.39714813232420 -1.21095049381256, 25.39760017395010 -1.21185600757598, 25.39805221557610 -1.21321427822113, 25.39850616455070 -1.21411991119384, 25.39895820617670 -1.21547818183898, 25.39895820617670 -1.21638369560241, 25.39986419677730 -1.21819484233856, 25.40031623840330 -1.21955311298370, 25.40076828002920 -1.22045862674713, 25.40076828002920 -1.22181701660156, 25.40122032165520 -1.22226977348327, 25.40122032165520 -1.22408080101013, 25.40212631225580 -1.22498643398284, 25.40212631225580 -1.22634470462799, 25.40257835388180 -1.22725021839141, 25.40257835388180 -1.22770309448242, 25.40303230285640 -1.22860860824584, 25.40303230285640 -1.23041963577270, 25.40348434448240 -1.23041963577270, 25.35475410461420 -1.20600892066955))"; - std::string const ticket17 = "POLYGON ((-122.28139163 37.37319149,-122.28100699 37.37273669,-122.28002186 37.37303123,-122.27979681 37.37290072,-122.28007349 37.37240493,-122.27977334 37.37220360,-122.27819720 37.37288580,-122.27714184 37.37275161,-122.27678628 37.37253167,-122.27766437 37.37180973,-122.27804382 37.37121453,-122.27687664 37.37101354,-122.27645829 37.37203386,-122.27604423 37.37249110,-122.27632234 37.37343339,-122.27760980 37.37391082,-122.27812478 37.37800320,-122.26117222 37.39121007,-122.25572289 37.39566631,-122.25547269 37.39564971,-122.25366304 37.39552993,-122.24919976 37.39580268,-122.24417933 37.39366907,-122.24051443 37.39094143,-122.23246277 37.38100418,-122.23606766 37.38141338,-122.24001587 37.37738940,-122.23666848 37.37609347,-122.23057450 37.37882170,-122.22679803 37.37807143,-122.22525727 37.37448817,-122.22523229 37.37443000,-122.23083199 37.37609347,-122.23033486 37.37777891,-122.23169030 37.37732117,-122.23229178 37.37709687,-122.23237761 37.37631249,-122.23297776 37.37438834,-122.23872850 37.37165986,-122.24044511 37.36934068,-122.24671067 37.36865847,-122.24825570 37.36981819,-122.25151719 37.36947713,-122.25357721 37.36756706,-122.26001451 37.36579354,-122.25615213 37.36545239,-122.25486458 37.36245083,-122.25357721 37.36108651,-122.25194642 37.36013139,-122.24885652 37.35958557,-122.24911401 37.35849399,-122.25357721 37.35808470,-122.25675286 37.35897159,-122.25855539 37.35753887,-122.26181687 37.35828939,-122.26713837 37.35897159,-122.26782510 37.36108651,-122.26662339 37.36456559,-122.27288911 37.36722601,-122.27366159 37.36531602,-122.27168740 37.36470213,-122.27391900 37.36374701,-122.27074326 37.36245083,-122.27134408 37.35951742,-122.27426240 37.36135926,-122.27709482 37.36115474,-122.27966974 37.36231438,-122.27958391 37.36463382,-122.27572152 37.36463382,-122.27563569 37.36524779,-122.27700899 37.36593000,-122.27709482 37.36763529,-122.27554978 37.36838573,-122.27667254 37.36931478,-122.27677932 37.36932073,-122.27769362 37.36853987,-122.27942490 37.36830803,-122.28178776 37.36677917,-122.28509559 37.36443500,-122.28845129 37.36413744,-122.29194403 37.36695946,-122.29382577 37.36726817,-122.29600414 37.36898512,-122.29733083 37.36995398,-122.29593239 37.37141436,-122.29416649 37.37075898,-122.29325026 37.37108436,-122.29652910 37.37311697,-122.29584237 37.37374461,-122.29537583 37.37573372,-122.29487677 37.37752502,-122.30923212 37.37593011,-122.31122484 37.38230086,-122.31467994 37.38092472,-122.31715663 37.38252181,-122.32307970 37.38166978,-122.31985618 37.37667694,-122.32210304 37.37580220,-122.32581446 37.37589532,-122.32401730 37.37331839,-122.32960417 37.37189020,-122.33465527 37.37331906,-122.33425328 37.37623680,-122.33620676 37.37726132,-122.33397986 37.37822382,-122.33358918 37.38036590,-122.33202637 37.37986918,-122.33147954 37.38101784,-122.33394080 37.38198017,-122.33545239 37.38587943,-122.33478058 37.38785697,-122.33386050 37.38723721,-122.33350041 37.38571137,-122.33122003 37.38548891,-122.33140008 37.38650606,-122.33366042 37.38817490,-122.33244019 37.39157602,-122.33298157 37.39419201,-122.33164013 37.39477028,-122.33202017 37.39518351,-122.33358038 37.39499282,-122.33376050 37.39597811,-122.33550067 37.39734478,-122.33556069 37.39481797,-122.33344040 37.39292676,-122.33638094 37.38892189,-122.34240644 37.38852719,-122.34906293 37.38726898,-122.35072321 37.39338769,-122.34910291 37.39445252,-122.34796272 37.39410291,-122.34449043 37.39640534,-122.34500223 37.39729709,-122.34936291 37.39670910,-122.35098322 37.39531066,-122.35364623 37.39554510,-122.35434369 37.39612111,-122.35798429 37.39600988,-122.35768430 37.39478621,-122.36334519 37.39206871,-122.36604726 37.39203267,-122.36778592 37.39335592,-122.36518870 37.40022011,-122.36554552 37.40247752,-122.36370519 37.40331974,-122.36270506 37.40530591,-122.36320512 37.40670418,-122.36149849 37.40851392,-122.36730580 37.41054938,-122.37263720 37.41378932,-122.37161871 37.42076600,-122.36566153 37.42006292,-122.36520547 37.42742106,-122.37165953 37.43661157,-122.35943972 37.44459022,-122.35356359 37.44600810,-122.33792254 37.45796329,-122.35228518 37.47478091,-122.35127080 37.48181199,-122.34867342 37.48487322,-122.34359717 37.48801082,-122.33388431 37.48677650,-122.33142321 37.48429747,-122.32929580 37.48473149,-122.32609609 37.48291144,-122.32344850 37.48228229,-122.31924364 37.48410234,-122.31677299 37.48114051,-122.31431751 37.47848973,-122.31259201 37.47682190,-122.31515972 37.47568196,-122.31691389 37.47360309,-122.31292494 37.46960081,-122.31130153 37.46937743,-122.30889894 37.47124987,-122.30612839 37.47011613,-122.30149630 37.46568378,-122.30064277 37.46363784,-122.29283821 37.45922376,-122.28630141 37.45415497,-122.28883099 37.44629920,-122.28316717 37.44197138,-122.27554148 37.42297597,-122.25597410 37.40553692,-122.25196579 37.40129593,-122.25012043 37.40049143,-122.24823207 37.39897758,-122.24754551 37.39740941,-122.24778582 37.39621607,-122.24934787 37.39599102,-122.25005170 37.39871849,-122.25222328 37.39863668,-122.25342491 37.39737529,-122.25520162 37.39667289,-122.25528737 37.39522726,-122.27747460 37.37809616,-122.27977493 37.37858717,-122.28157729 37.37920106,-122.28322534 37.37952846,-122.28416939 37.38092656,-122.28621223 37.37984219,-122.28638389 37.37613857,-122.28382607 37.37843722,-122.27930278 37.37718220,-122.28196361 37.37652740,-122.28295058 37.37568167,-122.28216101 37.37523148,-122.28114822 37.37543608,-122.27934569 37.37528613,-122.27996369 37.37448121,-122.28104521 37.37454944,-122.28185197 37.37422883,-122.28290767 37.37474038,-122.28376597 37.37467224,-122.28428104 37.37399012,-122.28402346 37.37338989,-122.28610922 37.37364914,-122.28651264 37.37327388,-122.28672722 37.37207343,-122.28628398 37.37205448,-122.28574460 37.37166682,-122.28479711 37.37200981,-122.28327731 37.37137228,-122.28285511 37.37100700,-122.28279409 37.37125669,-122.28315527 37.37173756,-122.28321872 37.37220569,-122.28187007 37.37231918,-122.28193109 37.37294908,-122.28139163 37.37319149))"; - std::string const toolkit = "POLYGON((170718 605997,170718 605997,170776 606016,170773 606015,170786 606020,170778 606016,170787 606021,170781 606017,170795 606028,170795 606028,170829 606055,170939 606140,170933 605968,170933 605968,170932 605908,170929 605834,170920 605866,170961 605803,170739 605684,170699 605749,170691 605766,170693 605762,170686 605775,170688 605771,170673 605794,170676 605790,170668 605800,170672 605796,170651 605818,170653 605816,170639 605829,170568 605899,170662 605943,170633 605875,170603 605961,170718 605997))"; + std::string const dissolve_ticket17 = "POLYGON ((-122.28139163 37.37319149,-122.28100699 37.37273669,-122.28002186 37.37303123,-122.27979681 37.37290072,-122.28007349 37.37240493,-122.27977334 37.37220360,-122.27819720 37.37288580,-122.27714184 37.37275161,-122.27678628 37.37253167,-122.27766437 37.37180973,-122.27804382 37.37121453,-122.27687664 37.37101354,-122.27645829 37.37203386,-122.27604423 37.37249110,-122.27632234 37.37343339,-122.27760980 37.37391082,-122.27812478 37.37800320,-122.26117222 37.39121007,-122.25572289 37.39566631,-122.25547269 37.39564971,-122.25366304 37.39552993,-122.24919976 37.39580268,-122.24417933 37.39366907,-122.24051443 37.39094143,-122.23246277 37.38100418,-122.23606766 37.38141338,-122.24001587 37.37738940,-122.23666848 37.37609347,-122.23057450 37.37882170,-122.22679803 37.37807143,-122.22525727 37.37448817,-122.22523229 37.37443000,-122.23083199 37.37609347,-122.23033486 37.37777891,-122.23169030 37.37732117,-122.23229178 37.37709687,-122.23237761 37.37631249,-122.23297776 37.37438834,-122.23872850 37.37165986,-122.24044511 37.36934068,-122.24671067 37.36865847,-122.24825570 37.36981819,-122.25151719 37.36947713,-122.25357721 37.36756706,-122.26001451 37.36579354,-122.25615213 37.36545239,-122.25486458 37.36245083,-122.25357721 37.36108651,-122.25194642 37.36013139,-122.24885652 37.35958557,-122.24911401 37.35849399,-122.25357721 37.35808470,-122.25675286 37.35897159,-122.25855539 37.35753887,-122.26181687 37.35828939,-122.26713837 37.35897159,-122.26782510 37.36108651,-122.26662339 37.36456559,-122.27288911 37.36722601,-122.27366159 37.36531602,-122.27168740 37.36470213,-122.27391900 37.36374701,-122.27074326 37.36245083,-122.27134408 37.35951742,-122.27426240 37.36135926,-122.27709482 37.36115474,-122.27966974 37.36231438,-122.27958391 37.36463382,-122.27572152 37.36463382,-122.27563569 37.36524779,-122.27700899 37.36593000,-122.27709482 37.36763529,-122.27554978 37.36838573,-122.27667254 37.36931478,-122.27677932 37.36932073,-122.27769362 37.36853987,-122.27942490 37.36830803,-122.28178776 37.36677917,-122.28509559 37.36443500,-122.28845129 37.36413744,-122.29194403 37.36695946,-122.29382577 37.36726817,-122.29600414 37.36898512,-122.29733083 37.36995398,-122.29593239 37.37141436,-122.29416649 37.37075898,-122.29325026 37.37108436,-122.29652910 37.37311697,-122.29584237 37.37374461,-122.29537583 37.37573372,-122.29487677 37.37752502,-122.30923212 37.37593011,-122.31122484 37.38230086,-122.31467994 37.38092472,-122.31715663 37.38252181,-122.32307970 37.38166978,-122.31985618 37.37667694,-122.32210304 37.37580220,-122.32581446 37.37589532,-122.32401730 37.37331839,-122.32960417 37.37189020,-122.33465527 37.37331906,-122.33425328 37.37623680,-122.33620676 37.37726132,-122.33397986 37.37822382,-122.33358918 37.38036590,-122.33202637 37.37986918,-122.33147954 37.38101784,-122.33394080 37.38198017,-122.33545239 37.38587943,-122.33478058 37.38785697,-122.33386050 37.38723721,-122.33350041 37.38571137,-122.33122003 37.38548891,-122.33140008 37.38650606,-122.33366042 37.38817490,-122.33244019 37.39157602,-122.33298157 37.39419201,-122.33164013 37.39477028,-122.33202017 37.39518351,-122.33358038 37.39499282,-122.33376050 37.39597811,-122.33550067 37.39734478,-122.33556069 37.39481797,-122.33344040 37.39292676,-122.33638094 37.38892189,-122.34240644 37.38852719,-122.34906293 37.38726898,-122.35072321 37.39338769,-122.34910291 37.39445252,-122.34796272 37.39410291,-122.34449043 37.39640534,-122.34500223 37.39729709,-122.34936291 37.39670910,-122.35098322 37.39531066,-122.35364623 37.39554510,-122.35434369 37.39612111,-122.35798429 37.39600988,-122.35768430 37.39478621,-122.36334519 37.39206871,-122.36604726 37.39203267,-122.36778592 37.39335592,-122.36518870 37.40022011,-122.36554552 37.40247752,-122.36370519 37.40331974,-122.36270506 37.40530591,-122.36320512 37.40670418,-122.36149849 37.40851392,-122.36730580 37.41054938,-122.37263720 37.41378932,-122.37161871 37.42076600,-122.36566153 37.42006292,-122.36520547 37.42742106,-122.37165953 37.43661157,-122.35943972 37.44459022,-122.35356359 37.44600810,-122.33792254 37.45796329,-122.35228518 37.47478091,-122.35127080 37.48181199,-122.34867342 37.48487322,-122.34359717 37.48801082,-122.33388431 37.48677650,-122.33142321 37.48429747,-122.32929580 37.48473149,-122.32609609 37.48291144,-122.32344850 37.48228229,-122.31924364 37.48410234,-122.31677299 37.48114051,-122.31431751 37.47848973,-122.31259201 37.47682190,-122.31515972 37.47568196,-122.31691389 37.47360309,-122.31292494 37.46960081,-122.31130153 37.46937743,-122.30889894 37.47124987,-122.30612839 37.47011613,-122.30149630 37.46568378,-122.30064277 37.46363784,-122.29283821 37.45922376,-122.28630141 37.45415497,-122.28883099 37.44629920,-122.28316717 37.44197138,-122.27554148 37.42297597,-122.25597410 37.40553692,-122.25196579 37.40129593,-122.25012043 37.40049143,-122.24823207 37.39897758,-122.24754551 37.39740941,-122.24778582 37.39621607,-122.24934787 37.39599102,-122.25005170 37.39871849,-122.25222328 37.39863668,-122.25342491 37.39737529,-122.25520162 37.39667289,-122.25528737 37.39522726,-122.27747460 37.37809616,-122.27977493 37.37858717,-122.28157729 37.37920106,-122.28322534 37.37952846,-122.28416939 37.38092656,-122.28621223 37.37984219,-122.28638389 37.37613857,-122.28382607 37.37843722,-122.27930278 37.37718220,-122.28196361 37.37652740,-122.28295058 37.37568167,-122.28216101 37.37523148,-122.28114822 37.37543608,-122.27934569 37.37528613,-122.27996369 37.37448121,-122.28104521 37.37454944,-122.28185197 37.37422883,-122.28290767 37.37474038,-122.28376597 37.37467224,-122.28428104 37.37399012,-122.28402346 37.37338989,-122.28610922 37.37364914,-122.28651264 37.37327388,-122.28672722 37.37207343,-122.28628398 37.37205448,-122.28574460 37.37166682,-122.28479711 37.37200981,-122.28327731 37.37137228,-122.28285511 37.37100700,-122.28279409 37.37125669,-122.28315527 37.37173756,-122.28321872 37.37220569,-122.28187007 37.37231918,-122.28193109 37.37294908,-122.28139163 37.37319149))"; + std::string const dissolve_reallife = "POLYGON((170718 605997,170718 605997,170776 606016,170773 606015,170786 606020,170778 606016,170787 606021,170781 606017,170795 606028,170795 606028,170829 606055,170939 606140,170933 605968,170933 605968,170932 605908,170929 605834,170920 605866,170961 605803,170739 605684,170699 605749,170691 605766,170693 605762,170686 605775,170688 605771,170673 605794,170676 605790,170668 605800,170672 605796,170651 605818,170653 605816,170639 605829,170568 605899,170662 605943,170633 605875,170603 605961,170718 605997))"; + + // https://svn.boost.org/trac/boost/ticket/10713 + std::string const dissolve_ticket10713 = "POLYGON((-0.7189743518829346 4.1308121681213379, 0.0831791982054710 4.1034231185913086, 0.1004156470298767 4.1107301712036133, 0.1044322624802589 4.1026973724365234, 0.0831791982054710 4.1034231185913086, -0.7711903452873230 3.7412264347076416, -0.7189743518829346 4.1308121681213379))"; } @@ -353,18 +377,14 @@ void test_dissolve(std::string const& caseid, Geometry const& geometry, << " type: " << string_from_type::name() ); - if (expected_clip_count > 0) - { - BOOST_CHECK_MESSAGE(dissolved1.size() == expected_clip_count, - "dissolve: " << caseid - << " #clips expected: " << expected_clip_count - << " detected: " << dissolved1.size() - << " type: " << string_from_type::name() - ); - } + BOOST_CHECK_MESSAGE(dissolved1.size() == expected_clip_count, + "dissolve: " << caseid + << " #clips expected: " << expected_clip_count + << " detected: " << dissolved1.size() + << " type: " << string_from_type::name() + ); - - //BOOST_CHECK_EQUAL(holes, expected_hole_count); + BOOST_CHECK_EQUAL(holes, expected_hole_count); BOOST_CHECK_CLOSE(length_or_area, expected_length_or_area, percentage); BOOST_CHECK_EQUAL(dissolved1.size(), dissolved2.size()); @@ -444,36 +464,18 @@ void test_all() TEST_DISSOLVE(dissolve_4, 8.0, 2, 0, 8); TEST_DISSOLVE(dissolve_5, 12.0, 2, 0, 8); TEST_DISSOLVE(dissolve_6, 16.0, 1, 0, 6); + + TEST_DISSOLVE(dissolve_7, 50.48056402439, 1, 0, 7); + TEST_DISSOLVE(dissolve_8, 25.6158412, 1, 0, 11); + TEST_DISSOLVE(dissolve_d1, 8.0, 1, 0, 4); TEST_DISSOLVE(dissolve_d2, 16.0, 1, 0, 10); TEST_DISSOLVE(dissolve_h1_a, 16.0, 1, 0, 6); TEST_DISSOLVE(dissolve_h1_b, 14.0, 1, 1, 10); - - // Hole: interior intersecting exterior - test_one("h2", - "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 3,5 4,1 1))", - 0, 8, 16.25); - - // Hole: two intersecting holes - test_one("h3", - "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 3,3 3,3 1,1 1),(2 2,2 3.5,3.5 3.5,3.5 2,2 2))", - 0, 5, 16); - - // Hole: self-intersecting hole - test_one("h4", - "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,3 3,3 2.5,1 3.5,1.5 3.5,1 1))", - 1, 9, 14.484848484848484); - - // See power point - test_one("case_1", - "POLYGON((1 3,0 9,9 5,1 7,9 8,2 5,10 10,9 2,1 3))", - 0, 7, 50.48056402439); - - // See power point, and http://en.wikipedia.org/wiki/Pentagram - test_one("pentagram", - "POLYGON((5 0,2.5 9,9.5 3.5,0.5 3.5,7.5 9,5 0))", - 0, 11, 25.6158412); + TEST_DISSOLVE(dissolve_h2, 16.25, 1, 0, 8); + TEST_DISSOLVE(dissolve_h3, 16.0, 1, 0, 5); // no generated hole (yet) + TEST_DISSOLVE(dissolve_h4, 14.484848, 1, 1, 9); TEST_DISSOLVE(dissolve_mail_2017_09_24_a, 0.5, 2, 0, 8); @@ -485,28 +487,20 @@ void test_all() TEST_DISSOLVE(dissolve_mail_2017_09_24_f, 0.000361308800, 5, 0, 69); #ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS - test_one("pentagram_rev", - "POLYGON((5 0,7.5 9,0.5 3.5,9.5 3.5,2.5 9,5 0))", - 0, 11, 25.6158412); + TEST_DISSOLVE(dissolve_9, 25.6158412, 1, 0, 11); #endif // CCW polygons should turn CW after dissolve - test_one("cw", - "POLYGON((2 8,8 8,8 0,0 0,0 6,4 6,4 4,2 4,2 8))", - 0, 7, 60); + TEST_DISSOLVE(dissolve_10, 60.0, 1, 0, 7); #ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS - test_one("ccw", - "POLYGON((2 8,2 4,4 4,4 6,0 6,0 0,8 0,8 8,2 8))", - 0, 12, 64); // TODO: should have the same, 7, 60. The polygon is dissolved (splitted) but the extra polygon is still on top of the other + // TODO: should be the same, 7, 60. The polygon is dissolved (splitted) but the extra polygon is still on top of the other + TEST_DISSOLVE(dissolve_11, 60.0, 1, 0, 7); #endif - // https://svn.boost.org/trac/boost/ticket/10713 - test_one("ticket_10713", - "POLYGON((-0.7189743518829346 4.1308121681213379, 0.0831791982054710 4.1034231185913086, 0.1004156470298767 4.1107301712036133, 0.1044322624802589 4.1026973724365234, 0.0831791982054710 4.1034231185913086, -0.7711903452873230 3.7412264347076416, -0.7189743518829346 4.1308121681213379))", - 0, 8, 0.157052766); + TEST_DISSOLVE(dissolve_ticket10713, 0.157052766, 2, 0, 8); #ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS - // Reported by Artem Pavlenko at gitter + // Reported by Artem Pavlenko at gitter - until now these did not work yet // https://gitter.im/boostorg/geometry?at=58ef46408e4b63533dc49b48 test_one("artem1", "POLYGON((36.9121 2.03883,26.2052 54.353,60.0781 64.2202,96.2171 55.9826,71.1506 39.8365,5.72552 94.1523,4.06819 13.9054,59.7155 44.5877,60.9243 16.4597,48.8696 93.039,36.9121 2.03883))", @@ -523,40 +517,38 @@ void test_all() test_one("three_triangles", "MULTIPOLYGON(((1 1,5 5,8 0,1 1)),((4 2,0 8,5 9,4 2)),((5 3,4 8,10 4,5 3)))" , - 1, 13, 42.614078674948232); + 1, 13, 42.614078674948232, 1); test_one("simplex_two", "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((2 2,3 6,6 3,2 2)))", - 0, 8, 14.7); + 0, 8, 14.7, 1); test_one("simplex_three", "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((2 2,3 6,6 3,2 2)),((3 4,5 6,6 2,3 4)))", - 0, 14, 16.7945); + 0, 14, 16.7945, 1); test_one("simplex_four", "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((2 2,3 6,6 3,2 2)),((3 4,5 6,6 2,3 4)),((5 5,7 7,8 4,5 5)))", - 0, 18, 20.7581); + 0, 18, 20.7581, 1); // disjoint test_one("simplex_disjoint", "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((1 6,2 10,5 7,1 6)),((3 4,5 6,6 2,3 4)),((6 5,8 7,9 4,6 5)))", - 0, 16, 24.0); + 0, 16, 24.0, 4); // new hole of four test_one("new_hole", "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((2 2,3 6,6 3,2 2)),((3 4,5 6,6 2,3 4)),((3 1,5 4,8 4,3 1)))", - 1, 18, 19.5206); + 1, 18, 19.5206, 1); // GGL mailing list - report Javier - 2011, March 7 test_one("ggl_list_20110307_javier_01_a", "MULTIPOLYGON(((560 -400, 600 -400, 600 -440, 560 -440, 560 -400)), ((480 -400, 520 -400, 520 -440, 480 -440, 480 -400)), ((600 -320, 640 -320, 640 -360, 600 -360, 600 -320)), ((520 -400, 560 -400, 560 -440, 520 -440, 520 -400)))", - 1, 14, 6400); + 0, 14, 6400, 2); test_one("ggl_list_20110307_javier_01_b", "POLYGON((0 0, 2000 0, 2000 -2000, 0 -2000, 0 0), (560 -400, 560 -440, 600 -440, 600 -400, 560 -400), (480 -400, 480 -440, 520 -440, 520 -400, 480 -400), (600 -320, 600 -360, 640 -360, 640 -320, 600 -320), (520 -400, 520 -440, 560 -440, 560 -400, 520 -400))", - 1, 19, 3993600); + 2, 19, 3993600, 1); } - - /* //Should be solved (completely) differently // From mail on the ggl-mailing list @@ -574,14 +566,8 @@ void test_all() 0, 11, 25.6158412); */ - - test_one("ticket17", ticket17, - 1, 228, 0.00920834633689); - - // Real-life - test_one("toolkit", toolkit, - 0, 25, 91756.916526794434); - + TEST_DISSOLVE(dissolve_ticket17, 0.00920834633689, 1, 1, 228); + TEST_DISSOLVE(dissolve_reallife, 91756.916526794434, 1, 0, 25); } From 23e9f8628bd0de3115c8757f40c93d3e77ee98c1 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 6 Oct 2017 16:38:35 +0200 Subject: [PATCH 15/16] [test] also move/cleanup multi-polygon tests --- extensions/test/algorithms/dissolve.cpp | 68 ++++++++++--------------- 1 file changed, 27 insertions(+), 41 deletions(-) diff --git a/extensions/test/algorithms/dissolve.cpp b/extensions/test/algorithms/dissolve.cpp index 24c7f5855..b59c38453 100644 --- a/extensions/test/algorithms/dissolve.cpp +++ b/extensions/test/algorithms/dissolve.cpp @@ -95,7 +95,18 @@ namespace // Hole: self-intersecting hole std::string const dissolve_h4 = "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,3 3,3 2.5,1 3.5,1.5 3.5,1 1))"; - // Testcases send by Johan Doré at September 24, 2017: + std::string const multi_three_triangles = "MULTIPOLYGON(((1 1,5 5,8 0,1 1)),((4 2,0 8,5 9,4 2)),((5 3,4 8,10 4,5 3)))"; + std::string const multi_simplex_two = "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((2 2,3 6,6 3,2 2)))"; + std::string const multi_simplex_three = "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((2 2,3 6,6 3,2 2)),((3 4,5 6,6 2,3 4)))"; + std::string const multi_simplex_four = "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((2 2,3 6,6 3,2 2)),((3 4,5 6,6 2,3 4)),((5 5,7 7,8 4,5 5)))"; + std::string const multi_disjoint = "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((1 6,2 10,5 7,1 6)),((3 4,5 6,6 2,3 4)),((6 5,8 7,9 4,6 5)))"; + std::string const multi_new_interior = "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((2 2,3 6,6 3,2 2)),((3 4,5 6,6 2,3 4)),((3 1,5 4,8 4,3 1)))"; + + // Testcases sent on GGL mailing list - report Javier - 2011, March 7 + std::string const ggl_list_20110307_javier_01_a = "MULTIPOLYGON(((560 -400, 600 -400, 600 -440, 560 -440, 560 -400)), ((480 -400, 520 -400, 520 -440, 480 -440, 480 -400)), ((600 -320, 640 -320, 640 -360, 600 -360, 600 -320)), ((520 -400, 560 -400, 560 -440, 520 -440, 520 -400)))"; + std::string const ggl_list_20110307_javier_01_b = "POLYGON((0 0, 2000 0, 2000 -2000, 0 -2000, 0 0), (560 -400, 560 -440, 600 -440, 600 -400, 560 -400), (480 -400, 480 -440, 520 -440, 520 -400, 480 -400), (600 -320, 600 -360, 640 -360, 640 -320, 600 -320), (520 -400, 520 -440, 560 -440, 560 -400, 520 -400))"; + + // Testcases sent by Johan Doré at September 24, 2017: std::string const dissolve_mail_2017_09_24_a = "POLYGON((0 1, 1 0, 1 1, 0 0, 0 1))"; // two triangles std::string const dissolve_mail_2017_09_24_b = "POLYGON((1 0, 0 0, 0 4, 4 4, 4 0))"; // input is not closed std::string const dissolve_mail_2017_09_24_c = "POLYGON((0 0, 1 0, 0 -1, 0.0001 1))"; // spike and not closed @@ -451,12 +462,15 @@ void test_one(std::string const& caseid, std::string const& wkt, #define TEST_DISSOLVE(caseid, area, clips, holes, points) \ (test_one) ( #caseid, caseid, holes, points, area, clips) +#define TEST_MULTI(caseid, area, clips, holes, points) \ + (test_one) ( #caseid, caseid, holes, points, area, clips) template void test_all() { typedef bg::model::ring

ring; typedef bg::model::polygon

polygon; + typedef bg::model::multi_polygon multi_polygon; TEST_DISSOLVE(dissolve_1, 8.0, 1, 0, 6); TEST_DISSOLVE(dissolve_2, 7.9296875, 1, 1, 12); @@ -499,6 +513,18 @@ void test_all() TEST_DISSOLVE(dissolve_ticket10713, 0.157052766, 2, 0, 8); + TEST_MULTI(multi_three_triangles, 42.614078674948232, 1, 1, 13); + TEST_MULTI(multi_simplex_two, 14.7, 1, 0, 8); + TEST_MULTI(multi_simplex_three, 16.7945, 1, 0, 14); + TEST_MULTI(multi_simplex_four, 20.7581, 1, 0, 18); + TEST_MULTI(multi_disjoint, 24.0, 4, 0, 16); + TEST_MULTI(multi_new_interior, 19.5206, 1, 1, 18); + TEST_MULTI(ggl_list_20110307_javier_01_a, 6400.0, 2, 0, 14); + + TEST_DISSOLVE(ggl_list_20110307_javier_01_b, 3993600.0, 1, 2, 19); + TEST_DISSOLVE(dissolve_ticket17, 0.00920834633689, 1, 1, 228); + TEST_DISSOLVE(dissolve_reallife, 91756.916526794434, 1, 0, 25); + #ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS // Reported by Artem Pavlenko at gitter - until now these did not work yet // https://gitter.im/boostorg/geometry?at=58ef46408e4b63533dc49b48 @@ -511,44 +537,6 @@ void test_all() 0, 0, 0); // TODO: expected #endif - // Multi-geometries - { - typedef bg::model::multi_polygon multi_polygon; - - test_one("three_triangles", - "MULTIPOLYGON(((1 1,5 5,8 0,1 1)),((4 2,0 8,5 9,4 2)),((5 3,4 8,10 4,5 3)))" , - 1, 13, 42.614078674948232, 1); - - test_one("simplex_two", - "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((2 2,3 6,6 3,2 2)))", - 0, 8, 14.7, 1); - test_one("simplex_three", - "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((2 2,3 6,6 3,2 2)),((3 4,5 6,6 2,3 4)))", - 0, 14, 16.7945, 1); - test_one("simplex_four", - "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((2 2,3 6,6 3,2 2)),((3 4,5 6,6 2,3 4)),((5 5,7 7,8 4,5 5)))", - 0, 18, 20.7581, 1); - - // disjoint - test_one("simplex_disjoint", - "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((1 6,2 10,5 7,1 6)),((3 4,5 6,6 2,3 4)),((6 5,8 7,9 4,6 5)))", - 0, 16, 24.0, 4); - - // new hole of four - test_one("new_hole", - "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((2 2,3 6,6 3,2 2)),((3 4,5 6,6 2,3 4)),((3 1,5 4,8 4,3 1)))", - 1, 18, 19.5206, 1); - - // GGL mailing list - report Javier - 2011, March 7 - test_one("ggl_list_20110307_javier_01_a", - "MULTIPOLYGON(((560 -400, 600 -400, 600 -440, 560 -440, 560 -400)), ((480 -400, 520 -400, 520 -440, 480 -440, 480 -400)), ((600 -320, 640 -320, 640 -360, 600 -360, 600 -320)), ((520 -400, 560 -400, 560 -440, 520 -440, 520 -400)))", - 0, 14, 6400, 2); - - test_one("ggl_list_20110307_javier_01_b", - "POLYGON((0 0, 2000 0, 2000 -2000, 0 -2000, 0 0), (560 -400, 560 -440, 600 -440, 600 -400, 560 -400), (480 -400, 480 -440, 520 -440, 520 -400, 480 -400), (600 -320, 600 -360, 640 -360, 640 -320, 600 -320), (520 -400, 520 -440, 560 -440, 560 -400, 520 -400))", - 2, 19, 3993600, 1); - } - /* //Should be solved (completely) differently // From mail on the ggl-mailing list @@ -566,8 +554,6 @@ void test_all() 0, 11, 25.6158412); */ - TEST_DISSOLVE(dissolve_ticket17, 0.00920834633689, 1, 1, 228); - TEST_DISSOLVE(dissolve_reallife, 91756.916526794434, 1, 0, 25); } From a04050a31aa6649f6c89115da1e172a1cbc59908 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 6 Oct 2017 17:38:04 +0200 Subject: [PATCH 16/16] [test] for dissolve unit tests now also check validity - and most cases are already valid --- extensions/test/algorithms/dissolve.cpp | 72 ++++++++++++++++++------- 1 file changed, 53 insertions(+), 19 deletions(-) diff --git a/extensions/test/algorithms/dissolve.cpp b/extensions/test/algorithms/dissolve.cpp index b59c38453..894e8dcb3 100644 --- a/extensions/test/algorithms/dissolve.cpp +++ b/extensions/test/algorithms/dissolve.cpp @@ -18,6 +18,7 @@ // To check results #include #include +#include #include #include @@ -262,6 +263,19 @@ private : #endif +//! Unittest settings: validity, tolerance +struct ut_settings +{ + double percentage; + bool test_validity; + + explicit ut_settings(double p = 0.001, bool tv = true) + : percentage(p) + , test_validity(tv) + {} + +}; + template std::string as_wkt(Geometry const& geometry) { @@ -272,10 +286,11 @@ std::string as_wkt(Geometry const& geometry) template void test_dissolve(std::string const& caseid, Geometry const& geometry, + double expected_area, std::size_t expected_clip_count, std::size_t expected_hole_count, std::size_t expected_point_count, - double expected_length_or_area, double percentage) + ut_settings const& settings) { typedef typename bg::coordinate_type::type coordinate_type; @@ -350,10 +365,20 @@ void test_dissolve(std::string const& caseid, Geometry const& geometry, std::vector dissolved2; bg::dissolve_inserter(geometry, std::back_inserter(dissolved2)); - // Check dissolve and difference dissolve/dissolve_inserter - std::vector dissolved3; + // Check dissolve and validity, assuming GeometryOut is a single polygon + typedef bg::model::multi_polygon multi_polygon; + multi_polygon dissolved3; bg::dissolve(geometry, dissolved3); + if (settings.test_validity) + { + std::string message; + bool const valid = bg::is_valid(dissolved3, message); + BOOST_CHECK_MESSAGE(valid, + "dissolve: " << caseid + << " geometry is not valid: " << message); + } + // Make output unique (TODO: this should probably be moved to dissolve itself) BOOST_FOREACH(GeometryOut& dissolved, dissolved1) { @@ -396,7 +421,7 @@ void test_dissolve(std::string const& caseid, Geometry const& geometry, ); BOOST_CHECK_EQUAL(holes, expected_hole_count); - BOOST_CHECK_CLOSE(length_or_area, expected_length_or_area, percentage); + BOOST_CHECK_CLOSE(length_or_area, expected_area, settings.percentage); BOOST_CHECK_EQUAL(dissolved1.size(), dissolved2.size()); BOOST_CHECK_EQUAL(dissolved1.size(), dissolved3.size()); @@ -417,17 +442,19 @@ void test_dissolve(std::string const& caseid, Geometry const& geometry, template void test_one(std::string const& caseid, std::string const& wkt, - std::size_t expected_hole_count, std::size_t expected_point_count, - double expected_length_or_area, - std::size_t expected_clip_count = 0, // to be moved later - double percentage = 0.001) + double expected_area, + std::size_t expected_clip_count, + std::size_t expected_hole_count, + std::size_t expected_point_count, + ut_settings const& settings) { Geometry geometry; bg::read_wkt(wkt, geometry); test_dissolve(caseid, geometry, + expected_area, expected_clip_count, expected_hole_count, expected_point_count, - expected_length_or_area, percentage); + settings); #ifdef BOOST_GEOMETRY_TEST_MULTI_PERMUTATIONS // Test different combinations of a multi-polygon @@ -452,18 +479,24 @@ void test_one(std::string const& caseid, std::string const& wkt, out << "_" << index; geometry2.push_back(geometry[index]); } - test_dissolve(out.str(), geometry2, expected_hole_count, - expected_point_count, expected_length_or_area, percentage); + test_dissolve(out.str(), geometry2, expected_area, + expected_clip_count, expected_hole_count, expected_point_count, settings); } while (std::next_permutation(indices.begin(), indices.end())); #endif } -#define TEST_DISSOLVE(caseid, area, clips, holes, points) \ - (test_one) ( #caseid, caseid, holes, points, area, clips) +#define TEST_DISSOLVE(caseid, area, clips, holes, points) { \ + ut_settings settings; \ + (test_one) ( #caseid, caseid, area, clips, holes, points, settings); } -#define TEST_MULTI(caseid, area, clips, holes, points) \ - (test_one) ( #caseid, caseid, holes, points, area, clips) +#define TEST_DISSOLVE_IGNORE(caseid, area, clips, holes, points) { \ + ut_settings settings; settings.test_validity = false; \ + (test_one) ( #caseid, caseid, area, clips, holes, points, settings); } + +#define TEST_MULTI(caseid, area, clips, holes, points) { \ + ut_settings settings; \ + (test_one) ( #caseid, caseid, area, clips, holes, points, settings); } template void test_all() @@ -493,10 +526,11 @@ void test_all() TEST_DISSOLVE(dissolve_mail_2017_09_24_a, 0.5, 2, 0, 8); - // These are not all complete yet - TEST_DISSOLVE(dissolve_mail_2017_09_24_b, 16.0, 1, 0, 5); - TEST_DISSOLVE(dissolve_mail_2017_09_24_c, 0.4999, 1, 0, 4); - TEST_DISSOLVE(dissolve_mail_2017_09_24_d, 0.5, 1, 0, 4); + // These do not have closed input, and output is not closed either. TODO. + TEST_DISSOLVE_IGNORE(dissolve_mail_2017_09_24_b, 16.0, 1, 0, 5); + TEST_DISSOLVE_IGNORE(dissolve_mail_2017_09_24_c, 0.4999, 1, 0, 4); + TEST_DISSOLVE_IGNORE(dissolve_mail_2017_09_24_d, 0.5, 1, 0, 4); + TEST_DISSOLVE(dissolve_mail_2017_09_24_e, 0.001801138128, 5, 0, 69); TEST_DISSOLVE(dissolve_mail_2017_09_24_f, 0.000361308800, 5, 0, 69);