From dc63848782bbafab83b32e01a0e726f81d576bce Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 18 May 2016 12:20:17 +0200 Subject: [PATCH] [traverse] check other ring while determining switches --- .../overlay/traversal_switch_detector.hpp | 65 +++++++++++++++---- .../set_operations/union/union_multi.cpp | 27 ++++---- 2 files changed, 65 insertions(+), 27 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp b/include/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp index c96ec9164..61ec493f2 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp @@ -131,11 +131,13 @@ struct traversal_switch_detector return traverse_error_none; } - inline traverse_error_type traverse(bool& do_switch, bool& dont_switch, + inline traverse_error_type traverse(bool& do_switch, bool& dont_switch, bool& touch_other_ring, signed_size_type start_turn_index, int start_op_index) { turn_type& start_turn = m_turns[start_turn_index]; turn_operation_type& start_op = m_turns[start_turn_index].operations[start_op_index]; + segment_identifier const& start_other_seg_id = + m_turns[start_turn_index].operations[1 - start_op_index].seg_id; signed_size_type current_turn_index = start_turn_index; int current_op_index = start_op_index; @@ -216,31 +218,56 @@ struct traversal_switch_detector { if (current_turn_index == start_turn_index) { - // Found the origin again without uu turns in between + // Found the origin again #if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR) std::cout << "FOUND ORIGIN AGAIN " << current_turn_index << " started at " << start_turn_index + << " " << (touch_other_ring ? " OTHER RING ENCOUNTERED" : "") << std::endl; #endif - do_switch = true; + do_switch = touch_other_ring; } if (start_turn.cluster_id >= 0 && start_turn.cluster_id == turn.cluster_id) { - // Found the origin-cluster again without uu turns in between + // Found the origin-cluster again #if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR) std::cout << "FOUND ORIGIN-CLUSTER AGAIN " << current_turn_index << " cl:" << turn.cluster_id << " started at " << start_turn_index << " cl:" << start_turn.cluster_id + << " " << (touch_other_ring ? " OTHER RING ENCOUNTERED" : "") << std::endl; #endif - do_switch = true; + do_switch = touch_other_ring; } - // Return, it does not need to be finished return traverse_error_none; } + + segment_identifier const& oseg_id + = turn.operations[1 - start_op_index].seg_id; + if (start_other_seg_id.multi_index == oseg_id.multi_index + && start_other_seg_id.ring_index == oseg_id.ring_index) + { + touch_other_ring = true; + // Basically we can also return here +#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR) + std::cout << " other ring encountered " + << " start: " << start_other_seg_id + << " " << turn.operations[0].seg_id + << " // " << turn.operations[1].seg_id + << std::endl; +#endif + } + +#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR) + std::cout << " TURN visited " + << " " << turn.operations[0].seg_id + << " // " << turn.operations[1].seg_id + << " " << (touch_other_ring ? " OTHER RING ENCOUNTERED" : "") + << std::endl; +#endif } // SWITCH if (current_turn_index == start_turn_index @@ -255,7 +282,7 @@ struct traversal_switch_detector return traverse_error_endless_loop; } - void traverse_with_operation(bool& do_switch, bool& dont_switch, + void traverse_with_operation(bool& do_switch, bool& dont_switch, bool& touch_other_ring, turn_type const& start_turn, std::size_t turn_index, int op_index) { turn_operation_type const& start_op = start_turn.operations[op_index]; @@ -269,7 +296,7 @@ struct traversal_switch_detector return; } - traverse_error_type traverse_error = traverse(do_switch, dont_switch, + traverse_error_type traverse_error = traverse(do_switch, dont_switch, touch_other_ring, turn_index, op_index); if (traverse_error != traverse_error_none) @@ -335,6 +362,17 @@ struct traversal_switch_detector { signed_size_type turn_index = *sit; turn_type& turn = m_turns[turn_index]; + + if (turn.both(operation_continue)) + { + // For cc-turns, happening when two rings continue together, + // don't examine: we will always find the other ring again +#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR) + std::cout << "- SKIP cc CLUSTER-TURN " << turn_index << std::endl; +#endif + continue; + } + #if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR) std::cout << "- EXAMINE CLUSTER-TURN " << turn_index << std::endl; #endif @@ -344,9 +382,13 @@ struct traversal_switch_detector for (int oi = 0; oi < 2; oi++) { #if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR) - std::cout << " - EXAMINE CLUSTER-TURN-OP " << turn_index << "[" << oi << "]" << std::endl; + std::cout << " - EXAMINE CLUSTER-TURN-OP " << turn_index << "[" << oi << "]" + << " " << turn.operations[oi].seg_id + << " // " << turn.operations[1 - oi].seg_id + << std::endl; #endif - traverse_with_operation(do_switch[oi], dont_switch[oi], + bool touch_other_ring = false; + traverse_with_operation(do_switch[oi], dont_switch[oi], touch_other_ring, turn, turn_index, oi); reset_visits(); } @@ -390,7 +432,8 @@ struct traversal_switch_detector << " // " << turn.operations[1 - oi].seg_id << std::endl; #endif - traverse_with_operation(do_switch[oi], dont_switch[oi], + bool touch_other_ring = false; + traverse_with_operation(do_switch[oi], dont_switch[oi], touch_other_ring, turn, turn_index, oi); } turn.switch_source = do_switch[0] || do_switch[1]; diff --git a/test/algorithms/set_operations/union/union_multi.cpp b/test/algorithms/set_operations/union/union_multi.cpp index 6104e768e..501176eb4 100644 --- a/test/algorithms/set_operations/union/union_multi.cpp +++ b/test/algorithms/set_operations/union/union_multi.cpp @@ -91,8 +91,7 @@ void test_areal() 3, 0, 15, 4.0); test_one("case_66_multi", case_66_multi[0], case_66_multi[1], - 2, 0, 23, 7.0, // #clips should be 3 - ignore_validity2); + 3, 0, 23, 7.0); test_one("case_72_multi", case_72_multi[0], case_72_multi[1], 1, 0, 13, 10.65); @@ -137,8 +136,7 @@ void test_areal() // Should have 9 holes, they are all separate and touching test_one("case_110_multi", case_110_multi[0], case_110_multi[1], - 1, 9, 45, 1250, - ignore_validity); + 1, 9, 45, 1250); test_one("case_111_multi", case_111_multi[0], case_111_multi[1], @@ -185,7 +183,7 @@ void test_areal() 1, 0, 14, 100.0); // Area from SQL Server test_one("case_recursive_boxes_3", case_recursive_boxes_3[0], case_recursive_boxes_3[1], - 15, 3, 159, 56.5, + 16, 3, 162, 56.5, ignore_validity); // Area from SQL Server test_one("case_recursive_boxes_4", @@ -193,7 +191,7 @@ void test_areal() 1, 2, 42, 96.75); test_one("case_recursive_boxes_5", case_recursive_boxes_5[0], case_recursive_boxes_5[1], - 2, 9, 115, 70.0, + 3, 8, 115, 70.0, ignore_validity); test_one("case_recursive_boxes_6", @@ -226,8 +224,7 @@ void test_areal() 3, 0, -1, 10.25); test_one("case_recursive_boxes_14", case_recursive_boxes_14[0], case_recursive_boxes_14[1], - 3, 0, -1, 4.5, // #clips should be 5 - ignore_validity2); + 5, 0, -1, 4.5); test_one("case_recursive_boxes_15", case_recursive_boxes_15[0], case_recursive_boxes_15[1], 3, 0, -1, 6.0); @@ -246,8 +243,7 @@ void test_areal() 3, 0, -1, 2.5); test_one("case_recursive_boxes_20", case_recursive_boxes_20[0], case_recursive_boxes_20[1], - 1, 0, -1, 2.0, // #clips should be 2 - ignore_validity2); + 2, 0, -1, 2.0); test_one("case_recursive_boxes_21", case_recursive_boxes_21[0], case_recursive_boxes_21[1], 1, 0, -1, 2.5); @@ -268,23 +264,22 @@ void test_areal() 3, 0, -1, 6.0); test_one("case_recursive_boxes_27", case_recursive_boxes_27[0], case_recursive_boxes_27[1], - 3, 0, -1, 4.5, // #clips should be 4 - ignore_validity2); + 4, 0, -1, 4.5); test_one("case_recursive_boxes_28", case_recursive_boxes_28[0], case_recursive_boxes_28[1], 1, 0, -1, 6.5, ignore_validity2); test_one("case_recursive_boxes_29", case_recursive_boxes_29[0], case_recursive_boxes_29[1], - 2, 1, -1, 15.5, + 2, 0, -1, 15.5, ignore_validity); test_one("case_recursive_boxes_30", case_recursive_boxes_30[0], case_recursive_boxes_30[1], - 1, 3, -1, 17.5); + 1, 2, -1, 17.5, + ignore_validity2); test_one("case_recursive_boxes_31", case_recursive_boxes_31[0], case_recursive_boxes_31[1], - 1, 0, -1, 5.0, - ignore_validity2); + 3, 0, -1, 5.0); test_one("case_recursive_boxes_32", case_recursive_boxes_32[0], case_recursive_boxes_32[1], 2, 0, -1, 5.75);