如何确定在逆时针从V1到V2的过程中,V3是否位于V1和V2之间?涉及IT技术。

6
我有三个向量V1、V2和V3。它们的起点都在坐标轴原点上。当我从V1逆时针移动到V2时,如何确定V3是否在V1和V2之间?

alt text 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] 范围内给出角度。因此,如果 angle(V1) = 120 (以度为单位),angle(V2) = -130,angle(V3) = 150,则答案(根据上面的代码)是“超出区间”,尽管如果你沿着逆时针方向从 V1 移动到 V2,它在它们之间。
你可以建议将 2*pi 添加到 angle(V2) 或类似的方法,但我已经尝试过这些方法,它不起作用。
我在 MATLAB 中进行编程。
编辑 1:这是二维的。

因为这个问题不是特定于MATLAB的。 - Jimmy
OP说他们正在使用MATLAB进行编程,因此我认为他们希望得到MATLAB编码的答案。 - gnovice
你为什么移除了Matlab标签?它可以帮助你的问题获得更多的关注。 - gnovice
+1 给出色的手绘艺术! - Isak Savo
5个回答

8

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

解释:

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

all(crossProds >= 0)

如果V1V2之间逆时针角度大于180度,则这两个向量的叉积将小于零。在这种情况下,当V3V1V2之间以顺时针方向时,叉积(V1,V3)(V3,V2)也小于零。因此,如果这些叉积不是都小于零,则V3必须在V1V2之间以逆时针方向。这解释了接下来的两个逻辑检查:
(crossProds(1) < 0) && ~all(crossProds(2:3) < 0)

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

谢谢,但是你的方法似乎是绕路方法。就像我对Nils Pipenbrinck说的那样,这种方法行不通。 - Kamran Bigdely
我相信我的方法与尼尔斯的方法非常不同。它涉及叉积,但具有不同的逻辑检查。 - gnovice
我没有将它标记为作业,是Dinah标记的。我将它标记为Matlab。 - gnovice
它似乎正在工作!但是你能否更详细地解释一下? - Kamran Bigdely
1
@Himadri:当上述代码显示"V3 is between V1 and V2"时,意味着从V1到V2按逆时针方向移动时,V3位于V1和V2之间。当代码显示"out of the interval"时,表示从V1到V2按顺时针方向移动时,V3位于V1和V2之间。 - gnovice
显示剩余2条评论

3

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

你的答案是正确的,但我无法选择两个答案作为我的最终答案,甚至很难说哪一个更好:你的还是gnovice的答案... - Kamran Bigdely
1
我明天会进行评估,看哪个答案更快...谢谢 - Kamran Bigdely

2

V1仅是一个误导。同时考虑三个角度只会让你更加困惑。

  1. 按照V1的角度顺时针旋转所有元素
  2. 将剩余的两个角度标准化为[0,360)

现在,问题就是比较norm(angle(V2)-angle(V1))和norm(angle(V3)-angle(V1))。


0

对于大多数其他编程语言来说,这是一种相对容易的方法。

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


-2

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

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

谢谢,但是正如您在图片中所看到的,V1V3是正数,V3V2也是正数,而且V3位于V1和V2之间。但根据您的方法,它并不在它们之间! - Kamran Bigdely
我认为这种方法不起作用。例如,考虑这些向量:angle(V1) = 10,angle(V2) = -10,V3 = 180。当我们逆时针移动时,V3在V1和V2之间,但您的方法却说它不是。 - Kamran Bigdely
Kamran,你能画一张图片或者给出你的点的笛卡尔坐标吗? - Nils Pipenbrinck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接