Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Практический курс математического и компьютерного моделирования. Учебно-практическое пособие
.pdf
III. Приемы и методы программирования
чтобы облегчить в будущем работу по отладке и сопровождению
программы. Кроме этого, конечно, нужно отражать все изменения
программного кода в прилагающейся к проекту документации.
Следующие советы могут помочь повысить быстродействие программного кода.
а) по возможности, старайтесь исключить операции с пла-
вающей точкой, так как они выполняются много медленнее,
чем
манипуляции с целыми величинами.
б) операции целочисленного умножения и деления лучше
заменить сложением и вычитанием или, что еще лучше, сдвигами. Например, вместо
3 + k shl 1 + k;
поскольку выполняется равенство 11 = 23 + 2 + 1.
k := k*11; можно использовать k := k shl
в) так как перед каждым вызовом процедуры или функции
ее параметры помещаются в стек, а затем изымаются оттуда,
то процедуры лучше спроектировать так, чтобы они имели как
можно меньше параметров. Если фактические параметры
имеют большой объем, то нужно передавать процедурам не
сами эти параметры, а указатели на них.
г)
если есть возможность не выполнять какие-либо расчеты
в реальном времени, можно их предварительно подготовить, а
затем уже использовать (см. листинги).
д) вместо применения процедур и функций VCL
тесь соответствующими функциями Windows API
38
пользуй-
39
. В самых
критических случаях можно использовать Assembler, программирование на котором более трудоемко по сравнению с
языками высокого уровня, но обеспечивает максимальную
скорость выполнения программы. Даже встроенный в Delphi
Assembler дает значительные преимущества по сравнению с
использованием функций Object Pascal и VCL. Кроме того,
можно вынести ассемблерный код в отдельный модуль и подключать к проекту
38
Visual Component Library — библиотека визуальных компонент
Delphi, функции и процедуры которой содержат вызовы стандартных
функций API Windows и значительно упрощают работу с последними.
39
Application Programming Interface — программный интерфейс при-
ложений, множество системных функций Windows.
, предварительно откомпилировав его.
111

Математическое и компьютерное моделирование
Следует отметить, что самым лучшим способом оптимизации является выбор более эффективного алгоритма — пузырьковая сортировка будет всегда идти медленно, несмотря
на все программистские ухищрения. По проблемам, связанным с построением и анализом вычислительных алгоритмов,
рекомендуются книги [40; 32].
III.5. Анимация
Анимация изображений может потребоваться при решении
многих задач компьютерного моделирования. Рассмотрим
способы решения некоторых проблем, возникающих при этом.
Алгоритм анимации в самом общем виде можно описать
как цикл: построить изображение кадра — сделать временную
задержку — стереть изображение кадра, построить картинку
следующего кадра. При этом, если построение и стирание картинки отображать непосредственно
обычно возникает
40
неприятное для глаз дрожание изображе-
на экран монитора, то
ния. Так, в программе примера 1 (см. листинги), несмотря на
очень простое изображение, при некоторых значениях входных параметров модели можно заметить мерцание.
В компьютерной графике эту проблему решают обычно
при помощи двойной буферизации (double buffering). Эта техника заключается в том, что вначале изображение строится во
вспомогательной
области памяти, называемой задним буфе-
ром кадра, а затем оно выводится на экран — передний буфер
кадра. Таким образом, в цикле анимации картинка в переднем
буфере, через некоторый временной интервал, постоянно подменяется изображением из заднего буфера кадра.
В качестве примера создадим программу, изображающую
двигающийся по круговой орбите черный круг. В качестве
заднего буфера используем объект класса
40
Зависит от характеристик hardware, сложности картинки и длины
временного интервала кадра.
TBitmap.
112

III. Приемы и методы программирования
// файл animUnit.pas
unit animUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Menus;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - type TanimForm = class(TForm)
Panel1 : TPanel;
runButton : TButton;
Edit_delay : TEdit;
Edit_alpha_h : TEdit;
StaticText1 : TStaticText;
StaticText2 : TStaticText;
Timer1 : TTimer;
StaticText7 : TStaticText;
Edit_interval : TEdit;
StaticText8 : TStaticText;
StaticText9 : TStaticText;
MainMenu1 : TMainMenu;
menuFile : TMenuItem;
menuExit : TMenuItem;
menuAbout : TMenuItem;
procedure runButtonClick( Sender: TObject );
procedure FormActivate( Sender: TObject );
procedure Timer1Timer( Sender: TObject );
procedure Edit_intervalChange( Sender: TObject );
procedure Edit_delayChange( Sender: TObject );
procedure menuAboutClick( Sender: TObject );
procedure menuExitClick( Sender: TObject );
private
alpha : double; // угол вращения;
alpha_h : double; // приращение угла;
center_x : word; // центр
center_y : word; // вращения;
r : word; // радиус-вектор;
r0 : word; // радиус круга;
113

