Ez a program síkbeli és térbeli
mozgásokat szimulál. A program fmMozgas főformjának stílusa: fsMDIForm, a sík
fmSik form és a tér fmTer stílusa: fsMDIChild. Azaz ez egy MDI alkalmazás,
melyben menük találhatók.
A főmenü amivel az egyes
formok hívhatók:

A
Sík form menüje, mellyel kiválaszthatjuk a mozgatni kívánt alakzatot, illetve
visszaléphetünk a főformra:

A
Tér form menüje, mellyel kiválaszthatjuk a kockát, mint mozgó testet, illetve
visszaléphetünk a főformra:

A Sík form futási képe, miközben egy
Hatszöget mozgat. A nyomógombok segítségével külön-külön az x és y irányba
történő lépés nagyságát (a mozgás sebességét), illetve az alakzat méretét
változtathatjuk. Mozgás közben az alakzat középpontja a képernyőn marad.

A Tér form futási képe, miközben rajta a kocka
rögzített középponttal forog. Nyomógombokkal az egyes irányok körüli forgás
sebességét változtathatjuk (szögváltozást két megjelenés között). A térbeliség
létrehozását a kocka oldallapjainak megvilágítottságának változásával oldjuk
meg. A fényforrás mögöttünk van, minél jobban elfordul a kocka lapja, annál
sötétebb zöld színű lesz:

