Этот тест можно возобновить с помощью теста в одну строку. Даже если хороший ответ уже опубликован, позвольте мне представить мой.
Предположим, что первая дуга равна A:(a0,a1)
, а вторая - B:(b0,b1)
. Я предполагаю, что значения углов уникальны, то есть в диапазоне [0°,360°[
, [0,2*pi[
или ]-pi,pi]
(сам диапазон не важен, мы увидим, почему). Я возьму диапазон ]-pi,pi]
как диапазон всех углов.
Чтобы подробно объяснить подход, я спроектировал тест для пересечения интервалов в R . Таким образом, мы имеем здесь a1>=a0
и b1>=b0
. Следуя тем же обозначениям для реальных интервалов, я вычисляю следующее количество:
S = (b0-a1)*(b1-a0)
Если S>0
, два сегмента не перекрываются, иначе их пересечение не является пустым. Действительно легко понять, почему эта формула работает. Если S>0
, у нас есть два случая:
b0>a1
подразумевает, что b1>a0
, поэтому пересечения нет: a0=<a1<b0=<b1
.
b1<a0
означает, что b0<b1
, поэтому пересечения нет: b0=<b1<a0=<a1
.
Итак, у нас есть единственное математическое выражение, которое хорошо работает в R .
Теперь я расширяю его по круговой области ]-pi,pi]
. Гипотезы a0<a1
и b0<b1
больше не верны: например, дуга может перейти от pi/2
до -pi/2
, это левый полукруг.
Поэтому я вычисляю следующее количество:
S = (b0-a1)*(b1-a0)*H(a1-a0)*H(b1-b0)
где H - шаговая функция, определяемая как H(x)=-1 if x<0 else H(x)=1
Опять же, если S>0
, между дугами A и B нет пересечения. Есть 16 случаев, которые я хочу исследовать, и я не буду здесь это делать ... но их легко сделать на листе :) .
Замечание : Значение S не важно, только знаки терминов. Прелесть этой формулы в том, что она не зависит от выбранного вами диапазона. Также вы можете переписать его как логический тест:
T := (b0>a1)^(b1>a0)^(a1>=a0)^(b1>=b0)
где ^
является логическим XOR
EDIT
Увы, в этой формуле есть очевидный случай отказа ... Поэтому я исправляю это здесь. Я понимаю, что здесь есть случай, когда пересечение двух дуг может быть двумя дугами, например, когда -pi<a0<b1<b0<a1<pi
.
Чтобы исправить это, нужно ввести второй тест: если сумма углов больше 2*pi
, дуги точно пересекаются.
Таким образом, формула оказывается:
T := (a1+b1-a0-b0+2*pi*((b1<b0)+(a1<a0))<2*pi) | ((b0>a1)^(b1>a0)^(a1>=a0)^(b1>=b0))
Хорошо, это менее элегантно, чем предыдущий, но теперь это правильно.