TVec3 = array[1..3] of Extended; TMatrix3x3 = array[1..3, 1..3] of Extended; function MVMult(M: TMatrix3x3; V: TVec3): TVec3;
TAbstractVector = array of Extended; TAbstractMatrix = array of array of Extended;
TQuaternion = record private FData: array[0..3] of Extended; procedure SetElement(Index: Byte; Value: Extended); function GetElement(Index: Byte): Extended; public property Element[Index: Byte]: Extended read GetElement write SetElement; default; end; TVector = record private FData: TAbstractVector; FCount: Word; procedure SetElement(Index: Word; Value: Extended); function GetElement(Index: Word): Extended; public constructor Create(ElementsCount: Word); property Count: Word read FCount; property Elements[Index: Word]: Extended read GetElement write SetElement; default; end; TMatrix = record private FData: TAbstractMatrix; FRowsCount: Word; FColsCount: Word; procedure SetElement(Row, Col: Word; Value: Extended); function GetElement(Row, Col: Word): Extended; public constructor Create(RowsCount, ColsCount: Word); property RowCount: Word read FRowsCount; property ColCount: Word read FColsCount; property Elements[Row, Col: Word]: Extended read GetElement write SetElement; default; end;
constructor TVector.Create(ElementsCount: Word); begin FCount := ElementsCount; FData := nil; SetLength(FData, FCount); end; constructor TMatrix.Create(RowsCount, ColsCount: Word); begin FRowsCount := RowsCount; FColsCount := ColsCount; FData := nil; SetLength(FData, FRowsCount, FColsCount); end;
function TVector.GetElement(Index: Word): Extended; begin {$R+} Result := FData[Pred(Index)]; end; procedure TVector.SetElement(Index: Word; Value: Extended); begin {$R+} FData[Pred(Index)] := Value; end;
var V: TVector; . . . V := TVector.Create(3); V[1] := 1; V[2] := 2; V[3] := 3;
TQuaternion = record public . . . constructor Create(Q: TAbstractVector); class operator Implicit(V: TAbstractVector): TQuaternion; end; TVector = record public . . . constructor Create(V: TAbstractVector); overload; class operator Implicit(V: TAbstractVector): TVector; end; TMatrix = record public . . . constructor Create(M: TAbstractMatrix); overload; class operator Implicit(M: TAbstractMatrix): TMatrix; end;
constructor TQuaternion.Create(Q: TAbstractVector); begin if Length(Q) <> 4 then raise EMathError.Create(WRONG_SIZE); Move(Q[0], FData[0], SizeOf(FData)); end; class operator TQuaternion.Implicit(V: TAbstractVector): TQuaternion; begin Result.Create(V); end; constructor TVector.Create(V: TAbstractVector); begin FCount := Length(V); FData := Copy(V); end; class operator TVector.Implicit(V: TAbstractVector): TVector; begin Result.Create(V); end; constructor TMatrix.Create(M: TAbstractMatrix); var I: Integer; begin FRowsCount := Length(M); FColsCount := Length(M[0]); FData := nil; SetLength(FData, FRowsCount, FColsCount); for I := 0 to Pred(FRowsCount) do FData[I] := Copy(M[I]); end; class operator TMatrix.Implicit(M: TAbstractMatrix): TMatrix; begin Result.Create(M); end;
var V: TVector; M: TMatrix; . . . V := [4, 5, 6]; // M := [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
TMatrix = record public . . . class operator Multiply(M: TMatrix; V: TVector): TVector; end; class operator TMatrix.Multiply(M: TMatrix; V: TVector): TVector; var I, J: Integer; begin if (M.FColsCount <> V.FCount) then raise EMathError.Create(WRONG_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;
var V, VResult: TVector; M: TMatrix; . . . VResult := M * V;
function TVec(V: TAbstractVector): TVector; begin Result.Create(V); end; function TMat(M: TAbstractMatrix): TMatrix; begin Result.Create(M); end; function TQuat(Q: TAbstractVector): TQuaternion; begin Result.Create(Q); end;
V := TMat([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) * TVec([4, 5, 6]);
TMatrix = record public . . . function Inv: TMatrix; end; function TMatrix.Inv: TMatrix; var Ipiv, Indxr, Indxc: array of Integer; DimMat, I, J, K, L, N, ICol, IRow: Integer; Big, Dum, Pivinv: Extended; begin // . if (FRowsCount <> FColsCount) then raise EMathError.Create(NOT_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(SINGULAR); 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;
var M, MStore: TMatrix; . . . MStore := M; M := M.Inv;
{$POINTERMATH ON} function NotUnique(var Arr): Boolean; begin Result := (PCardinal(Arr) - 2)^ > 1; end;
procedure TVector.SetElement(Index: Word; Value: Extended); begin {$R+} CheckUnique; FData[Pred(Index)] := Value; end; procedure TVector.CheckUnique; begin if NotUnique(FData) then FData := Copy(FData); end; procedure TMatrix.SetElement(Row, Col: Word; Value: Extended); begin {$R+} CheckUnique; FData[Pred(Row), Pred(Col)] := Value; end; procedure TMatrix.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;
var V: TVector; M: TMatrix; begin // V[1] := 1; // : V := TVector.Create(4); // M := TMatrix.Create(4, 4); // // V := [1, 0, 0, 0]; // // V := M * TVec([1, 0, 0, 0]); // V[1] := 1; // :
TMovement = record R: TVector; V: TVector; W: TVector; Color: TVector; end; TMovementScheme = class private FMovement: array[1..100] of TMovement; FOrientation: TMatrix; 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; constructor TDim.Create(ARowCount: Integer; AColCount: Integer = 0); begin FRowCount := ARowCount; FColCount := AColCount; end;
TMovement = record [TDim(3)] R: TVector; [TDim(3)] V: TVector; [TDim(3)] W: TVector; [TDim(4)] Color: TVector; end; TMovementScheme = class private FMovement: array[1..100] of TMovement; [TDim(3, 3)] FOrientation: TMatrix; end;
procedure Init(Obj, TypeInfoOfObj: Pointer; Offset: Integer = 0); const DefaultRowCount = 3; DefaultColCount = 3; VectorTypeName = 'TVector'; MatrixTypeName = 'TMatrix'; 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 PVector(Integer(Obj) + Field.Offset + OffsetFromArray + Offset)^ := TVector.Create(RowCount) else if ArrFld.ElementType.Name = MatrixTypeName then PMatrix(Integer(Obj) + Field.Offset + OffsetFromArray + Offset)^ := TMatrix.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 PVector(Integer(Obj) + Field.Offset + Offset)^ := TVector.Create(RowCount) else if Field.FieldType.Name = MatrixTypeName then PMatrix(Integer(Obj) + Field.Offset + Offset)^ := TMatrix.Create(RowCount, ColCount) else Init(Obj, Field.FieldType.Handle, Field.Offset) end; end; end; end;
TMovementScheme = class . . . public constructor Create; end; constructor TMovementScheme.Create; begin Init(Self, Self.ClassInfo); end;
var Movement: TMovement; . . . Init(@Movement, TypeInfo(TMovement));
Source: https://habr.com/ru/post/340612/
All Articles