fix: add condition to handle_as_touch

Fixes #1288
This commit is contained in:
Barend Gehrels 2024-11-24 10:32:55 +01:00 committed by Vissarion Fisikopoulos
parent 7546959690
commit 9c4d7529b1
5 changed files with 52 additions and 4 deletions

View File

@ -343,10 +343,14 @@ 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)
{
@ -354,6 +358,20 @@ struct touch_interior : public base_turn_handler
}
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)
@ -1461,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;
}
@ -1475,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;
}

View File

@ -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)))",

View File

@ -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],

View File

@ -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);

View File

@ -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);