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

Popov_vorobev

.pdf
Скачиваний:
7
Добавлен:
22.06.2018
Размер:
1.57 Mб
Скачать

2. Если в позиции экрана y ≠ f(x) и y=0 (т.е. ось абсцисс) или y ≠ f(x) и x=0 (т.е. ось ординат) выводим ось белым цветом, например так:

Image1.Canvas.Pixels[x, y]:=clWhite;

3. Во всех остальных случаях — не выводим ничего, либо закрашиваем точку в цвет фона окна.

Выбор и разработка математической модели. Определим-

ся с преобразованием координат. По условию функцию нужно отобразить в прямоугольнике со следующими координатами: (x1,y1) — (x2,y2) — система координат К1.

На текстовой консоли имеется прямоугольник размером MX на MY символов. Имеем прямоугольник с координатами (1,1) — (MX, MY) — система координат К2. Причем значения координат — целые числа в диапазонах 1.. MX по оси Х и 1..MY по оси Y.

x

 

 

 

 

 

 

(1,1)

(MX,1)

y

(X1,Y2)

 

(X2,Y2)

 

 

 

 

 

 

 

 

 

 

 

 

(Xэ,Yэ)

 

 

 

 

 

 

 

 

 

 

 

 

y

 

 

 

 

 

 

 

(1,MY)

(MX, MY)

 

 

 

(Xc,Yc)

 

(X2,Y1)

 

 

(X1,Y1)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

x

 

 

Рис. 24. Преобразование координат

Согласно правилам преобразования координат, чтобы найти координату системы К1 на основе соответствующей ей координаты Xэ (Х на экране) в системе К2 нужно составить пропорции по размерам соответствующих систем координат, и из этой пропорции найти зависимость. В нашем случае пропорция следующая:

40

Xc X1

=

1

, откуда Xc =

X1 +

(X 2 X1)(1)

 

 

M X 1

X2 X1

 

M X 1

 

 

или =1+ (M X 1)(Xc X1)

,

 

(1)

 

 

(X2 X1)

 

 

 

 

Аналогично составляем пропорцию для пересчета по оси ординат координаты Yc системы К1 в координату Yэ (Y на экране) системы К2. Заметим, что в координатной системе К2 отсчет идет из левого верхнего угла экрана, т.е. координата левой верхней точки экрана равна (1,1). А правой нижней — (MX, MY). Получаем пропорцию

Yc Y1

=

MY

, откуда = MY

(MY

1)

(Yc Y1)

.

(2)

 

Y2 Y1

 

MY 1

 

 

 

Y2 Y1

 

Для определения позиций осей ординат и абсцисс в выражении

(1) нужно положить XC = 0, а в выражении (2) — YC = 0. Получаем следующие уравнения для осей:

для оси ординат =1X1

(M X 1)

;

(X 2 X1)

для оси абсцисс = MY +Y1 (MY 1) .

Y2 Y1

Практическая часть

Разработка алгоритма

Составим словесное описание алгоритма.

1.Выбираем каждую позицию на экране, начиная с левого верхнего угла, и двигаемся сначала по строке вправо, потом переходим к следующей строке.

2.Для текущей позиции делаем преобразование из К2 в К1 и вычисляем значение функции.

3.Проверяем текущую позицию на экране на условия:

если в позиции экрана y = f(x), то выводим точку графика функции красным цветом;

41

если в позиции экрана y f(x) и y = 0 (т.е. ось абсцисс) или y f(x) и x = 0 (т.е. ось ординат) выводим ось белым цветом; во всех остальных случаях — не выводим ничего, либо за-

крашиваем точку в цвет фона окна.

4. Переходим к следующей позиции на экране. Блок-схема алгоритма представлена на рис. 25.

Начало

Цикл по строкам экрана Y:=1 Y<=MAX_Y

Цикл по столбцам экрана X:=1 X<=MAX_X

Цикл по X

X:=X+1

Цикл по Y

Y:=Y+1

Конец

Вычислить текущую координату Xc (X)

Вычислить значение функции в текущей координате f(Xc)

Текущая точка экрана

 

+

Вывести

 

 

 

(X,Y) соответствует

 

 

 

 

 

 

красн. точку

 

значению функции?

 

 

 

 

 

 

 

 

+

 

Вывести бел.

 

 

Ось ординат

 

 

 

 

 

 

