From 6d7c43c85f8852ed3b3fa9cefc742bc87e941842 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Wed, 17 Dec 2025 12:12:16 +0100 Subject: =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20=D1=82?= =?UTF-8?q?=D1=80=D0=B5=D1=82=D1=8C=D1=8E=20=D0=B3=D0=BB=D0=B0=D0=B2=D1=83?= =?UTF-8?q?=20=D0=B7=D0=B0=D0=BD=D0=B8=D0=BC=D0=B0=D1=82=D0=B5=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=BF=D1=80=D0=BE=D0=B3=D1=80=D0=B0?= =?UTF-8?q?=D0=BC=D0=BC=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../3/5_ideal_gas/octahedron.pas" | 129 +++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 "\320\227\320\260\320\275\320\270\320\274\320\260\321\202\320\265\320\273\321\214\320\275\320\276\320\265 \320\277\321\200\320\276\320\263\321\200\320\260\320\274\320\274\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265/3/5_ideal_gas/octahedron.pas" (limited to 'Занимательное программирование/3/5_ideal_gas/octahedron.pas') diff --git "a/\320\227\320\260\320\275\320\270\320\274\320\260\321\202\320\265\320\273\321\214\320\275\320\276\320\265 \320\277\321\200\320\276\320\263\321\200\320\260\320\274\320\274\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265/3/5_ideal_gas/octahedron.pas" "b/\320\227\320\260\320\275\320\270\320\274\320\260\321\202\320\265\320\273\321\214\320\275\320\276\320\265 \320\277\321\200\320\276\320\263\321\200\320\260\320\274\320\274\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265/3/5_ideal_gas/octahedron.pas" new file mode 100644 index 0000000..31fe970 --- /dev/null +++ "b/\320\227\320\260\320\275\320\270\320\274\320\260\321\202\320\265\320\273\321\214\320\275\320\276\320\265 \320\277\321\200\320\276\320\263\321\200\320\260\320\274\320\274\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265/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. + -- cgit v1.2.3