Как определить, находится ли V3 между V1 и V2, когда мы переходим от V1 к V2 против часовой стрелки?
Вопрос
У меня есть три вектора V1, V2 и V3.Их исходные точки находятся в начале координат осей.Как я могу определить, находится ли V3 между V1 и V2, когда я перемещаюсь против часовой стрелки от V1 к V2?
альтернативный текст http://www.freeimagehosting.net/uploads/1448ea8896.jpg
Это невозможно сделать, получив их углы и вычислив такие условия (псевдокод):
if angle(V3) > angle(V1) && angle(V3) < angle(V2)
printf("V3 is between V1 and V2")
else
printf("out of the interval")
Чтобы увидеть его недостаток, предположим, что angle
функция дает углы в диапазоне [-pi pi].Итак, если угол(V1) = 120 (в градусах), угол(V2) = -130 и угол(V3) = 150, то ответ (согласно приведенному выше коду) — «вне интервала», хотя если вы двигаетесь против часовой стрелки от V1 до V2, он находится между ними.
Вы можете предложить добавить 2*pi к angular(V2) или что-то в этом роде, но я пробовал такие вещи, и это не работает.
Я программирую в MATLAB.
РЕДАКТИРОВАТЬ 1:это в 2D.
Решение
Поскольку вы делаете это в MATLAB, вот одно решение, которое должно работать:
crossProds = [V1(1)*V2(2)-V1(2)*V2(1) ...
V1(1)*V3(2)-V1(2)*V3(1) ...
V3(1)*V2(2)-V3(2)*V2(1)];
if (all(crossProds >= 0) || ...
(crossProds(1) < 0) && ~all(crossProds(2:3) < 0)),
disp("V3 is between V1 and V2");
else
disp("out of the interval");
end
ОБЪЯСНЕНИЕ:
Перекрестное произведение двумерных векторов V1 и V2 хранится в первом элементе кроссПроды.Это значение будет больше или равно нулю, если угол против часовой стрелки между V1 и V2 находится в диапазоне от 0 до 180 градусов включительно.В этом случае, когда V3 между V1 и V2 против часовой стрелки, то векторные произведения (В1,В3) и (В3,В2) также больше или равны нулю.Это объясняет первую логическую проверку:
all(crossProds >= 0)
Если угол против часовой стрелки между V1 и V2 больше 180 градусов, то векторное произведение этих двух векторов будет меньше нуля.В этом случае, когда V3 между V1 и V2 в по часовой стрелке направление, то векторные произведения (В1,В3) и (В3,В2) также меньше нуля.Следовательно, если эти перекрестные произведения нет оба меньше нуля, тогда V3 должно быть между V1 и V2 в против часовой направление.Это объясняет следующие две логические проверки:
(crossProds(1) < 0) && ~all(crossProds(2:3) < 0)
Вышеуказанные логические проверки должны охватывать все возможные ситуации.Операторы || и && есть операторы короткого замыкания в МАТЛАБ:они пропустят вторые операторы, если они не нужны.Например, если первое утверждение в OR истинно, нет смысла проверять второе утверждение, поскольку только один аргумент в OR должен быть истинным, чтобы результат был истинным.
Другие советы
Вычислите угол (V1), угол (V2) и угол (v3) (a1, a2, a3).
Измените a2 и a3 (при необходимости добавьте 2*pi), чтобы
a1 <= a2 < a1 + 2*pi
a1 <= a3 < a1 + 2*pi
Теперь вам просто нужно сравнить a2 и a3.V3 находится между V1 и V2, в результате чего a3 уступает a2.
V1 — отвлекающий маневр.Вы просто запутаетесь, думая о трех углах одновременно.
- Поверните все по часовой стрелке на угол (V1).
- Нормализуйте оставшиеся два угла до [0,360)
Теперь вопрос состоит в том, чтобы просто сравнить норму(угол(V2)-угол(V1)) и норму(угол(V3)-угол(V1)).
Несколько более простой метод для большинства других языков программирования.
Если V1, V2 и V3 заданы векторами, и нам нужно решить, погода V3 находится между V1 и V2, и Ri = atan2(Vi) (который возвращает угол в радианах от -pi до pi):
по часовой стрелке:
R1 -= R3;
R2 -= R3;
if (R1 < 0) R1 += 2 * PI;
if (R2 <= 0) R2 += 2 * PI;
return (r1 < r2);
Для против часовой, просто поменяйте местами R1 и R2.
Чтобы проверить это условие, вам придется рассчитать намотку двух треугольников:
Треугольник, образованный V1, началом координат и V3.Этот треугольник должен быть против часовой стрелки.
Треугольник, образованный V3, началом координат и V2.Этот треугольник также должен быть против часовой стрелки.
Чтобы проверить намотку треугольника, достаточно проверить знак двумерного векторного произведения вершин.
Тест выглядит так (извините — C-код):
int IsBetween (vector v1, vector v2, vector v3)
{
float winding1 = (v1.x * v3.y - v1.y * v3.x);
float winding2 = (v3.x * v2.y - v3.y * v2.x);
// this test could be exactly the wrong way around. This depends
// on how you define your coordinate system (e.g. is Y going up or down?)
if ((winding1 <0) && (winding2 < 0))
{
printf ("V3 is between them\n");
}
else
{
printf ("it's not\n");
}
}