diff options
Diffstat (limited to 'boost/geometry/algorithms/detail/overlay/handle_colocations.hpp')
-rw-r--r-- | boost/geometry/algorithms/detail/overlay/handle_colocations.hpp | 93 |
1 files changed, 74 insertions, 19 deletions
diff --git a/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp b/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp index f3311b34e9..c634fc450f 100644 --- a/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp +++ b/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp @@ -24,6 +24,7 @@ #include <boost/geometry/core/point_order.hpp> #include <boost/geometry/algorithms/detail/overlay/cluster_info.hpp> #include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp> +#include <boost/geometry/algorithms/detail/overlay/is_self_turn.hpp> #include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp> #include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp> #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp> @@ -181,6 +182,7 @@ inline signed_size_type add_turn_to_cluster(Turn const& turn, if (cid0 == -1 && cid1 == -1) { + // Because of this, first cluster ID will be 1 ++cluster_id; add_cluster_id(turn.operations[0], cluster_per_segment, cluster_id); add_cluster_id(turn.operations[1], cluster_per_segment, cluster_id); @@ -314,7 +316,7 @@ inline void assign_cluster_to_turns(Turns& turns, if (it != cluster_per_segment.end()) { #if defined(BOOST_GEOMETRY_DEBUG_HANDLE_COLOCATIONS) - if (turn.cluster_id != -1 + if (turn.is_clustered() && turn.cluster_id != it->second) { std::cout << " CONFLICT " << std::endl; @@ -503,6 +505,7 @@ inline void discard_interior_exterior_turns(Turns& turns, Clusters& clusters) template < + overlay_type OverlayType, typename Turns, typename Clusters > @@ -517,38 +520,65 @@ inline void set_colocation(Turns& turns, Clusters const& clusters) cluster_info const& cinfo = cit->second; std::set<signed_size_type> const& ids = cinfo.turn_indices; - bool has_ii = false; - bool has_uu = false; + bool both_target = false; for (set_iterator it = ids.begin(); it != ids.end(); ++it) { turn_type const& turn = turns[*it]; - if (turn.both(operation_intersection)) - { - has_ii = true; - } - if (turn.both(operation_union) || turn.combination(operation_union, operation_blocked)) + if (turn.both(operation_from_overlay<OverlayType>::value)) { - has_uu = true; + both_target = true; + break; } } - if (has_ii || has_uu) + + if (both_target) { for (set_iterator it = ids.begin(); it != ids.end(); ++it) { turn_type& turn = turns[*it]; - if (has_ii) - { - turn.colocated_ii = true; - } - if (has_uu) + + if (both_target) { - turn.colocated_uu = true; + turn.has_colocated_both = true; } } } } } +template +< + typename Turns, + typename Clusters +> +inline void check_colocation(bool& has_blocked, + int cluster_id, Turns const& turns, Clusters const& clusters) +{ + typedef typename boost::range_value<Turns>::type turn_type; + + has_blocked = false; + + typename Clusters::const_iterator mit = clusters.find(cluster_id); + if (mit == clusters.end()) + { + return; + } + + cluster_info const& cinfo = mit->second; + + for (std::set<signed_size_type>::const_iterator it + = cinfo.turn_indices.begin(); + it != cinfo.turn_indices.end(); ++it) + { + turn_type const& turn = turns[*it]; + if (turn.any_blocked()) + { + has_blocked = true; + } + } +} + + // Checks colocated turns and flags combinations of uu/other, possibly a // combination of a ring touching another geometry's interior ring which is // tangential to the exterior ring @@ -627,6 +657,10 @@ inline bool handle_colocations(Turns& turns, Clusters& clusters, > cluster_per_segment_type; cluster_per_segment_type cluster_per_segment; + + // Assign to zero, because of pre-increment later the cluster_id + // effectively starts with 1 + // (and can later be negated to use uniquely with turn_index) signed_size_type cluster_id = 0; for (typename map_type::const_iterator it = map.begin(); @@ -640,7 +674,9 @@ inline bool handle_colocations(Turns& turns, Clusters& clusters, } assign_cluster_to_turns(turns, clusters, cluster_per_segment); - set_colocation(turns, clusters); + // Get colocated information here and not later, to keep information + // on turns which are discarded afterwards + set_colocation<OverlayType>(turns, clusters); discard_interior_exterior_turns < do_reverse<geometry::point_order<Geometry1>::value>::value != Reverse1, @@ -758,14 +794,21 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns, cinfo.open_count = sbs.open_count(for_operation); - // Unset the startable flag for all 'closed' zones + bool const set_startable + = OverlayType != overlay_dissolve_union + && OverlayType != overlay_dissolve_intersection; + + // Unset the startable flag for all 'closed' zones. This does not + // apply for self-turns, because those counts are not from both + // polygons for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++) { const typename sbs_type::rp& ranked = sbs.m_ranked_points[i]; turn_type& turn = turns[ranked.turn_index]; turn_operation_type& op = turn.operations[ranked.operation_index]; - if (for_operation == operation_union && cinfo.open_count == 0) + if (set_startable + && for_operation == operation_union && cinfo.open_count == 0) { op.enriched.startable = false; } @@ -780,6 +823,18 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns, op.enriched.rank = ranked.rank; op.enriched.zone = ranked.zone; + if (! set_startable) + { + continue; + } + + if (OverlayType != overlay_difference + && is_self_turn<OverlayType>(turn)) + { + // Difference needs the self-turns, TODO: investigate + continue; + } + if ((for_operation == operation_union && ranked.count_left != 0) || (for_operation == operation_intersection |