Математическое и компьютерное моделирование
4
bitmap : TBitmap; // буфер для кадра;
delay_anim : LongWord; // задержка смены кадров;
procedure frame; // кадр анимации;
public
{ Public declarations }
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
var animForm: TanimForm;
implementation
{$R *.dfm}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// прорисовка кадра анимации и стирание предыдущего;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
procedure TanimForm.frame;
var a0, b0 : word;
begin
bitmap.Canvas.Brush.Color := clWhite;
bitmap.Canvas.Pen.Color := clWhite;
a0 := center_x + round( r*cos( alpha - PI/alpha_h ) );
b0 := center_y - round( r*sin( alpha - PI/alpha_h ) );
bitmap.Canvas.Ellipse( a0 - r0, b0 - r0, a0 + r0, b0 + r0 );
bitmap.Canvas.Pen.Color := clBlack;
bitmap.Canvas.Ellipse( center_x - r, center_y - r,
center_x + r, center_y + r );
bitmap.Canvas.Ellipse( center_x - 3, center_y - 3,
center_x + 3, center_y + 3 );
bitmap.Canvas.Brush.Color := clBlack;
a0 := center_x + round( r*cos( alpha ) );
b0 := center_y - round( r*sin( alpha ) );
bitmap.Canvas.Ellipse( a0 - r0, b0 - r0, a0 + r0, b0 + r0 );
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// задержка на s, точность измерения интервала времени
// не превосходит 0.055 секунды (1 "тик" CPU)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
procedure Delay( s : Double );
var tick0 : LongWord;
11

III. Приемы и методы программирования
5
begin
tick0 := getTickCount;
repeat
//Application.ProcessMessages;
until ( ( ( getTickCount - tick0 ) ) >= s );
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// пуск/останов анимации;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
procedure TanimForm.runButtonClick( Sender: TObject );
begin
try // обработка ошибки ввода приращения alpha;
alpha_h := StrToFloat( Edit_alpha_h.Text );
except on EConvertError
do begin
ShowMessage( 'Неверный ввод данных' + #13#10 +
'проверьте десятичную ./, ' );
exit;
end;
end; // конец обработки ошибок ввода;
Timer1.Enabled := not Timer1.Enabled;
if ( Timer1.Enabled ) then runButton.Caption := 'STOP'
else runButton.Caption := 'RUN';
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// инициализация параметров
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
procedure TanimForm.FormActivate( Sender: TObject );
begin
alpha := 0;
center_x := ( animForm.ClientWidth - Panel1.Width ) div 2;
center_y := animForm.ClientHeight div 2;
r := ( animForm.ClientWidth - Panel1.Width ) div 3;
r0 := ( animForm.ClientWidth - Panel1.Width ) div 24;
Timer1.Enabled := FALSE;
bitmap := TBitmap.Create;
bitmap.Width := animForm.ClientWidth;
11

Математическое и компьютерное моделирование
6
bitmap.Height := animForm.ClientHeight;
animForm.Color := clWhite;
delay_anim := StrToInt( Edit_delay.Text );
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// анимация
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
procedure TanimForm.Timer1Timer( Sender: TObject );
begin
if ( alpha > 2*PI ) then alpha := alpha - 2*PI;
frame; // кадр подготовлен;
animForm.Canvas.Draw( 0, 0, bitmap ); // кадр показан;
delay( delay_anim ); // задержка;
alpha := alpha + PI/alpha_h;
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// изменение интервала таймера
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
procedure TanimForm.Edit_intervalChange( Sender: TObject );
var inter: word;
begin
if ( Timer1.Enabled ) then exit;
try // обработка ошибочного ввода для интервала таймера;
inter := StrToInt( Edit_interval.Text );
except on EConvertError
do begin
ShowMessage( 'Неверный ввод данных,' + #13#10 +
'нужно - натуральное число' );
exit;
end;
end; // конец обработки ошибок ввода;
Timer1.Interval := inter;
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// изменение величины задержки смены кадров
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
procedure TanimForm.Edit_delayChange( Sender: TObject );
11

