Курсовая работа_ф_3 / Иванова Г.С. - Основы программирования
.pdf8. Управление техническими средствами и взаимодействие с MS DOS
Begin
ClrScr;
WriteСВведите начало и конец интервала:');
ReadLn(xn,xk); |
|
|
|
|
h:=(xk-xn)/(k-l); |
|
{определяем шаг по оси х} |
||
х[1]: =хп; |
|
|
|
|
ymin:=le30; |
|
|
|
|
ymax:=-lelO; |
|
|
|
|
for |
i:=] to к do |
{табулируем функцию и ищем экстремумы} |
||
begin |
|
|
|
|
|
yfiJ:=cos(x[iJ+2)/2; |
|
||
|
if y[i]>ymax |
then |
ymax:=y[ij; |
|
|
if y[i]<ymin |
then |
ymin:=y[ij; |
|
|
if iolOO |
thenx[i+]J:=x[iJ+h; |
||
end; |
|
|
|
|
mx:=(kxk-kxn)/(xfkj'xf]j); |
{определяем масштаб по оси х} |
|||
my:=(kyk-kyn)/(ymax-yminj; |
{определяем масштаб по оси у} |
|||
for |
i:=J to к do |
|
|
{определяем координаты точек} |
|
begin |
|
|
|
|
kxfij: =round{(xfiJ'X[lJ) *тх) +кхп; |
|||
|
kyfij: =round((ymax-y[iJ) *ту) +куп; |
|||
|
end; |
|
|
|
gd: =detect; |
|
|
|
|
InitGraph(gd,gm, "); |
{инициализируем графический режим} |
|||
SetColor(4); |
|
{текущий цвет - красный} |
||
OutTextXY(180,20, T=cos(x-^2J/2'); {выводим заголовок} |
||||
SetColor(17); |
|
{цвет рисования - голубой} |
||
SetBKColor(7); |
|
{на сером фоне} |
||
Rectangle(кхп,куп,кхккук); |
{рисуем прямоугольник для вывода |
|||
SetColor(4); |
|
|
графика} |
|
|
|
{текущий цвет ~ красный} |
||
for |
i:=l to к-1 do |
|
{выводим график} |
|
|
Line (kx[i],ky[i],kx[i+l],ky[i^l]); |
|||
dkx:='round((kxk'kxn)/nx); |
{определяем шаг сетки по х} |
|||
dky:=round((kyk'kyn)/ny); |
{определяем шаг сетки по у} |
|||
SetColorf] 7); |
|
|
{текущий цвет - светло-синий} |
|
for |
i:=J to пх do |
{рисуем сетку, параллельную оси х} |
||
|
Line(kxn+dkx*r,kyn,kxn-^dkx*i,kyk); |
|||
for |
i:=] to ny do |
|
{рисуем сетку, параллельную оси у} |
|
Line(kxn,kyk-dky*i,kxk,kyk'dky*i); |
||||
dx:=(x[kJ'X[]JJ/nx; |
{определяем шаг для сетки по х} |
|||
dy:=(ymax-ymin)/ny; |
{определяем шаг для сетки по у} |
|||
SetTextJustify(1,2); |
{выравнивание «по центру снизу»} |
|||
281
Часть 1. Основы алгоритмизации и процедурное программирование
Y = cos(x+2)/2
0.50
0.31
0.12
-0.07
-0.26
-0.46
2.00 |
3.00 |
4.00 |
5.00 |
6.00 |
7.00 |
Рис. 8.7. Результат работы программы
for i:=J to пх+1 do {выводим значения аргумента} begin
Str((xflJ+dx*(i-])):n:m,st);{преобразуем число в строку} OutTextXY(kxn+dkx*(i'l), kyk+6,st); {вывод значений под лини
ей сетки}
end;
SetTextJustijy(2J); {выравнивание «слева по центру»} for i:=l to ny+I do {выводим значения функции}
begin
Str((ymin+dy*(i'l)):n:m,stJ;{преобразуем число в строку} OutTextXY(kxn-6,kyk'dky*(i'l),st); {вывод слева от оси у} end;
ReadLn; {ожидаем нажатия ENTER}
Closegraph;
End.
Результатом работы программы является график функции на заданном интервале изменения аргумента, представленный на рис. 8.7.
Помимо графиков для представления результатов также могут использо ваться диаграммы и гистограммы различных видов. Рассмотрим еще один пример.
Пример 8.6. Разработать программу построения круговой диаграммы по заданным значениям не более 12, которые должны выводиться рядом с со ответствующим сектором диаграммы.
Круговая диаграмма рисуется как совокупность закрашенных секторов круга. Угол сектора пропорционален доле соответствующего значения в об-
282
<^. Управление техническими средствами и взаимодействие с MS DOS
щей сумме значений. Надпись должна выводиться напротив биссектрисы уг ла сектора соответственно слева или справа диаграммы.
Ниже приведена программа.
Program difgramma; Uses Graph;
Const
kmax=12; {максимальное количество значений функции} r=J50; {радиус диаграммы}
п=5; {ширина поля вывода} т=2; {размер дробной части числа}
Туре
mas=array[J..kmax+JJ of integer; masl=array[L.kmax] of real;
Var |
|
fmasl; |
{массив значений функции} |
alfa:mas; |
{массив значений углов диаграммы} |
driver,err, |
{тип и режим работы адаптера} |
К{фактическое количество значений функции}
bet, {величина угла, образованного радиусом и биссектрисой сек тора диаграммы}
у,х, {координаты точки, являющейся центром дуги сектора} х1,у1, {координаты начальной точки вывода надписи} хп,уп, {координаты центра диаграммы}
i:integer;
st:string[5]; {строка для хранения выводимой надписи} s:real; {сумма значений функции}
begin
WriteLnCВведите количество точек (от 1 до\ктах:3,') '); ReadLn(k);
{вводим значения функций и определяем их сумму}
for i:=l to к do begin
WriteLnCBeedume\i:3, '-e значение функции'); ReadLn(f[i]);
whilef[i]<0 do begin
WriteLnCНедопустимое значение, повторите ввод'); WriteLnCBeedume\i:3, '-e значение функции); ReadLn(f[i]);
end;
283
Часть 1. Основы алгоритмизации и процедурное программирование
s:-s+f[i]: end;
if s=0 then begin
WriteLn('Bce значения нулевые.');
ReadLn; |
|
|
halt(l); |
|
{выход no ошибке} |
end; |
|
|
{инициализируем графический режим} |
||
driver: =detect; |
|
|
InitGraph(driver,err, "); |
||
SetBkColor(15); {белый цвет фона} |
||
SetPalette(lO); |
|
|
SetColor(l); |
{черный цвет рисования} |
|
{вычисляем координаты центра диаграммы} |
||
хп: =GetMaxX div 2; |
|
|
уп: =GetMaxY div 2;' |
||
{рассчитываем значения углов секторов диаграммы} |
||
alfa[l]:=0; |
|
|
for i:= 2 to k+1 do |
|
|
begin |
|
|
ifi<>k+l |
then |
alfa[ij:=alfa[i'lj+round(ffi']]/s*360) |
|
else |
alfa[k+l]:^360; |
SetFillStyle(i mod 10, i); {установим тип и цвет закраски сектора} |
||
Pieslice(xn,yn,alfafi'lJ,alfafiJ,r); {изобразим сектор} |
||
{вычисляем начальные координаты вывода надписей} |
||
bet:=(alfa[i'lj+alfa[ij) |
div 2; |
|
|
|
x:==xn+round(r*cos(bet*pi/I80)); |
|
|||
у: =yn'round(r*sin(bet*pi/I80)); |
|
|||
if ((bet> =0)and(bet< ^90))or((bet> =2 70)and(bet< -=360)) |
||||
thenxl:=x-^10 |
|
elsexJ:=X'8*n']0; |
||
if((bet>=0)and(bet<=J80)) |
thenyl—y-lS |
|||
Sir(f[i'l]:n:m,st); |
|
|
else |
yli^y^l; |
{преобразуем значение в строку} |
||||
OutTextXY(xl,yl,st); |
|
{выведем надпись} |
||
end; |
|
|
|
|
ReadLn;
CloseGraph; End
Результатом работы программы является изображение круговой диа граммы, приведенное на рис. 8.8.
284
8. Управление техническими средствами и взаимодействие с MS DOS
|
56.00 |
35.00 |
79.00 |
|
24.00
23.00
66.00 |
44.00 |
38.00 |
79.00 |
|
Рис. 8.8. Результат работы программы построения круговой диаграммы
8.7. Практикум. Создание движущихся изображений
Движение на экране создается по принципу мультипликации: на экран с соответствующей задержкой выводят последовательность кадров с неболь шими изменениями положения «движущихся» объектов или объектов «фо на», если эффект движения достигается изменением фона.
Сам «перемещаемый» объект может быть двумерным (плоским) и трех мерным (пространственным), причем движение может осуществляться по двум типам траектории: лежащей в плоскости экрана или выходящей за нее. Из аналитической геометрии известны формулы, по которым можно, зная за кон движения, определить изменения положения каждой точки изображения движущегося объекта на экране. Проекции трехмерных объектов при движе нии изменяются достаточно сложным образом, и в то же время ничего прин ципиально нового в программировании движения трехмерных объектов по сравнению с двумерными не существует, поэтому в настоящем учебнике эти вопросы рассматриваться не будут.
Движение плоских объектов. Любое сложное движение плоских объ ектов на экране складывается из базовых: перемещения, масштабирования и поворота. Формулы пересчета координат изображений для базовых видов движения следующие.
285
Часть 1. Основы алгоритмизации и процедурное программирование
(х,,у,)
(Х,У) |
( х , у ) ^ . (''''У') |
C(x,,yJ С(х,,уЛ
Рис. 8.9. Элементарные изменения изображения:
а - перемещение; б- масштабирование; в - поворот
Перемещение (рис. 8.9, а)
Х| = X + dx,
y i = y + dy,
где X, у - исходные координаты точки; xj, У| - координаты точки после пе ремещения; dx, dy - смещения по оси х и у соответственно.
Масштабирование относительно точки С (х^, у^>) (рис. 8.9, б):
Х] =(х-Хс)Мх + Хс, У1 =(у-Ус)Му + Ус,
где Mj^, My - масштабы по х и у соответственно; х^., у^. - координаты точки, относительно которой ведется масштабирование.
Поворот относительно точки С с координатами (х^,, у^,) (рис. 8.9, в):
Х| = (х - х^) cosa + (у - у^,) sin а + х^,, У1 = (у - Ус) cosa - (х - x j sin а + у^ ,
где а - угол поворота.
Пример 8.7. Разработать программу, которая демонстрирует на экране движение прямоугольника: прямоугольник улетает от нас к некоторой точке горизонта, одновременно вращаясь вокруг своей оси.
Обобщенный алгоритм последовательного показа кадров данной задачи выглядит следующим образом.
Начало:
Установить точку отсчета координат (условное время). Рассчитать координаты квадрата.
Цикл-пока не истекло время или не нажата любая клавиша Установить цвет рисования.
Изобразить квадрат.
Приостановить выполнение программы на время просмотра кадра.
286
8. Управление техническими средствами и взаимодействие с MS DOS
Точка Повернутое горизонта изображение
|
Результат |
Исходное положение |
масштабирования |
Рис. 8.10. Разложение движения
Установить в качестве цвета рисования цвет фона. Изобразить квадрат цветом фона - стереть. Изменить точку отсчета (условное время). Пересчитать координаты квадрата.
все-цикл Конец.
В а р и а н т ! . Координаты вершин квадрата будем хранить в специаль ных массивах х, у, а квадрат рисовать линиями, проводя их из одной верши ны в другую. Изображение квадрата будет осуществлять специальная проце дура Square.
Пересчет координат вершин реализуем через разложение «движения» прямоугольника на элементарные составляющие (рис. 8.10): эффект удале ния от зрителя получим, используя масштабирование относительно точки го ризонта, эффект вращения - за счет поворота вокруг геометрического цент ра.
Вначале определим координаты вершин и центра квадрата после мас штабирования, а затем координаты вершин после поворота вокруг центра квадрата. Ниже приведена соответствующая программа:
Program ex; Uses Crt,Graph; Const
r=]00;
Type
mas =array[I.. 4] of integer; Var
X, y, xl, yl:mas; gd,gm,xn,yn,xc,yc, ij, kl: integer; t,k:reaJ;
287
Часть L Основы алгоритмизации и процедурное программирование
{изображение квадрата по координатам его вершин}
Procedure Square(х,у:mas); Begin
Line(x[lly[llx[2],y[2]);
Line(x[2],y[2],x[3],y[3]);
Line(x[3],y[3lx[4].y[4]);
Line(x[4M4Ml].y[l]):
End:
{определение координат повернутой точки}
Procedure Pow(xc,yc,x,y:integer;t:real;var xl,yl:integer); Begin
xl: =xc+round((X'Xc) ^cos(t)) -^rounddy-yc) '^sin(t)); yl: =yc+round((y'yc) *cos(t))'round((X'Xc) *sin(t));
End;
{определение координат точки после масштабирования}
Procedure Massch(xc,yc,x,y: integer;k:real;var xJ,y J.'integer); Begin
xJ:=round(x*k-^(]-k) *xc); yl: =round(y*k+(l'k) *yc); End;
{основная программа}
Begin
gd: =detect; InitGraph(gd,gm, 'd:\bp\bgi); SetColor(2);
xn: =GetMaxX div 4; yn: =GetMaxY div 3 *2; xc: =GetMaxX'Xn; yc:=GetMaxY'yn;
{расчет начальных координат вершин квадрата}
xflj: =xn-r; |
yflj: =уП'Г; |
x[2]: =xn+r; |
у[2]: =yn-r; |
x[3]: =xn+r; |
y[3]: =yn-^r; |
x[4]: =xn-r; |
у[4J: =yn+r; |
k:=0.99; |
|
t:=0;
{покадровый вывод на экран} while (t<l) and not KeyPressed do
begin
SetColor(2); {установим цвет рисования} Square(x,y); {нарисуем квадрат} t:=t-^0.001; {увеличим угол поворота}
288
8. Управление техническими средствами и взаимодействие с MS DOS
{масштабирование}
forj:=I to 4 do {определим координаты вершин}
Massch(xc,yc,xljJ,y/jJ,kx] [flyJ /jj): Massch(xc,yc,xn,yn,kxn,yn); {определим координаты центра}
{поворот} |
|
|
forj:=l |
to 4 do |
{определим координаты вершин} |
Pow(xn,yn,x]/jJ.yW7rt,x]/jlylOJ)>' |
||
forj:=I |
to 1500 do Delay(lOOO); {или NewDelay см. параграф 8.3} |
|
SetColor(O); |
{установим цвет рисования - цвет фона} |
|
Square(x,y); |
{стираем квадрат} |
|
x:=xJ; |
|
{заменим координаты вершин на новые} |
y:=yJ;
end;
CloseGraph; End
Недостатком данного способа является то, что квадрат на экране через несколько кадров уже выглядит не квадратным. Это происходит вследствие накопления ошибки округления при пересчете координат вершин. Избежать этого можно двумя способами:
1) все вычисления выполнять в вещественной арифметике и координаты также хранить как вещественные числа, преобразуя их в целые непосредст венно перед использованием в процедуре рисования;
2) пересчитывать координаты не всех вершин, а какой-нибудь одной и центра квадрата, восстанавливая квадрат по одной вершине и положению центра квадрата.
Способы являются взаимодополняющими, поэтому используем оба.
В а р и а н т |
2. Для упрощения |
|
вычислений вместо массивов, хра |
|
|
нящих координаты вершин квадра |
A4dxl,dyl) |
|
та, будем использовать смещения |
|
|
этих вершин относительно центра |
А (dx,dy) |
|
(рис. 8.И). Соответственно проце |
||
дура рисования |
квадрата Square 1 |
|
должна использовать именно эти |
|
|
параметры. Также учтем, что при |
|
|
масштабировании изменяются раз |
|
|
мер диагонали и положение центра, |
|
|
а при повороте ~ смещения вершин |
|
|
относительно центра. Ниже пред- |
Рис. 8.11. Два соседних кадра |
|
ставлен текст программы. |
при повороте |
|
289
Часть I. Основы алгоритмизации и процедурное программирование
Program ex; Uses Crt,Graph;
Const r:real=100; {размер половины стороны квадрата}
Var
X, у, dx, dy, dxl, dyJ, xn, yn, xc, yc, xnl, ynl.real; gd,gmJJ: integer;
tyk:real; {угол поворота и масштаб}
{изображение квадрата}
Procedure Squarel(x,ydx,dy:integer); Begin
Line(x+dx,y-^dy,X'dy,y+dx);
Line(X'dy,y+dx,X'dx,y'dyJ;
Line(x-dx,y'dy,x+dy,y'dx);
Line(x+dyy-dx,x+dx,y+dyJ; End;
{основная программа}
Begin gd:=detect;
InitGraph(gd,gm, *d:\bp\bgi');
{устанавливаем начальную и конечную точки}
хп: =GetMaxX div 4; yn:--GetMaxYdiv3*2; xc: ^'GetMaxX-xn; yc:=GetMaxY'yn;
{определяем начальные значения}
dy:=0; к: =0,95; t:=0;
{покадровый вывод на экран}
while (t<100) and not KeyPressed do begin
SetColor(2); {выводим кадр}
Squarel(round(xn)у round(yn), round(dx), round(dy));
{масштабирование} xnl: = xn *k+(]'k) *xc; yn1: =yn *k+ (J-k) *>'c; r:= k'^r;
{поворот}
t:=t+l; {увеличиваем угол поворота} dxl:=r'^cos(t);
dyl:= r*sin(t);
forj:=J to 5000 do Delay(lOOO); {приостановка}
290
