Lineáris algebra demonstrációs
program
Ez a program azt próbálja bemutatni, hogy a
kétdimenziós vektortérben hogyan hatnak az egyes vektorokra a lineáris
transzformációk. Megadhatjuk a transzformáció mátrixát, megadhatjuk a
koordinátarendszerben az egységet. A statikus képen az egységkör kerületére
mutató vektorok képét fehér színnel rajzolja a program (a vektor végét jelző
nyíltól eltekintve), majd sárgával a transzformált vektorokat, melyek mindig egy
ellipszis (speciális esetben egy kör) kerületére mutatnak. Animációt is
bekapcsolhatunk, ekkor az eredeti vektor piros, a képvektor kék színben jelenik
meg, és a változási sebesség menet közben módosítható. Jó szórakozást a program
használatához.
A program egy futási képe:
A
program listája:
unit ULinalgDemo;
interface
uses
Windows, Messages, SysUtils, Classes,
Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Spin;
type
TfmLinalgDemo = class(TForm)
btKilepes: TButton;
btStart: TButton;
lbA11: TLabel;
edA11: TEdit;
lbA12: TLabel;
edA12: TEdit;
lbA21: TLabel;
edA21: TEdit;
lbA22: TLabel;
edA22: TEdit;
btAlap: TButton;
edMaxKoord: TEdit;
lbMaxKoord: TLabel;
lbSajat: TLabel;
lbSzogValt: TLabel;
edSzogValt: TEdit;
btAnimacio: TButton;
tiIdozito: TTimer;
seSebes: TSpinEdit;
lbSebes: TLabel;
Procedure KepTorles;
Procedure Alap;
procedure btAlapClick(Sender: TObject);
Procedure MatrixOlvas;
Procedure TranszformKepre;
Procedure SajatErtek;
Procedure IrEgyenes(M, B: Real);
Procedure NormEgyenes(A, B, C: Real);
procedure btStartClick(Sender: TObject);
procedure btKilepesClick(Sender: TObject);
procedure tiIdozitoTimer(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure btAnimacioClick(Sender: TObject);
procedure seSebesChange(Sender: TObject);
procedure edA11Change(Sender: TObject);
procedure edA12Change(Sender: TObject);
procedure edA21Change(Sender: TObject);
procedure edA22Change(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
Const Max=5000;
var
fmLinalgDemo: TfmLinalgDemo;
Xm,Ym, Xk,Yk: Integer; //képenyő és félképernyő méretek
N: Integer; //vektorok száma az egységkörben
P: Integer; //maximális egész koordináta
D: Integer; //egész koordináta-távolsága pixelben
Ds: Integer; //fokonkénti rajzolás
A: Array[1..2,1..2] Of Real; //a lineáris transzformáció mátrixa
K1, K2: Real; //a lineáris transzformáció sajátértékei
Animal: Boolean; //az animációt figyelő
AN: Integer; //az animációban aktuális vektor sorszáma
implementation
{$R *.DFM}
Procedure TfmLinalgDemo.KepTorles; //a képernyő törlése
Var R: TRect;
Begin
R.Left:= 0; R.Top:= 0; R.Right:= Xm; R.Bottom:= Ym; Canvas.FillRect(R);
lbMaxKoord.Repaint; lbSzogValt.Repaint;
lbA11.Repaint; lbA12.Repaint;
lbA21.Repaint; lbA22.Repaint;
lbSajat.Repaint;
End;
procedure TfmLinalgDemo.Alap; //koordinátarendszer és az egységkör
Var I: Integer;
Begin
Xm:= ClientWidth; Ym:= ClientHeight;
Xk:= Xm Div 2; Yk:= Ym Div 2; D:= Yk Div P;
With Canvas Do
Begin
Pen.Color:= clBlack;
MoveTo(Xk,0); LineTo(Xk,Ym);
MoveTo(Xk-Yk,Yk); LineTo(Xk+Yk,Yk);
For I:= 1 To P Do
Begin
MoveTo(Xk+I*D,Yk-5); LineTo(Xk+I*D,Yk+5);
TextOut(Xk+I*D,Yk+10,IntToStr(I));
MoveTo(Xk-I*D,Yk-5); LineTo(Xk-I*D,Yk+5);
TextOut(Xk-I*D-4,Yk+10,'-'+IntToStr(I));
MoveTo(Xk-5,Yk+I*D); LineTo(Xk+5,Yk+I*D);
TextOut(Xk-20,Yk+I*D-6,'-'+IntToStr(I));
MoveTo(Xk-5,Yk-I*D); LineTo(Xk+5,Yk-I*D);
TextOut(Xk-20,Yk-I*D-6,IntToStr(I));
End;
Pen.Color:= clWhite;
For I:= 1 To N Do
Begin
MoveTo(Xk,Yk);
LineTo(Xk + Round(D*Cos(I*Ds*Pi/180)), Yk - Round(D*Sin(I*Ds*Pi/180)));
End;
End;
End;
procedure TfmLinalgDemo.btAlapClick(Sender: TObject);
Var Kod: Integer;
begin
Val(edSzogValt.Text,Ds,Kod); N:= Round(360/Ds);
Val(edMaxKoord.Text,P,Kod);
KepTorles; Alap;
Animal:= False; btAnimacio.Enabled:= False;
end;
Procedure TfmLinalgDemo.MatrixOlvas; //a maátrix beolvasása ellenőrzés nélkül
Var Kod: Integer;
Begin
Val(edA11.Text,A[1,1],Kod); Val(edA12.Text,A[1,2],Kod);
Val(edA21.Text,A[2,1],Kod); Val(edA22.Text,A[2,2],Kod);
End;
procedure TfmLinalgDemo.edA11Change(Sender: TObject);
begin
MatrixOlvas; Keptorles;
btAlapClick(Sender); btStartClick(Sender);
end;
procedure TfmLinalgDemo.edA12Change(Sender: TObject);
begin
MatrixOlvas; Keptorles;
btAlapClick(Sender); btStartClick(Sender);
end;
procedure TfmLinalgDemo.edA21Change(Sender: TObject);
begin
MatrixOlvas; Keptorles;
btAlapClick(Sender); btStartClick(Sender);
end;
procedure TfmLinalgDemo.edA22Change(Sender: TObject);
begin
MatrixOlvas; Keptorles;
btAlapClick(Sender); btStartClick(Sender);
end;
Procedure TfmLinalgDemo.TranszformKepre; //a kör transzformáltjának rajzolása
Var I: Word;
Begin
With Canvas Do
Begin
Pen.Color:= clYellow;
For I:= 1 To N Do
Begin
MoveTo(Xk,Yk);
LineTo(Xk + Round(A[1,1]*D*Cos(I*Ds*Pi/180)+A[1,2]*D*Sin(I*Ds*Pi/180)),
Yk - Round(A[2,1]*D*Sin(I*Ds*Pi/180)+A[2,2]*D*Sin(I*Ds*Pi/180)));
End;
End;
End;
Procedure TfmLinalgDemo.SajatErtek; //a sájátértékek meghatározása
Var DetA, SpurA, Di: Real;
S1, S2, S: String;
N1, N2, M1, M2: Real;
Begin
DetA:= A[1,1]*A[2,2]-A[2,1]*A[1,2]; //a mátrix determinánsa
SpurA:= A[1,1]+A[2,2]; //a mátrix spurja
//a karakterisztikus egyenlet: k*k - SpurA*k + DetA = 0
Di:= SpurA*SpurA-4*DetA; //a karakterisztikus egyenlet
//diszkriminánsa
If Di>=0 Then //két valós gyök
Begin
K1:= (SpurA+Sqrt(Di))/2; //sajátértékek
K2:= (SpurA-Sqrt(Di))/2;
Str(K1:4:2, S1);
Str(K2:4:2, S2);
S:= 'Sajátérték: '+S1+' és '+S2;
N1:= A[2,2]-A[1,2]-K1;
N2:= A[2,2]-A[1,2]-K2;
With Canvas Do
Begin
If N1<>0 Then M1:= (A[1,1]-A[2,1]-K1)/N1 Else M1:= Max;
If N2<>0 Then M2:= (A[1,1]-A[2,1]-K2)/N2 Else M2:= Max;
Pen.Color:= clGreen;
If M1=0 Then M1:= 1/Max; IrEgyenes(M1,0);
If M2=0 Then M2:= 1/Max; IrEgyenes(M2,0);
End;
End
Else S:= 'Nincs sajátérték';
lbSajat.Caption:= S;
End;
Procedure TfmLinalgDemo.IrEgyenes(M, B: Real); //irányvektoros egyenes
Begin
If M=0 Then Exit;
NormEgyenes(M,-1,B);
End;
Procedure TfmLinalgDemo.NormEgyenes(A, B, C: Real); //normálvektoros egyenes
Const Dx=50;
Dy=50;
Var Xh, Yh: Real;
Begin
If A*B=0 Then Exit;
Xh:= Xk/Dx; Yh:= Yk/Dy;
With Canvas Do
Begin
MoveTo(0, Yk+Round(Dy*(C-Xh*A)/B));
LineTo(Xm, Yk+Round(Dy*(C+Xh*A)/B));
MoveTo(Xk-Round(Dx*(C-Yh*B)/A), Ym);
LineTo(Xk-Round(Dx*(C+Yh*B)/A), 0);
End;
End;
procedure TfmLinalgDemo.btStartClick(Sender: TObject);
begin
KepTorles; btAlapClick(Sender);
MatrixOlvas; TranszformKepre; SajatErtek;
btAnimacio.Enabled:= True;
end;
procedure TfmLinalgDemo.tiIdozitoTimer(Sender: TObject);
begin
If Not Animal Then Exit;
With Canvas Do
Begin
Pen.Color:= clWhite;
MoveTo(Xk,Yk);
LineTo(Xk + Round(D*Cos(AN*Ds*Pi/180)), Yk - Round(D*Sin(AN*Ds*Pi/180)));
Pen.Color:= clYellow;
MoveTo(Xk,Yk);
LineTo(Xk + Round(A[1,1]*D*Cos(AN*Ds*Pi/180)+A[1,2]*D*Sin(AN*Ds*Pi/180)),
Yk - Round(A[2,1]*D*Sin(AN*Ds*Pi/180)+A[2,2]*D*Sin(AN*Ds*Pi/180)));
Inc(AN);
Pen.Color:= clRed;
MoveTo(Xk,Yk);
LineTo(Xk + Round(D*Cos(AN*Ds*Pi/180)), Yk - Round(D*Sin(AN*Ds*Pi/180)));
Pen.Color:= clBlue;
MoveTo(Xk,Yk);
LineTo(Xk + Round(A[1,1]*D*Cos(AN*Ds*Pi/180)+A[1,2]*D*Sin(AN*Ds*Pi/180)),
Yk - Round(A[2,1]*D*Sin(AN*Ds*Pi/180)+A[2,2]*D*Sin(AN*Ds*Pi/180)));
End;
end;
procedure TfmLinalgDemo.seSebesChange(Sender: TObject);
begin
tiIdozito.Interval:= seSebes.Value;
end;
procedure TfmLinalgDemo.FormCreate(Sender: TObject);
begin
Animal:= False; AN:= 0;
tiIdozito.Interval:= seSebes.Value;
end;
procedure TfmLinalgDemo.btAnimacioClick(Sender: TObject);
begin
Animal:= Not Animal;
With btAnimacio Do If Animal Then
Caption:= 'Animáció Ki' Else Caption:= 'Animáció Be';
end;
procedure TfmLinalgDemo.btKilepesClick(Sender: TObject);
begin
Close;
end;
end.