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)
ます。
Self を評価するように設定された行にブレークポイントを設定してデバッガーでこれを実行するとResult := Self
、Self は(1,0,0)
まだ結果になり(Very Low Number,0,0)
ます。Very Low Number
プログラムを実行するたびに場所が変わりますが、常に周りにあるようE-38/E-39
です。
なぜこれが起こるのかわかりません。なぜそれが起こるのか、そしてそれNormalise
を避けるために私の機能をどのように変更するのが最善なのか.