两个向量之间的角度

JHo*_*lta 2 delphi math

所以,我试图在Delphi中获得两个TPoints之间的角度,结果证明它比我预期的更难.我得到的结果我无法解释(似乎是"to degrees"-part的一些问题,或者ArcTan2没有以我期望的形式返回一个总和. - Delpi-v7:

function Modulo(x,y:Extended): Extended;
var d: Extended;
begin
  d := x / y;
  Result := (d - floor(d)) * y;
end;

function Degrees(Rads: Extended): Extended;
begin
  Result := Rads*(180/Pi);
end;

function GetPointAngle(P1, P2: TPoint): Extended;
begin
  Result := Modulo(Degrees(ArcTan2(-(P1.Y - P2.Y), P1.X - P2.X)) - 90, 360);
end;
Run Code Online (Sandbox Code Playgroud)

然而,当我将代码移植到Python或在另一个Pascal变体中测试它时,上面的工作.但现在,它似乎返回一个静态的总和(如果我"移动"第二个TPoint则不会改变).

如果你想知道; 我创建"模数"函数只是因为"mod" - 运算符中使用的除法运算符舍入为0而不是向下(因此负数不起作用).

编辑:我注意到,GetPointAngle()p距离另一个点更远时,返回的值(角度)会增加c(反之亦然),即使p是沿着第二个TPoint(c)的X轴拖动TPoint()也是如此.

编辑:

你们已经超越了自己,我已经查看了大部分答案,而且似乎很难选择最佳答案!既然你们都写了这么详细的东西,我会用相同的细节去做所有事情:-)

另外:我在最初的帖子中没有分享的是,我的函数被导出为DLL,可以从另一个pascal-interpretor(与delphi兼容)中访问.

最后的解决方案(已更改):

GetPointAngle(P1, P2: TPoint) 至: GetPointAngle(const P1, P2: TPoint)

^ 我不明白宣告常数的需要...

NGL*_*GLN 6

我假设你想要计算相对于在这两点之间形成的线的X轴的角度.

在此输入图像描述

对于这种情况,以下公式适用:

Tan(a) = (P2.Y - P1.Y) / (P2.X - P1.X)
Run Code Online (Sandbox Code Playgroud)

这意味着:

a = ArcTan((P2.Y - P1.Y) / (P2.X - P1.X))
Run Code Online (Sandbox Code Playgroud)

当两个点具有相同的X坐标时,这显然会导致EDivByZero异常,因此您必须自己处理.此外,ArcTan导致角度在0°..90°范围内(即0..π/ 2),因此忽略正确的象限,同时ArcTan2产生-180°.180°内的角度.向结果添加360°以将负角度转换为正角度:

function AngleOfLine(const P1, P2: TPoint): Double;
begin
  if P2.X = P1.X then
    if P2.Y > P1.Y then
      Result := 90
    else
      Result := 270
  else
    Result := RadToDeg(ArcTan2(P2.Y - P1.Y, P2.X - P1.X));
  if Result < 0 then
    Result := Result + 360;
end;
Run Code Online (Sandbox Code Playgroud)

结果如下:

  A := AngleOfLine(Point(10, 10), Point(20, 10)); // 0
  A := AngleOfLine(Point(10, 10), Point(20, 20)); // 45
  A := AngleOfLine(Point(10, 10), Point(10, 20)); // 90
  A := AngleOfLine(Point(10, 10), Point(0, 20));  // 135
  A := AngleOfLine(Point(10, 10), Point(0, 10));  // 180
  A := AngleOfLine(Point(10, 10), Point(0, 0));   // 225
  A := AngleOfLine(Point(10, 10), Point(10, 0));  // 270
  A := AngleOfLine(Point(10, 10), Point(20, 0));  // 315
Run Code Online (Sandbox Code Playgroud)

现在,这是相对于世界坐标系,其正Y轴向上指向默认.如果要将结果转换为正Y轴向下的设备坐标系,则从360°中减去结果:

Result := 360 - Result;
Run Code Online (Sandbox Code Playgroud)

更新:

看起来ArcTan2dóes照顾除零,(即使在D7中,尽管文档),所以例程变得更简单:

function AngleOfLine(const P1, P2: TPoint): Double;
begin
  Result := RadToDeg(ArcTan2((P2.Y - P1.Y),(P2.X - P1.X)));
  if Result < 0 then
    Result := Result + 360;
end;
Run Code Online (Sandbox Code Playgroud)

编辑:

我注意到,GetPointAngle()p远离另一个点时,返回的值会增加c(反之亦然).

那要看.查看上图,如果第二个点沿x轴进一步移动,则角度会减小.如果第二点沿y轴进一步移动,则角度增加.当然,这取决于两个点都在哪个象限.

此外,您的代码否定了第一个参数,ArcTan2并从结果中减去另外90°.我不知道你的意思是什么,是否是有意的,但它可能是意外结果的来源.

  • 否定第一个参数是顺时针而不是逆时针.从真实而非横向减去90项措施. (2认同)