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 ed71641da..c91c19713 100644 --- a/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -99,39 +100,62 @@ inline void enrich_assign(Container& operations, operation_type , Geometry1 const& , Geometry2 const& , Strategy const& ) + { + typedef typename boost::range_value::type turn_type; typedef typename IndexType::type operations_type; - typedef typename boost::range_iterator::type iterator_type; + typedef typename boost::range_iterator::type iterator_type; if (operations.size() > 0) { // Assign travel-to-vertex/ip index for each turning point. - // Because IP's are circular, PREV starts at the very last one, - // being assigned from the first one. - // "next ip on same segment" should not be considered circular. - bool first = true; - iterator_type it = boost::begin(operations); - for (iterator_type prev = it + (boost::size(operations) - 1); - it != boost::end(operations); - prev = it++) + // Iterator "next" is circular + + geometry::ever_circling_range_iterator next(operations); + ++next; + + for (iterator_type it = boost::begin(operations); + it != boost::end(operations); ++it) { - operations_type& prev_op - = turn_points[prev->turn_index].operations[prev->operation_index]; - operations_type& op - = turn_points[it->turn_index].operations[it->operation_index]; + turn_type& turn = turn_points[it->turn_index]; + operations_type& op = turn.operations[it->operation_index]; - prev_op.enriched.travels_to_ip_index - = static_cast(it->turn_index); - prev_op.enriched.travels_to_vertex_index - = it->subject->seg_id.segment_index; - - if (! first - && prev_op.seg_id.segment_index == op.seg_id.segment_index) + // Normal behaviour: next should point at next turn: + if (it->turn_index == next->turn_index) { - prev_op.enriched.next_ip_index = static_cast(it->turn_index); + ++next; + } + + // Cluster behaviour: next should point after cluster: + while (turn.cluster_id != -1 + && turn.cluster_id == turn_points[next->turn_index].cluster_id + && it->turn_index != next->turn_index) + { + ++next; + } + + if (it->turn_index == next->turn_index) + { + std::cout << "Only one turn" << std::endl; + } + + turn_type const& next_turn = turn_points[next->turn_index]; + operations_type const& next_op = next_turn.operations[next->operation_index]; + + op.enriched.travels_to_ip_index + = static_cast(next->turn_index); + op.enriched.travels_to_vertex_index + = next->subject->seg_id.segment_index; + + if (op.seg_id.segment_index == next_op.seg_id.segment_index + && op.fraction < next_op.fraction) + { + // Next turn is located further on same segment + // assign next_ip_index + // (this is one not circular therefore fraction is considered) + op.enriched.next_ip_index = static_cast(next->turn_index); } - first = false; } } diff --git a/include/boost/geometry/algorithms/detail/overlay/traverse.hpp b/include/boost/geometry/algorithms/detail/overlay/traverse.hpp index c3b646328..8a6ddd00e 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traverse.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traverse.hpp @@ -215,56 +215,6 @@ struct traversal return has_tp; } - - inline signed_size_type traverse_cluster(sbs_type const& sbs, - std::size_t index) - { - typedef typename boost::range_value::type turn_type; - typename sbs_type::rp const& ranked_point = sbs.m_ranked_points[index]; - std::size_t result = ranked_point.turn_index; - - turn_type& ranked_turn = m_turns[ranked_point.turn_index]; - turn_operation_type& ranked_op - = ranked_turn.operations[ranked_point.op_index]; - - signed_size_type next_turn_index = ranked_op.enriched.next_ip_index; - if (next_turn_index == -1) - { - next_turn_index = ranked_op.enriched.travels_to_ip_index; - } - if (next_turn_index == -1) - { - // Turn found but dead end, do not use this turn. Can happen if, - // for example, in intersection ux is not filtered out - return -1; - } - - for (std::size_t i = index + 1; - i < sbs.m_ranked_points.size(); - i++) - { - const typename sbs_type::rp& next = sbs.m_ranked_points[i]; - if (next.main_rank != ranked_point.main_rank) - { - return result; - } - if (next.turn_index == next_turn_index) - { - set_visited(ranked_turn, ranked_op); - m_visitor.visit_traverse(m_turns, ranked_turn, ranked_op, "Cluster skip"); - - result = next.turn_index; - - // If there are more consecutively in same cluster, move - // to next one - return traverse_cluster(sbs, i); - } - } - return result; - } - - - inline void select_turn_from_cluster( typename boost::range_iterator::type& turn_it, turn_operation_type const& op) { @@ -321,8 +271,9 @@ struct traversal return; } - // Use this turn, or, in a cluster, traverse through it - signed_size_type turn_index = traverse_cluster(sbs, i); + // Use this turn (if also part of a cluster, it will point to + // next turn outside cluster) + signed_size_type const turn_index = ranked_point.turn_index; if (turn_index != -1) { turn_it = m_turns.begin() + turn_index; diff --git a/test/algorithms/overlay/overlay.cpp b/test/algorithms/overlay/overlay.cpp index 8538619f9..74098fd98 100644 --- a/test/algorithms/overlay/overlay.cpp +++ b/test/algorithms/overlay/overlay.cpp @@ -394,6 +394,13 @@ void test_all() 4.75 ); + test_overlay + ( + "case_recursive_boxes_11_intersection", + case_recursive_boxes_11[0], case_recursive_boxes_11[1], + 1.0 + ); + // std::cout // << " \"" // << bg::inverse(case_65_multi[0], 1.0)