diff --git a/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp b/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp index 2201be8b54..d462bb524d 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp @@ -100,7 +100,6 @@ struct get_distance_measure // Get the distance measure / side value // It is not a real distance and purpose is // to detect small differences in collinearity - auto const line = detail::make::make_infinite_line(p1, p2); result_type result; result.measure = arithmetic::side_value(line, p); @@ -117,17 +116,32 @@ namespace detail // 0 (absolutely 0, not even an epsilon) means collinear. Like side, // a negative means that p is to the right of p1-p2. And a positive value // means that p is to the left of p1-p2. - template inline auto get_distance_measure(SegmentPoint const& p1, SegmentPoint const& p2, Point const& p, Strategies const&) { - return detail_dispatch::get_distance_measure - < - typename select_coordinate_type::type, - typename Strategies::cs_tag - >::apply(p1, p2, p); + using calc_t = typename select_coordinate_type::type; + + // Verify equality, without using a tolerance + // (so don't use equals or equals_point_point) + // because it is about very tiny differences. + auto identical = [](const auto& point1, const auto& point2) + { + return geometry::get<0>(point1) == geometry::get<0>(point2) + && geometry::get<1>(point1) == geometry::get<1>(point2); + }; + if (identical(p1, p) || identical(p2, p)) + { + detail::distance_measure const result; + return result; + } + + return detail_dispatch::get_distance_measure + < + calc_t, + typename Strategies::cs_tag + >::apply(p1, p2, p); } } // namespace detail 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 0079afdbcd..8be9538f0d 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -25,7 +25,6 @@ #include #include #include - #include #include @@ -589,12 +588,14 @@ struct touch : public base_turn_handler // >----->P qj is LEFT of P1 and pi is LEFT of Q2 // (the other way round is also possible) - auto const dm_qj_p1 = get_distance_measure(range_p.at(0), range_p.at(1), range_q.at(1), - umbrella_strategy); - auto const dm_pi_q2 = get_distance_measure(range_q.at(1), range_q.at(2), range_p.at(0), - umbrella_strategy); + auto has_distance = [&](const auto& r1, const auto& r2) -> bool + { + auto const d1 = get_distance_measure(r1.at(0), r1.at(1), r2.at(1), umbrella_strategy); + auto const d2 = get_distance_measure(r2.at(1), r2.at(2), r1.at(0), umbrella_strategy); + return d1.measure > 0 && d2.measure > 0; + }; - if (dm_qj_p1.measure > 0 && dm_pi_q2.measure > 0) + if (has_distance(range_p, range_q)) { // Even though there is a touch, Q(j) is left of P1 // and P(i) is still left from Q2. @@ -607,12 +608,7 @@ struct touch : public base_turn_handler return true; } - auto const dm_pj_q1 = get_distance_measure(range_q.at(0), range_q.at(1), range_p.at(1), - umbrella_strategy); - auto const dm_qi_p2 = get_distance_measure(range_p.at(1), range_p.at(2), range_q.at(0), - umbrella_strategy); - - if (dm_pj_q1.measure > 0 && dm_qi_p2.measure > 0) + if (has_distance(range_q, range_p)) { // Even though there is a touch, Q(j) is left of P1 // and P(i) is still left from Q2. diff --git a/test/algorithms/overlay/overlay_cases.hpp b/test/algorithms/overlay/overlay_cases.hpp index 2252752405..68ffd77459 100644 --- a/test/algorithms/overlay/overlay_cases.hpp +++ b/test/algorithms/overlay/overlay_cases.hpp @@ -1077,6 +1077,12 @@ static std::string issue_876b[2] = "POLYGON((-71.6230763305201634 -132.587678014412745,-106.959839171856814 -102.936613347248112,-40.4477408440520776 -23.6705812141075285,-5.11097800271543878 -53.3216458812721612,-71.6230763305201634 -132.587678014412745))" }; +static std::string issue_1076[2] = +{ + "POLYGON((981.792858339935151 98, 927.152135631899114 0, 970 98, 981.792858339935151 98))", + "POLYGON((927.152135631899114 0, 981.792858339935151 98, 995 98, 927.152135631899114 0))" +}; + static std::string ggl_list_20120229_volker[3] = { "POLYGON((1716 1554,2076 2250,2436 2352,2796 1248,3156 2484,3516 2688,3516 2688,3156 2484,2796 1248,2436 2352,2076 2250, 1716 1554))", diff --git a/test/algorithms/set_operations/union/union.cpp b/test/algorithms/set_operations/union/union.cpp index 005e13e7ec..5d246b5a9c 100644 --- a/test/algorithms/set_operations/union/union.cpp +++ b/test/algorithms/set_operations/union/union.cpp @@ -444,6 +444,9 @@ void test_areal() TEST_UNION(issue_838, 1, 0, -1, expectation_limits(1.3333, 1.33785)); TEST_UNION_REV(issue_838, 1, 0, -1, expectation_limits(1.3333, 1.33785)); + TEST_UNION(issue_1076, 1, 0, -1, 1225.0); + TEST_UNION_REV(issue_1076, 1, 0, -1, 1225.0); + { // Rescaling produces an invalid result ut_settings settings;