точку

 

 

 

 

 

 

 

‘|’

 

+

 

Вывести бел.

 

 

Ось абсцисс

 

 

 

 

 

точку

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Вывести

 

 

 

 

 

 

 

цвет фона

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Рис. 25. Блок-схема алгоритма

42

Рассмотрим частный случай, когда график функции нужно выводить в текстовом режиме на экран консоли размером MX = 80 символов и MY = 25 строк.

Тогда для отображения графика на экране консоли будем пользоваться следующим символами:

символ ‘*‘ — если в этой позиции экрана y = f(x);

символ ‘-‘ — если в этой позиции экрана y ≠ f(x) и y=0 (ось абсцисс);

символ ‘|’ — если в этой позиции экрана y ≠ f(x) и x=0 (ось ординат);

символ ‘ ‘ (пробел) — во всех остальных случаях. Напишем программу для этого частного случая.

programDrawFunc; {$APPTYPE CONSOLE} uses

SysUtils, Math; const

MAX_X=80; MAX_Y=25;

type

FuncToDraw = function (x:real):real;

function func1(x:real):real; begin

func1:=(sin(x));

end;

function func2(x:real):real; begin

func2:=arctan(x);

end;

function func3(x:real):real; begin

func3:=x*x;

end;

43

procedureDrawUserFunc(x1,x2,y1,y2:real; Func: FuncToDraw);

varx,y:integer; f,xcur :real; begin

for y:=1 to MAX_Y do begin for x:=1 to MAX_X do begin

//вычислить текущую координату по ф-ле (1) xcur:=x1+(x-1)*(x2-x1)/(MAX_X-1);

f:= Func(xcur); //вычислить значение функции в текущей позиции

// проверяем условие (3) -

//Текущая точка экрана (X,Y) соответствует значению функции?

if y = MAX_Y-round((MAX_Y-1)*(f-y1)/(y2-y1)) then write ('*')

else //осьординат?

if x = 1 — round(x1 * (MAX_X-1) / (x2-x1)) then write ('|')

else //осьабсцисс?

if y = MAX_Y + round(y1 * (MAX_Y-1)/ /(y2-y1)) then write ('-')

else write (' '); end;

end;

end;

begin

DrawUserFunc(-3,3,-1,1,func1); readln; DrawUserFunc(-4,4,-1.3,1.3,func2); readln; DrawUserFunc(-4,4,0,9,func3); readln; end.

Результаты выполнения программы приведены на рис. 26.

44

Рис. 26. Результаты выполнения программы

45

Задания к лабораторной работе.

1.Используя методы и свойства компонента Canvas реализо-

вать процедуру DrawUserFunc (x1,x2,y1,y2:Real; X0, Y0, Mx, My:Integer; Func: FuncToDraw), которая выводит в прямоугольник

слевой верхней вершиной в точке X0, Y0 размером MX на MY график функции Func на интервале [x1,x2] со значениями в диапазоне [y1,y2]. Для вычисления произвольной функции определить пользовательский тип FuncToDraw.

2.Доработать программу таким образом, чтобы можно было рисовать графики кривых второго, третьего и высших порядков. Для этого переработать программу так, чтобы функция, содержащая уравнение кривой, выдавала TRUE, если точка (x,y) принадлежит кривой и FALSE — в противном случае. Учесть, что сравнение типа «if A=B then … » для вещественных переменных A и B не допустимо, из-за различной точности вычислений. Сравнивать можно только целочисленные переменные.

Примечание 1. Каноническое уравнение кривой второго порядка имеет вид: ax2 + by2 = c, общим уравнением кривой второго порядка называется уравнение вида: ax2 + 2bxy + cy2 + 2dx + 2ey + с = 0.

Примечание 2. Уравнения кривых третьего порядка содержат члены с переменными x, y, имеющих степень 3. Уравнения кривых высших порядков — содержат члены с переменными x, y, имеющих степень более 3.

46

Лабораторная работа № 6

Разработка приложения «Часы»

с использованием графической библиотеки OpenGL

Теоретическая часть

В данной лабораторной работе необходимо нарисовать на форме приложения с помощью библиотеки OpenGL часы со стрелкой, которые будут ходить в соответствии с системным временем.

Прежде чем перейти к знакомству с библиотекой OpenGL, необходимо научиться работать с окнами в Delphi, познакомиться с такими понятиями, как контекст устройства, контекст воспроизведения и т. д.

