我有一个非常简单的 3D 矢量类定义TVector3D
,以及一些用于实现该TVector3D.Normalise
功能的方法。如果我向Normalise
函数传递一个已经标准化的向量,我希望它返回我传递给它的向量。我在这里使用过Result := Self
,但我得到了一些疯狂的回报。
控制台应用程序:
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
TVector3D = Class
public
x : Single;
y : Single;
z : Single;
constructor Create(x : Single;
y : Single;
z : Single);
function GetMagnitude() : Single;
function IsUnitVector() : Boolean;
function Normalise() : TVector3D;
end;
constructor TVector3D.Create(x : Single;
y : Single;
z : Single);
begin
Self.x := x;
Self.y := y;
Self.z := z;
end;
function TVector3D.GetMagnitude;
begin
Result := Sqrt(Sqr(Self.x) + Sqr(Self.y) + Sqr(Self.z));
end;
function TVector3D.IsUnitVector;
begin
if Self.GetMagnitude = 1 then
Result := True
else
Result := False;
end;
function TVector3D.Normalise;
var
x : Single;
y : Single;
z : Single;
MagnitudeFactor : Single;
begin
if IsUnitVector then
Result := Self
else
MagnitudeFactor := 1/(Self.GetMagnitude);
x := Self.x*MagnitudeFactor;
y := Self.y*MagnitudeFactor;
z := Self.z*MagnitudeFactor;
Result := TVector3D.Create(x,
y,
z);
end;
procedure TestNormalise;
var
nonUnitVector : TVector3D;
unitVector : TVector3D;
nUVNormed : TVector3D;
uVNormed : TVector3D;
begin
//Setup Vectors for Test
nonUnitVector := TVector3D.Create(1,
1,
1);
unitVector := TVector3D.Create(1,
0,
0);
//Normalise Vectors & Free Memory
nUVNormed := nonUnitVector.Normalise;
nonUnitVector.Free;
uVNormed := unitVector.Normalise;
unitVector.Free;
//Print Output & Free Memory
WriteLn('nUVNormed = (' + FloatToStr(nUVNormed.x) + ', ' + FloatToStr(nUVNormed.y) + ', ' + FloatToStr(nUVNormed.z) + ')');
nUVNormed.Free;
WriteLn('uVNormed = (' + FloatToStr(uVNormed.x) + ', ' + FloatToStr(uVNormed.y) + ', ' + FloatToStr(uVNormed.z) + ')');
uVNormed.Free;
end;
begin
try
TestNormalise;
Sleep(10000);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Normalise
适用于非单位向量,即IsUnitVector
返回 false。但是对于单位向量,例如(1,0,0)
,而不是返回自身,我得到一个非常低的非零数的结果,只要之前有一个非零,例如(8.47122...E-38,0,0)
。
如果我通过调试器运行此程序,并在Result := Self
设置为评估 Self 的行上设置断点,Self(1,0,0)
仍然结果变为(Very Low Number,0,0)
. Very Low Number
每次我运行程序时都会发生变化,但似乎总是在E-38/E-39
.
我不明白为什么会这样。为什么会发生这种情况以及如何最好地改变我的Normalise
功能以避免它。