/ Мне нужно определить, пересекается ли пара линий, определенных несколькими отрезками, например, линия, определенная (0,0), (1,2), (3,1)
и еще один (0,2), (2,-1), (4,1)
,
Мне не нужно определять, где находится пересечение, но мне нужен эффективный метод, потому что я могу иметь очень большое количество ребер. Я использую приведенный ниже код, чтобы определить, пересекаются ли два сегмента, но это неэффективно для линии большей длины. Кроме того, линии являются ребрами графа, и они ограничены известной максимальной длиной.
static bool IsOnSegment(float xi, float yi, float xj, float yj,
float xk, float yk) {
return (xi <= xk || xj <= xk) && (xk <= xi || xk <= xj) &&
(yi <= yk || yj <= yk) && (yk <= yi || yk <= yj);
}
static char ComputeDirection(float xi, float yi, float xj, float yj,
float xk, float yk) {
float a = (xk - xi) * (yj - yi);
float b = (xj - xi) * (yk - yi);
return a < b ? -1 : a > b ? 1 : 0;
}
// Do line segments (x1, y1)--(x2, y2) and (x3, y3)--(x4, y4) intersect? /
bool DoLineSegmentsIntersect(float x1, float y1, float x2, float y2,
float x3, float y3, float x4, float y4) {
char d1 = ComputeDirection(x3, y3, x4, y4, x1, y1);
char d2 = ComputeDirection(x3, y3, x4, y4, x2, y2);
char d3 = ComputeDirection(x1, y1, x2, y2, x3, y3);
char d4 = ComputeDirection(x1, y1, x2, y2, x4, y4);
return (((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) &&
((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0))) ||
(d1 == 0 && IsOnSegment(x3, y3, x4, y4, x1, y1)) ||
(d2 == 0 && IsOnSegment(x3, y3, x4, y4, x2, y2)) ||
(d3 == 0 && IsOnSegment(x1, y1, x2, y2, x3, y3)) ||
(d4 == 0 && IsOnSegment(x1, y1, x2, y2, x4, y4));
}
Вы бы немного изменились Алгоритм Бентли-Оттмана который вычисляет все k
пересечения в O((n+k)logn)
время и O(n+k)
пространство.
Предлагаемая модификация — алгоритм Бентли-Оттмана получает множество сегментов и сообщает обо всех пересечениях. Вы бы разбили свои сегментированные линии на наборы сегментов и дали бы этот набор в качестве входных данных для алгоритма. Когда найдено какое-либо пересечение, просто проверьте, принадлежат ли пересекающиеся сегменты одной сегментированной линии или нет. Если нет, значит, вы только что нашли пересечение сегментированных линий.
Обратите внимание, что в худшем случае сложность будет O(n^2)
когда количество пересечений очень велико. Худший случай для вас — две сегментированные линии, которые выглядят как переплетающиеся змеи. Помните, что есть хотя бы O(N)
псевдо-пересечения — каждая сегментированная линия будет производить O(length)
псевдо-пересечения и так как длина1 + длина2 = N, где N — общее количество сегментов, существует O (N) псевдо-пересечений. Псевдо-пересечение — это такое пересечение, которое будет обнаружено алгоритмом Бентли-Оттмана, но не должно приниматься во внимание.
Советы по реализации — Алгоритм Бентли-Оттмана, основанный на алгоритме линии развертки, который основан на точках сортировки — парах (X, Y). Теперь вам нужно просто отсортировать тройки (X, Y, сегментыLineID). В вашем случае все тройки будут (X, Y, 1) или (X, Y, 2)
Других решений пока нет …