Popov_vorobev
.pdf2. Если в позиции экрана 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. Преобразование координат
Согласно правилам преобразования координат, чтобы найти координату Xс системы К1 на основе соответствующей ей координаты Xэ (Х на экране) в системе К2 нужно составить пропорции по размерам соответствующих систем координат, и из этой пропорции найти зависимость. В нашем случае пропорция следующая:
40
Xc − X1 |
= |
Xэ−1 |
, откуда Xc = |
X1 + |
(X 2 − X1)(Xэ−1) |
|
|
|
M X −1 |
||||||
X2 − X1 |
|
M X −1 |
|
|
|||
или Xэ=1+ (M X −1)(Xc − X1) |
, |
|
(1) |
||||
|
|
(X2 − X1) |
|
|
|
|
Аналогично составляем пропорцию для пересчета по оси ординат координаты Yc системы К1 в координату Yэ (Y на экране) системы К2. Заметим, что в координатной системе К2 отсчет идет из левого верхнего угла экрана, т.е. координата левой верхней точки экрана равна (1,1). А правой нижней — (MX, MY). Получаем пропорцию
Yc −Y1 |
= |
MY −Yэ |
, откуда Yэ= MY |
−(MY |
−1) |
(Yc −Y1) |
. |
(2) |
|
||||||||
Y2 −Y1 |
|
MY −1 |
|
|
|
Y2 −Y1 |
|
Для определения позиций осей ординат и абсцисс в выражении
(1) нужно положить XC = 0, а в выражении (2) — YC = 0. Получаем следующие уравнения для осей:
для оси ординат Xэ=1− X1 |
(M X −1) |
; |
(X 2 − X1) |
для оси абсцисс Yэ= 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