From cda90e5cff78d849ac2a0fedf7bfbc1ef41d6eda Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 1 Jan 2025 23:23:53 +0100 Subject: [PATCH] refactor: removed unused functionality and minor changes preparing next pr --- extensions/test/algorithms/dissolve.cpp | 17 -- .../detail/buffer/buffer_policies.hpp | 34 ---- .../overlay/enrich_intersection_points.hpp | 147 ++++++------------ .../detail/overlay/handle_colocations.hpp | 17 -- .../detail/overlay/less_by_segment_ratio.hpp | 2 - .../algorithms/detail/overlay/overlay.hpp | 25 ++- .../extensions/algorithms/dissolve.hpp | 17 ++ test/algorithms/overlay/sort_by_side.cpp | 6 + .../buffer/recursive_polygons_buffer.cpp | 61 ++++---- 9 files changed, 119 insertions(+), 207 deletions(-) diff --git a/extensions/test/algorithms/dissolve.cpp b/extensions/test/algorithms/dissolve.cpp index 46a7aa6440..438cebdfed 100644 --- a/extensions/test/algorithms/dissolve.cpp +++ b/extensions/test/algorithms/dissolve.cpp @@ -185,23 +185,6 @@ struct map_visitor : m_mapper(mapper) {} - void print(char const* header) - {} - - template - void print(char const* header, Turns const& turns, int turn_index) - { - 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) { diff --git a/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp b/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp index 4f2b8f0a82..1685bc8585 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp @@ -87,20 +87,6 @@ g_backtrack_warning_count++; struct buffer_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& ) {} @@ -170,26 +156,6 @@ struct buffer_turn_info {} }; -struct buffer_less -{ - template - inline bool operator()(Indexed const& left, Indexed const& right) const - { - if (! (left.subject->seg_id == right.subject->seg_id)) - { - return left.subject->seg_id < right.subject->seg_id; - } - - // Both left and right are located on the SAME segment. - if (! (left.subject->fraction == right.subject->fraction)) - { - return left.subject->fraction < right.subject->fraction; - } - - return left.turn_index < right.turn_index; - } -}; - template struct piece_get_box { diff --git a/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp b/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp index 934f942711..91c504cb8d 100644 --- a/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp @@ -104,8 +104,7 @@ inline void enrich_sort(Operations& operations, // Assign travel-to-vertex/ip index for each turn. template -inline void enrich_assign(Operations& operations, Turns& turns, - bool check_consecutive_turns) +inline void enrich_assign(Operations& operations, Turns& turns) { for (auto const& item : util::enumerate(operations)) { @@ -131,34 +130,6 @@ inline void enrich_assign(Operations& operations, Turns& turns, return next_turn.operations[operations[next_index].operation_index]; }; - if (check_consecutive_turns - && indexed.turn_index == operations[next_index].turn_index - && op.seg_id == next_operation().seg_id) - { - // If the two operations on the same turn are ordered consecutively, - // and they are on the same segment, then the turn where to travel to should - // be considered one further. Therefore next is increased. - // - // It often happens in buffer, in these configurations: - // +---->--+ - // | | - // | +->-*----> - // | | | - // ^ +-<-+ - // If the next index is not corrected, the small rectangle - // will be kept in the output. - - // This is a normal situation and occurs, for example, in every concave bend. - // In general it should always travel from turn to next turn. - // Only in some circumstances traveling to the same turn is necessary, for example - // if there is only one turn in the outer ring. - // - // (For dissolve this is not done, turn_index is often - // the same for two consecutive operations - but the conditions are changed - // and this should be verified again) - next_index = advance(next_index); - } - // Cluster behaviour: next should point after cluster, unless // their seg_ids are not the same // (For dissolve, this is still to be examined - TODO) @@ -285,36 +256,50 @@ struct enriched_map_default_include_policy // Add all (non discarded) operations on this ring // Blocked operations or uu on clusters (for intersection) // should be included, to block potential paths in clusters -template -inline void create_map(Turns const& turns, MappedVector& mapped_vector, - IncludePolicy const& include_policy) +template +inline auto create_map(Turns const& turns, IncludePolicy const& include_policy) { + using turn_type = typename boost::range_value::type; + using indexed_turn_operation = detail::overlay::indexed_turn_operation + < + typename turn_type::turn_operation_type + >; + + std::map + < + ring_identifier, + std::vector + > mapped_vector; + for (auto const& turn_item : util::enumerate(turns)) { auto const& index = turn_item.index; auto const& turn = turn_item.value; - if (! turn.discarded) + if (turn.discarded) { - for (auto const& op_item : util::enumerate(turn.operations)) + continue; + } + + for (auto const& op_item : util::enumerate(turn.operations)) + { + auto const& op_index = op_item.index; + auto const& op = op_item.value; + if (include_policy.include(op.operation)) { - auto const& op_index = op_item.index; - auto const& op = op_item.value; - if (include_policy.include(op.operation)) - { - ring_identifier const ring_id - ( - op.seg_id.source_index, - op.seg_id.multi_index, - op.seg_id.ring_index - ); - mapped_vector[ring_id].emplace_back - ( - index, op_index, op, turn.operations[1 - op_index].seg_id - ); - } + ring_identifier const ring_id + ( + op.seg_id.source_index, + op.seg_id.multi_index, + op.seg_id.ring_index + ); + mapped_vector[ring_id].emplace_back + ( + index, op_index, op, turn.operations[1 - op_index].seg_id + ); } } } + return mapped_vector; } template @@ -356,7 +341,6 @@ inline void calculate_remaining_distance(Turns& turns) } } - }} // namespace detail::overlay #endif //DOXYGEN_NO_DETAIL @@ -398,51 +382,14 @@ inline void enrich_intersection_points(Turns& turns, ? detail::overlay::operation_intersection : detail::overlay::operation_union; constexpr bool is_dissolve = OverlayType == overlay_dissolve; - constexpr bool is_buffer = OverlayType == overlay_buffer; - - using turn_type = typename boost::range_value::type; - using indexed_turn_operation = detail::overlay::indexed_turn_operation - < - typename turn_type::turn_operation_type - > ; - - using mapped_vector_type = std::map - < - ring_identifier, - std::vector - >; // Turns are often used by index (in clusters, next_index, etc) // and turns may therefore NOT be DELETED - they may only be flagged as discarded - bool has_cc = false; - bool has_colocations = false; - - if BOOST_GEOMETRY_CONSTEXPR (! is_buffer) - { - // Handle colocations, gathering clusters and (below) their properties. - has_colocations = detail::overlay::handle_colocations - < - Reverse1, Reverse2, OverlayType, Geometry1, Geometry2 - >(turns, clusters); - // Gather cluster properties (using even clusters with - // discarded turns - for open turns) - detail::overlay::gather_cluster_properties - < - Reverse1, - Reverse2, - OverlayType - >(clusters, turns, target_operation, - geometry1, geometry2, strategy); - } - else - { - // For buffer, this was already done before calling enrich_intersection_points. - has_colocations = ! clusters.empty(); - } - discard_duplicate_turns(turns, geometry1, geometry2); + bool has_cc = false; + // Discard turns not part of target overlay for (auto& turn : turns) { @@ -491,11 +438,15 @@ inline void enrich_intersection_points(Turns& turns, strategy); } + if (! clusters.empty()) + { + detail::overlay::cleanup_clusters(turns, clusters); + detail::overlay::colocate_clusters(clusters, turns); + } + // Create a map of vectors of indexed operation-types to be able // to sort intersection points PER RING - mapped_vector_type mapped_vector; - - detail::overlay::create_map(turns, mapped_vector, + auto mapped_vector = detail::overlay::create_map(turns, detail::overlay::enriched_map_default_include_policy()); for (auto& pair : mapped_vector) @@ -506,14 +457,6 @@ inline void enrich_intersection_points(Turns& turns, strategy); } - if (has_colocations) - { - detail::overlay::cleanup_clusters(turns, clusters); - detail::overlay::colocate_clusters(clusters, turns); - } - - // After cleaning up clusters assign the next turns - for (auto& pair : mapped_vector) { #ifdef BOOST_GEOMETRY_DEBUG_ENRICH @@ -524,7 +467,7 @@ inline void enrich_intersection_points(Turns& turns, detail::overlay::enrich_adapt(pair.second, turns); } - detail::overlay::enrich_assign(pair.second, turns, ! is_dissolve); + detail::overlay::enrich_assign(pair.second, turns); } if (has_cc) diff --git a/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp b/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp index d4f9ec19af..80c15e36e6 100644 --- a/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp @@ -364,23 +364,6 @@ inline bool handle_colocations(Turns& turns, Clusters& clusters) return true; } - -struct is_turn_index -{ - is_turn_index(signed_size_type index) - : m_index(index) - {} - - template - inline bool operator()(Indexed const& indexed) const - { - // Indexed is a indexed_turn_operation - return indexed.turn_index == m_index; - } - - signed_size_type m_index; -}; - template < typename Sbs, diff --git a/include/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp b/include/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp index a10017acc8..6f595d3320 100644 --- a/include/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp @@ -43,7 +43,6 @@ struct indexed_turn_operation std::size_t turn_index; std::size_t operation_index; - bool skip; // use pointers to avoid copies, const& is not possible because of usage in vector segment_identifier const* other_seg_id; // segment id of other segment of intersection of two segments TurnOperation const* subject; @@ -53,7 +52,6 @@ struct indexed_turn_operation segment_identifier const& oid) : turn_index(ti) , operation_index(oi) - , skip(false) , other_seg_id(&oid) , subject(boost::addressof(sub)) {} diff --git a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp index 27e9142e7a..04a95f1345 100644 --- a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp @@ -60,14 +60,6 @@ namespace detail { namespace overlay //! Default visitor for overlay, doing nothing struct overlay_null_visitor { - void print(char const* ) {} - - template - void print(char const* , Turns const& , int) {} - - template - void print(char const* , Turns const& , int , int ) {} - template void visit_turns(int , Turns const& ) {} @@ -271,6 +263,8 @@ struct overlay cluster_info >; + constexpr operation_type target_operation = operation_from_overlay::value; + turn_container_type turns; detail::get_turns::no_interrupt_policy policy; @@ -303,6 +297,21 @@ struct overlay cluster_type clusters; std::map turn_info_per_ring; + // Handle colocations, gathering clusters and (below) their properties. + detail::overlay::handle_colocations + < + Reverse1, Reverse2, OverlayType, Geometry1, Geometry2 + >(turns, clusters); + + // Gather cluster properties (using even clusters with + // discarded turns - for open turns) + detail::overlay::gather_cluster_properties + < + Reverse1, + Reverse2, + OverlayType + >(clusters, turns, target_operation, geometry1, geometry2, strategy); + geometry::enrich_intersection_points( turns, clusters, geometry1, geometry2, strategy); diff --git a/include/boost/geometry/extensions/algorithms/dissolve.hpp b/include/boost/geometry/extensions/algorithms/dissolve.hpp index 958cf7c251..1c54449f2a 100644 --- a/include/boost/geometry/extensions/algorithms/dissolve.hpp +++ b/include/boost/geometry/extensions/algorithms/dissolve.hpp @@ -173,6 +173,8 @@ struct dissolve_ring typename segment_ratio_type::type >; + constexpr operation_type target_operation = operation_from_overlay::value; + std::deque turns; detail::dissolve::no_interrupt_policy policy; detail::self_get_turn_points::self_turns @@ -198,6 +200,21 @@ struct dissolve_ring std::map clusters; // Enrich/traverse the polygons + // Handle colocations, gathering clusters and (below) their properties. + detail::overlay::handle_colocations + < + Reverse1, Reverse2, OverlayType, Geometry1, Geometry2 + >(turns, clusters); + + // Gather cluster properties (using even clusters with + // discarded turns - for open turns) + detail::overlay::gather_cluster_properties + < + Reverse1, + Reverse2, + OverlayType + >(clusters, turns, target_operation, geometry1, geometry2, strategy); + enrich_intersection_points(turns, clusters, input_ring, input_ring, rescale_policy, strategy); diff --git a/test/algorithms/overlay/sort_by_side.cpp b/test/algorithms/overlay/sort_by_side.cpp index 702fbf0c05..9c9e12f917 100644 --- a/test/algorithms/overlay/sort_by_side.cpp +++ b/test/algorithms/overlay/sort_by_side.cpp @@ -159,6 +159,12 @@ std::vector apply_overlay( cluster_type clusters; + // Handle colocations, gathering clusters and (below) their properties. + bg::detail::overlay::handle_colocations + < + Reverse1, Reverse2, OverlayType, Geometry1, Geometry2 + >(turns, clusters); + bg::enrich_intersection_points(turns, clusters, geometry1, geometry2, strategy); diff --git a/test/robustness/overlay/buffer/recursive_polygons_buffer.cpp b/test/robustness/overlay/buffer/recursive_polygons_buffer.cpp index 0369d5d619..1c5235461d 100644 --- a/test/robustness/overlay/buffer/recursive_polygons_buffer.cpp +++ b/test/robustness/overlay/buffer/recursive_polygons_buffer.cpp @@ -79,45 +79,52 @@ void create_svg(std::string const& filename mapper.map(buffer, "stroke-opacity:0.9;stroke:rgb(0,0,0);fill:none;stroke-width:1"); } -template -bool verify(std::string const& caseid, MultiPolygon const& mp, MultiPolygon const& buffer, Settings const& settings) +template +bool verify_buffer(Geometry const& geometry, Buffer const& buffer, std::string& reason, bool check_validity) { - using polygon_type = typename boost::range_value::type; - - bool result = true; + if (buffer.empty()) + { + reason = "Buffer is empty"; + return false; + } // Area of buffer must be larger than of original polygon - auto const area_mp = bg::area(mp); + auto const area_mp = bg::area(geometry); auto const area_buf = bg::area(buffer); - if (area_buf < area_mp) { - result = false; + reason = "Buffer area is smaller than input area"; + return false; } // Verify if all points are IN the buffer - if (result) + bool all_within = true; + bg::for_each_point(geometry, [&all_within, &buffer](auto const& point) { - for (auto const& polygon : mp) + if (! bg::within(point, buffer)) { - typename bg::point_type::type point; - bg::point_on_border(point, polygon); - if (! bg::within(point, buffer)) - { - result = false; - } + all_within = false; } + }); + + if (! all_within) + { + reason = "Any input points are outside the buffer"; + return false; } - if (result && settings.check_validity) + return check_validity ? bg::is_valid(buffer, reason) : true; +} + +template +bool verify(std::string const& caseid, Geometry const& geometry, MultiPolygon const& buffer, Settings const& settings) +{ + std::string reason; + bool const result = verify_buffer(geometry, buffer, reason, settings.check_validity); + + if (! result) { - bg::validity_failure_type failure; - if (! bg::is_valid(buffer, failure) - && failure != bg::failure_intersecting_interiors) - { - std::cout << "Buffer is not valid: " << bg::validity_failure_type_message(failure) << std::endl; - result = false; - } + std::cout << caseid << " " << reason << std::endl; } bool svg = settings.svg; @@ -134,7 +141,7 @@ bool verify(std::string const& caseid, MultiPolygon const& mp, MultiPolygon cons { // Generate a unique name std::ostringstream out; - out << "rec_pol_buffer_" << geometry_to_crc(mp) + out << "rec_pol_buffer_" << geometry_to_crc(geometry) << "_" << string_from_type::type>::name() << "."; filename = out.str(); @@ -142,14 +149,14 @@ bool verify(std::string const& caseid, MultiPolygon const& mp, MultiPolygon cons if (svg) { - create_svg(filename + "svg", mp, buffer); + create_svg(filename + "svg", geometry, buffer); } if (wkt) { std::ofstream stream(filename + "wkt"); // Stream input WKT - stream << bg::wkt(mp) << std::endl; + stream << bg::wkt(geometry) << std::endl; // If you need the output WKT, then stream bg::wkt(buffer) }