| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398 |
- //
- // The graphics platform GLScene https://github.com/glscene
- //
- unit GLS.VectorTypesExt;
- interface
- { .$I GLScene.inc }
- uses
- System.Types,
- System.TypInfo,
- System.SysUtils,
- System.Rtti,
- System.Math,
- System.Math.Vectors,
- GLS.VectorTypes;
- type
- // Extended may be replaced with BigDecimals
- TIntegerArray = array of Integer;
- TVertexArray = array of TVector3f;
- TDoubleArray = array of Double;
- TVectorExt = array of Extended;
- TMatrixExt = array of array of Extended;
- TArray3DExt = array of array of array of Extended;
- TQuaternionRec = record
- private
- FData: array [0 .. 3] of Extended;
- procedure SetElement(Index: Byte; Value: Extended);
- function GetElement(Index: Byte): Extended;
- public
- constructor Create(Q: TVectorExt);
- class operator Multiply(Q1, Q2: TQuaternionRec): TQuaternionRec;
- class operator Multiply(Q: TQuaternionRec; Sc: Extended): TQuaternionRec;
- class operator Multiply(Scalar: Extended; Q: TQuaternionRec)
- : TQuaternionRec;
- class operator Implicit(V: TVectorExt): TQuaternionRec;
- function Inv: TQuaternionRec;
- function TruncateSTI: TQuaternionRec;
- property Element[index: Byte]: Extended read GetElement
- write SetElement; default;
- end;
- PVectorRec = ^TVectorRec;
- TVectorRec = record
- private
- FData: TVectorExt;
- FCount: Word;
- procedure SetElement(Index: Word; Value: Extended);
- function GetElement(Index: Word): Extended;
- procedure CheckUnique;
- public
- constructor Create(ElementsCount: Word); overload;
- constructor Create(V: TVectorExt); overload;
- class operator Add(V1, V2: TVectorRec): TVectorRec;
- class operator Add(V: TVectorRec; Scalar: Extended): TVectorRec;
- class operator Add(Scalar: Extended; V: TVectorRec): TVectorRec;
- class operator Subtract(V1, V2: TVectorRec): TVectorRec;
- class operator Subtract(Scalar: Extended; V: TVectorRec): TVectorRec;
- class operator Subtract(V: TVectorRec; Scalar: Extended): TVectorRec;
- class operator Multiply(V1, V2: TVectorRec): TVectorRec;
- class operator Multiply(V: TVectorRec; Scalar: Extended): TVectorRec;
- class operator Multiply(Scalar: Extended; V: TVectorRec): TVectorRec;
- class operator Divide(V: TVectorRec; Scalar: Extended): TVectorRec;
- class operator Divide(V1, V2: TVectorRec): TVectorRec;
- class operator Implicit(V: TVectorExt): TVectorRec;
- function Norm: Extended;
- function SumOfSquares: Extended;
- function SumOfElments: Extended;
- function TruncateSTI: TVectorRec;
- function ToQuat: TQuaternionRec;
- procedure Fill(Value: Extended);
- function ScalarMult(V: TVectorRec): Extended;
- property Count: Word read FCount;
- property Elements[index: Word]: Extended read GetElement
- write SetElement; default;
- end;
- PMatrixRec = ^TMatrixRec;
- TMatrixRec = record
- private
- FData: TMatrixExt;
- FRowsCount: Word;
- FColsCount: Word;
- procedure SetElement(Row, Col: Word; Value: Extended);
- function GetElement(Row, Col: Word): Extended;
- function GetRow(Row: Word): TVectorRec;
- procedure SetRow(Row: Word; Value: TVectorRec);
- function GetCol(Col: Word): TVectorRec;
- procedure SetCol(Col: Word; Value: TVectorRec);
- function Del(A: TMatrixRec; I, J: Integer; M: Integer): TMatrixRec;
- function Det(A: TMatrixRec; M: Integer): Extended;
- procedure CheckUnique;
- public
- constructor Create(RowsCount, ColsCount: Word); overload;
- constructor CreateDiag(Dim: Word; Value: Extended = 1.0);
- constructor Create(M: TMatrixExt); overload;
- class operator Add(M1, M2: TMatrixRec): TMatrixRec;
- class operator Subtract(M1, M2: TMatrixRec): TMatrixRec;
- class operator Multiply(M1, M2: TMatrixRec): TMatrixRec;
- class operator Multiply(M: TMatrixRec; V: TVectorRec): TVectorRec;
- class operator Multiply(V: TVectorRec; M: TMatrixRec): TVectorRec;
- class operator Multiply(M: TMatrixRec; Scalar: Extended): TMatrixRec;
- class operator Multiply(Scalar: Extended; M: TMatrixRec): TMatrixRec;
- class operator Multiply(M: TMatrixRec; Q: TQuaternionRec): TQuaternionRec;
- class operator Implicit(M: TMatrixExt): TMatrixRec;
- function Transp: TMatrixRec;
- function Inv: TMatrixRec;
- function ToQuat: TQuaternionRec;
- function Determinant: Extended;
- function TruncateSTI: TMatrixRec;
- function Trace: Extended; // sum on diagonal elements
- procedure Fill(Scalar: Extended);
- property RowCount: Word read FRowsCount;
- property ColCount: Word read FColsCount;
- property Row[Row: Word]: TVectorRec read GetRow write SetRow;
- property Col[Col: Word]: TVectorRec read GetCol write SetCol;
- property Elements[Row, Col: Word]: Extended read GetElement
- write SetElement; default;
- end;
- TQuaternionHelper = record helper for TQuaternionRec
- function ToMatrix: TMatrixRec;
- end;
- TVectorHelper = record helper for TVectorRec
- function ToDiagMatrix: TMatrixRec;
- end;
- TDim = class(TCustomAttribute)
- private
- FRowCount: Integer;
- FColCount: Integer;
- public
- constructor Create(ARowCount: Integer; AColCount: Integer = 0); overload;
- property RowCount: Integer read FRowCount;
- property ColCount: Integer read FColCount;
- end;
- function GetVectorRec(V: TVectorExt): TVectorRec;
- function GetMatrixRec(M: TMatrixExt): TMatrixRec;
- function GetQuaternionRec(Q: TVectorExt): TQuaternionRec;
- procedure Init(Obj, TypeInfoOfObj: Pointer; Offset: Integer = 0);
- // -----------------------
- // Point types
- // -----------------------
- type
- TGLScalarValue = Extended;
- TGLScalarField = function(X, Y, Z: Extended): TGLScalarValue;
- // if data are made on integer XYZ index may be replaced with BigIntegers
- TGLScalarFieldInt = function(iX, iY, iZ: Integer): TGLScalarValue of object;
- TVertexRec = record
- P, N: TVector3f; // Position and Normal
- Density: Extended;
- end;
- TFaceRec = record
- Normal: TVector3f;
- V1: TVector3f; // vertex 1
- V2: TVector3f; // vertex 2
- V3: TVector3f; // vertex 3
- Padding: array [0 .. 1] of Byte;
- end;
- PPoint2DRec = ^TPoint2DRec;
- TPoint2DRec = record
- X: Extended;
- Y: Extended;
- public
- function Create(X, Y: Extended): TPoint2DRec;
- procedure SetPosition(const X, Y: Extended);
- function Add(const APoint2D: TPoint2DRec): TPoint2DRec;
- function Length: Extended; // distance to origin
- function Distance(const APoint2D: TPoint2DRec): Extended;
- class function PointInCircle(const Point, Center: TPoint2DRec;
- const Radius: Integer): Boolean; static; inline;
- procedure Offset(const ADeltaX, ADeltaY: Extended);
- end;
- PPoint3DRec = ^TPoint3DRec;
- TPoint3DRec = record
- X: Extended;
- Y: Extended;
- Z: Extended;
- public
- function Create(X, Y, Z: Extended): TPoint3DRec;
- procedure SetPosition(const X, Y, Z: Extended);
- function Add(const AGLPoint3D: TPoint3DRec): TPoint3DRec;
- function Length: Single; // distance to origin
- function Distance(const APoint3D: TPoint3DRec): Extended;
- procedure Offset(const ADeltaX, ADeltaY, ADeltaZ: Extended);
- end;
- TPoint2DArray = array of TPoint2DRec;
- TPoint3DArray = array of TPoint3DRec;
- // Voxel types
- TVoxelStatus = (bpExternal, bpInternal);
- PVoxelRec = ^TVoxelRec;
- TVoxelRec = record
- P: TVector3f;
- Density: TGLScalarValue;
- Status: TVoxelStatus;
- end;
- TVoxelData = array [0 .. (MaxInt shr 8)] of TVoxelRec;
- PVoxelData = ^TVoxelData;
- // -----------------------
- // Vector types
- // -----------------------
- TVector2DType = array [0 .. 1] of Extended;
- TVector3DType = array [0 .. 2] of Extended;
- TVector2DRec = record
- function Create(const AX, AY, AW: Single): TVector2DRec;
- function Add(const AVector2D: TVector2DRec): TVector2DRec;
- function Length: Extended;
- function Norm: Extended;
- function Normalize: TVector2DRec;
- function CrossProduct(const AVector: TVector2DRec): TVector2DRec;
- function DotProduct(const AVector: TVector2DRec): Extended;
- case Integer of
- 0:
- (V: TVector2DType;);
- 1:
- (X: Extended;
- Y: Extended;
- W: Extended;)
- end;
- TVector3DRec = record
- function Create(const AX, AY, AZ, AW: Single): TVector3DRec;
- function Add(const AVector3D: TVector3DRec): TVector3DRec;
- function Length: Single;
- function Norm: Single;
- function Normalize: TVector3DRec;
- function CrossProduct(const AVector3D: TVector3D): TVector3D;
- function DotProduct(const AVector3D: TVector3D): Single; inline;
- case Integer of
- 0:
- (V: TVector3DType;);
- 1:
- (X: Extended;
- Y: Extended;
- Z: Extended;
- W: Extended;)
- end;
- // Vector Arrays
- TVector2DArray = array of TVector2DRec;
- TVector3DArray = array of TVector3DRec;
- // -----------------------
- // Matrix types
- // -----------------------
- TMatrix2DType = array [0 .. 3] of TVector2DRec;
- TMatrix3DType = array [0 .. 3] of TVector3DRec;
- TMatrix2DRec = record
- private
- public
- case Integer of
- 0:
- (M: TMatrix2DType;);
- 1:
- (e11, e12, e13: Single;
- e21, e22, e23: Single;
- e31, e32, e33: Single);
- end;
- TMatrix3DRec = record
- private
- public
- case Integer of
- 0:
- (M: TMatrix3DType;);
- 1:
- (e11, e12, e13, e14: Single;
- e21, e22, e23, e24: Single;
- e31, e32, e33, e34: Single;
- e41, e42, e43, e44: Single);
- end;
- // Matrix Arrays
- TMatrix2DArray = array of TMatrix2DRec;
- TMatrix3DArray = array of TMatrix3DRec;
- // -----------------------
- // Polygon types
- // -----------------------
- TPolygon2D = TPoint2DArray;
- TPolygon3D = TPoint3DArray;
- (*
- TPolygon3D = record
- Vertices: array of TPoint3DRec;
- function Length;
- end;
- *)
- const
- ClosedPolygon2D: TPoint2DRec = (X: $FFFF; Y: $FFFF);
- ClosedPolygon3D: TPoint3DRec = (X: $FFFF; Y: $FFFF; Z: $FFFF);
- type
- PVertArray = ^TVertArray;
- TVertArray = array [0 .. (MaxInt shr 8)] of TVertexRec;
- type
- TTriangleRec = record
- V1, V2, V3: Integer;
- /// Vertices: array[0..2] of TPoint3DRec;
- /// function Area;
- end;
- PTriangleRecArray = ^TTriangleRecArray;
- TTriangleRecArray = array [0 .. (MaxInt shr 8)] of TTriangleRec;
- // -----------------------
- // Polyhedron types
- // -----------------------
- type
- TPolyhedronArray = array of TPolygon3D;
- (*
- TPolyhedron = record
- Facets: array of TGLPolygon3D;
- function NetLength;
- function Area;
- function Volume;
- end;
- *)
- // --------------------------
- // Mesh simple record types
- // --------------------------
- type
- TMesh2DVert = record
- X, Y: Single;
- NX, NY: Single;
- tU, tV: Single;
- end;
- TMesh3DVert = packed record
- X, Y, Z: Single;
- NX, NY, NZ: Single;
- tU, tV: Single;
- end;
- TMesh2DArray = array of TMesh2DVert;
- TMesh3DArray = array of TMesh3DVert;
- // --------------------------
- // Quaternion simple record types
- // --------------------------
- type
- TQuat3DRec = record
- ImPart: TVector3DRec;
- RePart: Single;
- end;
- TQuatArray = array of TQuat3DRec;
- type
- TBoxRec = record
- ALeft, ATop, ANear, ARight, ABottom, AFar: Single;
- end;
- const
- sWRONG_ELEMENT = 'Wrong element';
- sWRONG_SIZE = 'Wrong size';
- sNOT_QUAD = 'Matrix not quadratic';
- sSINGULAR = 'Singular matrix founded';
- // ---------------------------------------------------------------
- implementation
- // ---------------------------------------------------------------
- function GetVectorRec(V: TVectorExt): TVectorRec;
- begin
- Result.Create(V);
- end;
- function GetMatrixRec(M: TMatrixExt): TMatrixRec;
- begin
- Result.Create(M);
- end;
- function GetQuaternionRec(Q: TVectorExt): TQuaternionRec;
- begin
- Result.Create(Q);
- end;
- {$POINTERMATH ON}
- function NotUnique(PArr: PCardinal): Boolean;
- begin
- Result := (PArr - 2)^ > 1;
- end;
- // -------------------------------------
- // TMatrixRec
- // -------------------------------------
- // Removing i-th row and j-th col
- function TMatrixRec.Del(A: TMatrixRec; I, J: Integer; M: Integer): TMatrixRec;
- var
- K, G: Integer;
- begin
- for G := I to M - 1 do
- for K := 1 to M do
- A[G, K] := A[G + 1, K];
- for G := J to M - 1 do
- for K := 1 to M - 1 do
- A[K, G] := A[K, G + 1];
- Result := A;
- end;
- // Recursive calculation of det for matrix
- function TMatrixRec.Det(A: TMatrixRec; M: Integer): Extended;
- var
- I: Integer;
- Buf: Extended;
- begin
- Buf := 0;
- if M = 1 then
- Buf := A[1, 1]
- else
- for I := 1 to M do
- Buf := Buf + Power10(-1, I + 1) * A[I, 1] * Det(Del(A, I, 1, M), M - 1);
- Result := Buf;
- end;
- class operator TMatrixRec.Add(M1, M2: TMatrixRec): TMatrixRec;
- var
- I, J: Integer;
- begin
- if (M1.FRowsCount <> M2.FRowsCount) or (M1.FColsCount <> M2.FColsCount) then
- raise EMathError.Create(sWRONG_SIZE);
- Result.Create(M1.FRowsCount, M1.FColsCount);
- for I := 0 to M1.FRowsCount - 1 do
- for J := 0 to M1.FColsCount - 1 do
- Result.FData[I, J] := M1.FData[I, J] + M2.FData[I, J];
- end;
- procedure TMatrixRec.CheckUnique;
- var
- I: Integer;
- begin
- if NotUnique(@FData) then
- begin
- FData := Copy(FData);
- for I := 0 to Pred(FRowsCount) do
- FData[I] := Copy(FData[I]);
- end;
- end;
- constructor TMatrixRec.Create(RowsCount, ColsCount: Word);
- begin
- FRowsCount := RowsCount;
- FColsCount := ColsCount;
- FData := nil;
- SetLength(FData, FRowsCount, FColsCount);
- end;
- constructor TMatrixRec.Create(M: TMatrixExt);
- var
- I: Integer;
- begin
- FRowsCount := Length(M);
- FColsCount := Length(M[0]);
- FData := nil;
- SetLength(FData, FRowsCount, FColsCount);
- for I := 0 to Pred(FRowsCount) do
- begin
- if Length(M[I]) <> FColsCount then
- raise EMathError.Create('Wrong matrix proportions');
- FData[I] := Copy(M[I]);
- end;
- end;
- constructor TMatrixRec.CreateDiag(Dim: Word; Value: Extended = 1.0);
- var
- I: Integer;
- begin
- Create(Dim, Dim);
- for I := 0 to Dim - 1 do
- FData[I, I] := Value;
- end;
- function TMatrixRec.Determinant: Extended;
- begin
- if (FRowsCount <> FColsCount) then
- raise EMathError.Create(sNOT_QUAD);
- Result := Det(Self, FRowsCount);
- end;
- procedure TMatrixRec.Fill(Scalar: Extended);
- var
- I, J: Integer;
- begin
- if Scalar = 0 then
- begin
- FData := nil;
- SetLength(FData, FRowsCount, FColsCount);
- end
- else
- for I := 0 to FRowsCount - 1 do
- for J := 0 to FColsCount - 1 do
- FData[I, J] := Scalar;
- end;
- function TMatrixRec.GetCol(Col: Word): TVectorRec;
- var
- I: Integer;
- begin
- if (Col = 0) or (Col > FColsCount) then
- raise EMathError.Create(sWRONG_ELEMENT);
- Result.Create(FRowsCount);
- for I := 0 to FRowsCount - 1 do
- Result.FData[I] := FData[I, Col - 1];
- end;
- function TMatrixRec.GetElement(Row, Col: Word): Extended;
- begin
- {$R+}
- Result := FData[Pred(Row), Pred(Col)];
- end;
- function TMatrixRec.GetRow(Row: Word): TVectorRec;
- var
- I: Integer;
- begin
- if (Row = 0) or (Row > FRowsCount) then
- raise EMathError.Create(sWRONG_ELEMENT);
- Result.Create(FColsCount);
- for I := 0 to FColsCount - 1 do
- Result.FData[I] := FData[Row - 1, I];
- end;
- class operator TMatrixRec.Implicit(M: TMatrixExt): TMatrixRec;
- begin
- Result.Create(M);
- end;
- // --------------------------------------------------------
- function TMatrixRec.Inv: TMatrixRec;
- var
- Ipiv, Indxr, Indxc: array of Integer;
- DimMat, I, J, K, L, N, ICol, IRow: Integer;
- Big, Dum, Pivinv: Extended;
- begin
- // Jordan algorithm
- if (FRowsCount <> FColsCount) then
- raise EMathError.Create(sNOT_QUAD);
- Result := Self;
- DimMat := FRowsCount;
- SetLength(Ipiv, DimMat);
- SetLength(Indxr, DimMat);
- SetLength(Indxc, DimMat);
- IRow := 1;
- ICol := 1;
- for I := 1 to DimMat do
- begin
- Big := 0;
- for J := 1 to DimMat do
- if (Ipiv[J - 1] <> 1) then
- for K := 1 to DimMat do
- if (Ipiv[K - 1] = 0) then
- if (Abs(Result[J, K]) >= Big) then
- begin
- Big := Abs(Result[J, K]);
- IRow := J;
- ICol := K;
- end;
- Ipiv[ICol - 1] := Ipiv[ICol - 1] + 1;
- if (IRow <> ICol) then
- for L := 1 to DimMat do
- begin
- Dum := Result[IRow, L];
- Result[IRow, L] := Result[ICol, L];
- Result[ICol, L] := Dum;
- end;
- Indxr[I - 1] := IRow;
- Indxc[I - 1] := ICol;
- if Result[ICol, ICol] = 0 then
- raise EMathError.Create(sSINGULAR);
- Pivinv := 1.0 / Result[ICol, ICol];
- Result[ICol, ICol] := 1.0;
- for L := 1 to DimMat do
- Result[ICol, L] := Result[ICol, L] * Pivinv;
- for N := 1 to DimMat do
- if (N <> ICol) then
- begin
- Dum := Result[N, ICol];
- Result[N, ICol] := 0.0;
- for L := 1 to DimMat do
- Result[N, L] := Result[N, L] - Result[ICol, L] * Dum;
- end;
- end;
- for L := DimMat downto 1 do
- if (Indxr[L - 1] <> Indxc[L - 1]) then
- for K := 1 to DimMat do
- begin
- Dum := Result[K, Indxr[L - 1]];
- Result[K, Indxr[L - 1]] := Result[K, Indxc[L - 1]];
- Result[K, Indxc[L - 1]] := Dum;
- end;
- end;
- function TMatrixRec.ToQuat: TQuaternionRec;
- begin
- Result[0] := 0.5 * Sqrt(Abs(1 + Self[1, 1] + Self[2, 2] + Self[3, 3]));
- Result[1] := 0.5 * Sqrt(Abs(1 + Self[1, 1] - Self[2, 2] - Self[3, 3]));
- if Self[3, 2] < Self[2, 3] then
- Result[1] := -Result[1];
- Result[2] := 0.5 * Sqrt(Abs(1 - Self[1, 1] + Self[2, 2] - Self[3, 3]));
- if Self[1, 3] < Self[3, 1] then
- Result[2] := -Result[2];
- Result[3] := 0.5 * Sqrt(Abs(1 - Self[1, 1] - Self[2, 2] + Self[3, 3]));
- if Self[2, 1] < Self[1, 2] then
- Result[3] := -Result[3];
- end;
- class operator TMatrixRec.Multiply(M: TMatrixRec; Q: TQuaternionRec)
- : TQuaternionRec;
- var
- I, J: Integer;
- begin
- if (M.FRowsCount <> 4) or (M.FRowsCount <> M.FColsCount) then
- raise EMathError.Create(sWRONG_SIZE);
- FillChar(Result.FData, SizeOf(Result.FData), 0);
- for I := 0 to 3 do
- for J := 0 to 3 do
- Result.FData[I] := Result.FData[I] + M.FData[I, J] * Q.FData[J];
- end;
- class operator TMatrixRec.Multiply(Scalar: Extended; M: TMatrixRec): TMatrixRec;
- begin
- Result := M * Scalar;
- end;
- class operator TMatrixRec.Multiply(V: TVectorRec; M: TMatrixRec): TVectorRec;
- var
- I, J: Integer;
- begin
- if (V.FCount <> M.FRowsCount) then
- raise EMathError.Create(sWRONG_SIZE);
- Result.Create(V.FCount);
- for I := 0 to V.FCount - 1 do
- for J := 0 to V.FCount - 1 do
- Result.FData[I] := Result.FData[I] + V.FData[J] * M.FData[J, I];
- end;
- class operator TMatrixRec.Multiply(M: TMatrixRec; V: TVectorRec): TVectorRec;
- var
- I, J: Integer;
- begin
- if (M.FColsCount <> V.FCount) then
- raise EMathError.Create(sWRONG_SIZE);
- Result.Create(M.FRowsCount);
- for I := 0 to M.FRowsCount - 1 do
- for J := 0 to M.FColsCount - 1 do
- Result.FData[I] := Result.FData[I] + M.FData[I, J] * V.FData[J];
- end;
- class operator TMatrixRec.Multiply(M: TMatrixRec; Scalar: Extended): TMatrixRec;
- var
- I, J: Integer;
- begin
- Result.Create(M.FRowsCount, M.FColsCount);
- for I := 0 to M.FRowsCount - 1 do
- for J := 0 to M.FColsCount - 1 do
- Result.FData[I, J] := M.FData[I, J] * Scalar;
- end;
- class operator TMatrixRec.Multiply(M1, M2: TMatrixRec): TMatrixRec;
- var
- I, J, K: Integer;
- begin
- if (M1.FColsCount <> M2.FRowsCount) then
- raise EMathError.Create(sWRONG_SIZE);
- Result.Create(M1.FRowsCount, M2.FColsCount);
- for I := 0 to M1.FRowsCount - 1 do
- for J := 0 to M2.FColsCount - 1 do
- for K := 0 to M1.FColsCount - 1 do
- Result.FData[I, J] := Result.FData[I, J] + M1.FData[I, K] *
- M2.FData[K, J];
- end;
- procedure TMatrixRec.SetCol(Col: Word; Value: TVectorRec);
- var
- I: Integer;
- begin
- if (Col = 0) or (Col > FColsCount) then
- raise EMathError.Create(sWRONG_ELEMENT);
- if (Value.Count <> FRowsCount) then
- raise EMathError.Create(sWRONG_SIZE);
- for I := 0 to FRowsCount - 1 do
- FData[I, Col - 1] := Value.FData[I];
- end;
- procedure TMatrixRec.SetElement(Row, Col: Word; Value: Extended);
- begin
- {$R+}
- CheckUnique;
- FData[Pred(Row), Pred(Col)] := Value;
- end;
- procedure TMatrixRec.SetRow(Row: Word; Value: TVectorRec);
- var
- I: Integer;
- begin
- if (Row = 0) or (Row > FRowsCount) then
- raise EMathError.Create(sWRONG_ELEMENT);
- if (Value.Count <> FColsCount) then
- raise EMathError.Create(sWRONG_SIZE);
- for I := 0 to FColsCount - 1 do
- FData[Row - 1, I] := Value.FData[I];
- end;
- class operator TMatrixRec.Subtract(M1, M2: TMatrixRec): TMatrixRec;
- var
- I, J: Integer;
- begin
- if (M1.FColsCount <> M2.FColsCount) or (M1.FRowsCount <> M2.FRowsCount) then
- raise EMathError.Create(sWRONG_SIZE);
- Result.Create(M1.FRowsCount, M1.FColsCount);
- for I := 0 to M1.FRowsCount - 1 do
- for J := 0 to M1.FColsCount - 1 do
- Result.FData[I, J] := M1.FData[I, J] - M2.FData[I, J];
- end;
- function TMatrixRec.Trace: Extended;
- var
- I: Integer;
- begin
- Result := 0;
- if FColsCount <> FRowsCount then
- raise EMathError.Create(sNOT_QUAD);
- for I := 0 to FColsCount - 1 do
- Result := Result + FData[I, I];
- end;
- function TMatrixRec.Transp: TMatrixRec;
- var
- I, J: Integer;
- begin
- Result.Create(FColsCount, FRowsCount);
- for I := 0 to FColsCount - 1 do
- for J := 0 to FRowsCount - 1 do
- Result.FData[I, J] := FData[J, I];
- end;
- function TMatrixRec.TruncateSTI: TMatrixRec;
- const
- Int32Max: Double = Integer.MaxValue;
- Int32Min: Double = Integer.MinValue;
- var
- I, J: Integer;
- begin
- Result.Create(FRowsCount, FColsCount);
- for I := 0 to FRowsCount - 1 do
- for J := 0 to FColsCount - 1 do
- begin
- if (FData[I, J] >= Int32Min) and (FData[I, J] <= Int32Max) then
- Result.FData[I, J] := Trunc(FData[I, J])
- else if (FData[I, J] < Int32Min) then
- Result.FData[I, J] := Int32Min
- else
- Result.FData[I, J] := Int32Max;
- end;
- end;
- // -----------------------------
- // TVectorRec
- // -----------------------------
- constructor TVectorRec.Create(V: TVectorExt);
- begin
- FCount := Length(V);
- FData := Copy(V);
- end;
- constructor TVectorRec.Create(ElementsCount: Word);
- begin
- FCount := ElementsCount;
- FData := nil;
- SetLength(FData, FCount);
- end;
- class operator TVectorRec.Add(V1, V2: TVectorRec): TVectorRec;
- var
- I: Integer;
- begin
- if (V1.FCount <> V2.FCount) then
- raise EMathError.Create(sWRONG_SIZE);
- Result := TVectorRec.Create(V1.FCount);
- for I := 0 to V1.FCount - 1 do
- Result.FData[I] := V1.FData[I] + V2.FData[I];
- end;
- class operator TVectorRec.Add(V: TVectorRec; Scalar: Extended): TVectorRec;
- var
- I: Integer;
- begin
- Result.Create(V.FCount);
- for I := 0 to V.FCount - 1 do
- Result.FData[I] := V.FData[I] + Scalar;
- end;
- class operator TVectorRec.Add(Scalar: Extended; V: TVectorRec): TVectorRec;
- begin
- Result := V + Scalar;
- end;
- procedure TVectorRec.CheckUnique;
- begin
- if NotUnique(@FData) then
- FData := Copy(FData);
- end;
- class operator TVectorRec.Divide(V1, V2: TVectorRec): TVectorRec;
- var
- I: Integer;
- begin
- if (V1.FCount <> V2.FCount) then
- raise EMathError.Create(sWRONG_SIZE);
- Result.Create(V1.FCount);
- for I := 0 to V1.FCount - 1 do
- Result.FData[I] := V1.FData[I] / V2.FData[I];
- end;
- class operator TVectorRec.Divide(V: TVectorRec; Scalar: Extended): TVectorRec;
- begin
- Result := V * (1 / Scalar);
- end;
- class operator TVectorRec.Implicit(V: TVectorExt): TVectorRec;
- begin
- Result.Create(V);
- end;
- procedure TVectorRec.Fill(Value: Extended);
- var
- I: Integer;
- begin
- if Value = 0 then
- begin
- FData := nil;
- SetLength(FData, FCount);
- end
- else
- for I := 0 to FCount - 1 do
- FData[I] := Value;
- end;
- function TVectorRec.GetElement(Index: Word): Extended;
- begin
- if (Index = 0) or (Index > FCount) then
- raise EMathError.Create(sWRONG_ELEMENT);
- Result := FData[Pred(Index)];
- end;
- class operator TVectorRec.Multiply(V: TVectorRec; Scalar: Extended): TVectorRec;
- var
- I: Integer;
- begin
- Result.Create(V.FCount);
- for I := 0 to V.FCount - 1 do
- Result.FData[I] := V.FData[I] * Scalar;
- end;
- class operator TVectorRec.Multiply(Scalar: Extended; V: TVectorRec): TVectorRec;
- begin
- Result := V * Scalar;
- end;
- function TVectorRec.Norm: Extended;
- begin
- Result := System.Math.Norm(FData);
- end;
- class operator TVectorRec.Multiply(V1, V2: TVectorRec): TVectorRec;
- begin
- if (V1.FCount <> 3) or (V2.FCount <> 3) then
- raise EMathError.Create(sWRONG_SIZE);
- Result.Create(V1.FCount);
- Result.FData[0] := V1.FData[1] * V2.FData[2] - V1.FData[2] * V2.FData[1];
- Result.FData[1] := V1.FData[2] * V2.FData[0] - V1.FData[0] * V2.FData[2];
- Result.FData[2] := V1.FData[0] * V2.FData[1] - V1.FData[1] * V2.FData[0];
- end;
- function TVectorRec.ScalarMult(V: TVectorRec): Extended;
- var
- I: Integer;
- begin
- if V.FCount <> FCount then
- raise EMathError.Create(sWRONG_SIZE);
- Result := 0.0;
- for I := 0 to FCount - 1 do
- Result := Result + FData[I] * V.FData[I];
- end;
- procedure TVectorRec.SetElement(Index: Word; Value: Extended);
- begin
- if (Index = 0) or (Index > FCount) then
- raise EMathError.Create(sWRONG_ELEMENT);
- CheckUnique;
- FData[Pred(Index)] := Value;
- end;
- class operator TVectorRec.Subtract(V1, V2: TVectorRec): TVectorRec;
- var
- I: Integer;
- begin
- if (V1.FCount <> V2.FCount) then
- raise EMathError.Create(sWRONG_SIZE);
- Result.Create(V1.FCount);
- for I := 0 to V1.FCount - 1 do
- Result.FData[I] := V1.FData[I] - V2.FData[I];
- end;
- class operator TVectorRec.Subtract(Scalar: Extended; V: TVectorRec): TVectorRec;
- var
- I: Integer;
- begin
- Result.Create(V.FCount);
- for I := 0 to V.FCount - 1 do
- Result.FData[I] := Scalar - V.FData[I];
- end;
- class operator TVectorRec.Subtract(V: TVectorRec; Scalar: Extended): TVectorRec;
- var
- I: Integer;
- begin
- Result.Create(V.FCount);
- for I := 0 to V.Count - 1 do
- Result.FData[I] := V.FData[I] - Scalar;
- end;
- function TVectorRec.SumOfElments: Extended;
- begin
- Result := Sum(FData);
- end;
- function TVectorRec.SumOfSquares: Extended;
- begin
- Result := System.Math.SumOfSquares(FData);
- end;
- function TVectorRec.ToQuat: TQuaternionRec;
- var
- ModVec: Extended;
- C1, C2: Extended;
- begin
- if (FCount <> 3) then
- raise EMathError.Create(sWRONG_SIZE);
- ModVec := Norm;
- C1 := Cos(ModVec / 2);
- if ModVec > 1E-15 then
- C2 := Sin(ModVec / 2) / ModVec
- else
- C2 := 1;
- Result := [C1, FData[0] * C2, FData[1] * C2, FData[2] * C2];
- end;
- function TVectorRec.TruncateSTI: TVectorRec;
- const
- Int32Max: Double = Integer.MaxValue;
- Int32Min: Double = Integer.MinValue;
- var
- I: Integer;
- begin
- Result.Create(FCount);
- for I := 0 to FCount - 1 do
- begin
- if (FData[I] >= Int32Min) and (FData[I] <= Int32Max) then
- Result.FData[I] := Trunc(FData[I])
- else if (FData[I] < Int32Min) then
- Result.FData[I] := Int32Min
- else
- Result.FData[I] := Int32Max;
- end;
- end;
- // -----------------------------
- // TQuaternionHelper
- // -----------------------------
- function TQuaternionHelper.ToMatrix: TMatrixRec;
- begin
- Result.Create(3, 3);
- Result[1, 1] := Sqr(FData[0]) + Sqr(FData[1]) - Sqr(FData[2]) - Sqr(FData[3]);
- Result[1, 2] := 2 * (FData[1] * FData[2] - FData[0] * FData[3]);
- Result[1, 3] := 2 * (FData[1] * FData[3] + FData[0] * FData[2]);
- Result[2, 1] := 2 * (FData[1] * FData[2] + FData[0] * FData[3]);
- Result[2, 2] := Sqr(FData[0]) - Sqr(FData[1]) + Sqr(FData[2]) - Sqr(FData[3]);
- Result[2, 3] := 2 * (FData[2] * FData[3] - FData[0] * FData[1]);
- Result[3, 1] := 2 * (FData[1] * FData[3] - FData[0] * FData[2]);
- Result[3, 2] := 2 * (FData[2] * FData[3] + FData[0] * FData[1]);
- Result[3, 3] := Sqr(FData[0]) - Sqr(FData[1]) - Sqr(FData[2]) + Sqr(FData[3]);
- end;
- // -----------------------------
- // TVectorHelper
- // -----------------------------
- function TVectorHelper.ToDiagMatrix: TMatrixRec;
- var
- I: Integer;
- begin
- Result.Create(FCount, FCount);
- for I := 0 to FCount - 1 do
- Result.FData[I, I] := FData[I];
- end;
- procedure Init(Obj, TypeInfoOfObj: Pointer; Offset: Integer = 0);
- const
- DefaultRowCount = 3;
- DefaultColCount = 3;
- VectorTypeName = 'TVectorRec';
- MatrixTypeName = 'TMatrixRec';
- var
- RTTIContext: TRttiContext;
- Field: TRttiField;
- ArrFld: TRttiArrayType;
- I: Integer;
- Dim: TCustomAttribute;
- RowCount, ColCount: Integer;
- OffsetFromArray: Integer;
- begin
- for Field in RTTIContext.GetType(TypeInfoOfObj).GetFields do
- begin
- if Field.FieldType <> nil then
- begin
- RowCount := DefaultRowCount;
- ColCount := DefaultColCount;
- for Dim in Field.GetAttributes do
- begin
- RowCount := (Dim as TDim).RowCount;
- ColCount := (Dim as TDim).ColCount;
- end;
- if Field.FieldType.TypeKind = tkArray then
- begin
- ArrFld := TRttiArrayType(Field.FieldType);
- if ArrFld.ElementType.TypeKind = tkRecord then
- begin
- for I := 0 to ArrFld.TotalElementCount - 1 do
- begin
- OffsetFromArray := I * ArrFld.ElementType.TypeSize;
- if ArrFld.ElementType.Name = VectorTypeName then
- PVectorRec(Integer(Obj) + Field.Offset + OffsetFromArray + Offset)
- ^ := TVectorRec.Create(RowCount)
- else if ArrFld.ElementType.Name = MatrixTypeName then
- PMatrixRec(Integer(Obj) + Field.Offset + OffsetFromArray + Offset)
- ^ := TMatrixRec.Create(RowCount, ColCount)
- else
- Init(Obj, ArrFld.ElementType.Handle,
- Field.Offset + OffsetFromArray);
- end;
- end;
- end
- else if Field.FieldType.TypeKind = tkRecord then
- begin
- if Field.FieldType.Name = VectorTypeName then
- PVectorRec(Integer(Obj) + Field.Offset + Offset)^ :=
- TVectorRec.Create(RowCount)
- else if Field.FieldType.Name = MatrixTypeName then
- PMatrixRec(Integer(Obj) + Field.Offset + Offset)^ :=
- TMatrixRec.Create(RowCount, ColCount)
- else
- Init(Obj, Field.FieldType.Handle, Field.Offset)
- end;
- end;
- end;
- end;
- // -----------------------------
- // TDim
- // -----------------------------
- constructor TDim.Create(ARowCount: Integer; AColCount: Integer = 0);
- begin
- FRowCount := ARowCount;
- FColCount := AColCount;
- end;
- // -----------------------------
- // TPoint2DRec
- // -----------------------------
- function TPoint2DRec.Create(X, Y: Extended): TPoint2DRec;
- begin
- Result.X := X;
- Result.Y := Y;
- end;
- procedure TPoint2DRec.SetPosition(const X, Y: Extended);
- begin
- Self.X := X;
- Self.Y := Y;
- end;
- function TPoint2DRec.Length: Extended;
- begin
- Result := Sqrt(Self.X * Self.X + Self.Y * Self.Y);
- end;
- function TPoint2DRec.Add(const APoint2D: TPoint2DRec): TPoint2DRec;
- begin
- Result.SetPosition(Self.X + APoint2D.X, Self.Y + APoint2D.Y);
- end;
- function TPoint2DRec.Distance(const APoint2D: TPoint2DRec): Extended;
- begin
- Result := Sqrt(Sqr(Self.X - APoint2D.X) + Sqr(Self.Y - APoint2D.Y));
- end;
- procedure TPoint2DRec.Offset(const ADeltaX, ADeltaY: Extended);
- begin
- Self.X := Self.X + ADeltaX;
- Self.Y := Self.Y + ADeltaY;
- end;
- class function TPoint2DRec.PointInCircle(const Point, Center: TPoint2DRec;
- const Radius: Integer): Boolean;
- begin
- Result := Point.Distance(Center) <= Radius;
- end;
- // -----------------------------
- // TPoint3DRec
- // -----------------------------
- function TPoint3DRec.Create(X, Y, Z: Extended): TPoint3DRec;
- begin
- Result.X := X;
- Result.Y := Y;
- Result.Z := Z;
- end;
- function TPoint3DRec.Add(const AGLPoint3D: TPoint3DRec): TPoint3DRec;
- begin
- Result.X := Self.X + AGLPoint3D.X;
- Result.Y := Self.Y + AGLPoint3D.Y;
- Result.Z := Self.Z + AGLPoint3D.Z;
- end;
- function TPoint3DRec.Distance(const APoint3D: TPoint3DRec): Extended;
- begin
- Result := Self.Length - APoint3D.Length;
- end;
- function TPoint3DRec.Length: Single;
- begin
- Result := Sqrt(Self.X * Self.X + Self.Y * Self.Y + Self.Z * Self.Z);
- end;
- procedure TPoint3DRec.Offset(const ADeltaX, ADeltaY, ADeltaZ: Extended);
- begin
- Self.X := Self.X + ADeltaX;
- Self.Y := Self.Y + ADeltaY;
- Self.Z := Self.Z + ADeltaZ;
- end;
- procedure TPoint3DRec.SetPosition(const X, Y, Z: Extended);
- begin
- Self.X := X;
- Self.Y := Y;
- Self.Z := Z;
- end;
- // -----------------------------
- // TVector2DRec
- // -----------------------------
- function TVector2DRec.Create(const AX, AY, AW: Single): TVector2DRec;
- begin
- Result.X := AX;
- Result.Y := AY;
- Result.W := AW;
- end;
- function TVector2DRec.CrossProduct(const AVector: TVector2DRec): TVector2DRec;
- begin
- Result.X := (Self.Y * AVector.W) - (Self.W * AVector.Y);
- Result.Y := (Self.W * AVector.X) - (Self.X * AVector.W);
- Result.W := (Self.X * AVector.Y) - (Self.Y * AVector.X);
- end;
- function TVector2DRec.DotProduct(const AVector: TVector2DRec): Extended;
- begin
- Result := (Self.X * AVector.X) + (Self.Y * AVector.Y) + (Self.W * AVector.W);
- end;
- function TVector2DRec.Add(const AVector2D: TVector2DRec): TVector2DRec;
- begin
- Result.X := Self.X + AVector2D.X;
- Result.Y := Self.Y + AVector2D.Y;
- Result.W := 1.0;
- end;
- function TVector2DRec.Length: Extended;
- begin
- Result := Sqrt((Self.X * Self.X) + (Self.Y * Self.Y));
- end;
- function TVector2DRec.Norm: Extended;
- begin
- Result := Sqr(Self.X) + Sqr(Self.Y);
- end;
- function TVector2DRec.Normalize: TVector2DRec;
- var
- invLen: Single;
- vn: Single;
- const
- Tolerance: Single = 1E-12;
- begin
- vn := Self.Norm;
- if vn > Tolerance then
- begin
- invLen := 1 / Sqrt(vn);
- Result.X := Self.X * invLen;
- Result.Y := Self.Y * invLen;
- end
- else
- Result := Self;
- end;
- // ---------------------------------
- // TVector3DRec
- // ---------------------------------
- function TVector3DRec.Create(const AX, AY, AZ, AW: Single): TVector3DRec;
- begin
- Result.X := AX;
- Result.Y := AY;
- Result.Z := AZ;
- Result.W := AW;
- end;
- function TVector3DRec.Add(const AVector3D: TVector3DRec): TVector3DRec;
- begin
- Result.X := Self.X + AVector3D.X;
- Result.Y := Self.Y + AVector3D.Y;
- Result.Z := Self.Z + AVector3D.Z;
- Result.W := 1.0;
- end;
- function TVector3DRec.Norm: Single;
- begin
- Result := Self.X * Self.X + Self.Y * Self.Y + Self.Z * Self.Z;
- end;
- function TVector3DRec.Normalize: TVector3DRec;
- var
- invLen: Single;
- vn: Single;
- const
- Tolerance: Single = 1E-12;
- begin
- vn := Self.Norm;
- if vn > 0 then
- begin
- invLen := 1 / Sqrt(vn);
- Result.X := Self.X * invLen;
- Result.Y := Self.Y * invLen;
- Result.Z := Self.Z * invLen;
- Result.W := 0;
- end
- else
- Result := Self;
- end;
- function TVector3DRec.DotProduct(const AVector3D: TVector3D): Single;
- begin
- Result := (Self.X * AVector3D.X) + (Self.Y * AVector3D.Y) +
- (Self.Z * AVector3D.Z);
- end;
- function TVector3DRec.CrossProduct(const AVector3D: TVector3D): TVector3D;
- begin
- Result.X := (Self.Y * AVector3D.Z) - (Self.Z * AVector3D.Y);
- Result.Y := (Self.Z * AVector3D.X) - (Self.X * AVector3D.Z);
- Result.Z := (Self.X * AVector3D.Y) - (Self.Y * AVector3D.X);
- end;
- function TVector3DRec.Length: Single;
- begin
- Result := Sqrt((Self.X * Self.X) + (Self.Y * Self.Y) + (Self.Z * Self.Z));
- end;
- // ---------------------------------
- // TQuaternionRec
- // ---------------------------------
- function TQuaternionRec.GetElement(Index: Byte): Extended;
- begin
- if (Index > 3) then
- raise EMathError.Create(sWRONG_ELEMENT);
- Result := FData[Index];
- end;
- class operator TQuaternionRec.Implicit(V: TVectorExt): TQuaternionRec;
- begin
- if (Length(V) <> 4) then
- raise EMathError.Create(sWRONG_SIZE);
- Move(V[0], Result.FData, SizeOf(Result.FData));
- end;
- function TQuaternionRec.Inv: TQuaternionRec;
- begin
- Result := [FData[0], -FData[1], -FData[2], -FData[3]];
- end;
- class operator TQuaternionRec.Multiply(Scalar: Extended; Q: TQuaternionRec)
- : TQuaternionRec;
- begin
- Result := Q * Scalar;
- end;
- class operator TQuaternionRec.Multiply(Q: TQuaternionRec; Sc: Extended)
- : TQuaternionRec;
- begin
- Result := [Q.FData[0] * Sc, Q.FData[1] * Sc, Q.FData[2] * Sc,
- Q.FData[3] * Sc];
- end;
- class operator TQuaternionRec.Multiply(Q1, Q2: TQuaternionRec): TQuaternionRec;
- var
- Mat: TMatrixRec;
- begin
- Mat := [[Q1.FData[0], -Q1.FData[1], -Q1.FData[2], -Q1.FData[3]],
- [Q1.FData[1], Q1.FData[0], -Q1.FData[3], Q1.FData[2]],
- [Q1.FData[2], Q1.FData[3], Q1.FData[0], -Q1.FData[1]],
- [Q1.FData[3], -Q1.FData[2], Q1.FData[1], Q1.FData[0]]];
- Result := Mat * Q2;
- end;
- constructor TQuaternionRec.Create(Q: TVectorExt);
- begin
- if Length(Q) <> 4 then
- raise EMathError.Create(sWRONG_SIZE);
- Move(Q[0], FData[0], SizeOf(FData));
- end;
- procedure TQuaternionRec.SetElement(Index: Byte; Value: Extended);
- begin
- if (Index > 3) then
- raise EMathError.Create(sWRONG_ELEMENT);
- FData[Index] := Value;
- end;
- function TQuaternionRec.TruncateSTI: TQuaternionRec;
- const
- Int32Max: Double = Integer.MaxValue;
- Int32Min: Double = Integer.MinValue;
- function xTrunc(Value: Extended): Double;
- begin
- if (Value >= Int32Min) and (Value <= Int32Max) then
- Result := Trunc(Value)
- else if (Value < Int32Min) then
- Result := Int32Min
- else
- Result := Int32Max;
- end;
- begin
- Result[0] := xTrunc(FData[0]);
- Result[1] := xTrunc(FData[1]);
- Result[2] := xTrunc(FData[2]);
- Result[3] := xTrunc(FData[3]);
- end;
- end.
|