Skip to content

Commit

Permalink
Merge pull request #1346 from barendgehrels/fix/issue-1345
Browse files Browse the repository at this point in the history
fix: add condition to handle_imperfect_touch
  • Loading branch information
vissarion authored Nov 25, 2024
2 parents 372e86c + 68d4129 commit a9c3a24
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 11 deletions.
1 change: 1 addition & 0 deletions doc/release_notes.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
* [@https://github.com/boostorg/geometry/issues/1293 1293] [@https://github.com/boostorg/geometry/issues/1294 1294] [@https://github.com/boostorg/geometry/issues/1295 1295] Fix traversal through non clustered rings
* [@https://github.com/boostorg/geometry/issues/893 893] [@https://github.com/boostorg/geometry/issues/1299 1299] Fix blocking rings for non union conditions
* [@https://github.com/boostorg/geometry/issues/1342 1342] Fix discarding a start turn for combination with touch
* [@https://github.com/boostorg/geometry/issues/1288 1288] [@https://github.com/boostorg/geometry/issues/1345 1345] Fixes in handling (imperfect) touch

[/=================]
[heading Boost 1.85]
Expand Down
37 changes: 32 additions & 5 deletions include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,17 +343,35 @@ struct touch_interior : public base_turn_handler
template
<
typename IntersectionInfo,
typename UniqueSubRange
typename SideCalculator,
typename UniqueSubRange1,
typename UniqueSubRange2
>
static bool handle_as_touch(IntersectionInfo const& info,
UniqueSubRange const& non_touching_range)
SideCalculator const& side,
UniqueSubRange1 const& non_touching_range,
UniqueSubRange2 const& other_range)
{
if BOOST_GEOMETRY_CONSTEXPR (! VerifyPolicy::use_handle_as_touch)
{
return false;
}
else // else prevents unreachable code warning
{
bool const has_k = ! non_touching_range.is_last_segment()
&& ! other_range.is_last_segment();
if (has_k
&& (same(side.pj_wrt_q1(), side.qj_wrt_p2())
|| same(side.pj_wrt_q2(), side.qj_wrt_p1())))
{
// At a touch, the touching points (pj and qj) should be collinear
// with both other segments.
// If that is not the case (both left or both right), it should not be handled as a touch,
// (though the intersection point might be close to the end),
// because segments might cross each other or touch the other in the middle.
return false;
}

//
//
// ^ Q(i) ^ P(i)
Expand Down Expand Up @@ -569,7 +587,7 @@ struct touch : public base_turn_handler
// ||
// |^----
// >----->P
// * * they touch here (P/Q are (nearly) on top)
// * * they touch here (P/Q are (nearly) on top of each other)
//
// Q continues from where P comes.
// P continues from where Q comes
Expand All @@ -586,6 +604,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)

// There are also cases like this:
// P
// ^
// ||
// ||
// P----^-----<Q
// This code is not for these cases because of the condition opposite(side.pi_wrt_q1(), side.qk_wrt_p2())

auto has_distance = [&](auto const& r1, auto const& r2) -> bool
{
auto const d1 = get_distance_measure(r1.at(0), r1.at(1), r2.at(1), umbrella_strategy);
Expand Down Expand Up @@ -674,6 +700,7 @@ struct touch : public base_turn_handler
{
if (side_qk_p1 == 0 && side_pk_q1 == 0
&& has_pk && has_qk
&& opposite(side.pi_wrt_q1(), side.qk_wrt_p2())
&& handle_imperfect_touch(range_p, range_q, side_pk_q2, umbrella_strategy, ti))
{
// If q continues collinearly (opposite) with p, it should be blocked
Expand Down Expand Up @@ -1452,7 +1479,7 @@ struct get_turn_info
if ( inters.d_info().arrival[1] == 1 )
{
// Q arrives
if (handler::handle_as_touch(inters.i_info(), range_p))
if (handler::handle_as_touch(inters.i_info(), inters.sides(), range_p, range_q))
{
handle_as_touch = true;
}
Expand All @@ -1466,7 +1493,7 @@ struct get_turn_info
else
{
// P arrives, swap p/q
if (handler::handle_as_touch(inters.i_info(), range_q))
if (handler::handle_as_touch(inters.i_info(), inters.swapped_sides(), range_q, range_p))
{
handle_as_touch = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ struct side_calculator
, m_range_q(range_q)
{}

inline int pi_wrt_q1() const { return m_side_strategy.apply(get_qi(), get_qj(), get_pi()); }

inline int pj_wrt_q1() const { return m_side_strategy.apply(get_qi(), get_qj(), get_pj()); }
inline int pj_wrt_q2() const { return m_side_strategy.apply(get_qj(), get_qk(), get_pj()); }
inline int qj_wrt_p1() const { return m_side_strategy.apply(get_pi(), get_pj(), get_qj()); }
inline int qj_wrt_p2() const { return m_side_strategy.apply(get_pj(), get_pk(), get_qj()); }

inline int pk_wrt_p1() const { return m_side_strategy.apply(get_pi(), get_pj(), get_pk()); }
inline int pk_wrt_q1() const { return m_side_strategy.apply(get_qi(), get_qj(), get_pk()); }
inline int qk_wrt_p1() const { return m_side_strategy.apply(get_pi(), get_pj(), get_qk()); }
Expand All @@ -66,12 +73,6 @@ struct side_calculator
inline int pk_wrt_q2() const { return m_side_strategy.apply(get_qj(), get_qk(), get_pk()); }
inline int qk_wrt_p2() const { return m_side_strategy.apply(get_pj(), get_pk(), get_qk()); }

// Necessary when rescaling turns off:
inline int qj_wrt_p1() const { return m_side_strategy.apply(get_pi(), get_pj(), get_qj()); }
inline int qj_wrt_p2() const { return m_side_strategy.apply(get_pj(), get_pk(), get_qj()); }
inline int pj_wrt_q1() const { return m_side_strategy.apply(get_qi(), get_qj(), get_pj()); }
inline int pj_wrt_q2() const { return m_side_strategy.apply(get_qj(), get_qk(), get_pj()); }

inline auto const& get_pi() const { return m_range_p.at(0); }
inline auto const& get_pj() const { return m_range_p.at(1); }
inline auto const& get_pk() const { return m_range_p.at(2); }
Expand Down
14 changes: 14 additions & 0 deletions test/algorithms/overlay/multi_overlay_cases.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1580,6 +1580,20 @@ static std::string issue_1109[2] =
"MULTIPOLYGON(((0 -88,0 -115.40000152587890625,-10 -88,0 -88)))"
};

static std::string issue_1222[2] =
{
"MULTIPOLYGON(((2 4,2 2,0 2,0 4,2 4)),((6 4,4 4,2 4,2 6,0 6,0 10,6 10,6 4)))",
"MULTIPOLYGON(((4 4,4 2,2 2,2 4,4 4)),((4 8,4 6,2 6,2 8,4 8)))"
};

static std::string issue_1288[3] =
{
// Issue with differences in behaviour for multi polygon vs polygon
"MULTIPOLYGON(((-2.0 -1.5, 2.0 -1.5, 2.0 1.5, -2.0 1.5)))",
"MULTIPOLYGON(((-0.5 -1.49999999, -2.0 -0.1, -1.99999999 -1.5)))",
"POLYGON((-0.5 -1.49999999, -2.0 -0.1, -1.99999999 -1.5))"
};

static std::string bug_21155501[2] =
{
"MULTIPOLYGON(((-8.3935546875 27.449790329784214,4.9658203125 18.729501999072138,11.8212890625 23.563987128451217,9.7119140625 25.48295117535531,9.8876953125 31.728167146023935,8.3056640625 32.99023555965106,8.5693359375 37.16031654673677,-1.8896484375 35.60371874069731,-0.5712890625 32.02670629333614,-8.9208984375 29.458731185355344,-8.3935546875 27.449790329784214)))",
Expand Down
53 changes: 53 additions & 0 deletions test/algorithms/overlay/overlay_cases.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,59 @@ static std::string issue_1342_b[2] =
"POLYGON((2.000000861538488 2.944711629068049e-16,2.000000861538488 2.0000008,23.52786548447633 2.0000008,23.52786548447633 2.944711629068049e-16,2.000000861538488 2.944711629068049e-16))"
};

static std::string issue_1345_a[2] =
{
// Needs check for opposite in handle_imperfect_touch
R""""(
POLYGON((
-2.0785311235613415 -0.6304193410175202,
-2.0534946127981359 -0.6304193410175202,
-2.0534946127981359 -0.8867932112327471,
-2.3098684830133629 -0.8867932112327471,
-2.3098684830133629 -0.6554558517807265,
-2.2848319722501573 -0.6554558517807265,
-2.0785311235613415 -0.6554558517807265,
-2.0785311235613415 -0.6304193410175202
))
)"""",
R""""(
POLYGON((
-2.0785311235613420 -0.6304193410175202,
-2.0534946127981359 -0.6304193410175202,
-2.0534946127981359 -0.6554558517807265,
-2.0785311235613420 -0.6554558517807265,
-2.0785311235613420 -0.6304193410175202
))
)""""
};

static std::string issue_1345_b[2] =
{
// Needs check for opposite in handle_imperfect_touch
R""""(
POLYGON((
-6.1723606999999996 3.2834021000000000,
-6.1723606999999996 2.8006724999999992,
-5.7133718999999994 2.8006724999999992,
-5.7133718999999994 3.2834021000000000,
-5.6896310999999997 3.2834021000000000,
-5.6896310999999997 2.7769316999999996,
-6.1961014999999993 2.7769316999999996,
-6.1961014999999993 3.2834021000000000,
-6.1723606999999996 3.2834021000000000
))
)"""",
R""""(
POLYGON((
-6.1723606999999996 2.8006724999999997,
-5.7133718999999994 2.8006724999999997,
-5.7133718999999994 2.7769316999999996,
-6.1723606999999996 2.7769316999999996,
-6.1723606999999996 2.8006724999999997
))
)""""
};

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/difference/difference.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,9 @@ void test_all()
TEST_DIFFERENCE(issue_1342_a, 2, 5.762381026454777, 0, 0.0, 2);
TEST_DIFFERENCE(issue_1342_b, 2, 5.762381026454777, 1, 2.55e-14, 3);

TEST_DIFFERENCE(issue_1345_a, 1, 0.059308854, 0, 0.0, 1);
TEST_DIFFERENCE(issue_1345_b, 2, 0.024048025, 0, 0.0, 2);

TEST_DIFFERENCE(mysql_21977775, 2, 160.856568913, 2, 92.3565689126, 4);
TEST_DIFFERENCE(mysql_21965285, 1, 92.0, 1, 14.0, 1);
TEST_DIFFERENCE(mysql_23023665_1, 1, 92.0, 1, 142.5, 2);
Expand Down
10 changes: 10 additions & 0 deletions test/algorithms/set_operations/difference/difference_multi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,16 @@ void test_areal()

TEST_DIFFERENCE(issue_900, 0, 0.0, 2, 35, 2);

TEST_DIFFERENCE(issue_1222, 2, 32.0, 1, 4.0, 1);
{
// "method: t; operations: c/c;" still happening in the result
// for multi/multi
ut_settings settings;
settings.set_test_validity(BG_IF_TEST_FAILURES);
settings.validity_of_sym = BG_IF_TEST_FAILURES;
TEST_DIFFERENCE_WITH(0, 1, issue_1288, 2, 10.95, 0, 0.0, 2);
}

// Areas and #clips correspond with POSTGIS (except sym case)
test_one<Polygon, MultiPolygon, MultiPolygon>("case_101_multi",
case_101_multi[0], case_101_multi[1],
Expand Down
3 changes: 3 additions & 0 deletions test/algorithms/set_operations/intersection/intersection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,9 @@ void test_areal()
TEST_INTERSECTION(issue_1342_a, 1, -1, 43.05575);
TEST_INTERSECTION(issue_1342_b, 1, -1, 43.05575);

TEST_INTERSECTION(issue_1345_a, 1, -1, 0.00062682687);
TEST_INTERSECTION(issue_1345_b, 1, -1, 0.010896761);

test_one<Polygon, Polygon, Polygon>("buffer_mp1", buffer_mp1[0], buffer_mp1[1],
1, 31, 2.271707796);
test_one<Polygon, Polygon, Polygon>("buffer_mp2", buffer_mp2[0], buffer_mp2[1],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,9 @@ void test_areal()
TEST_INTERSECTION(issue_888_34, 7, -1, 0.0256838);
TEST_INTERSECTION(issue_888_37, 13, -1, 0.0567043);

TEST_INTERSECTION(issue_1222, 1, -1, 4.0);
TEST_INTERSECTION(issue_1288, 1, -1, 1.05);

TEST_INTERSECTION(mysql_23023665_7, 2, 11, 9.80505786783);
TEST_INTERSECTION(mysql_23023665_12, 2, 0, 11.812440191387557);
TEST_INTERSECTION(mysql_regression_1_65_2017_08_31, 2, -1, 29.9022122);
Expand Down
6 changes: 6 additions & 0 deletions test/algorithms/set_operations/union/union.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,12 @@ void test_areal()
TEST_UNION(issue_1342_b, 1, 0, -1, 48.81812749462214);
TEST_UNION_REV(issue_1342_b, 1, 0, -1, 48.81812749462214);

TEST_UNION(issue_1345_a, 1, 0, -1, 0.059935681);
TEST_UNION_REV(issue_1345_a, 1, 0, -1, 0.059935681);

TEST_UNION(issue_1345_b, 1, 0, -1, 0.034944786);
TEST_UNION_REV(issue_1345_b, 1, 0, -1, 0.034944786);

TEST_UNION(geos_1, 1, 0, -1, expectation_limits(3458.0, 3461.3203125));
TEST_UNION(geos_2, 1, 0, -1, expectation_limits(349.0625, 350.55102539));
TEST_UNION(geos_3, 1, 0, -1, 29391548.4998779);
Expand Down
3 changes: 3 additions & 0 deletions test/algorithms/set_operations/union/union_multi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,9 @@ void test_areal()

TEST_UNION(issue_1109, 2, 0, -1, 3946.5);

TEST_UNION(issue_1222, 1, 0, -1, 40.0);
TEST_UNION(issue_1288, 1, 0, -1, 12.0);

// One or two polygons, the ideal case is 1
TEST_UNION(mail_2019_01_21_johan, count_set(1, 2), 0, -1, 0.00058896);

Expand Down

0 comments on commit a9c3a24

Please sign in to comment.