diff options
| author | Eugen Wissner <belka@caraus.de> | 2025-12-17 12:12:16 +0100 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2025-12-17 12:13:15 +0100 |
| commit | 6d7c43c85f8852ed3b3fa9cefc742bc87e941842 (patch) | |
| tree | 20da65c403c17b962027469897500de626a958f4 /Занимательное программирование/3/5_ideal_gas | |
| parent | 2878f1e34c2c2e19d5b7f6fd368dbf9ec0c6277f (diff) | |
| download | book-exercises-6d7c43c85f8852ed3b3fa9cefc742bc87e941842.tar.gz | |
Добавил третью главу занимательного программирования
Diffstat (limited to 'Занимательное программирование/3/5_ideal_gas')
6 files changed, 825 insertions, 0 deletions
diff --git a/Занимательное программирование/3/5_ideal_gas/geometry.pas b/Занимательное программирование/3/5_ideal_gas/geometry.pas new file mode 100644 index 0000000..cbbff5d --- /dev/null +++ b/Занимательное программирование/3/5_ideal_gas/geometry.pas @@ -0,0 +1,344 @@ +unit Geometry;
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils;
+
+type
+ { Вершины }
+ Vertex = record
+ x, y, z: Real; { Координаты вершины }
+ end;
+ { Ребра }
+ Edge = record
+ src, dest: Integer; { Индексы соединяемых вершин }
+ end;
+
+ Object3D = class
+ public
+ vertices: array of Vertex; { вершины }
+ edges: array of Edge; { ребра }
+ xc, yc, zc: Real; { координаты центра объекта }
+ vx, vy, vz: Real; { значения составляющих его скорости }
+ xa, ya, za: Real; { скорость вращения вокруг оси }
+
+ constructor Create(var center, velocity, axis: Vertex);
+
+ procedure MoveCenter();
+ end;
+
+ Matrix = array[1..4, 1..4] of Real; { матрица 4x4 }
+ Column = array[1..4] of Real; { столбец }
+
+function CopyObject3D(Shape: Object3D): Object3D;
+
+{ умножение матрицы на матрицу }
+function MMMult(lhs, rhs: Matrix): Matrix;
+{ умножение матрицы на столбец }
+function MCMult(lhs: Matrix; rhs: Column): Column;
+{ матрица поворота модели }
+function RotateMatrix(xa, ya, za: Real): Matrix;
+function MoveMatrix(tx, ty, tz: Real): Matrix;
+function ResizeMatrix(sx, sy, sz: Real): Matrix;
+procedure RotateShape(Shape: Object3D);
+procedure MoveShape(Shape: Object3D; Width, Height: Real);
+procedure ResizeShape(var Shape: Object3D; sx, sy, sz: Real);
+
+implementation
+
+constructor Object3D.Create(var center, velocity, axis: Vertex);
+const
+ size = 10;
+ cubeVertices: array of Vertex = (
+ (x: -size; y: -size; z: -size),
+ (x: -size; y: size; z: -size),
+ (x: size; y: size; z: -size),
+ (x: size; y: -size; z: -size),
+ (x: -size; y: -size; z: size),
+ (x: -size; y: size; z: size),
+ (x: size; y: size; z: size),
+ (x: size; y: -size; z: size)
+ );
+ cubeEdges: array of Edge = (
+ (src: 0; dest: 1),
+ (src: 1; dest: 2),
+ (src: 2; dest: 3),
+ (src: 3; dest: 0),
+ (src: 4; dest: 5),
+ (src: 5; dest: 6),
+ (src: 6; dest: 7),
+ (src: 7; dest: 4),
+ (src: 0; dest: 4),
+ (src: 1; dest: 5),
+ (src: 2; dest: 6),
+ (src: 3; dest: 7)
+ );
+begin
+ vertices := cubeVertices;
+ edges := cubeEdges;
+ xc := center.x;
+ yc := center.y;
+ zc := center.z;
+ vx := velocity.x;
+ vy := velocity.y;
+ vz := velocity.z;
+ xa := axis.x;
+ ya := axis.y;
+ za := axis.z
+end;
+
+procedure Object3D.MoveCenter();
+begin
+ xc := xc + Vx;
+ yc := yc + Vy;
+ zc := zc + Vz
+end;
+
+function CopyObject3D(Shape: Object3D): Object3D;
+begin
+ CopyObject3D.vertices := Copy(Shape.vertices, 0);
+ CopyObject3D.edges := Copy(Shape.edges, 0);
+
+ CopyObject3D.xc := Shape.xc;
+ CopyObject3D.yc := Shape.yc;
+ CopyObject3D.zc := Shape.zc
+end;
+
+function MMMult(lhs, rhs: Matrix): Matrix;
+var
+ i, j, k: Integer;
+ r: Matrix;
+ s: Real;
+begin
+ for i := 1 to 4 do
+ for j := 1 to 4 do
+ begin
+ s := 0;
+ for k := 1 to 4 do
+ s := s + lhs[i, k] * rhs[k, j];
+ r[i, j] := s;
+ end;
+ MMMult := r;
+end;
+
+function MCMult(lhs: Matrix; rhs: Column): Column;
+var
+ k, i: Integer;
+ s: Real;
+ r: Column;
+begin
+ for i := 1 to 4 do { аналогично MMMult }
+ begin
+ s := 0;
+
+ for k := 1 to 4 do
+ s := s + lhs[i, k] * rhs[k];
+ r[i] := s;
+ end;
+
+ MCMult := r;
+end;
+
+function RotateMatrix(xa, ya, za: Real): Matrix;
+var
+ xr, yr, zr: Matrix;
+begin
+ { матрица поворота вокруг оси Ox }
+ xr[1, 1] := 1;
+ xr[1, 2] := 0;
+ xr[1, 3] := 0;
+ xr[1, 4] := 0;
+
+ xr[2, 1] := 0;
+ xr[2, 2] := Cos(xa);
+ xr[2, 3] := -Sin(xa);
+ xr[2, 4] := 0;
+
+ xr[3, 1] := 0;
+ xr[3, 2] := Sin(xa);
+ xr[3, 3] := Cos(xa);
+ xr[3, 4] := 0;
+
+ xr[4, 1] := 0;
+ xr[4, 2] := 0;
+ xr[4, 3] := 0;
+ xr[4, 4] := 1;
+
+ { матрица поворота вокруг оси Oy }
+ yr[1, 1] := Cos(ya);
+ yr[1, 2] := 0;
+ yr[1, 3] := Sin(ya);
+ yr[1, 4] := 0;
+
+ yr[2, 1] := 0;
+ yr[2, 2] := 1;
+ yr[2, 3] := 0;
+ yr[2, 4] := 0;
+
+ yr[3, 1] := -Sin(ya);
+ yr[3, 2] := 0;
+ yr[3, 3] := Cos(ya);
+ yr[3, 4] := 0;
+
+ yr[4, 1] := 0;
+ yr[4, 2] := 0;
+ yr[4, 3] := 0;
+ yr[4, 4] := 1;
+
+ { матрица поворота вокруг оси Oz }
+ zr[1, 1] := Cos(za);
+ zr[1, 2] := -Sin(za);
+ zr[1, 3] := 0;
+ zr[1, 4] := 0;
+
+ zr[2, 1] := Sin(za);
+ zr[2, 2] := Cos(za);
+ zr[2, 3] := 0;
+ zr[2, 4] := 0;
+
+ zr[3, 1] := 0;
+ zr[3, 2] := 0;
+ zr[3, 3] := 1;
+ zr[3, 4] := 0;
+
+ zr[4, 1] := 0;
+ zr[4, 2] := 0;
+ zr[4, 3] := 0;
+ zr[4, 4] := 1;
+
+ RotateMatrix := MMMult(MMMult(xr, yr), zr)
+end;
+
+function MoveMatrix(tx, ty, tz: Real): Matrix;
+begin
+ MoveMatrix[1, 1] := 1;
+ MoveMatrix[1, 2] := 0;
+ MoveMatrix[1, 3] := 0;
+ MoveMatrix[1, 4] := tx;
+
+ MoveMatrix[2, 1] := 0;
+ MoveMatrix[2, 2] := 1;
+ MoveMatrix[2, 3] := 0;
+ MoveMatrix[2, 4] := ty;
+
+ MoveMatrix[3, 1] := 0;
+ MoveMatrix[3, 2] := 0;
+ MoveMatrix[3, 3] := 1;
+ MoveMatrix[3, 4] := tz;
+
+ MoveMatrix[4, 1] := 0;
+ MoveMatrix[4, 2] := 0;
+ MoveMatrix[4, 3] := 0;
+ MoveMatrix[4, 4] := 1
+end;
+
+function ResizeMatrix(sx, sy, sz: Real): Matrix;
+begin
+ ResizeMatrix[1, 1] := sx;
+ ResizeMatrix[1, 2] := 0;
+ ResizeMatrix[1, 3] := 0;
+ ResizeMatrix[1, 4] := 0;
+
+ ResizeMatrix[2, 1] := 0;
+ ResizeMatrix[2, 2] := sy;
+ ResizeMatrix[2, 3] := 0;
+ ResizeMatrix[2, 4] := 0;
+
+ ResizeMatrix[3, 1] := 0;
+ ResizeMatrix[3, 2] := 0;
+ ResizeMatrix[3, 3] := sz;
+ ResizeMatrix[3, 4] := 0;
+
+ ResizeMatrix[4, 1] := 0;
+ ResizeMatrix[4, 2] := 0;
+ ResizeMatrix[4, 3] := 0;
+ ResizeMatrix[4, 4] := 1
+end;
+
+procedure RotateShape(Shape: Object3D);
+var
+ rm: Matrix;
+ i: Integer;
+ c: Column;
+begin
+ rm := RotateMatrix(Shape.xa, Shape.ya, Shape.za); { сгенерировать матрицу вращения }
+ c[4] := 1; { последний элемент столбца всегда равен единице }
+
+ for i := 0 to High(Shape.vertices) do { цикл по всем вершинам }
+ begin { High(a) возвращает верхний индекс массива a }
+ c[1] := Shape.vertices[i].x; { инициализация столбца }
+ c[2] := Shape.vertices[i].y;
+ c[3] := Shape.vertices[i].z;
+
+ c := MCMult(rm, c); { вызов преобразования }
+
+ Shape.vertices[i].x := c[1]; { внесение изменений в модель }
+ Shape.vertices[i].y := c[2]; { в соответствии с полученным }
+ Shape.vertices[i].z := c[3] { результатом преобразования }
+ end
+end;
+
+procedure MoveShape(Shape: Object3D; Width, Height: Real);
+begin
+ if Shape.xc > Width then
+ begin
+ Shape.xc := Width;
+ Shape.Vx := -Shape.Vx
+ end;
+ if Shape.xc < -Width then
+ begin
+ Shape.xc := -Width;
+ Shape.Vx := -Shape.Vx
+ end;
+
+ if Shape.yc > Height then
+ begin
+ Shape.yc := Height;
+ Shape.Vy := -Shape.Vy
+ end;
+ if Shape.yc < -Height then
+ begin
+ Shape.yc := -Height;
+ Shape.Vy := -Shape.Vy
+ end;
+
+ if Shape.zc > 500 then
+ begin
+ Shape.zc := 500;
+ Shape.Vz := -Shape.Vz
+ end;
+ if Shape.zc < 200 then
+ begin
+ Shape.zc := 200;
+ Shape.Vz := -Shape.Vz
+ end;
+end;
+
+procedure ResizeShape(var Shape: Object3D; sx, sy, sz: Real);
+var
+ mm: Matrix;
+ i: Integer;
+ c: Column;
+begin
+ mm := ResizeMatrix(sx, sy, sz);
+ c[4] := 1;
+
+ for i := 0 to High(Shape.vertices) do
+ begin
+ c[1] := Shape.vertices[i].x;
+ c[2] := Shape.vertices[i].y;
+ c[3] := Shape.vertices[i].z;
+
+ c := MCMult(mm, c);
+
+ Shape.vertices[i].x := c[1];
+ Shape.vertices[i].y := c[2];
+ Shape.vertices[i].z := c[3]
+ end
+end;
+
+end.
+
diff --git a/Занимательное программирование/3/5_ideal_gas/graphics_3d.lpi b/Занимательное программирование/3/5_ideal_gas/graphics_3d.lpi new file mode 100644 index 0000000..67fa0db --- /dev/null +++ b/Занимательное программирование/3/5_ideal_gas/graphics_3d.lpi @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+ <ProjectOptions>
+ <Version Value="12"/>
+ <PathDelim Value="\"/>
+ <General>
+ <SessionStorage Value="InProjectDir"/>
+ <Title Value="graphics_3d"/>
+ <Scaled Value="True"/>
+ <ResourceType Value="res"/>
+ <UseXPManifest Value="True"/>
+ <XPManifest>
+ <DpiAware Value="True"/>
+ </XPManifest>
+ <Icon Value="0"/>
+ </General>
+ <BuildModes>
+ <Item Name="Default" Default="True"/>
+ </BuildModes>
+ <PublishOptions>
+ <Version Value="2"/>
+ <UseFileFilters Value="True"/>
+ </PublishOptions>
+ <RunParams>
+ <FormatVersion Value="2"/>
+ </RunParams>
+ <RequiredPackages>
+ <Item>
+ <PackageName Value="LCL"/>
+ </Item>
+ </RequiredPackages>
+ <Units>
+ <Unit>
+ <Filename Value="graphics_3d.lpr"/>
+ <IsPartOfProject Value="True"/>
+ </Unit>
+ <Unit>
+ <Filename Value="octahedron.pas"/>
+ <IsPartOfProject Value="True"/>
+ <ComponentName Value="Form1"/>
+ <HasResources Value="True"/>
+ <ResourceBaseClass Value="Form"/>
+ <UnitName Value="Octahedron"/>
+ </Unit>
+ <Unit>
+ <Filename Value="geometry.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="Geometry"/>
+ </Unit>
+ <Unit>
+ <Filename Value="octahedron.txt"/>
+ <IsPartOfProject Value="True"/>
+ </Unit>
+ </Units>
+ </ProjectOptions>
+ <CompilerOptions>
+ <Version Value="11"/>
+ <PathDelim Value="\"/>
+ <Target>
+ <Filename Value="graphics_3d"/>
+ </Target>
+ <SearchPaths>
+ <IncludeFiles Value="$(ProjOutDir)"/>
+ <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+ </SearchPaths>
+ <Linking>
+ <Debugging>
+ <DebugInfoType Value="dsDwarf3"/>
+ </Debugging>
+ <Options>
+ <Win32>
+ <GraphicApplication Value="True"/>
+ </Win32>
+ </Options>
+ </Linking>
+ </CompilerOptions>
+ <Debugging>
+ <Exceptions>
+ <Item>
+ <Name Value="EAbort"/>
+ </Item>
+ <Item>
+ <Name Value="ECodetoolError"/>
+ </Item>
+ <Item>
+ <Name Value="EFOpenError"/>
+ </Item>
+ </Exceptions>
+ </Debugging>
+</CONFIG>
diff --git a/Занимательное программирование/3/5_ideal_gas/graphics_3d.lpr b/Занимательное программирование/3/5_ideal_gas/graphics_3d.lpr new file mode 100644 index 0000000..3778580 --- /dev/null +++ b/Занимательное программирование/3/5_ideal_gas/graphics_3d.lpr @@ -0,0 +1,29 @@ +program graphics_3d;
+
+{$mode objfpc}{$H+}
+
+uses
+ {$IFDEF UNIX}
+ cthreads,
+ {$ENDIF}
+ {$IFDEF HASAMIGA}
+ athreads,
+ {$ENDIF}
+ Interfaces, // this includes the LCL widgetset
+ Forms, Octahedron, geometry
+ { you can add units after this };
+
+{$R *.res}
+
+begin
+ Randomize;
+ RequireDerivedFormResource:=True;
+ Application.Scaled:=True;
+ {$PUSH}{$WARN 5044 OFF}
+ Application.MainFormOnTaskbar:=True;
+ {$POP}
+ Application.Initialize;
+ Application.CreateForm(TForm1, Form1);
+ Application.Run;
+end.
+
diff --git a/Занимательное программирование/3/5_ideal_gas/graphics_3d.lps b/Занимательное программирование/3/5_ideal_gas/graphics_3d.lps new file mode 100644 index 0000000..d227996 --- /dev/null +++ b/Занимательное программирование/3/5_ideal_gas/graphics_3d.lps @@ -0,0 +1,179 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+ <ProjectSession>
+ <PathDelim Value="\"/>
+ <Version Value="12"/>
+ <BuildModes Active="Default"/>
+ <Units>
+ <Unit>
+ <Filename Value="graphics_3d.lpr"/>
+ <IsPartOfProject Value="True"/>
+ <EditorIndex Value="1"/>
+ <CursorPos X="20"/>
+ <UsageCount Value="58"/>
+ <Loaded Value="True"/>
+ </Unit>
+ <Unit>
+ <Filename Value="octahedron.pas"/>
+ <IsPartOfProject Value="True"/>
+ <ComponentName Value="Form1"/>
+ <HasResources Value="True"/>
+ <ResourceBaseClass Value="Form"/>
+ <UnitName Value="Octahedron"/>
+ <IsVisibleTab Value="True"/>
+ <TopLine Value="13"/>
+ <CursorPos X="23" Y="21"/>
+ <UsageCount Value="58"/>
+ <Bookmarks Count="1">
+ <Item0 X="17" Y="48" Left="1" Top="79" ID="3"/>
+ </Bookmarks>
+ <Loaded Value="True"/>
+ <LoadedDesigner Value="True"/>
+ </Unit>
+ <Unit>
+ <Filename Value="geometry.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="Geometry"/>
+ <EditorIndex Value="2"/>
+ <TopLine Value="50"/>
+ <CursorPos X="29" Y="52"/>
+ <UsageCount Value="58"/>
+ <Loaded Value="True"/>
+ </Unit>
+ <Unit>
+ <Filename Value="octahedron.txt"/>
+ <IsPartOfProject Value="True"/>
+ <EditorIndex Value="-1"/>
+ <CursorPos X="15" Y="13"/>
+ <UsageCount Value="58"/>
+ <DefaultSyntaxHighlighter Value="Text"/>
+ </Unit>
+ </Units>
+ <JumpHistory HistoryIndex="29">
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="81" Column="24" TopLine="56"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="96" Column="10" TopLine="72"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="103" Column="22" TopLine="79"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="106" Column="24" TopLine="81"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="107" Column="22" TopLine="83"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="112" Column="12" TopLine="88"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="15" Column="11" TopLine="8"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="81" Column="24" TopLine="56"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="87" Column="19" TopLine="76"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="98" Column="11" TopLine="76"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="106" Column="21" TopLine="82"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="108" Column="23" TopLine="84"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="110" Column="21" TopLine="86"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="115" Column="11" TopLine="91"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="81" Column="24" TopLine="65"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="98" Column="11" TopLine="74"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="108" Column="22" TopLine="89"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="110" Column="27" TopLine="89"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="112" Column="25" TopLine="89"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="117" Column="15" TopLine="93"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="81" Column="26" TopLine="65"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="98" Column="13" TopLine="74"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="108" Column="25" TopLine="84"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="110" Column="27" TopLine="86"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="112" Column="25" TopLine="88"/>
+ </Position>
+ <Position>
+ <Filename Value="octahedron.pas"/>
+ <Caret Line="117" Column="15" TopLine="93"/>
+ </Position>
+ <Position>
+ <Filename Value="geometry.pas"/>
+ <Caret Line="14" Column="11"/>
+ </Position>
+ <Position>
+ <Filename Value="geometry.pas"/>
+ <Caret Line="49" Column="26" TopLine="33"/>
+ </Position>
+ <Position>
+ <Filename Value="geometry.pas"/>
+ <Caret Line="103" Column="34" TopLine="90"/>
+ </Position>
+ <Position>
+ <Filename Value="geometry.pas"/>
+ <Caret Line="28" Column="24" TopLine="11"/>
+ </Position>
+ </JumpHistory>
+ <RunParams>
+ <FormatVersion Value="2"/>
+ <Modes ActiveMode=""/>
+ </RunParams>
+ </ProjectSession>
+</CONFIG>
diff --git a/Занимательное программирование/3/5_ideal_gas/octahedron.lfm b/Занимательное программирование/3/5_ideal_gas/octahedron.lfm new file mode 100644 index 0000000..8db0965 --- /dev/null +++ b/Занимательное программирование/3/5_ideal_gas/octahedron.lfm @@ -0,0 +1,54 @@ +object Form1: TForm1
+ Left = 352
+ Height = 673
+ Top = 32
+ Width = 600
+ Caption = 'Form1'
+ ClientHeight = 673
+ ClientWidth = 600
+ DesignTimePPI = 120
+ LCLVersion = '4.2.0.0'
+ object BackScreen: TImage
+ AnchorSideLeft.Control = Owner
+ AnchorSideTop.Control = Owner
+ AnchorSideRight.Control = Owner
+ AnchorSideRight.Side = asrBottom
+ AnchorSideBottom.Control = StartStopBtn
+ Left = 0
+ Height = 600
+ Top = 0
+ Width = 600
+ Anchors = [akTop, akLeft, akRight, akBottom]
+ BorderSpacing.Bottom = 15
+ end
+ object Screen: TPaintBox
+ AnchorSideLeft.Control = Owner
+ AnchorSideTop.Control = Owner
+ AnchorSideRight.Control = Owner
+ AnchorSideRight.Side = asrBottom
+ AnchorSideBottom.Control = StartStopBtn
+ Left = 0
+ Height = 600
+ Top = 0
+ Width = 600
+ Anchors = [akTop, akLeft, akRight, akBottom]
+ BorderSpacing.Bottom = 15
+ end
+ object StartStopBtn: TButton
+ AnchorSideLeft.Control = Owner
+ AnchorSideLeft.Side = asrCenter
+ AnchorSideRight.Control = Owner
+ AnchorSideRight.Side = asrCenter
+ AnchorSideBottom.Control = Owner
+ AnchorSideBottom.Side = asrBottom
+ Left = 241
+ Height = 48
+ Top = 615
+ Width = 118
+ Anchors = [akLeft, akBottom]
+ BorderSpacing.Bottom = 10
+ Caption = 'Пуск'
+ TabOrder = 0
+ OnClick = StartStopBtnClick
+ end
+end
diff --git a/Занимательное программирование/3/5_ideal_gas/octahedron.pas b/Занимательное программирование/3/5_ideal_gas/octahedron.pas new file mode 100644 index 0000000..31fe970 --- /dev/null +++ b/Занимательное программирование/3/5_ideal_gas/octahedron.pas @@ -0,0 +1,129 @@ +unit Octahedron;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls,
+ Geometry;
+
+type
+
+ { TForm1 }
+
+ TForm1 = class(TForm)
+ BackScreen: TImage;
+ StartStopBtn: TButton;
+ Screen: TPaintBox;
+ procedure StartStopBtnClick(Sender: TObject);
+ private
+ Model: array[1..10] of Object3D; { трехмерный объект }
+ public
+
+ end;
+
+var
+ Form1: TForm1;
+ IsRunning: Boolean = false;
+
+implementation
+
+{$R *.lfm}
+
+procedure ShowShape(Shape: Object3D); { нарисовать объект }
+var
+ i, Xs, Ys: Integer;
+ x, y, z: Real;
+const
+ N = 300; { "глубина" экрана }
+begin
+ for i := 0 to High(Shape.edges) do { цикл по всем ребрам }
+ begin { координаты первой точки ребра }
+ x := Shape.vertices[Shape.edges[i].src].x + Shape.xc;
+ y := Shape.vertices[Shape.edges[i].src].y + Shape.yc;
+ z := Shape.vertices[Shape.edges[i].src].z + Shape.zc;
+ if Abs(z) < 0.01 then z := 0.01; { избегаем деления на нуль }
+ { вычисляем экранные координаты }
+ Xs := Round(Form1.Screen.Width div 2 + N * x / z);
+ Ys := Round(Form1.Screen.Height div 2 + N * y / z);
+
+ Form1.BackScreen.Canvas.MoveTo(Xs, Ys);
+ { координаты второй точки зрения }
+ x := Shape.vertices[Shape.edges[i].dest].x + Shape.xc;
+ y := Shape.vertices[Shape.edges[i].dest].y + Shape.yc;
+ z := Shape.vertices[Shape.edges[i].dest].z + Shape.zc;
+ if Abs(z) < 0.01 then z := 0.01; { избегаем деления на нуль }
+ { и ее экранные координаты }
+ Xs := Round(Form1.Screen.Width div 2 + N * x / z);
+ Ys := Round(Form1.Screen.Height div 2 + N * y / z);
+
+ Form1.BackScreen.Canvas.LineTo(Xs, Ys); { рисуем ребро }
+ end;
+end;
+
+{ TForm1 }
+
+procedure TForm1.StartStopBtnClick(Sender: TObject); { главная процедура }
+var
+ oldtime: TDateTime;
+ pause: Integer;
+ center, velocity, axis: Vertex;
+ i: Integer;
+const
+ MSecsPerFrame = 25; { скорость работы (кадров в секунду) }
+begin
+ if IsRunning then
+ begin
+ IsRunning := false;
+ StartStopBtn.Caption := 'Пуск';
+ for i := 1 to Length(Model) do
+ FreeAndNil(Model[i]);
+ Exit;
+ end;
+ StartStopBtn.Caption := 'Стоп';
+ IsRunning := true;
+
+ for i := 1 to Length(Model) do
+ begin
+ axis.x := Random(10) / 100; { скорость вращения вокруг оси Ox }
+ axis.y := Random(10) / 100; { скорость вращения вокруг оси Oy }
+ axis.z := Random(10) / 100; { скорость вращения вокруг оси Oz }
+ velocity.x := 10 - Random(20); { и составляющие }
+ velocity.y := 15 - Random(30); { скорости }
+ velocity.z := 20 - Random(40);
+ center.x := (Screen.Width div 2) - Random(Screen.Width); { начальное положение }
+ center.y := (Screen.Width div 2) - Random(Screen.Width); { начальное положение }
+ center.z := Random(300) + 200;
+ Model[i] := Object3D.Create(center, velocity, axis) { загрузить объект }
+ end;
+
+ while IsRunning do
+ begin
+ oldtime := Now;
+ BackScreen.Canvas.FillRect(Rect(0, 0, Screen.Width, Screen.Height));
+
+ for i := 1 to Length(Model) do
+ begin
+ { отразить от стена (3D-аналог "молекулы в закрытом сосуде") }
+ MoveShape(Model[i], BackScreen.Width div 2, BackScreen.Height div 2);
+
+ RotateShape(Model[i]); { поворот модели }
+ ShowShape(Model[i]); { очистить экран и нарисовать объект }
+ Model[i].MoveCenter()
+ end;
+ { отобразить объект на основном экране }
+ Screen.Canvas.CopyRect(Rect(0, 0, Screen.Width, Screen.Height),
+ BackScreen.Canvas, Rect(0, 0, Screen.Width, Screen.Height));
+
+
+ Application.ProcessMessages;
+ pause := Round(MSecsPerFrame - (Now - oldtime) * MSecsPerDay);
+ if pause > 0 then Sleep(pause); { задержка }
+
+ if Application.Terminated then Exit;
+ end;
+end;
+
+end.
+
|
