mirror of
https://github.com/boostorg/geometry.git
synced 2025-05-11 21:44:04 +00:00
[intersection] check for disjoint-by-range.
Without it, in FP calculations, for nearly collinear segments, it might happen that an intersection is calculated even if the ranges are farther apart from each other
This commit is contained in:
parent
cc0643941a
commit
761170b0b4
@ -371,6 +371,38 @@ struct cartesian_segments
|
||||
return unified<ratio_type>(sinfo, p, q, policy, modelled_range_p, modelled_range_q);
|
||||
}
|
||||
|
||||
//! Returns true if two segments do not overlap.
|
||||
//! If not, then no further calculations need to be done.
|
||||
template
|
||||
<
|
||||
std::size_t Dimension,
|
||||
typename CoordinateType,
|
||||
typename PointP,
|
||||
typename PointQ
|
||||
>
|
||||
static inline bool disjoint_by_range(PointP const& p1, PointP const& p2,
|
||||
PointQ const& q1, PointQ const& q2)
|
||||
{
|
||||
CoordinateType minp = get<Dimension>(p1);
|
||||
CoordinateType maxp = get<Dimension>(p2);
|
||||
CoordinateType minq = get<Dimension>(q1);
|
||||
CoordinateType maxq = get<Dimension>(q2);
|
||||
if (minp > maxp)
|
||||
{
|
||||
std::swap(minp, maxp);
|
||||
}
|
||||
if (minq > maxq)
|
||||
{
|
||||
std::swap(minq, maxq);
|
||||
}
|
||||
|
||||
// In this case, max(p) < min(q)
|
||||
// P Q
|
||||
// <-------> <------->
|
||||
// (and the space in between is not extremely small)
|
||||
return math::smaller(maxp, minq) || math::smaller(maxq, minp);
|
||||
}
|
||||
|
||||
// Implementation for either rescaled or non rescaled versions.
|
||||
template
|
||||
<
|
||||
@ -413,6 +445,12 @@ struct cartesian_segments
|
||||
;
|
||||
}
|
||||
|
||||
if (disjoint_by_range<0, coordinate_type>(p1, p2, q1, q2)
|
||||
|| disjoint_by_range<1, coordinate_type>(p1, p2, q1, q2))
|
||||
{
|
||||
return Policy::disjoint();
|
||||
}
|
||||
|
||||
side_info sides;
|
||||
sides.set<0>(side_strategy_type::apply(q1, q2, p1),
|
||||
side_strategy_type::apply(q1, q2, p2));
|
||||
@ -467,8 +505,8 @@ struct cartesian_segments
|
||||
{
|
||||
// If this is the case, no rescaling is done for FP precision.
|
||||
// We set it to collinear, but it indicates a robustness issue.
|
||||
sides.set<0>(0,0);
|
||||
sides.set<1>(0,0);
|
||||
sides.set<0>(0, 0);
|
||||
sides.set<1>(0, 0);
|
||||
collinear = true;
|
||||
}
|
||||
else
|
||||
|
@ -483,8 +483,8 @@ int test_main(int, char* [])
|
||||
test_aimes<bg::model::point<default_test_type, 2, bg::cs::cartesian> >();
|
||||
|
||||
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
|
||||
// Non-rescaled reports 22 failures (failures in validity only)
|
||||
BoostGeometryWriteExpectedFailures(BG_NO_FAILURES, 22);
|
||||
// Non-rescaled reports failures, but in validity only
|
||||
BoostGeometryWriteExpectedFailures(BG_NO_FAILURES, 4);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -281,9 +281,7 @@ void test_areal()
|
||||
TEST_UNION(case_precision_17, 1, 1, -1, 73.0);
|
||||
TEST_UNION(case_precision_18, 1, 1, -1, 73.0);
|
||||
TEST_UNION(case_precision_19, 1, 1, -1, 73.0);
|
||||
#if ! defined(BOOST_GEOMETRY_EXCLUDE)
|
||||
TEST_UNION(case_precision_20, 1, 0, -1, 22.0);
|
||||
#endif
|
||||
TEST_UNION(case_precision_21, 1, 0, -1, 22.0);
|
||||
TEST_UNION(case_precision_22, 1, 1, -1, 73.0);
|
||||
TEST_UNION(case_precision_23, 1, 1, -1, 73.0);
|
||||
@ -310,9 +308,7 @@ void test_areal()
|
||||
TEST_UNION_REV(case_precision_17, 1, 1, -1, 73.0);
|
||||
TEST_UNION_REV(case_precision_18, 1, 1, -1, 73.0);
|
||||
TEST_UNION_REV(case_precision_19, 1, 1, -1, 73.0);
|
||||
#if ! defined(BOOST_GEOMETRY_EXCLUDE)
|
||||
TEST_UNION_REV(case_precision_20, 1, 0, -1, 22.0);
|
||||
#endif
|
||||
TEST_UNION_REV(case_precision_21, 1, 0, -1, 22.0);
|
||||
TEST_UNION_REV(case_precision_22, 1, 1, -1, 73.0);
|
||||
TEST_UNION_REV(case_precision_23, 1, 1, -1, 73.0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user