Skip to content

Commit 761170b

Browse files
committed
[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
1 parent cc06439 commit 761170b

3 files changed

Lines changed: 42 additions & 8 deletions

File tree

include/boost/geometry/strategies/cartesian/intersection.hpp

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,38 @@ struct cartesian_segments
371371
return unified<ratio_type>(sinfo, p, q, policy, modelled_range_p, modelled_range_q);
372372
}
373373

374+
//! Returns true if two segments do not overlap.
375+
//! If not, then no further calculations need to be done.
376+
template
377+
<
378+
std::size_t Dimension,
379+
typename CoordinateType,
380+
typename PointP,
381+
typename PointQ
382+
>
383+
static inline bool disjoint_by_range(PointP const& p1, PointP const& p2,
384+
PointQ const& q1, PointQ const& q2)
385+
{
386+
CoordinateType minp = get<Dimension>(p1);
387+
CoordinateType maxp = get<Dimension>(p2);
388+
CoordinateType minq = get<Dimension>(q1);
389+
CoordinateType maxq = get<Dimension>(q2);
390+
if (minp > maxp)
391+
{
392+
std::swap(minp, maxp);
393+
}
394+
if (minq > maxq)
395+
{
396+
std::swap(minq, maxq);
397+
}
398+
399+
// In this case, max(p) < min(q)
400+
// P Q
401+
// <-------> <------->
402+
// (and the space in between is not extremely small)
403+
return math::smaller(maxp, minq) || math::smaller(maxq, minp);
404+
}
405+
374406
// Implementation for either rescaled or non rescaled versions.
375407
template
376408
<
@@ -413,6 +445,12 @@ struct cartesian_segments
413445
;
414446
}
415447

448+
if (disjoint_by_range<0, coordinate_type>(p1, p2, q1, q2)
449+
|| disjoint_by_range<1, coordinate_type>(p1, p2, q1, q2))
450+
{
451+
return Policy::disjoint();
452+
}
453+
416454
side_info sides;
417455
sides.set<0>(side_strategy_type::apply(q1, q2, p1),
418456
side_strategy_type::apply(q1, q2, p2));
@@ -467,8 +505,8 @@ struct cartesian_segments
467505
{
468506
// If this is the case, no rescaling is done for FP precision.
469507
// We set it to collinear, but it indicates a robustness issue.
470-
sides.set<0>(0,0);
471-
sides.set<1>(0,0);
508+
sides.set<0>(0, 0);
509+
sides.set<1>(0, 0);
472510
collinear = true;
473511
}
474512
else

test/algorithms/buffer/buffer_linestring_aimes.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -483,8 +483,8 @@ int test_main(int, char* [])
483483
test_aimes<bg::model::point<default_test_type, 2, bg::cs::cartesian> >();
484484

485485
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
486-
// Non-rescaled reports 22 failures (failures in validity only)
487-
BoostGeometryWriteExpectedFailures(BG_NO_FAILURES, 22);
486+
// Non-rescaled reports failures, but in validity only
487+
BoostGeometryWriteExpectedFailures(BG_NO_FAILURES, 4);
488488
#endif
489489

490490
return 0;

test/algorithms/set_operations/union/union.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,7 @@ void test_areal()
281281
TEST_UNION(case_precision_17, 1, 1, -1, 73.0);
282282
TEST_UNION(case_precision_18, 1, 1, -1, 73.0);
283283
TEST_UNION(case_precision_19, 1, 1, -1, 73.0);
284-
#if ! defined(BOOST_GEOMETRY_EXCLUDE)
285284
TEST_UNION(case_precision_20, 1, 0, -1, 22.0);
286-
#endif
287285
TEST_UNION(case_precision_21, 1, 0, -1, 22.0);
288286
TEST_UNION(case_precision_22, 1, 1, -1, 73.0);
289287
TEST_UNION(case_precision_23, 1, 1, -1, 73.0);
@@ -310,9 +308,7 @@ void test_areal()
310308
TEST_UNION_REV(case_precision_17, 1, 1, -1, 73.0);
311309
TEST_UNION_REV(case_precision_18, 1, 1, -1, 73.0);
312310
TEST_UNION_REV(case_precision_19, 1, 1, -1, 73.0);
313-
#if ! defined(BOOST_GEOMETRY_EXCLUDE)
314311
TEST_UNION_REV(case_precision_20, 1, 0, -1, 22.0);
315-
#endif
316312
TEST_UNION_REV(case_precision_21, 1, 0, -1, 22.0);
317313
TEST_UNION_REV(case_precision_22, 1, 1, -1, 73.0);
318314
TEST_UNION_REV(case_precision_23, 1, 1, -1, 73.0);

0 commit comments

Comments
 (0)