从V1逆时针走到V2时,如何判断V3是否在V1和V2之间?

发布于 2024-07-15 09:29:45 字数 714 浏览 8 评论 0原文

我有三个向量 V1、V2 和 V3。 它们的原点位于轴的原点上。 当我从V1逆时针移动到V2时,如何判断V3是否在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 添加到角度(V2)或类似的东西,但我已经尝试过这样的事情,但它不起作用。

我正在使用 MATLAB 进行编程。

编辑1:它是二维的。

I have three vectors V1, V2, and V3. Their origin points are on the axes' origin. How could I determine whether V3 is between V1 and V2 when I move around counterclockwise from V1 to V2?

alt text http://www.freeimagehosting.net/uploads/1448ea8896.jpg

It can't be done with obtaining their angles and evaluating these kind of conditions (pseudo-code):

if angle(V3) > angle(V1) && angle(V3) < angle(V2) 
   printf("V3 is between V1 and V2") 
else 
   printf("out of the interval")

To see its defect, suppose that the angle function gives angles in the range of [-pi pi]. So, if angle(V1) = 120 (in degree), angle(V2) = -130 and angle(V3) = 150 then the answer (according to the above code) is "out of the interval" although if you move around counterclockwise from V1 to V2, it is between them.

You may suggest adding 2*pi to angle(V2) or something like that, but I've tried such things and it doesn't work.

I'm programming in MATLAB.

EDIT 1 : it is in 2D.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

街角卖回忆 2024-07-22 09:29:45

由于您是在 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

说明:

二维向量 V1V2 之间的叉积> 存储在 crossProds 的第一个元素中。 如果 V1V2 之间的逆时针角度在 0 到 180 度(含)之间,则该值将大于或等于 0。 在这种情况下,当V3逆时针方向位于V1V2之间时,叉积(V1,V3) (V3,V2) 也大于或等于零。 这解释了第一个逻辑检查:

all(crossProds >= 0)

如果V1V2之间的逆时针角度大于180度,那么这两个向量的叉积将小于零。 在这种情况下,当V3顺时针方向上位于V1V2之间时,叉积 (V1,V3)(V3,V2) 也小于零。 因此,如果这些叉积都小于零,则 V3 必须位于 V1V2 之间逆时针方向。 这解释了接下来的两个逻辑检查:

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

上述逻辑检查应该涵盖所有可能的情况。 运算符 || 和&& 是 MATLAB 中的短路运算符:它们将跳过第二个声明(如果没有必要)。 例如,如果 OR 中的第一个语句为 true,则没有理由检查第二个语句,因为 OR 中只需要一个参数为 true 即可使结果为 true。

Since you are doing this in MATLAB, here is one solution that should work:

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

EXPLANATION:

The cross product between the 2-D vectors V1 and V2 is stored in the first element of crossProds. This value will be greater than or equal to zero if the counter-clockwise angle between V1 and V2 is between 0 and 180 degrees, inclusive. In this case, when V3 is between V1 and V2 in the counter-clockwise direction then the cross products (V1,V3) and (V3,V2) are also greater than or equal to zero. This explains the first logical check:

all(crossProds >= 0)

If the counter-clockwise angle between V1 and V2 is greater than 180 degrees, then the cross product of these two vectors will be less than zero. In this case, when V3 is between V1 and V2 in the clockwise direction then the cross products (V1,V3) and (V3,V2) are also less than zero. Therefore, if these cross products are not both less than zero then V3 must be between V1 and V2 in the counter-clockwise direction. This explains the next two logical checks:

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

The above logical checks should cover all possible situations. The operators || and && are short circuit operators in MATLAB: they will skip the second statements if they are not necessary. For example, if the first statement in an OR is true, there is no reason to check the second statement since only one argument in an OR needs to be true for the result to be true.

枉心 2024-07-22 09:29:45

计算角度(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。

Calculate angle(V1), angle(V2) and angle(v3) (a1, a2, a3).

Modify a2 and a3 (add 2*pi if needed) so that

a1 <= a2 < a1 + 2*pi
a1 <= a3 < a1 + 2*pi

Now you simply have to compare a2 and a3.
V3 is between V1 and V2 is resulting a3 is inferior to a2.

莫多说 2024-07-22 09:29:45

V1 是一个转移注意力的话题。 同时思考 3 个角度会让你感到困惑。

  1. 将所有内容顺时针旋转角度(V1)
  2. 将剩余两个角度标准化为[0,360)

现在问题只是比较norm(角度(V2)-角度(V1))和norm(角度(V3)-角度(V1))。

V1 is a red herring. You're just going to confuse yourself thinking about 3 angles at once.

  1. Rotate everything clockwise by angle(V1)
  2. Normalize the remaining two angles to [0,360)

Now the question is simply to compare norm(angle(V2)-angle(V1)) and norm(angle(V3)-angle(V1)).

烟燃烟灭 2024-07-22 09:29:45

对于大多数其他编程语言来说,这是更简单的方法。

如果给定向量 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即可。

Somewhat easier method for most other programing languages.

If V1, V2 and V3 are given vectors, and we need to decide weather V3 is between V1 and V2, and Ri = atan2(Vi) (which returns an angle in radians from -pi to pi):

Clockwise:

R1 -= R3;
R2 -= R3;

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

return (r1 < r2);

For counterclockwise, just swap R1 and R2.

咽泪装欢 2024-07-22 09:29:45

要测试此条件,您必须计算两个三角形的绕线:

  1. 由 V1、原点和 V3 形成的三角形。 这个三角形必须是逆时针方向的。

  2. 由 V3、原点和 V2 构成的三角形。 这个三角形也必须是逆时针的。

要测试三角形的缠绕,检查顶点的 2D 叉积的符号就足够了。

测试看起来像这样(抱歉 - 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");
  }
}

To test this condition you have to calculate the winding of two triangles:

  1. The triangle formed by V1, the origin and V3. This triangle must be counter-clockwise.

  2. The triangle formed by V3, the origin and V2. This triangle must be counter-clockwise as well.

To test the winding of a triangle it's enough to check the sign of the 2D cross-product of the vertices.

The test looks like this (sorry - C-code):

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");
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文