确定一个点是否在从原点创建无限延伸线的另外两个点的范围内

时间:2012-07-12 16:47:51

标签: xna geometry formula angle

如果我有三个点创建一个角度,那么确定第四个点是否位于前三个角度所创造的角度内的最佳方法是什么?

目前,我确定从原点开始到所有三个点的线的角度,然后检查测试角度是否介于两个其他角度之间,但是我试图弄清楚是否存在&# 39;更好的方法。该功能运行了数万次更新,我希望有更好的方法来实现我想要做的事情。

4 个答案:

答案 0 :(得分:2)

假设你有角度DEFE是“尖”部分),ED是左射线而EF是右射线。

      * D (Dx, Dy)
     /
    /          * P (Px, Py)
   /
  /
 *---------------*
E (Ex, Ey)       F (Fx, Fy)

第1步。在经典 Al * x + Bl * y + Cl = 0表单中构建行ED的线方程,即只需计算

    Al = Dy - Ey                    // l - for "left"
    Bl = -(Dx - Ex)
    Cl = -(Al * Ex + Bl * Ey)

(注意减法顺序。)

第2步。在经典 Ar * x + Br * y + Cr = 0表单中构建行FE(反向)的线方程,即简单地计算

    Ar = Ey - Fy                    // r - for "right"
    Br = -(Ex - Fx)
    Cr = -(Ar * Ex + Br * Ey)

(注意减法顺序。)

第3步。对于您的测试点P计算表达式

    Sl = Al * Px + Bl * Py + Cl
    Sr = Ar * Px + Br * Py + Cr

当且仅当SlSr都为正时,您的观点位于角度内。如果其中一个是正数而另一个是零,那么你的观点就在于相应的侧射线。

就是这样。

注1:要使此方法正常工作,务必确保角度的左右光线确实射线。即如果您将EDEF视为时钟指针,则DF的方向应为顺时针。如果不能保证输入的情况,则需要进行一些调整。例如,它可以作为算法的附加步骤完成,插入步骤2和3之间

步骤2.5。计算Al * Fx + Bl * Fy + Cl的值。如果此值为负,则反转所有ABC系数的符号:

Al = -Al, Bl = -Bl, Cl = -Cl
Ar = -Ar, Br = -Br, Cr = -Cr

注2:上述计算是在假设我们正在坐标系中进行的,X轴指向右侧,Y轴指向顶部。如果您的某个坐标轴被翻转,则必须反转所有六个ABC系数的符号。请注意,顺便说一句,如果您执行上面步骤2.5中描述的测试,它将自动处理所有事情。如果您没有执行步骤2.5,那么您必须从一开始就考虑轴方向。


如您所见,这是一个精确的整数方法(没有浮点计算,没有除法)。价格是溢出的危险。使用适当大小的类型进行乘法。

这种方法在线方向或实际非反射角的值方面没有特殊情况:它可以立即用于锐角,钝角,零角和直角。它可以很容易地与反射角度一起使用(只需进行补充测试)。

PS +/-Sl的{​​{1}}符号的四种可能组合对应于四个扇区,平面按行{{1 }和Sr

ED

通过使用此方法,您可以执行完整的“点落入哪个扇区”测试。对于小于180的角度,您恰好只对其中一个扇区感兴趣:EF。如果在某些时候你需要调整这种方法的反射角度(角度大于180),你将不得不测试三个扇区而不是一个: * D / (-,+) / (+,+) / -------*------------* F / E (-,-) / (+,-) / (+, +),{{ 1}}。

答案 1 :(得分:1)

描述你的原点O,另外2点A和B然后你的角度是AOB。现在考虑一下你的测试点,然后在图中调用它。

enter image description here

现在考虑我们可以通过获取向量OA的一些倍数和OB的一些倍数来获得C的向量方程。明确

  C = K1 x OA + K2 OB

我们需要计算一些K1,K2。通过从所有其他点中减去(矢量)来将O设置为原点。如果A的坐标是(a1,a2),B =(b1,b2)和C =(c1,c2)我们有矩阵术语

 [ a1 b1 ] [ K1 ] = [ c1 ]
 [ a2 b2 ] [ K2 ] = [ c2 ]

因此我们可以使用矩阵的逆来求解K1和K2

  1 / (a1b2 - b1a2)  [ b2 -b1 ] [ c1 ] = [ K1 ]
                     [ -a2 a1 ] [ c2 ] = [ K2 ] 

减少到

 K1 = (b2c1 - b1c2)/(a1b2 - b1a2)
 K2 = (-a2c1 + a1c2)/(a1b2 - b1a2)

现在,如果C点位于您的角度内,则向量OA和OB的倍数将为正。如果C位于'OB'之下,那么我们需要负数量的OA才能以相同的方式进入另一个方向。因此,当 K1和K2都大于(或等于)零时,您的条件就会得到满足。你需要注意a1b2 = b1a2的情况,因为这对应于奇异矩阵并除以零。几何上它意味着OA和OB是平行的,因此没有解决方案。上面的代数可能需要验证任何轻微的拼写错误,但方法是正确的。也许是啰嗦,但你可以简单地从点坐标得到它,并节省你计算逆三角函数来获得角度。

以上适用于角度< 180度,所以如果你的角度大于180度,你应该检查

 !(K1 >= 0 && K2 >= 0)

因为这是小于180度的段的外部。请记住,对于0度和180度,您将有一个除以零的错误,必须检查该错误(确保a1b2 - b1a2 != 0

答案 2 :(得分:0)

是的,我的意思是上面评论中的最小角度。请查看this主题,以便找到关于找到两个向量之间角度度量的廉价方法的广泛讨论。我在很多场合都使用了查找表方法并取得了巨大的成功。

答案 3 :(得分:0)

三角形O B C必须是正向和三角形O C A.要计算方向,只需使用Shoelace公式。两个值都必须是正值。