Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add condition to handle_imperfect_touch #1346

Merged
merged 4 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/release_notes.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
* [@https://github.com/boostorg/geometry/issues/1226 1226] [@https://github.com/boostorg/geometry/issues/1326 1326] Fix extra round on ring
* [@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/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.
vissarion marked this conversation as resolved.
Show resolved Hide resolved
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())
vissarion marked this conversation as resolved.
Show resolved Hide resolved
&& 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:
vissarion marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -1231,6 +1231,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""""(
vissarion marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -647,6 +647,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 @@ -211,6 +211,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 @@ -315,6 +315,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 @@ -493,6 +493,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
Loading