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

У меня есть три вектора 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 * пи к углу (V2) или что-то в этом роде, но я пробовал такие вещи, и это не работает.

Я программирую в MATLAB.

РЕДАКТИРОВАТЬ 1: это в 2D.

Ответы [ 5 ]

8 голосов
/ 29 марта 2009

Поскольку вы делаете это в 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 сохраняется в первом элементе crossProds . Это значение будет больше или равно нулю, если угол против часовой стрелки между V1 и V2 составляет от 0 до 180 градусов включительно. В этом случае, когда V3 находится между V1 и V2 в направлении против часовой стрелки, тогда перекрестные произведения (V1, V3) и (V3, V2) также больше или равно нулю. Это объясняет первую логическую проверку:

all(crossProds >= 0)

Если угол против часовой стрелки между V1 и V2 больше 180 градусов, то перекрестное произведение этих двух векторов будет меньше нуля. В этом случае, когда V3 находится между V1 и V2 в направлении по часовой стрелке , тогда перекрестные произведения (V1, V3 ) и (V3, V2) также меньше нуля. Следовательно, если эти перекрестные произведения равны , а не и меньше нуля, тогда V3 должно быть между V1 и V2 в счетчике - по часовой стрелке направление. Это объясняет следующие две логические проверки:

(crossProds(1) < 0) && ~all(crossProds(2:3) < 0)

Приведенные выше логические проверки должны охватывать все возможные ситуации. Операторы || и && являются операторами короткого замыкания в MATLAB: они пропустят вторые операторы, если в них нет необходимости. Например, если первый оператор в операторе «ИЛИ» имеет значение «истина», нет смысла проверять второй оператор в операторе «ИЛИ», поскольку для истинного результата требуется только один аргумент в операторе «ИЛИ».

3 голосов
/ 29 марта 2009

Рассчитать угол (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.

2 голосов
/ 29 марта 2009

V1 - красная сельдь. Вы просто запутаете себя, думая о 3-х углах одновременно.

  1. Повернуть все по часовой стрелке на угол (V1)
  2. Нормализовать оставшиеся два угла до [0,360)

Теперь вопрос состоит в том, чтобы просто сравнить норму (angle (V2) -angle (V1)) и norm (angle (V3) -angle (V1)).

0 голосов
/ 06 декабря 2014

Несколько более простой метод для большинства других языков программирования.

Если V1, V2 и V3 заданы векторы, и нам нужно решить, что погода V3 находится между V1 и V2, и Ri = atan2 (Vi) (которая возвращает угол в радианах от -pi до pi):

* По часовой стрелке 1007 *

R1 -= R3;
R2 -= R3;

if (R1 < 0) R1 += 2 * PI;
if (R2 <= 0) R2 += 2 * PI;

return (r1 < r2);

Для против часовой стрелки , просто поменяйте местами R1 и R2.

0 голосов
/ 29 марта 2009

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

  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");
  }
}
...