Skip to content

Commit

Permalink
[turn] fix distance measure for equal points
Browse files Browse the repository at this point in the history
Fixes #1076
  • Loading branch information
barendgehrels committed Nov 16, 2022
1 parent 455822d commit 75742b0
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ struct get_distance_measure<CalculationType, cartesian_tag>
// 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<CalculationType>(p1, p2);
result_type result;
result.measure = arithmetic::side_value(line, p);
Expand All @@ -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 <typename SegmentPoint, typename Point, typename Strategies>
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<SegmentPoint, Point>::type,
typename Strategies::cs_tag
>::apply(p1, p2, p);
using calc_t = typename select_coordinate_type<SegmentPoint, Point>::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<calc_t> const result;
return result;
}

return detail_dispatch::get_distance_measure
<
calc_t,
typename Strategies::cs_tag
>::apply(p1, p2, p);
}

} // namespace detail
Expand Down
20 changes: 8 additions & 12 deletions include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>

#include <boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp>

#include <boost/geometry/util/condition.hpp>
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand Down
6 changes: 6 additions & 0 deletions test/algorithms/overlay/overlay_cases.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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))",
Expand Down
3 changes: 3 additions & 0 deletions test/algorithms/set_operations/union/union.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 75742b0

Please sign in to comment.