所以,我试图在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)
^ 我不明白宣告常数的需要...
我假设你想要计算相对于在这两点之间形成的线的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)
看起来ArcTan2
dó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°.我不知道你的意思是什么,是否是有意的,但它可能是意外结果的来源.
归档时间: |
|
查看次数: |
4414 次 |
最近记录: |