Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Практический курс математического и компьютерного моделирования. Учебно-практическое пособие

.pdf
Скачиваний:
0
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
II. Программная реализация математической модели
+ ' время ' + FloatToStrF( t0, ffGeneral, 5,2 ) + ', скорость '+ FloatToStrF( v0, ffGeneral, 5,2 ); y1 := Ty1.birth( t0, 0, -k*v0, k, trunc( N*k ) + 1 ); dt := ( y1.get_t_impact - t0 )/N; q := y1.get_top_list; inc( impact_count ); end; // while ( impact_count <= impacts )... y1.Kill; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // движок модели, учитывающей сопротивление среды // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - procedure TForm_main.Engine_Y2; var t0, dt, t : double; impact_count : LongWord; begin t0 := 0.0; impact_count := 1; // счетчик ударов; dt := ( y2.get_t_impact - t0 )/N; Form_ball.Frame( q.value, dt*tau ); q := q^.link; q_v := q_v^.link; t := dt; while ( impact_count <= impacts ) do begin Form_ball.Frame( 0.0, 0.0 ); while ( q.link <> NIL ) do begin Form_ball.Frame( q.value, dt*tau ); Series1.AddXY( t, u*q_v.value ); q := q^.link; q_v := q_v^.link; t := t + dt; end;
71
Математическое и компьютерное моделирование
Form_ball.Frame( 0.0, dt*tau, FALSE ); // момент удара: t0 := y2.get_t_impact; // новые начальные значения v0 := y2.get_v_impact; // времени и скорости; y2.Kill; StatusBar1.SimpleText := IntToStr( impact_count) +'-й удар:' + ' время ' + FloatToStrF( t0, ffGeneral, 5,2 ) + ', скорость '+ FloatToStrF( v0, ffGeneral, 5,2 ); y2 := Ty2.birth( t0, 0, -k*v0, k, u, trunc( N*k ) + 1 ); dt := ( y2.get_t_impact - t0 )/N; q := y2.get_top_list; q_v := y2.get_v_list; inc( impact_count ); end; // while ( impact_count <= impacts )... y2.Kill; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - procedure TForm_main.STARTbuttonClick( Sender: TObject ); begin STARTbutton.Enabled := FALSE; StatusBar1.SimpleText := ''; Series1.Clear; if ( RadioGroup1.ItemIndex = 0 ) then Engine_Y1; if ( RadioGroup1.ItemIndex = 1 ) then Engine_Y2; RadioGroup1.Enabled := TRUE; INITbutton.Enabled := TRUE; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - procedure TForm_main.RadioGroup1Click( Sender: TObject ); begin if ( RadioGroup1.ItemIndex = 0 ) then Edit_u.Enabled := FALSE; if ( RadioGroup1.ItemIndex = 1 ) then Edit_u.Enabled := TRUE; end;
72
II. Программная реализация математической модели
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // инициализация входных параметров моделей и их движков, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - procedure TForm_main.INITButtonClick( Sender: TObject ); begin INITbutton.Enabled := FALSE; RadioGroup1.Enabled := FALSE; try begin // обработка ошибок ввода данных: y0 := StrToFloat( Edit_y0.Text ); v0 := StrToFloat( Edit_v0.Text ); N := StrToInt ( Edit_N.Text ); k := StrToFloat( Edit_k.Text ); u := StrToFloat( Edit_u.Text ); tau := StrToFloat( Edit_tau.Text ); impacts := StrToInt ( Edit_imp.Text ); end except on EConvertError do begin ShowMessage( 'Неверный ввод данных' + #13#10 + ‘проверьте десятичную ./,' ); INITbutton.Enabled := TRUE; exit; end; end; // конец обработки ошибок ввода данных; // обработка ввода ошибочных параметров модели: if ( (y0 < 0) OR ( (k < 0) OR (k > 1) ) OR (u <= 0) ) then begin ShowMessage( 'Должно быть' + #13#10 + 'y0 >= 0; 0 <= k < 1; u > 0' ); INITbutton.Enabled := TRUE; exit; end; if ( ( y0 = 0 ) AND ( v0 = 0 ) ) then begin ShowMessage( 'Не должно быть одновременно' + #13#10 +
73
Математическое и компьютерное моделирование
4
'y0 = 0 и v0 = 0' ); INITbutton.Enabled := TRUE; exit; end; // конец обработки ввода ошибочных параметров; if ( RadioGroup1.ItemIndex = 0 ) then // выбор модели 1; begin y1 := Ty1.birth( 0.0, y0, v0, k, N ); q := y1.get_top_list; maxH := y1.get_Max_value; Chart1.Title.Text.Text:='Зависимость коорд. от времени'; end; if ( RadioGroup1.ItemIndex = 1 ) then // выбор модели 2; begin if ( u*v0 <= -g ) then begin ShowMessage( 'Должно быть' + #13#10 + ' u*v0 > -g' ); INITbutton.Enabled := TRUE; exit; end; y2 := Ty2.birth( 0.0, y0, v0, k, u, N ); q := y2.get_top_list; maxH := y2.get_Max_value; q_v := y2.get_v_list; Chart1.Title.Text.Text := ' Зависимость сопротивления' + ' среды от времени'; end; if ( not Assigned ( Form_ball ) ) then Form_ball := TForm_ball.Create( self ); Form_ball.Show; Form_ball.ClearWind; Form_ball.Frame( q.value, 0, FALSE ); STARTbutton.Enabled := TRUE; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - procedure TForm_main.FormCreate( Sender: TObject ); begin STARTbutton.Enabled := FALSE;
7
II. Программная реализация математической модели
5
Edit_u.Enabled := FALSE; Application.OnHint := ShowHint; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - procedure TForm_main.About1Click(Sender: TObject); begin
ShowMessage( 'В. Зенкин, КГУ, 2005 г.' + #13#10 + 'модель пры-
гающего мяча' + #13#10 + 'учебный пример' ); end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - procedure TForm_main.Exite1Click(Sender: TObject); begin Close; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - procedure TForm_main.ShowHint(Sender: TObject); begin StatusBar1.SimpleText := Application.Hint; end; end. // конец головного файла mainUnit.pas.
II.7. Пример 2. Реалистичное освещение
Рассмотрим программную реализацию модели, построенной в
I.4, не останавливаясь подробно на вопросах проектирования ие-
рархии классов, так как ее вид в данном случае вполне очевиден.
Для того чтобы иметь возможность работать с лучами и зада­вать координаты точек в пространстве (рис. II. 5 — координатная система), нужны векторы — соответствующие процедуры и функции сосредоточим в
классе31 Tvector (см. листинги) и в моду-
ле vectorUnit. Для работы с цветами нам понадобятся соответст-
31
Нужно заметить, что на языках, допускающих перегрузку операций,
например на C++, данный класс выглядел бы более элегантно.
7
Математическое и компьютерное моделирование
6
вующие процедуры и функции32 — модуль colorUnit. Объект луч, который нужен для работы с источником света, по существу является вектором, имеющим цвет, поэтому выведем соответст­вующий класс
Tray из класса Tvector (см. листинги).
Рис. II. 5
Несмотря на то что в нашей модели только один тип тел — сфера, с учетом возможных дальнейших модификации про­граммы, когда к сферам на сцену могут добавиться и другие виды объектов, сосредоточим общие для них методы в базовом классе женного луча, вычисления коэффициентов диффузии и отраже­ния в заданной точке, для которых нужно знать нормаль к дан­ной точке. Поскольку нормаль можно определить только для конкретного тела, то метод абстрактным — с тем, чтобы в дальнейшем иметь возможность его переопределения в производных классах.
класса должен иметь возможность рассчитывать вектор нормали
32
цвета в виде тройки компонент: красной (Red), зелёной (Green) и синей (Blue). Такую модель называют RGB. В данной программе используется 24-битовый цвет, по 8 бит на каждую цветовую компоненту; таким обра­зом, всего программа может отобразить 2
7
Tfigure. Этот класс содержит методы для расчета отра-
set_normal объявлен виртуальным и
Из класса
Используется традиционное для компьютерной графики представление
Tfigure выведем класс Tsphere (сфера). Объект этого
24
различных цветов.
II. Программная реализация математической модели
7
к любой точке своей поверхности, определять факт пересечения трассирующего луча с поверхностью и, кроме того, определять расстояние до камеры. Для этого в классе
Tsphere заданы методы
set_normal и intersection, последний из которых возвращает множи-
t, на который нужно умножить направляющий вектор трас-
тель сирующего луча, чтобы этот луч попал на сферу. Если луч не попадает на сферу, то метод возвращает -1,0. В модуле traceUnit содержится процедура инициализации сцены
init_scene (исполь-
зуется левая координатная система — см. рис., картинная плос­кость фиксирована и совпадает с плоскостью XY), задающая по­ложение камеры, источника света, количество и параметры сфер и т.д., и трассировщик —
рекурсивная функция trace, которая
собственно и выполняет всю основную работу по трассировке лучей. Алгоритм работы трассировщика вполне понятен из ком­ментариев к исходному коду и описания, приведенного в I.4.
Головной модуль mainUnit содержит процедуру отрисовки изображения, средства для поддержки управления программой и для сохранения трассированного изображения в файле (на рисунке II. 6 — окно программы на этапе выполнения).
Рис. II.6
Прекрасным примером реализации идей рейтрессинга яв­ляется программа POV-Ray (Persistence of Vision Raytracer). Эта программа свободно распостраняется, причем с исходны-
7
Математическое и компьютерное моделирование
ми кодами (на языке C++), снабжена отличной справочной документацией. На сайте разработчиков [33] можно найти множество материалов по рейтрессингу и соответствующему программному обеспечению.
II.8. Листинги примера 2
II.8.1. Базовый класс tvector (вектор)
и векторные операции
// файл vectorUnit.pas unit vectorUnit; interface // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type Tpoint3D = record x, y, z : double; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type Tvector = class protected coordinate: Tpoint3D; public function get_coord : Tpoint3D; function get_module : double; procedure normalization; constructor birth( xx, yy, zz: double ); overload; constructor birth( p: Tpoint3d ); overload; end; //-- векторные операции: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function summ_vectors( v_1, v_2: Tvector ): Tvector; function dot_product( v_1, v_2: Tvector ) : double; function mult_on_scal( k: double; v: Tvector ): Tvector; //==================================================== implementation // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function Tvector.get_coord: Tpoint3D;
78
II. Программная реализация математической модели
begin result := coordinate; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function Tvector.get_module: double; begin result := sqrt( coordinate.x*coordinate.x + coordinate.y*coordinate.y + coordinate.z*coordinate.z ); end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - procedure Tvector.normalization; var module: double; begin module := get_module; if ( module <> 0.0 ) then begin coordinate.x := coordinate.x/module; coordinate.y := coordinate.y/module; coordinate.z := coordinate.z/module; end; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - constructor Tvector.birth( xx, yy, zz: double ); begin coordinate.x := xx; coordinate.y := yy; coordinate.z := zz; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - constructor Tvector.birth( p: Tpoint3d ); begin coordinate.x := p.x; coordinate.y := p.y; coordinate.z := p.z; end; //====================================================
79
Математическое и компьютерное моделирование
0
function summ_vectors( v_1, v_2: Tvector ): Tvector; var c1, c2: Tpoint3D; begin c1 := v_1.get_coord; c2 := v_2.get_coord; result := Tvector.birth(c1.x + c2.x, c1.y + c2.y, c1.z + c2.z); end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function dot_product( v_1, v_2: Tvector ): double; var c1, c2: Tpoint3D; begin c1 := v_1.get_coord; c2 := v_2.get_coord; result := c1.x*c2.x + c1.y*c2.y + c1.z*c2.z; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function mult_on_scal( k: double; v: Tvector ): Tvector; var c: Tpoint3D; begin c := v.get_coord; result := Tvector.birth( c.x*k, c.y*k, c.z*k ); end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - end. // конец файла vectorUnit.pas
II.8.2. Класс TRay (луч)
// файл rayUnit.pas unit rayUnit; interface uses vectorUnit, colorUnit; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Type Tray = class( Tvector ) protected color : Tcvet;
8
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]