Как определить, находится ли V3 между V1 и V2, когда мы переходим от V1 к V2 против часовой стрелки?

StackOverflow https://stackoverflow.com/questions/693806

  •  22-08-2019
  •  | 
  •  

Вопрос

У меня есть три вектора 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 — отвлекающий маневр.Вы просто запутаетесь, думая о трех углах одновременно.

  1. Поверните все по часовой стрелке на угол (V1).
  2. Нормализуйте оставшиеся два угла до [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.

Чтобы проверить это условие, вам придется рассчитать намотку двух треугольников:

  1. Треугольник, образованный V1, началом координат и V3.Этот треугольник должен быть против часовой стрелки.

  2. Треугольник, образованный 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");
  }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top