III. Приемы и методы программирования
7
begin
try // обработка ошибочного ввода для задержки;
delay_anim := StrToInt( Edit_delay.Text );
except on EConvertError
do begin
ShowMessage( 'Неверный ввод данных,' + #13#10 +
'нужно - натуральное число' );
exit;
end;
end; // конец обработки ошибок ввода;
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
procedure TanimForm.menuAboutClick(Sender: TObject);
begin
ShowMessage( 'Анимация' + #13#10 + 'учебный пример'
+ #13#10 + 'В. Зенкин, 2005 г.' );
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
procedure TanimForm.menuExitClick(Sender: TObject);
begin
close;
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
end.
// конец файла animUnit.pas
Объект bitmap, используемый в качестве заднего буфера, обладает рядом полезных свойств, в том числе, например, имеет
метод для сохранения изображения на диске в виде графического
файла, что позволит, сохранив все кадры в файлах, позднее (при
желании), очень просто создать анимационный фильм. На рисунке III. 1 показано окно программы на этапе выполнения.
Нужно
отметить особенность измерения временных промежутков — данная программа не может получить и использовать временной интервал, меньший 55 миллисекунд. Следовательно, если задать интервал таймера, меньший этого значения, скорость работы от этого не увеличится. Это может стать
11

Математическое и компьютерное моделирование
проблемой, особенно, если потребуется воспроизводить работу моделируемой системы в реальном времени. Кроме этого,
если обработчик «тика» таймера не успеет выполнить все действия за установленный интервал, то последующие вызовы
этого обработчика помещаются в очередь. Такая ситуация может привести к тому, что программа будет работать на разных
компьютерах с различной
скоростью.
Рис. III.1
Есть разные способы решения этой проблемы. Например,
можно использовать мультимедийный таймер (модуль
MMSystem). Это позволит обрабатывать события с частотой,
которая ограничивается только мощностью аппаратного обеспечения компьютера, причем кадры, которые не успели воспроизвестись, накапливаться в очереди не будут. Запускается
и останавливается мультимедийный таймер специальными
функциями — API
timeSetEvent и timeKillEvent соответственно
(подробнее см. справку в Microsoft Multimedia Programmer's
Reference из входящего в стандартную поставку Delphi MS
SDK Help Files).
В случаях более сложных изображений, чем рассмотренное, особенно трехмерных, при программировании анимации
можно использовать средства графических библиотек OpenGL
или DirectX.
118

IV. ЗАДАНИЯ
Решение задач — специфическое достижение разума, разум же — особый дар, которым наделен человек. Способность
к преодолению препятствий, к нахождению обходного маневра там, где не видно прямого пути, возвышает умное животное над тупым, человека — над самым умным животным и
талантливых людей — над другими людьми.
Д. Пойа [35]
Трудно, если не
тая теорию и не применяя полученную информацию для решения специальных задач и тем самым не заставляя себя обдумывать то, что было прочитано. Кроме того, мы лучше заучиваем то, что сами открываем для себя.
невозможно изучить предмет, только чи-
Д. Кнут [32]
IV.1. Требования к оформлению работ
Лабораторная работа должна содержать следующее.
а) Программу на языке высокого уровня (предпочтительно
использовать C/C++, Pascal/Object Pascal).
б) Исходные коды программы, снабженные подробными
комментариями для всех алгоритмов, процедур и функций, а
также фамилию автора, дату реализации.
в) Набор тестовых значений параметров и описание результатов тестирования программы с этими параметрами (не
менее 4–5 вариантов).
г)
Электронную (help-файл) и/или бумажную документа-
цию, включающую:
119

Математическое и компьютерное моделирование
0
— задание;
— подробное описание модели, включая перечисление
всех принятых упрощений и ограничений;
— подробный вывод всех формул;
— используемые при построении модели физические, механические, биологические и другие законы;
— описание применяемых при решении уравнений модели
численных методов (если используются) с соответствующими
ссылками на литературу;
— cписок использованной литературы.
Интерфейс программы с пользователем
должен быть по
возможности простым и понятным («дружественным»).
Кроме того, следует помнить, что пользователю, вообще
говоря, никакой интерфейс сам по себе — даже самый хороший — не нужен, ему нужно уметь делать свое дело. Чем
меньше различных действий (нажатий клавиш, щелчков
мышью и т.
дить для решения задачи, тем лучше. Применяйте стандартные элементы GUI операционной системы
ложении «бантики»
д.) пользователю программы придется произво-
41
42
неуместны. Чем меньше интерфейс
, в деловом при-
отвлекает пользователя от выполнения его работы, тем
лучше. Используйте различные виды подсказок относительно назначения элементов управления, например — в статусной строке. При выполнении программой длительных про-
41
Графический пользовательский интерфейс (GUI) Windows, ко-
нечно, не самый лучший, но множество пользователей привыкли
именно к нему.
42
Различные анимированные изображения, звуковые эффекты,
нестандартные меню и прочее, не относящееся напрямую к решению задачи. Например, в программе для решения задачи 2.12
можно было бы реализовать трёхмерное анимированное изображение сердца и сопроводить эту анимацию замечательной композицией группы King Crimson «Heartbeat», но первое явно избыточно, так как соответствующая модель не является
второе — лишнее.
12
трёхмерной, а
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
