是否有将圆的度数移过0的函数?

时间:2012-11-10 23:40:41

标签: delphi math geometry delphi-xe2

我正在寻找Delphi XE2中某个类似于Inc()的函数,它允许我从当前的度数中加/减几度,并产生新的度数。例如,如果我的圆周围有一个点为5度,我想减去10,我不应该得到-5度,而是355(360 - 5)。与添加过去360相同 - 当它达到360时应该回到0.

Delphi中是否有这样的东西,所以我不必重写它?也许在Math单位?

5 个答案:

答案 0 :(得分:10)

uses
  System.SysUtils,Math;

Function WrapAngle( angle : Double) : Double;
Const
  modAngle : Double = 360.0;
begin
  Result := angle - modAngle*Floor(angle/modAngle);
end;

begin
  WriteLn(FloatToStr(WrapAngle(-5)));
  WriteLn(FloatToStr(WrapAngle(5-720)));
  WriteLn(FloatToStr(WrapAngle(360)));
  ReadLn;    
end.

产生结果:

355
5 
0

更新

正如@Giel发现的那样,在XE3中有一个新功能DegNormalize()可以完成这项工作。甚至快25%左右。诀窍是用Floor()取代Int()来电,如果结果是否定的,则将modAngle添加到结果中。

答案 1 :(得分:4)

function WrapAngle(Value: Integer): Integer;
begin
  Result := Value mod 360;
  if Result < 0 then
    Inc(Result, 360);
end;

答案 2 :(得分:3)

我用来执行此任务的代码是:

function PosFrac(x: Double): Double;
(* PosFrac(1.2)=0.2 and PosFrac(-1.2)=0.8. *)
begin
  Result := Frac(x); (* Frac(x)=x-Int(x) *)
  if Result<0.0 then begin
    Result := 1.0+Result;
  end;
end;

function ModR(const x, y: Double): Double;
(* ModR(1.2,1)=0.2 and ModR(-1.2,1)=0.8 *)
var
  absy: Double;
begin
  if y=0.0 then begin
    Result := 0.0;
  end else begin
    absy := abs(y);
    Result := PosFrac(x/absy)*absy;
  end;
end;

function Mod360(const x: Double): Double;
begin
  Result := ModR(x, 360.0);
end;

此代码会将所有角度调整到0360的范围内。例如:

Writeln(Round(Mod360(5-10)));
Writeln(Round(Mod360(5-360)));
Writeln(Round(Mod360(5-720)));
Writeln(Round(Mod360(5+720)));

输出:

355
5
5
5

答案 3 :(得分:1)

我不知道,但我更喜欢使用更通用的解决方案......

Procedure IncOverFlow(var Value:Double;Difference:Double;Limit:Double=360);
begin
   Value := Value + Difference;
   While Value < 0 do Value := Value + Limit;
   While Value >= Limit do Value := Value -Limit;
end;

答案 4 :(得分:1)

procedure WrapAngle(var Degs: Integer);
begin
  Degs := Degs mod 360;
  if Degs < 0 then
    Inc(Degs, 360);
end;