给定三分 "slight right turn" 的逻辑

Logic for "slight right turn" given three points

给定三个共面 (2D) 点 (X1, Y1)、(X2, Y2) 和 (X3, Y3),它们分别表示(...)“1=我所在的位置,2=我在哪里,3=我要去哪里”,我需要一个简单的算法来告诉我,例如

换句话说,(a)是向左或向右转; (b) 转弯有多急(让我对此随意)。

对于第一部分,我已经了解了如何使用(参见维基百科:Graham Scan,以及此处的问题 #26315401)叉积来确定转弯是向左还是向右,基于关于路径是否逆时针。

而且,我确信 ATAN2() 将是决定转弯有多急的核心。

但我不能.. 完全.. 将我的头脑围绕在 所有 方向上工作的正确数学。 (尤其是角度越过零线的时候。(350度到10度的方位是20度的间隙,不是340,etc。)

好吧,我累了。 [...今天早上我的头撞到墙上了。] "Every time I think I've got it, I'm not sure." 所以,好吧,是时候了问...:-)

当你用Atan2计算方向变化角度时,不要在意绝对角度。您不必计算两个方位并减去它们 - Atan2 可以为您提供 范围 -Pi..Pi (-180..180) 中第一个和第二个向量之间的相对角度 (范围可能取决于编程语言)。

x12 = x2-x1
y12 = y2-y1
x23 = x3-x2
y23 = y3-y2
DirChange = Atan2(x12*y23-x23*y12, x12*x23+y12*y23)

一些解释:我们可以通过叉积和向量范数计算向量-向量夹角的正弦值(|A| = Sqrt(A.x*A.x + A.y*A.y)):

Sin(A_B) = (A x B) / (|A|*|B|)

通过点(标量)积和向量范数的向量-向量角的余弦:

Cos(A_B) = (A * B) / (|A|*|B|)

假设Atan2用这个角度的正弦和余弦计算角度,不包括公分母(范数的乘积)

A_B = Atan2(Sin(A_B), Cos(A_B))

Delphi中的示例:

var
  P1, P2, P3: TPoint;
  x12, y12, x23, y23: Integer;
  DirChange: Double;
begin
  P1 := Point(0, 0);
  P2 := Point(1, 0);
  P3 := Point(2, 1);
  x12 := P2.X - P1.X;
  y12 := P2.Y - P1.Y;
  x23 := P3.X - P2.X;
  y23 := P3.Y - P2.Y;
  DirChange := Math.ArcTan2(x12 * y23 - x23 * y12, x12 * x23 + y12* y23);
  Memo1.Lines.Add(Format('%f radians   %f degrees',
    [DirChange, RadToDeg(DirChange)]));

输出: 0.79 radians 45.00 degrees(左转)

对于您的示例数据集 (1,1)、(3,2) 和 (6,3)

-0.14 radians -8.13 degrees(右转)

已编辑 - 以下是错误的。 我的原始回复如下...

当我尝试使用您的回复时,我没有想出预期的答案。

假设这些点是:(1,1)、(3,2) 和 (6,3)。轻轻右转。

使用电子表格,我得出:X12=2、X23=3、Y12=1、Y23=3,ATAN2 结果(以度为单位)为 101.3。超过90度的非常急转弯。第 2 行的电子表格公式(列出 X1、Y1、X2、Y2、X3、Y3、X12、X23、Y12、Y23 和答案)为:

=DEGREES(ATAN2(G2*J2-H2*I2; G2*I2+H2*J2))

(OpenOffice 电子表格将 "X" 列为 ATAN2 的第一个参数。)

你确定错字是我这边的吗?

并且,事实上(可以这么说),"YES, IT WAS!"

(嘿,其实我自己也说过。我只是没想到,呃,已经交换它们了。)

我的电子表格版本的 ATAN2 函数首先指定了 X 参数。大多数编程语言 (Delphi, Perl, PHP ...) 首先指定 Y ,这就是 (正确!)已给出答案。

当我编辑公式,反转参数以满足电子表格的定义时,问题就消失了,我能够重现 (edited) 回复中的值。这是更正后的公式,参数颠倒了:

=DEGREES(ATAN2(G2*I2+H2*J2; G2*J2-H2*I2))
               ^^== X ==^^  ^^== Y ==^^

同样,需要对公式进行更改,因为此电子表格的 ATAN2 实现与大多数编程语言的实现相比是倒退的。最初给出的答案,首先列出 Y,对于大多数编程语言都是正确的

嗯,我似乎仍然有点问题。 . .

如果这些点在几乎一条直线上彼此相距很远,我想出 "large angles." 示例:

P1: (0.60644,0.30087) .. P2: (0.46093,0.30378) .. P3: (0.19335,0.30087)

X坐标增加,Y坐标几乎不变

x12=-0.145507 .. y12=-0.00290698

x23=-0.267578125 .. y23=0.002906976

(我倒转了 Y 差异,因为坐标在象限 IV,其中 Y 向下增加。)

x=-0.000354855 .. y=-0.00120083

ans= -106.462 (度)

因为这些点几乎是共线的,所以我预计答案会很小。正如你所看到的,它超过了106度。