diff --git a/include/boost/geometry/algorithms/detail/overlay/aggregate_operations.hpp b/include/boost/geometry/algorithms/detail/overlay/aggregate_operations.hpp index ad4ee55b2..f691d822d 100644 --- a/include/boost/geometry/algorithms/detail/overlay/aggregate_operations.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/aggregate_operations.hpp @@ -75,6 +75,26 @@ struct rank_with_rings return all_equal(sort_by_side::dir_from); } + template + inline bool traversable(Turns const& turns) const + { + typedef typename boost::range_value::type turn_type; + typedef typename turn_type::turn_operation_type turn_operation_type; + + for (std::set::const_iterator it = rings.begin(); + it != rings.end(); ++it) + { + const ring_with_direction& rwd = *it; + turn_type const& turn = turns[rwd.turn_index]; + turn_operation_type const& op = turn.operations[rwd.operation_index]; + if (op.visited.finalized()) + { + return false; + } + } + return true; + } + }; template @@ -90,16 +110,12 @@ inline void aggregate_operations(Sbs const& sbs, std::vector& a typename Sbs::rp const& ranked_point = sbs.m_ranked_points[i]; turn_type const& turn = turns[ranked_point.turn_index]; + turn_operation_type const& op = turn.operations[ranked_point.operation_index]; - if (op.visited.finalized()) - { - // Skip finalized operations in aggregation - // to avoid selecting them - continue; - } + if (! (op.operation == operation_intersection || op.operation == operation_continue)) { - // Don't consider union/blocked + // Don't consider union/blocked (aggregate is only used for intersections) continue; } diff --git a/include/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp b/include/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp index 0d0b78190..fdffd665e 100644 --- a/include/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp @@ -37,6 +37,7 @@ struct enrichment_info , startable(true) , count_left(0) , count_right(0) + , rank(-1) , zone(-1) , region_id(-1) , isolated(false) @@ -63,6 +64,7 @@ struct enrichment_info // Counts if polygons left/right of this operation std::size_t count_left; std::size_t count_right; + signed_size_type rank; // in cluster signed_size_type zone; // open zone, in cluster signed_size_type region_id; bool isolated; diff --git a/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp b/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp index 505ae5cca..c761e7d76 100644 --- a/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp @@ -751,6 +751,7 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns, op.enriched.count_left = ranked.count_left; op.enriched.count_right = ranked.count_right; + op.enriched.rank = ranked.rank; op.enriched.zone = ranked.zone; if ((for_operation == operation_union diff --git a/include/boost/geometry/algorithms/detail/overlay/traversal.hpp b/include/boost/geometry/algorithms/detail/overlay/traversal.hpp index 30c39869f..8d15c6119 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traversal.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traversal.hpp @@ -137,9 +137,9 @@ struct traversal } } - //! Sets visited for ALL truns traveling to the same turn (TODO: in same direction) + //! Sets visited for ALL turns traveling to the same turn inline void set_visited_in_cluster(signed_size_type cluster_id, - signed_size_type next_turn_index) + signed_size_type rank) { typename Clusters::const_iterator mit = m_clusters.find(cluster_id); BOOST_ASSERT(mit != m_clusters.end()); @@ -157,7 +157,7 @@ struct traversal { turn_operation_type& op = turn.operations[i]; if (op.visited.none() - && op.enriched.get_next_turn_index() == next_turn_index) + && op.enriched.rank == rank) { op.visited.set_visited(); } @@ -182,10 +182,9 @@ struct traversal { op.visited.set_visited(); } - if (turn.cluster_id >= 0 - && target_operation == operation_intersection) + if (turn.cluster_id >= 0) { - set_visited_in_cluster(turn.cluster_id, op.enriched.get_next_turn_index()); + set_visited_in_cluster(turn.cluster_id, op.enriched.rank); } } @@ -474,6 +473,7 @@ struct traversal sort_by_side::rank_with_rings const& rwr = aggregation[i]; if (rwr.all_to() + && rwr.traversable(m_turns) && selected_rank == 0) { // Take the first (= right) where segments leave, @@ -543,7 +543,7 @@ struct traversal { // This direction is already traveled before, the same // cannot be traveled again - return false; + continue; } // Take the last turn from this rank