handle cases where multiple endpoints are colinear as non-intersecting for line segments (because otherwise it cannot be used to check if intersection() has undefined behaviour, as there will be an infinite number of intersections)

This commit is contained in:
Patrick Brosi 2018-08-17 15:07:20 +02:00
parent 95ce5ba03d
commit 69a360c48f
2 changed files with 10 additions and 4 deletions

View file

@ -398,9 +398,13 @@ inline bool contains(const std::vector<GeometryA<T>>& multigeo,
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline bool intersects(const LineSegment<T>& ls1, const LineSegment<T>& ls2) { inline bool intersects(const LineSegment<T>& ls1, const LineSegment<T>& ls2) {
// two line segments intersect of there is a single, well-defined intersection
// point between them. If more than 1 endpoint is colinear with any line,
// the segments have infinite intersections. We handle this case as non-
// intersecting
return intersects(getBoundingBox(ls1), getBoundingBox(ls2)) && return intersects(getBoundingBox(ls1), getBoundingBox(ls2)) &&
(contains(ls1.first, ls2) || contains(ls1.second, ls2) || (((contains(ls1.first, ls2) ^ contains(ls1.second, ls2)) ^
contains(ls2.first, ls1) || contains(ls2.second, ls1) || (contains(ls2.first, ls1) ^ contains(ls2.second, ls1))) ||
(((crossProd(ls1.first, ls2) < 0) ^ (((crossProd(ls1.first, ls2) < 0) ^
(crossProd(ls1.second, ls2) < 0)) && (crossProd(ls1.second, ls2) < 0)) &&
((crossProd(ls2.first, ls1) < 0) ^ ((crossProd(ls2.first, ls1) < 0) ^

View file

@ -972,12 +972,14 @@ CASE("geometry") {
EXPECT(geo::intersects(lsa, lsb)); EXPECT(geo::intersects(lsa, lsb));
EXPECT(geo::intersects(lsa, lsa)); EXPECT(!geo::intersects(lsa, lsa));
EXPECT(geo::intersects(lsb, lsb)); EXPECT(!geo::intersects(lsb, lsb));
EXPECT(!geo::intersects(lsa, lsc)); EXPECT(!geo::intersects(lsa, lsc));
EXPECT(!geo::intersects(geo::Point<double>(871569.2, 6104550.4), geo::Point<double>(871581.2, 6104536), geo::Point<double>(871580.3, 6104541.3), geo::Point<double>(871625.7, 6104510.1))); EXPECT(!geo::intersects(geo::Point<double>(871569.2, 6104550.4), geo::Point<double>(871581.2, 6104536), geo::Point<double>(871580.3, 6104541.3), geo::Point<double>(871625.7, 6104510.1)));
EXPECT(!geo::intersects(geo::Point<double>(0, 0), geo::Point<double>(1, 1), geo::Point<double>(0.5, 0.5), geo::Point<double>(1.5, 1.5)));
geo::Line<double> l{geo::Point<double>(1, 1), geo::Point<double>(2, 2), geo::Point<double>(2, 4)}; geo::Line<double> l{geo::Point<double>(1, 1), geo::Point<double>(2, 2), geo::Point<double>(2, 4)};
EXPECT(!geo::contains(geo::Point<double>(1, 2), l)); EXPECT(!geo::contains(geo::Point<double>(1, 2), l));
EXPECT(geo::contains(geo::Point<double>(2, 2), l)); EXPECT(geo::contains(geo::Point<double>(2, 2), l));