Можно ли использовать boost :: geometry, чтобы проверить, пересекаются ли два линейных сегмента (каждый из которых задан двумя точками в 2D)? Если это возможно, позволяет ли boost :: geometry проверять также особые случаи, например, что только одна точка (численно) находится на другой строке или что обе линии равны?
Использование усиленной геометрии для проверки пересечения двух линий
Ответы (4)
Если вы говорите конкретно о Boost.Geometry API, то это, конечно, возможно.
Ваш код должен выглядеть примерно так
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/algorithms/intersection.hpp>
typedef boost::geometry::model::segment<Point> Segment;
Segment AB( Point(x1,y1), Point(x2,y2) );
Segment CD; //similar code
bool result = boost::geometry::intersects(AB, CD);
Если вам нужны точки пересечения:
std::vector<Point> output;
boost::geometry::intersection(AB, CD, output);
Теперь на выходе будет 0, 1 или 2 балла, в зависимости от местоположения.
Конечно, ваш тип Point должен "соответствовать" концепциям Boost.Geometry. Следующий код сделает QPointF совместимым:
#include <boost/geometry/geometries/register/point.hpp>
BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET(QPointF, qreal, cs::cartesian, x, y, setX, setY);
Вы спрашиваете, пересекаются ли две линии. Две линии всегда будут пересекаться, если они не параллельны.
Следующий алгоритм поможет вам вычислить, пересекает ли сегмент линию. Он работает следующим образом: имея координаты трех точек, вы вычисляете определитель
x1 y1 1
x2 y2 1
x3 y3 1
Где (x1; y1) и (x2; y2) - это точка, представляющая вашу линию, а (x3; y3) - вашу 3-ю точку (одну из крайностей вашего сегмента). Если определитель положительный, то (x3; y3) находится справа от вектора, ориентированного от (x1; y1) к (x2; y2), если он отрицательный, то вправо. И если определитель равен 0, то точка находится на прямой.
Что вам нужно сделать, так это применить этот алгоритм дважды, один раз для одного конца сегмента и один раз для другого, если произведение детерминант отрицательное, оно пересекается, если нет, это не так.
Вы можете пойти дальше и вычислить, пересекаются ли два сегмента. Все, что вам нужно сделать, это применить ту же идею дважды, только во второй раз ваши (x1; y1) и (x2; y2) будут значениями, которые вы использовали для (x3; y3), а ваш новый (x3; y3) ваш старые (x1; y1) и (x2; y2).
Я изучил этот алгоритм под «алгоритмом Сарруса», так что, возможно, поиск в Google может дать лучшее объяснение.
пример для новичков без использования BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET
namespace bg = boost::geometry;
typedef bg::model::point<double, 2, bg::cs::cartesian> point_t;
typedef bg::model::segment<point_t> segment_t;
segment_t seg1(point_t(0.0, 0.0), point_t(5.0, 5.0));
segment_t seg2(point_t(10.0, 5.0), point_t(5.0, 0.0));
bool result = boost::geometry::intersects(seg1, seg2);
Вы можете попробовать использовать алгоритм пересечения. Если линии пересекаются, вывод будет непустым.