A főmodul listája:
unit UMozgas;
interface
uses
Windows, Messages, SysUtils, Classes,
Graphics, Controls, Forms, Dialogs,
Menus, USik, UTer;
type
TfmMozgasok = class(TForm)
MainMenu1: TMainMenu;
Sikbeli1: TMenuItem;
Sikbeli2: TMenuItem;
Trbeli2: TMenuItem;
N1: TMenuItem;
Kilps1: TMenuItem;
procedure Kilps1Click(Sender: TObject);
procedure Sikbeli2Click(Sender: TObject);
procedure Trbeli2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
fmMozgasok: TfmMozgasok;
implementation
{$R *.DFM}
procedure TfmMozgasok.Kilps1Click(Sender: TObject);
begin
Close;
end;
procedure TfmMozgasok.Sikbeli2Click(Sender: TObject);
Var fmSik:TfmSik;
begin
fmSik:= TfmSik.Create(Self);
fmSik.Show;
end;
procedure TfmMozgasok.Trbeli2Click(Sender: TObject);
Var fmTer: TfmTer;
begin
fmTer:= TfmTer.Create(Self);
fmTer.Show;
end;
end.
A síkbeli mozgások modulja:
unit USik;
interface
uses
Windows, Messages, SysUtils, Classes,
Graphics, Controls, Forms, Dialogs, Menus, StdCtrls, ExtCtrls;
type
TfmSik = class(TForm)
MainMenu1: TMainMenu;
Sik1: TMenuItem;
miKor: TMenuItem;
miHaromszog: TMenuItem;
miNegyzet: TMenuItem;
miHatszog: TMenuItem;
N1: TMenuItem;
miKilepes: TMenuItem;
pnGomb: TPanel;
btX: TButton;
Timer1: TTimer;
btY: TButton;
btR: TButton;
procedure miKilepesClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure miKorClick(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure btXClick(Sender: TObject);
procedure btYClick(Sender: TObject);
procedure btRClick(Sender: TObject);
procedure miHaromszogClick(Sender: TObject);
procedure miNegyzetClick(Sender: TObject);
procedure miHatszogClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
fmSik: TfmSik;
mx,my,mb: Integer;
x,y,r,dx,dy,dr: Integer;
al,dal: Integer;
kor, haromszog, negyzet, hatszog: Boolean;
Pontok: Array[0..6] Of TPoint;
implementation
Procedure Ki;
Begin
Kor:= False;
Haromszog:= False;
Negyzet:= False;
Hatszog:= False;
End;
Procedure Allit;
Begin
Inc(x,dx); If (x-r<0) Or (x+r>mx) Then dx:=-dx;
Inc(y,dy); If (y-r<0) Or (y+r+r>my) Then dy:=-dy;
Inc(r,dr); If (r<10) Or (r>100) Then dr:=-dr;
Inc(al,dal); al:= al mod 360;
End;
Procedure Forgat;
Var px, py: Real;
i: Byte;
Begin
For i:=0 To 6 do
Begin
px:= (Pontok[i].x-x)*Cos(al*pi/180)
-(Pontok[i].y-y)*Sin(al*pi/180);
py:= (Pontok[i].x-x)*Sin(al*pi/180)
+(Pontok[i].y-y)*Cos(al*pi/180);
Pontok[i].x:= Round(px)+x;
Pontok[i].y:= Round(py)+y;
End;
End;
{$R *.DFM}
procedure TfmSik.miKilepesClick(Sender: TObject);
begin
Close;
end;
procedure TfmSik.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:= caFree;
end;
procedure TfmSik.FormCreate(Sender: TObject);
begin
mx:= GetDeviceCaps(Canvas.Handle,HorzRes);
my:= GetDeviceCaps(Canvas.Handle,VertRes);
mb:= GetDeviceCaps(Canvas.Handle,BitsPixel);
x:= mx div 2;
y:= my div 2;
r:= 20;
dx:= 1;
dy:= 1;
dr:= 0;
al:= 0;
dal:= 5;
Ki;
end;
procedure TfmSik.miKorClick(Sender: TObject);
begin
Ki; Kor:= True;
With Canvas Do
Begin
Brush.Color:=rgb(192,192,192);
Rectangle(0,0,mx,my);
Brush.Color:=rgb(0,0,192);
Ellipse(x-r,y-r,x+r,y+r);
Allit;
End;
end;
procedure TfmSik.Timer1Timer(Sender: TObject);
begin
If kor Then miKorClick(Sender);
If Haromszog Then miHaromszogClick(Sender);
If Negyzet Then miNegyzetClick(Sender);
If Hatszog Then miHatszogClick(Sender);
end;
procedure TfmSik.btXClick(Sender: TObject);
begin
dx:= dx+1;
btX.Caption:='DX='+IntToStr(dx);
end;
procedure TfmSik.btYClick(Sender: TObject);
begin
dy:= dy+1;
btY.Caption:='DY='+IntToStr(dy);
end;
procedure TfmSik.btRClick(Sender: TObject);
begin
dr:=dr+1;
btR.Caption:='DR='+IntToStr(dr);
end;
procedure TfmSik.miHaromszogClick(Sender: TObject);
begin
KI; Haromszog:= True;
Pontok[0].x:= x + r;
Pontok[0].y:= y;
Pontok[1].x:= x - Round(r/2);
Pontok[1].y:= y - Round(r*sqrt(3)/2);
Pontok[2].x:= x - Round(r/2);
Pontok[2].y:= y + Round(r*sqrt(3)/2);
Forgat;
With Canvas Do
Begin
Brush.Color:=rgb(192,192,192);
Rectangle(0,0,mx,my);
Brush.Color:=rgb(192,0,192);
Polygon(Slice(Pontok,3));
Allit;
End;
end;
procedure TfmSik.miNegyzetClick(Sender: TObject);
begin
KI; Negyzet:= True;
Pontok[0].x:= x + r;
Pontok[0].y:= y;
Pontok[1].x:= x;
Pontok[1].y:= y - r;
Pontok[2].x:= x - r;
Pontok[2].y:= y;
Pontok[3].x:= x;
Pontok[3].y:= y + r;
Forgat;
With Canvas Do
Begin
Brush.Color:=rgb(192,192,192);
Rectangle(0,0,mx,my);
Brush.Color:=rgb(192,0,192);
Polygon(Slice(Pontok,4));
Allit;
End;
end;
procedure TfmSik.miHatszogClick(Sender: TObject);
begin
KI; Hatszog:= True;
Pontok[0].x:= x + r;
Pontok[0].y:= y;
Pontok[1].x:= x + round(r/2);
Pontok[1].y:= y - Round(r*sqrt(3)/2);
Pontok[2].x:= x - Round(r/2);
Pontok[2].y:= y - Round(r*sqrt(3)/2);
Pontok[3].x:= x - r;
Pontok[3].y:= y;
Pontok[4].x:= x - Round(r/2);
Pontok[4].y:= y + Round(r*sqrt(3)/2);
Pontok[5].x:= x + Round(r/2);
Pontok[5].y:= y + Round(r*sqrt(3)/2);
Forgat;
With Canvas Do
Begin
Brush.Color:=rgb(192,192,192);
Rectangle(0,0,mx,my);
Brush.Color:=rgb(192,0,192);
Polygon(Slice(Pontok,6));
Allit;
End;
end;
end.
A térbeli mozgás modulja:
unit UTer;
interface
uses
Windows, Messages, SysUtils, Classes,
Graphics, Controls, Forms, Dialogs, Menus, StdCtrls, ExtCtrls;
type
TfmTer = class(TForm)
MainMenu1: TMainMenu;
Tr1: TMenuItem;
miKocka: TMenuItem;
N1: TMenuItem;
miKilepes: TMenuItem;
pnGomb: TPanel;
btPAl: TButton;
Timer1: TTimer;
btPBe: TButton;
btPGa: TButton;
btMAl: TButton;
btMBe: TButton;
btMGa: TButton;
procedure miKilepesClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure miKockaClick(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure btPAlClick(Sender: TObject);
procedure btPBeClick(Sender: TObject);
procedure btPGaClick(Sender: TObject);
procedure btMAlClick(Sender: TObject);
procedure btMBeClick(Sender: TObject);
procedure btMGaClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
Const c = 80; {Vetítés kp-ja a képernyőtől}
t = 50; {A valós tér középpontja a képernyőtől}
a = 2; {A kocka fél élhossza}
qx = 15; {Pixelsűrűség centiméterenként}
qy = 12;
Cs = 8; {Csúcsok száma}
Lc = 4; {Lapok csúcsszáma}
Ls = 6; {Lapok száma}
Type Vekt = Array[1..3] Of Real;
Csucsok= Array[1..Cs] Of Vekt;
Lapok = Array[1..Ls,1..Lc] Of Byte;
Const KTest: Csucsok= (( a,-a, a), ( a,-a,-a), (-a,-a,-a), (-a,-a, a),
( a, a, a), ( a, a,-a), (-a, a,-a), (-a, a, a));
KTestL: Lapok= ((1,4,3,2),(1,2,6,5),(2,3,7,6),
(3,4,8,7),(1,5,8,4),(5,6,7,8));
Al : Integer= 1;
Be : Integer= 2;
Ga : Integer= 3;
var
fmTer: TfmTer;
mx,my,mb: Integer;
x,y,r,dx,dy,dr: Integer;
kx, ky: Integer;
Gomb, Kocka, Oktaeder: Boolean;
implementation
{$R *.DFM}
Procedure Ki;
Begin
Gomb:= False;
Kocka:= False;
Oktaeder:= False;
End;
Procedure Forgatas;
Var i: Byte;
Px, Py, Pz: Real;
SinAl, CosAl, SinBe, CosBe, SinGa, CosGa: Real;
Begin
SinAl:= Sin(Al*pi/180); CosAl:= Cos(Al*pi/180);
SinBe:= Sin(Be*pi/180); CosBe:= Cos(Be*pi/180);
SinGa:= Sin(Ga*pi/180); CosGa:= Cos(Ga*pi/180);
For i:= 1 To Cs Do
Begin
Px:= KTest[i,1]*CosBe*CosGa-KTest[i,2]*CosBe*SinGa+KTest[i,3]*SinBe;
Py:= KTest[i,1]*(CosAl*SinGa+SinAl*SinBe*CosGa)+
KTest[i,2]*(CosAl*CosGa-SinAl*SinBe*SinGa)-
KTest[i,3]*SinAl*CosBe;
Pz:= KTest[i,1]*(SinAl*SinGa-CosAl*SinBe*CosGa)+
KTest[i,2]*(SinAl*CosGa+CosAl*SinBe*SinGa)+
KTest[i,3]*CosAl*CosBe;
KTest[i,1]:= Px;
KTest[i,2]:= Py;
KTest[i,3]:= Pz;
End;
End;
Procedure VektSzor(a, b: Vekt; Var s: Vekt);
Begin
s[1]:= a[2]*b[3]-a[3]*b[2];
s[2]:= a[3]*b[1]-a[1]*b[3];
s[3]:= a[1]*b[2]-a[2]*b[1];
End;
Procedure VektKul(a, b: Vekt; Var k: Vekt);
Begin
k[1]:= a[1]-b[1];
k[2]:= a[2]-b[2];
k[3]:= a[3]-b[3];
End;
procedure TfmTer.miKilepesClick(Sender: TObject);
begin
Close;
end;
procedure TfmTer.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:= caFree;
end;
procedure TfmTer.FormCreate(Sender: TObject);
begin
ki;
mx:= GetDeviceCaps(Canvas.Handle,HorzRes);
my:= GetDeviceCaps(Canvas.Handle,VertRes);
mb:= GetDeviceCaps(Canvas.Handle,BitsPixel);
kx:= mx div 2;
ky:= my div 2;
end;
procedure TfmTer.miKockaClick(Sender: TObject);
Procedure Vetites;
Var Kp: Array[1..Lc+1] Of TPoint;
i, j: Byte;
s, k1, k2: Vekt;
CosDe: Real;
Begin
With Canvas Do
Begin
Brush.Color:=rgb(192,192,192);
Rectangle(0,0,mx,my);
For I:= 1 To Ls Do
Begin
For J:= 1 To Lc Do
Begin
If j = 1 Then
Begin
Kp[Lc+1].x:= Round(Kx + c * KTest[KTestL[i,j],1] * qx/
(c - t - KTest[KTestL[i,j],3]));
Kp[Lc+1].y:= Round(Ky - c * KTest[KTestL[i,j],2] * qy/
(c - t - KTest[KTestL[i,j],3]));
End;
Kp[j].x:= Round(Kx + c * KTest[KTestL[i,j],1] * qx/
(c - t - KTest[KTestL[i,j],3]));
Kp[j].y:= Round(Ky - c * KTest[KTestL[i,j],2] * qy/
(c - t - KTest[KTestL[i,j],3]));
End;
If Kp[1].x*(Kp[2].y-Kp[3].y)+
Kp[2].x*(Kp[3].y-Kp[1].y)+
Kp[3].x*(Kp[1].y-Kp[2].y)<0 Then
Begin
VektKul(KTest[KTestL[i,2]],KTest[KTestL[i,1]],K1);
VektKul(KTest[KTestL[i,3]],KTest[KTestL[i,2]],K2);
VektSzor(K1, K2, S);
CosDe:= s[3] / Sqrt(s[1]*s[1]+s[2]*s[2]+s[3]*s[3]);
Brush.Color:=rgb(0,
Round(255*CosDe),
Round(255*CosDe));
Polygon(Slice(Kp,Lc));
End;
End;
End;
End;
begin
Ki; Kocka:= True;
Vetites;
Forgatas;
end;
procedure TfmTer.Timer1Timer(Sender: TObject);
begin
If Kocka Then miKockaClick(Sender);
end;
procedure TfmTer.btPAlClick(Sender: TObject);
begin
Inc(Al);
btPAl.Caption:='+Al='+IntToStr(Al);
btMAl.Caption:='-Al='+IntToStr(Al);
end;
procedure TfmTer.btPBeClick(Sender: TObject);
begin
Inc(Be);
btPBe.Caption:='+Be='+IntToStr(Be);
btMBe.Caption:='-Be='+IntToStr(Be);
end;
procedure TfmTer.btPGaClick(Sender: TObject);
begin
Inc(Ga);
btPGa.Caption:='+Ga='+IntToStr(Ga);
btMGa.Caption:='-Ga='+IntToStr(Ga);
end;
procedure TfmTer.btMAlClick(Sender: TObject);
begin
Dec(Al);
btPAl.Caption:='+Al='+IntToStr(Al);
btMAl.Caption:='-Al='+IntToStr(Al);
end;
procedure TfmTer.btMBeClick(Sender: TObject);
begin
Dec(Be);
btPBe.Caption:='+Be='+IntToStr(Be);
btMBe.Caption:='-Be='+IntToStr(Be);
end;
procedure TfmTer.btMGaClick(Sender: TObject);
begin
Dec(GA);
btPGa.Caption:='+Ga='+IntToStr(Ga);
btMGa.Caption:='-Ga='+IntToStr(Ga);
end;
end.
Ha kifeszített húrt, vagy egyik végén rögzített pálcát
megpendítünk, akkor rajtuk állóhullámok jönnek létre, és hangot adnak.
Ha húrt pendítünk meg, akkor az állóhullámoknak a húr
mindkét végén csomópontja van, ugyanis ezek rögzítve vannak, nem tudnak
elmozdulni. A kialakuló állóhullámok hullámhossza csak olyan lehet, hogy a húr
hossza a fél-hullámhossznak egész számú többszöröse. Ha egyik végén rögzített
pálcát pendítünk meg, akkor a húr hossza a kialakuló állóhullámok
negyed-hullámhosszának páratlanszám többszöröse (a rögzített végen csomópont, a
szabad végnél duzzadási hely van).
Ez a program a most leírt jelenségeket demonstrálja. A
húrt illetve a rudat kis átmérőjű fillezett körök alkotják, melyek
mint objektumok önálló, de egymással
összehangolt, rögzített amplitúdójú rezgőmozgást végeznek, ezzel együttes
hatásukban, a húr illetve a rúd rezgését szimulálják. Nyomógombok segítségével
a frekvenciát növelhetjük, illetve csökkenthetjük, valamint egy radiogroup
segítségével a jobb oldalon, a rögzített, illetve szabad vég között
választhatunk.
Egy húr rezgésének a maximális
kitéréshez közeli állapota, amikor a fél-hullámhossznak az ötszöröse a húr
hossza:

Egy rúd rezgésének a maximális kitéréshez közeli
állapota, amikor a negyed-hullámhossznak a tizenegyszerese a húr hossza:

A program listája:
unit URezgesek;
interface
uses
Windows, Messages, SysUtils, Variants, Classes,
Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;
type
TfmRezgesek = class(TForm)
lbRezgesek: TLabel;
tiIdozito: TTimer;
btKilepes: TButton;
btFrekiInc: TButton;
btFrekiDec: TButton;
rgVeg: TRadioGroup;
Procedure AtomInit;
procedure FormCreate(Sender: TObject);
procedure tiIdozitoTimer(Sender: TObject);
procedure btKilepesClick(Sender: TObject);
procedure btFrekiIncClick(Sender: TObject);
procedure btFrekiDecClick(Sender: TObject);
procedure FormPaint(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TAtom = Class
Fc, Fh: TColor;
Fa, Fx, Fy: Integer;
Fw, Fsz: Real;
Procedure Init(Ic,Ih: TColor; Ia,Ix,Iy: Integer; Iw,Isz: Real);
Procedure Show;
Procedure Hide;
Procedure Move;
Private
Ft: LongInt;
End;
Const Max=600;
Am=160;
R=3;
var
fmRezgesek: TfmRezgesek;
Xk,Yk: Integer;
AT: Array[1..Max] Of TAtom;
Fr, Sz: Word;
implementation
{$R *.dfm}
Procedure TAtom.Init(Ic,Ih: TColor; Ia,Ix,Iy: Integer; Iw,Isz: Real);
Begin
Fc:= Ic; Fh:= Ih;
Fa:= Ia; Fx:= Ix; Fy:= Iy;
Fw:= Iw; Fsz:= Isz;
Ft:= 0;
End;
Procedure TAtom.Show;
Begin
With fmRezgesek.Canvas Do
Begin
Brush.Color:= Fc;
Pen.Color:= Fc;
If R>0 Then
Ellipse(Fx-R,Fy-R,Fx+R,Fy+R) Else
Pixels[Fx,Fy]:= Fc;
End;
End;
Procedure TAtom.Hide;
Begin
With fmRezgesek.Canvas Do
Begin
Brush.Color:= Fh;
Pen.Color:= Fh;
If R>0 Then
Ellipse(Fx-R,Fy-R,Fx+R,Fy+R) Else
Pixels[Fx,Fy]:= Fh;
End;
End;
Procedure TAtom.Move;
Begin
Hide;
Inc(Ft);
Fy:= Yk+Round(Fa*Sin(Fw*Ft));
Show;
End;
Procedure TfmRezgesek.AtomInit;
Var I: Word;
Begin
With Canvas Do
Begin
Brush.Color:= clBtnFace;
Pen.Color:= clBtnFace;
Rectangle(Xk-Max Div 2-10,0, Xk+Max Div 2+10,Yk+Am+10);
With Font Do
Begin
Color:= clBlue;
Size:= 20;
End;
TextOut(Xk,20,FloatToStr(Fr*0.5));
End;
Sz:= 1+rgVeg.ItemIndex;
For I:= 1 To Max Do
AT[I].Init(clBlue,clBtnFace,
Round(Am*Sin(I*Pi/(Sz*600/Fr))),
Xk-(Max Div 2)+I,Yk,
0.04,I);
End;
procedure TfmRezgesek.btKilepesClick(Sender: TObject);
begin
Close;
end;
procedure TfmRezgesek.FormPaint(Sender: TObject);
begin
With Canvas Do
Begin
With Font Do
Begin
Color:= clBlue;
Size:= 20;
End;
TextOut(Xk,20,FloatToStr(Fr*0.5))
End;
end;
procedure TfmRezgesek.FormCreate(Sender: TObject);
Var I: Word;
begin
rgVeg.ItemIndex:= 0;
Xk:= ClientWidth Div 2;
Yk:= ClientHeight Div 2;
For I:= 1 To Max Do AT[I]:= TAtom.Create;
Fr:= 1;
AtomInit;
end;
procedure TfmRezgesek.btFrekiIncClick(Sender: TObject);
begin
Inc(Fr);
If (rgVeg.ItemIndex=1) And Not Odd(Fr) Then Inc(Fr); AtomInit;
end;
procedure TfmRezgesek.btFrekiDecClick(Sender: TObject);
begin
If Fr>1 Then
Begin
Dec(Fr);
AtomInit;
If (rgVeg.ItemIndex=1) And Odd(Fr) Then Dec(Fr);
End;
end;
procedure TfmRezgesek.tiIdozitoTimer(Sender: TObject);
Var I: Word;
begin
For I:= 1 To Max Do AT[I].Move;
end;
end.
Ha két egymásra merőleges tengelyű,
transzverzális sinusos rezgés interferál, az eredő a két rezgőmozgás relatív
fázisának és frekvenciájának megfelelően változik. Ha például a két rezgés
frekvenciája azonos és fáziskülönbségük nulla vagy 180 fok, akkor az eredő
rengés lineáris, ha a fáziskülönbség ettől eltérő, akkor ellipszis, egyenlő
amplitúdó és 90 fok eltérés esetén kör mentén játszódik le a rezgés. Ha a két
frekvencia nem azonos, akkor a rezgés a két frekvencia arányától függő,
bonyolultabb ábrákat, Lissayou görbéket kapunk. Ha a fáziskülönbségeket kis
mértékben folyamatosan változtatjuk, akkor a keletkezett rezgés is folyamatosan
változik.
Ez a program az utóbb leírt,
folyamatosan átalakuló Lissayou görbéket szemlélteti. A listába belejavítva, a
paraméterek változtatható (amplitúdó, fázisugrás). Futás közben az alap
frekvenciaarányok négy nyomógomb segítségével, egyesével változtathatók. A
folyamatos megjelenést időzítőre bíztam, melynek a kapcsolási intervalluma 1
ezred. A program 30000 ponttal rajzolja a görbéket, mely szám lassúbb gépeknél
csökkenthető.
A következő két futási képen a két
frekvenciának az aránya 6:5. Az első képen a fáziskülönbség 90 foknak egész
számú többszöröse, a második egy ettől kicsit eltérő (röviddel az előző után
létrejövő) fáziskülönbségű állapotot mutat.


A program listája:
unit ULissayou;
interface
uses
Windows, Messages, SysUtils, Variants, Classes,
Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TfmLissayou = class(TForm)
lbLissayou: TLabel;
btKilepes: TButton;
tiIdozito: TTimer;
btIncM: TButton;
btDecM: TButton;
btIncN: TButton;
btDecN: TButton;
Procedure KiirMN;
procedure btKilepesClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure tiIdozitoTimer(Sender: TObject);
procedure btIncMClick(Sender: TObject);
procedure btDecMClick(Sender: TObject);
procedure btIncNClick(Sender: TObject);
procedure btDecNClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
Type TPont= Class
Fc, Fh: TColor;
Fa, Fx, Fy: Integer;
Fw, Fsz: Real;
Procedure Init(Ic,Ih: TColor; Ia,Ix,Iy: Integer; Iw,Isz: Real);
Procedure Show;
Procedure Hide;
Procedure Move;
Private
Ft: Real;
End;
Const Max=30000;
Am=240;
D=0.55;
var
fmLissayou: TfmLissayou;
Xk,Yk: Integer;
PT: Array[1..Max] Of TPont;
M, N: Word;
implementation
{$R *.dfm}
Procedure TPont.Init(Ic,Ih: TColor; Ia,Ix,Iy: Integer; Iw,Isz: Real);
Begin
Fc:= Ic; Fh:= Ih;
Fa:= Ia; Fx:= Ix; Fy:= Iy;
Fw:= Iw; Fsz:= Isz;
Ft:= 0;
End;
Procedure TPont.Show;
Begin
fmLissayou.Canvas.Pixels[Fx,Fy]:= Fc;
End;
Procedure TPont.Hide;
Begin
fmLissayou.Canvas.Pixels[Fx,Fy]:= Fh;
End;
Procedure TPont.Move;
Begin
Hide;
Ft:= Ft+0.05;
Fx:= Xk+Round(Fa*Sin(Fw*Ft+M*Fsz));
Fy:= Yk+Round(Fa*Cos(Fw*Ft+N*Fsz+D*Ft));
Show;
End;
Procedure TfmLissayou.KiirMN;
Begin
With Canvas Do
Begin
Brush.Color:= clBtnFace;
Pen.Color:= clBtnFace;
Rectangle(Xk-20,10,Xk+80,40);
Rectangle(Xk+280,Yk,Xk+380,Yk+30);
With Font Do
Begin
Size:= 20;
Color:= clBlue;
End;
TextOut(Xk-20,10,'N: '+IntToStr(N));
TextOut(Xk+280,Yk,'M: '+IntToStr(M));
End;
End;
procedure TfmLissayou.btKilepesClick(Sender: TObject);
begin
Close;
end;
procedure TfmLissayou.FormCreate(Sender: TObject);
Var I: Word;
begin
Xk:= ClientWidth Div 2;
Yk:= ClientHeight Div 2;
M:= 1; N:= 2;
For I:= 1 To Max Do
Begin
PT[I]:= TPont.Create;
PT[I].Init(clBlue,clBtnFace, Am, Xk,Yk, 1, 0.04*I);
End;
end;
procedure TfmLissayou.tiIdozitoTimer(Sender: TObject);
Var I: Word;
begin
KiirMN;
For I:= 1 To Max Do PT[I].Move;
end;
procedure TfmLissayou.btIncMClick(Sender: TObject);
begin
Inc(M);
end;
procedure TfmLissayou.btDecMClick(Sender: TObject);
begin
If M>0 Then Dec(M);
end;
procedure TfmLissayou.btIncNClick(Sender: TObject);
begin
Inc(N);
end;
procedure TfmLissayou.btDecNClick(Sender: TObject);
begin
If N>0 Then Dec(N);
end;
end.
Az anyag atomjai, molekulái termikus
mozgást végeznek. Szilárd testekben egy hely közelében térbeli rezgőmozgás,
folyadékokban és gázokban helyváltoztató mozgás figyelhető meg. Folyadékban és
gázokban a részecskék mozgására a Brown mozgás létéből következtethetünk, ahol
a részecskék az anyagban lebegő makroszkopikus részecskéknek ütközve, azokat
rendszertelen, zegzugos mozgásra kényszerítik. Ez a jelenség annál intenzívebb,
minél magasabb az anyag hőmérséklete. A helyváltoztató mozgás közben egymással
is ütköznek, a mozgás kaotikus lesz.
Ez a program az ütközés mellett, néhány, a termikus
mozgás következtében létrejövő makroszkopikus jelenséget modellez úgy, hogy az anyag alkotó elemeit látható mértékig növeli, számát viszont
kezelhető számosságra csökkenti. A program futási képe animáció nélkül:

Az animációk a nyomógombokkal indíthatók. Az
elindított animációt az újabb animáció leállítja, de csak leállítást elérhetünk
a Stop nyomógombbal is.
Két egymástól különböző tömegű
részecske ütközésekor az egymásnak okozott lendületváltozások a részecskék
tömegével arányos. Az animáció automatikusan akkor is leáll, ha a részecskék
elhagyják a képernyőt.

Kiterjedés: a kezdetben nagyon
kis helyre lokalizált részecske a hő-mozgás következtében egyre nagyobb teret
foglal el, végső soron mintegy gázfelhő, egyenletesen kitölti a rendelkezésre
álló teret.

Keveredés: helyezkedjen el
egymáshoz közel két nagyszámú, de különböző részecskékből (kék és piros) álló
anyaghalmaz. Ha megengedett a hő-mozgás miatti kapcsolatuk (nincs elválasztó
fal köztük), akkor egy bizonyos idő elteltével a részecskék teljesen
összekeverednek. A kezdet:

Rövid idő múlva:

A párolgás: az edényben,
kezdetben 820 részecske található. A hő-mozgás következtében a folyadék
felszínén részecskék távoznak. Mindig az, amelyik elég közel kerül a
felülethez, és a mozgás következtében az új helye a folyadékfelszín fölött
lenne. A folyamatot lényegesen gyorsíthatjuk a hőmérséklet növelésével, melyet
a T+ feliratú nyomógomb segítségével érhetünk el (a T- nyomógomb a
hőmérsékletet csökkenti). A kezdet:

Melegítéssel gyorsítva a folyamatot:

Az ozmózis: az ozmózis
jelenségét egy féligáteresztő hártya két oldalán elhelyezkedő folyadék
keveredésével mutatjuk be. A féligáteresztő hártya például a kék színű
részecskéket nem engedi át, a pirosakat pedig igen. Ennek hatására a baloldali
tartályba a jobboldaliból piros részecskék diffundálnak át, és ennek
következtében a kezdetben egyenlő nyomásérték megváltozik, a baloldaliban
növekszik, a jobboldaliban csökken. A nyomáskülönbséget ozmózisnyomásnak
nevezzük. Például, ha egy meggyet, vagy szilvát vízbe helyezünk, akkor a víz
molekulái áthatolnak a gyümölcs féligáteresztő héján, és végül az ozmózisnyomás
a gyümölcsöket szétrepeszti. Az állapot a folyamat elején:

Majd a melegítés hatására, egy bizonyos
idő múlva, a következőt láthatjuk:

Áramlás: az utolsó animáció egy
csőben történő áramlást szemlélteti. A futási kép, amikor a gázfelhő a cső
közepén jár:

A program listája:
unit UAtomok;
interface
uses
Windows, Messages, SysUtils, Variants, Classes,
Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;
type
TfmAtomok = class(TForm)
btUtkozes: TButton;
btKilepes: TButton;
tiIdozito: TTimer;
btStop: TButton;
btKiterjedes: TButton;
btKeveredes: TButton;
btParolgas: TButton;
btTP: TButton;
btTM: TButton;
btOzmozis: TButton;
btAramlas: TButton;
lbAtom: TLabel;
procedure btUtkozesClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure btKilepesClick(Sender: TObject);
procedure tiIdozitoTimer(Sender: TObject);
procedure btStopClick(Sender: TObject);
procedure btKiterjedesClick(Sender: TObject);
procedure btKeveredesClick(Sender: TObject);
procedure btParolgasClick(Sender: TObject);
procedure btTPClick(Sender: TObject);
procedure btTMClick(Sender: TObject);
procedure btOzmozisClick(Sender: TObject);
procedure btAramlasClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TAtom= Object
Fr: Byte;
Fc: TColor;
Procedure Init(Ir: Byte; Ic: TColor);
Procedure SetXY(X, Y: Integer);
Procedure SetV(Vx, Vy: Integer);
Procedure Show;
Procedure Hide;
Procedure MozogXY(X, Y: Integer);
Procedure MozogRel(Dx, Dy: Integer);
Procedure MozogBent(Bx, By, Jx, Jy, Dx, Dy, Tip: Integer);
Procedure MozogSeb;
Function GetX: Integer;
Function GetY: Integer;
Function GetVx: Integer;
Function GetVy: Integer;
Private Fx, Fy, FVx, FVy: Integer;
End;
Const M= 1000;
var
fmAtomok: TfmAtomok;
Xk, Yk, Xm, Ym: Integer;
Tip: Byte;
A, B: TAtom;
Ra, Rb: Integer;
Sx, Sy: Integer;
At, Bt: Array[1..M] Of TAtom;
Bx, By, Jx, Jy: Integer;
K, L, P, Q, Dx, Dy, T, D: Longint;
implementation
{$R *.dfm}
procedure TfmAtomok.btKilepesClick(Sender: TObject);
begin
Close;
end;
procedure TfmAtomok.FormCreate(Sender: TObject);
begin
Xm:= ClientWidth; Xk:= Xm Div 2;
Ym:= ClientHeight; Yk:= Ym Div 2;
Tip:= 0;
Randomize;
end;
Procedure TAtom.Init(Ir: Byte; Ic: TColor);
Begin
Fr:= Ir; Fc:= Ic; Fx:= -Fr; Fy:= -Fr;
End;
Procedure TAtom.SetXY(X, Y: Integer);
Begin
Fx:= X; Fy:= Y;
End;
Procedure TAtom.SetV(Vx, Vy: Integer);
Begin
FVx:= Vx; FVy:= Vy;
End;
Procedure TAtom.Show;
Begin
With fmAtomok.Canvas Do
Begin
Pen.Color:= Fc;
Brush.Color:= Fc;
Ellipse(Fx-Fr,Fy-Fr, Fx+Fr,Fy+Fr);
End;
End;
Procedure TAtom.Hide;
Begin
With fmAtomok.Canvas Do
Begin
Pen.Color:= clBtnFace;
Brush.Color:= clBtnFace;
Ellipse(Fx-Fr,Fy-Fr, Fx+Fr,Fy+Fr);
End;
End;
Procedure TAtom.MozogXY(X, Y: Integer);
Begin
Hide; SetXY(X, Y); Show;
End;
Procedure TAtom.MozogRel(Dx, Dy: Integer);
Begin
Hide; SetXY(GetX + Dx, GetY + Dy); Show;
End;
Procedure TAtom.MozogBent(Bx, By, Jx, Jy, Dx, Dy, Tip: Integer);
Begin
Hide;
Case Tip Of
1: Begin {fent}
If (GetX+Dx<=Bx+1) Or (GetX+Dx>=Jx-1) Then Dx:= -Dx;
If (GetY+Dy>=Jy-1) Then Dy:= -Dy;
End;
2: Begin {jobbra}
If (GetX+Dx<=Bx+1) Then Dx:= -Dx;
If (GetY+DY<=BY+1) Or (GetY+Dy>=Jy-1) Then Dy:= -Dy;
End;
3: Begin {le}
If (GetX+Dx<=Bx+1) Or (GetX+Dx>=Jx-1) Then Dx:= -Dx;
If (GetY+DY<=BY+1) Then Dy:= -Dy;
End;
4: Begin {balra}
If (GetX+Dx>=Jx-1) Then Dx:= -Dx;
If (GetY+DY<=BY+1) Or (GetY+Dy>=Jy-1) Then Dy:= -Dy;
End;
5: Begin {fel-le}
If (GetX+Dx<=Bx+1) Or (GetX+Dx>=Jx-1) Then Dx:= -Dx;
End;
6: Begin {jobbra-balra}
If (GetY+DY<=BY+1) Or (GetY+Dy>=Jy-1) Then Dy:= -Dy;
End;
7: Begin {fel-jobbra}
If (GetX+Dx<=Bx+1) Then Dx:= -Dx;
If (GetY+Dy>=Jy-1) Then Dy:= -Dy;
End;
8: Begin {le-balra}
If (GetX+Dx>=Jx-1) Then Dx:= -Dx;
If (GetY+DY<=BY+1) Then Dy:= -Dy;
End;
9: Begin {fel-balra}
If (GetX+Dx<=Bx+1) Then Dx:= -Dx;
If (GetY+DY<=BY+1) Then Dy:= -Dy;
End;
10: Begin {le-jobbra}
If (GetX+Dx>=Jx-1) Then Dx:= -Dx;
If (GetY+Dy>=Jy-1) Then Dy:= -Dy;
End;
11: Begin {z rt}
If (GetX+Dx<=Bx+1) Or (GetX+Dx>=Jx-1) Then Dx:= -Dx;
If (GetY+DY<=BY+1) Or (GetY+Dy>=Jy-1) Then Dy:= -Dy;
End;
End;
MozogRel(Dx, Dy);
Show;
End;
Procedure TAtom.MozogSeb;
Begin
Hide; SetXY(GetX + FVx, GetY + FVy); Show;
End;
Function TAtom.GetX: Integer;
Begin
GetX:= Fx;
End;
Function TAtom.GetY: Integer;
Begin
GetY:= Fy;
End;
Function TAtom.GetVx: Integer;
Begin
GetVx:= FVx;
End;
Function TAtom.GetVy: Integer;
Begin
GetVy:= FVy;
End;
procedure TfmAtomok.btUtkozesClick(Sender: TObject);
begin
btStopClick(Sender);
Ra:= 25; Rb:= 10;
With A Do Begin Init(Ra, clBlue); SetXY( 0,0); SetV( 3,2); Show End;
With B Do Begin Init(Rb, ClRed); SetXY(Xk,0); SetV(-2,2); Show End;
Tip:= 1;
end;
procedure TfmAtomok.btKiterjedesClick(Sender: TObject);
Var I: Word;
begin
btStopClick(Sender);
For I:= 1 To M Do With At[I] Do
Begin Init(1,clRed); SetXY(Xk,Yk); Show End;
Tip:= 2;
end;
procedure TfmAtomok.btKeveredesClick(Sender: TObject);
Var I: Word;
begin
btStopClick(Sender);
For I:= 1 To M Do With At[I] Do
Begin Init(1,clBlue); SetXY(Xk-20,Yk); Show End;
For I:= 1 To M Do With Bt[I] Do
Begin Init(1,clRed); SetXY(Xk+20,Yk); Show End;
Tip:= 3;
end;
procedure TfmAtomok.btParolgasClick(Sender: TObject);
Var I, J: Word;
begin
btStopClick(Sender);
Bx:= Round(0.3*Xm); By:= Yk;
Jx:= Round(0.7*Xm); Jy:= Round(0.8*Ym);
With Canvas Do
Begin
With Pen Do
Begin
Color:= clWhite;
Width:= 3;
End;
MoveTo(Bx, Round(0.4*Ym)); LineTo(Bx, Jy);
LineTo(Jx, Jy); LineTo(Jx, Round(0.4*Ym));
Pen.Color:= clBlue;
MoveTo(Bx+1, By); LineTo(Jx-1, By);
End;
K:= Jx - Bx - 2; L:= Jy - By - 2;
P:= Round(Sqrt(K*M/L))-3; Q:= Round(Sqrt(L*M/K))-3;
Dx:= Round(K/P); Dy:= Round(L/Q);
For J:= 1 To Q Do For I:= 1 To P Do With At[(J-1)*P+I] Do
Begin Init(1,clBlue); SetXY(Bx+(I-1)*Dx+4, By+(J-1)*Dy+4); Show End;
T:= 3;
Tip:= 4;
end;
procedure TfmAtomok.btOzmozisClick(Sender: TObject);
Var I, J: Word;
begin
btStopClick(Sender);
Bx:= Round(0.2*Xm); By:= Round(0.25*Ym);
Jx:= Round(0.8*Xm); Jy:= Round(0.75*Ym);
With Canvas Do
Begin
With Pen Do
Begin
Color:= clWhite;
Width:= 3;
End;
Brush.Color:= clBtnFace;
Rectangle(Bx,By, Jx,Jy);
MoveTo(Xk, By+1); LineTo(Xk, Jy-1);
End;
K:= (Jx - Bx) Div 2 - 2; L:= Jy - By - 2;
P:= Round(Sqrt(K*M/L))-2; Q:= Round(Sqrt(L*M/K))-2;
Dx:= Round(K/P); Dy:= Round(L/Q);
For J:= 1 To Q Do For I:= 1 To P Do With At[(J-1)*P+I] Do
Begin Init(1,clBlue); SetXY(Bx+(I-1)*Dx+6, By+(J-1)*Dy+6); Show End;
For J:= 1 To Q Do For I:= 1 To P Do With Bt[(J-1)*P+I] Do
Begin Init(1,clRed); SetXY(Xk+(I-1)*Dx+6, By+(J-1)*Dy+6); Show End;
T:= 3;
Tip:= 5;
end;
procedure TfmAtomok.btAramlasClick(Sender: TObject);
Var I: Word;
begin
btStopClick(Sender);
D:= 20;
With Canvas Do
Begin
With Pen Do
Begin
Color:= clBlack;
Width:= 1;
End;
MoveTo(0,Yk-D); LineTo(Xm,Yk-D); MoveTo(0,Yk+D); LineTo(Xm,Yk+D);
End;
For I:= 1 To M Do With At[I] Do
Begin Init(1,clBlue); SetXY(0,Yk); Show End;
T:= 3;
Tip:= 6;
end;
procedure TfmAtomok.btTPClick(Sender: TObject);
begin
Inc(T,2);
end;
procedure TfmAtomok.btTMClick(Sender: TObject);
begin
If T>4 Then Dec(T,2);
end;
procedure TfmAtomok.tiIdozitoTimer(Sender: TObject);
Var I, S, Sa, Sb: Word;
begin
Case Tip Of
1: Begin
If B.GetX-A.GetX<= Ra+Rb Then
Begin
Sx:= Round(2*(Ra*Ra*A.GetVx+Rb*Rb*B.GetVx)/(Ra*Ra+Rb*Rb));
Sy:= Round(2*(Ra*Ra*A.GetVy+Rb*Rb*B.GetVy)/(Ra*Ra+Rb*Rb));
A.SetV(Sx-A.GetVx, Sy-A.GetVy);
B.SetV(Sx-B.GetVx, Sy-B.GetVy)
End;
A.MozogSeb; B.MozogSeb;
If (A.GetX>2*Xk) And (A.GetY>2*Yk) And
(B.GetX>2*Xk) And (B.GetY>2*Yk) Then btStopClick(Sender);
End;
2: For I:= 1 To M Do At[I].MozogRel(Random(5)-2, Random(5)-2);
3: For I:= 1 To M Do
Begin
At[I].MozogRel(Random(5)-2, Random(5)-2);
Bt[I].MozogRel(Random(5)-2, Random(5)-2);
End;
4: Begin
S:= 0;
For I:= 1 To Q*P Do With AT[I] Do
Begin
If GetY>By Then
Begin
Inc(S);
MozogBent(Bx+2, By+2, Jx-2, Jy-2,
Random(T)-(T Div 2),Random(T)-(T Div 2),1);
End Else Hide;
With Canvas Do
Begin
Pen.Color:= clBlue;
MoveTo(Bx+1, By); LineTo(Jx-1, By);
End;
End;
With Canvas Do
Begin
Pen.Color:= clBlue;
Brush.Color:= clBtnFace;
Font.Size:= 24;
TextOut(Xk-20,50,IntToStr(S)+'/'+IntToStr(T)+' ');
End;
End;
5: Begin
Sa:= 0; Sb:= 0;
For I:= 1 To Q*P Do With AT[I] Do
Begin
Inc(Sa);
MozogBent(Bx+2, By+2, Xk-2, Jy-2,
Random(T)-(T Div 2), Random(T)-(T Div 2),11);
End;
For I:= 1 To Q*P Do With BT[I] Do
Begin
If GetX<Xk Then Inc(Sa) Else Inc(Sb);
MozogBent(Bx+2, By+2, Jx-2, Jy-2,
Random(T)-(T Div 2), Random(T)-(T Div 2),11);
End;
With Canvas Do
Begin
Pen.Color:= clBlue;
MoveTo(Xk,By+1); LineTo(Xk,Jy-1);
Font.Size:= 24;
Brush.Color:= clBtnFace;
TextOut(Xk Div 2-20,50,IntToStr(Sa)+' ');
TextOut(Xk, 50, IntToStr(T)+' ');
TextOut(Xk+Xk Div 2-20,50,IntToStr(Sb)+' ');
End;
End;
6: For I:= 1 To M Do
At[I].MozogBent(0,Yk-D, Xm,Yk+D,
Random(T)-(T Div 2)+1, Random(T)-(T Div 2),6);
End;
end;
procedure TfmAtomok.btStopClick(Sender: TObject);
Var I: Word;
begin
A.Hide; B.Hide;
For I:= 1 To M Do Begin At[I].Hide; Bt[I].Hide End;
Canvas.Rectangle(0,0,Xm,Ym);
Tip:= 0;
lbAtom.Repaint;
end;
end.