Абсолютно все действия в Windows связаны с использованием окон. Любые документы или программы открываются именно в окнах, которые располагаются на рабочем столе Windows. Соответственно, у операционной системы должна быть возможность различать окна. Для этого каждое из них при создании получает уникальный идентификатор, который обычно называют «ссылкой на окно». В Delphi тип этой величины — HWND (HandleWiNDow).

Ссылка на окно может использоваться любым приложением для идентификации окна.

Для получения идентификатора окна можно, например, использо-

ватьфункциюFindWindow(ClassName, WindowName:PChar): HWnd. Сообщение (например, WM_CREATE, WM_PAINT и т. д.) от-

правляется операционной системой окну. Когда приложение получает какое-то сообщение, оно регистрирует соответствующее событие (например, сообщению WM_CREATE соответствует событие OnCreate), и, в случае необходимости, вызывает обработчик соответствующего события.

Таким образом, получив ссылку на окно, и отправив ему нужное сообщение, можно производить с ним почти любые действия.

47

Например, чтобы отправить сообщение, которое закроет окно с идентификатором, записанным в некоторой переменной H типа HWnd, нужно вызвать функцию SendMessage.

SendMessage (H, WM_CLOSE, 0, 0);

Вывод графической информации с использованием функ-

ций GDI.

GDI (GraphicsDeviceInterface) — это специальный графический интерфейс, реализованный в Windows, с помощью которого программист может представлять и передавать графическую информацию на устройства отображения, не задумываясь об особенностях того или иного устройства (видеокарты, принтера и т. д.). Этот интерфейс является одной из основных составляющих всей операционной системы Windows, наравне с ядром системы и WinAPI.

Выше написано, как получив ссылку на окно, можно передавать ему сообщения. Однако, для того чтобы, например, нарисовать что-нибудь на окне или произвести какие-то другие графические операции с ним, одного идентификатора окна мало. Необходима ещё так называемая ссылка на контекст устройства. В Delphi тип такой величины hdc (HandleDeviceContext — ссылка на контекст устройства). Чтобы получить её значение, необходимо вызвать API-функцию GetDC, которой в качестве параметра передается ссылка на окно (или другое устройство). Имея ссылку на контекст устройства, можно с помощью API-функций производить вывод графических элементов на данное окно:

procedure TForma1. Button1Click(Sender: TObject);

var

handleDC: HDC; // ссылка на контекст устройства

begin

handleDC: = GetDC (Canvas.Handle);

// Canvas.Handle — ссылка на текущее окно

Rectangle (handleDC, 10, 10, 10, 10); //

рисуемквадрат

48

ReleaseDC (Canvas.Handle, handleDC); // ос-

вобождениессылки

DeleteDC (handleDC); // удаление ссылки,

освобождение памяти end;

Но такой вывод недолговечен. При перерисовке окна квадрат пропадет, так как за эту перерисовку отвечает обработчик именно этого окна.

Графическая система OpenGL.

OpenGL (OpenGraphicsLibrary — открытая графическая библиоте-

ка) — это аппаратно-независимый графический интерфейс, который можно использовать на различных платформах. Он представляет собой DLL-библиотеку. Данной библиотеке также требуется ссылка на устройство. Однако для OpenGL эта ссылка отличается от обычнойссылки на контекст устройства типа HDC. У OpenGL — это ссылка на контекст воспроизведения — величина типа HGLRC (HandleopenGLRenderingContext). По сути, контекст воспроизведения дляOpenGL играеттакуюжероль, чтоиконтекстустройствадляGDI.

Итак, мы рассмотрели некоторые важные вопросы, касающиеся работы приложения с графической информацией и его взаимодействия с операционной системой. Теперь можно перейти непосредственно к применению OpenGL.

Для начала необходимо подключить модуль OpenGL в разделе uses, приложения Delphi.

Следующий важный момент для работы с OpenGL — это установка формата пикселя и контекста воспроизведения. Для начала нужно объявить глобальную переменную типа HGLRC:

hrc: HGLRC; // ссылка на контекст воспроизведения

Кроме того, нам нужно написать процедуру, в которой будет описываться формат пикселя. Процедура должна выглядеть примерно так:

procedureSetDCPixelFormat (hdc: HDC); var

pfd: TPixelFormatDescriptor; nPixelFormat: Integer;

49