diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp index 82449dc62..609825e34 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -589,14 +589,15 @@ struct collinear : public base_turn_handler if (side_pk != side_p || side_qk != side_q) { - //std::cout << " -> Collinear " + //std::cout << "ROBUSTNESS -> Collinear " // << " arr: " << arrival // << " prod: " << product // << " dir: " << side_p << " " << side_q // << " rev: " << side_pk << " " << side_qk // << std::endl; - handle_robustness(ti, product, side_p, side_q, side_pk, side_qk); + handle_robustness(ti, arrival, product, + side_p, side_q, side_pk, side_qk); } else { @@ -607,16 +608,19 @@ struct collinear : public base_turn_handler } static inline void handle_robustness(TurnInfo& ti, - int product, + int arrival, int product, int side_p, int side_q, int side_pk, int side_qk) { bool take_ui = product == 1; - if ((product == 1 && side_p == 1 && side_pk != 1) - || (product == -1 && side_q == 1 && side_qk != 1)) + if (product == arrival) { - //std::cout << " -> Reverse" << std::endl; - take_ui = ! take_ui; + if ((product == 1 && side_p == 1 && side_pk != 1) + || (product == -1 && side_q == 1 && side_qk != 1)) + { + //std::cout << "ROBUSTNESS: -> Reverse" << std::endl; + take_ui = ! take_ui; + } } ui_else_iu(take_ui, ti); diff --git a/include/boost/geometry/strategies/cartesian/cart_intersect.hpp b/include/boost/geometry/strategies/cartesian/cart_intersect.hpp index f805a76fd..bf7fdb7dd 100644 --- a/include/boost/geometry/strategies/cartesian/cart_intersect.hpp +++ b/include/boost/geometry/strategies/cartesian/cart_intersect.hpp @@ -203,6 +203,26 @@ struct relate_cartesian_segments promoted_type const zero = 0; promoted_type const one = 1; promoted_type const epsilon = std::numeric_limits::epsilon(); + + if (sides.crossing() && math::abs(da-d) < 0.1) + { + // ROBUSTNESS: the r value can in epsilon-cases be 1.14, while (with perfect arithmetic) + // it should be one. If segments are crossing (we can see that with the sides) + // and one is inside the other, there must be an intersection point. + // We correct for that. + // TODO: find more cases (this only solves case called ggl_list_20110820_christophe in unit tests + if (r > one) + { + // std::cout << "ROBUSTNESS: correction of r " << r << std::endl; + r = one; + } + else if (r < zero) + { + // std::cout << "ROBUSTNESS: correction of r " << r << std::endl; + r = zero; + } + } + if (r < zero) { if (r < -epsilon) diff --git a/include/boost/geometry/strategies/side_info.hpp b/include/boost/geometry/strategies/side_info.hpp index baa812983..35aa3581a 100644 --- a/include/boost/geometry/strategies/side_info.hpp +++ b/include/boost/geometry/strategies/side_info.hpp @@ -67,6 +67,13 @@ public : && sides[1].second == 0; } + inline bool crossing() const + { + return sides[0].first * sides[0].second == -1 + && sides[1].first * sides[1].second == -1; + } + + template inline bool zero() const {