Графика в Паскале

FIXME

Пример работы с графикой в системе Borland (что тоже самое - Turbo) Pascal:

USES GRAPH;                           // подключение "графической библиотеки"
 
VAR h,k,l: INTEGER;
 
BEGIN
 ...                                  // "Неграфическое" начало программы (если есть)
 
 DetectGrahp(k,l);                    // Определение параметров графики
 InitGraph(k,l,'d:\tp7\bgi\');        // Инициализация графики
 
 h:=GraphResult;                      // Проверка на ошибку запуска графики
 If h<>0 then                         // Реакция на ошибку запуска графики 
 begin
   writeln('Error - ', h);
   writeln('Press ENTER for EXIT!');  // Ожидание 
   readln; 
   halt;                               // Выход из программы
 end
 else ... ;                            // Здесь - код для работы с графикой 
 
 ...                                   // "Неграфическое" окончание программы (если есть)
 
END.

Пример работы с графикой в нашей системе.

uses oglgraph;                     // Необходимая библиотека, у нас заменяет graph
 
var 
  gd, gm: smallint;                // Имена не важны, а тип переменных - важен
 
begin
  gd := Detect;                    // Автоматическая установка разрешения
  gm := DetectMode;
  initgraph(gd, gm, '');           // Открытие "графического окна" 
 
{далее все, что Вы хотите нарисовать, например:}
 
  setcolor(green);
  line(0, 0, 100, 100);
 
{конец отрисовки}
  repeat until graphkeypressed;    // Задержка закрытия графического окна до нажатия 
                                   // клавиши для завершения работы программы - 
                                   // иначе рискуете ничего толком не увидеть
 
  closegraph();                    // закрытие графического окна - не обязательно, но рекомендуемо.
 
end.

        Mx := GetMaxX div 2;
	My := GetMaxY div 2;
	for y := -my to my do
		for x := -mx to mx do 
		begin
			n := 0;
			c.x := x * 0.005;
			c.y := y * 0.005;
			z.x := 0;
			z.y := 0;
			while (sqr(z.x) + sqr(z.y) < max) and (n < iter) do 
			begin
				t := z;
				z.x := sqr(t.x) - sqr(t.y) + c.x;
				z.y := 2 * t.x * t.y+ c.y;
				Inc(n);
				if KeyPressed then 
					Cancel := true;
			end;
		if n < iter then 
		begin
        		PutPixel(mx + x,my + y,16 - (n mod 16));
		end;
		if Cancel then 
			exit;
	end;

Примеры

Среди примеров - часто возникающие задачи.

Определение размеров экрана для рисования рамки экрана

uses oglgraph;          { Подключаем нашу библиотеку }
 
var 
  gd, gm: smallint;
  maxx, maxy : integer;
 
begin
  gd := Detect;
  gm := DetectMode;
  initgraph(gd, gm, ''); 
 
  maxx := getmaxx();     { Выясняем ширину экрана}
  maxy := getmaxy();     { Выясняем высоту экрана} 
 
  {Внимание! Функции getmaxx и getmaxy правильно работают только после вызова initgraph }
 
  setcolor(blue);        { устанавливаем синий цвет для рисования линий }
 
  rectangle(1, 1, maxx - 1, maxy - 1); { Рисуем прямоугольник с отступом в 1 пиксель от края экрана}
 
 
  repeat until graphkeypressed;        { Сохраняем рисунок на экране до нажатия кнопки} 
 
  closegraph();           
end.

Изменение цвета экрана заливкой

uses oglgraph;
 
var 
  gd, gm: smallint;
  color : integer;
 
begin
  gd := Detect;
  gm := DetectMode;
  initgraph(gd, gm, ''); 
 
    color := white;                      {выбираем цвет с помощью описанной в библиотеке константы white}
    setBkColor(color);                   {устанавливаем "нужный" цвет фона - ничего не происходит}
    cleardevice;                         {"очищаем" экран нужным цветом - установленным цветом фона } 
 
    ...                                  {Можно что-то рисовать}
 
  repeat until graphkeypressed;        { Сохраняем рисунок на экране до нажатия кнопки} 
 
  closegraph();           
end.

Другой способ

Изменение цвета экрана

    ...
  initgraph(gd, gm, ''); 
 
    color := white;                      {выбираем цвет с помощью описанной в библиотеке константы white}
    setfillstyle(1, color);              {устанавливаем "нужный" цвет и способ "штриховки" при заливке - ничего не происходит}
    floodfill(0,0,red);                  {"заливаем" экран нужным цветом - установленным цветом заливки, 
                                         пока не наткнёмся на красный, которого нет } 
    ...                                  {Можно что-то рисовать}
 

Процедуры и функции

Имя Описание
getmaxX()
Функция, которая определяет максимальную ширину экрана в пикселях
getMaxY()
Функция, которая определяет максимальную высоту экрана в пикселях
getX()
Функция, которая определяет текущее положение невидимого графического курсора по оси X
getY()
Функция, которая определяет текущее положение невидимого графического курсора по оси Y
moveTo(x, y)
Перемещает графический курсор к пикселю с координатами (x,y)
moveRel(dx, dy)
Смещает графический курсор на dx и dy пикселей по осям X и Y, соответственно
setColor(color)
Устанавливает цвет для линий (line, arc и т.д.) и замкнутых контуров (circle и т.д.)
setLineStyle(LineStyle, Pattern, Thickness)
Устанавливает тип и толщину линий (line, rectangle, circle и т.д.).
setBkColor(color)
Устанавливает цвет фона
cleardevice
Очищает экран, заливая его установленным цветом фона
setFillStyle(pattern, color)
Устанавливает тип и цвет заливки плошадей (bar, floodFill и т.д.)
putPixel(x, y, color)
Меняет цвет пикселя с координатами (x,y) на цвет, указанный параметром color
getPixel(x, y)
Функция, которая определяет текущий цвет пикселя c координатами x и y
line(x1, y1, x2, y2)
Рисует прямую линию из точки (x1,y1) в точку (x2,y2)
lineTo(x, y)
Рисует прямую линию из текущей позиции в точку (x,y), перемещая графический курсор
lineRel(dx, dy)
Рисует прямую линию из текущей позиции в позицию со сдвигом dx, dy, перемещая графический курсор
drawPoly(n, var An)
Рисует ломаную линию из n точек с координатами, взятыми попарно из массива An, размерностью 2*n*sizeof(integer)
circle(centerX, centerY, radius)
Рисует окружность (линию) с центром (x,y) и с радиусом r
arc(centerX, centerY, angle1, angle2, radius)
Рисует дугу с центром (centerX, centerY) и радиусом r от угла angle1 до угла angle2, указанными в градусах
ellipse(centerX, centerY, angle1, angle2, radiusX, radiusY)
Рисует эллипс с центром в (centerX, centerY) от угла angle1 до угла angle2, указанными в градусах, и с радиусами radiusX, radiusY
rectangle(x1, y1, x2, y2)
Рисует незаполненный прямоугольник (прямоугольный контур) с координатами левого верхнего угла - (x1,y1) и правого нижнего угла - (x2, y2)
bar(x1, y1, x2, y2)
Рисует заполненный прямоугольник (без граничной линии) с координатами левого верхнего угла — (x1,y1) и правого нижнего угла — (x2, y2)
bar3D(x1, y1, x2, y2, l, b)
Рисует параллелепипед с прямоугольной боковой стенкой, заданной противоположными углами (x1, y1) и (x2, y2), и толщиной l. Параметр b указывает, рисовать ли верхнюю грань
fillEllipse(centerX, centerY, radiusX, radiusY)
Рисует заполненный эллипс
fillPoly(n, an)
Рисует заполненный многоугольник
pieSlice(centerX, centerY, angle1, angle2, radius)
Рисует сектор круга
sector(centerX, centerY, angle1, angle2, radiusX, radiusY)
Рисует сектор эллипса
floodFill(x, y, color)
Определяет и заливает область, ограниченную контуром цвета сolor и краями экрана. Точка (x,y) должна находиться внутри контура. Внимание! Рисует очень медленно!

Типы линий

Имя Описание
SolidLn Сплошная линия
DottedLn Пунктирная линия
CenterLn
DashedLn
UserBitLn Пользовательский тип. Требуется задать параметр Pattern в процедуре setLineStyle значением от 0 до 65535

Толщина линий

Имя Значение Описание
NormWidth 1 Обычная линия
ThickWidth 3 Жирная линия

Обратите внимание, что значение параметра не задает толщину линии, а указывает режим рисования. Написать setLineStyle(LineStyle, Pattern, 4);, вообще говоря, ошибка!

Стили заливки

Имя Значения Описание
EmptyFill 0
SolidFill 1 Сплошная заливка
LineFill 2
LtSlashFill 3
SlashFill 4
BkSlashFill 5
LtBkSlashFill 6
HatchFill 7
XHatchFill 8
InterleaveFill 9
WideDotFill 10
CloseDotFill 11

Немигающий экран

Чтобы избежать мигания экрана при перерисовке «заполненных» объектов, применяется метод двойной буферизации. При этом используются два виртуальных экрана, один из которых виден, а другой в это время - перерисовывается. Затем он показывается на экране, а видимый ранее - убирается и перерисовывается.

В начале рисования один раз командой SetDoubleBuffer(true) вызывается двойная буферизация, затем, после прорисовки каждого нового кадра, производится обмен вновь перерисованого кадра с тем, который был показан на экране, командой graphSwapBuffers.

Отключается войная буферизация командой SetDoubleBuffer(false);

Установка произвольного разрешения

m640x200x16       = VGALo;
m640x400x16       = VGAMed;
m640x480x16       = VGAHi;
{ VESA Specific video modes. }
m320x200x32k      = $10D;
m320x200x64k      = $10E;
m640x400x256      = $100;
m640x480x256      = $101;
m640x480x32k      = $110;
m640x480x64k      = $111;
m800x600x16       = $102;
m800x600x256      = $103;
m800x600x32k      = $113;
m800x600x64k      = $114;
m1024x768x16      = $104;
m1024x768x256     = $105;
m1024x768x32k     = $116;
m1024x768x64k     = $117;
m1280x1024x16     = $106;
m1280x1024x256    = $107;
m1280x1024x32k    = $119;
m1280x1024x64k    = $11A;

Работа с клавиатурой

В графическом режиме обработка событий клавиатура происходит очень похоже на текстовый режим, так как реализованы аналоги функций readkey и keypressed из модуля crt. В модуле oglgraph они называются graphreadkey и graphkeypressed. Функция graphkeypressed служит для определения события нажатия на клавиатуру, это логическая функция, которая возвращает два значения: истина или ложь. Обычно результатом ее работы будет всегда false, кроме того случая если нажата какая-нибудь клавиша на клавиатуре. В примерах выше это ее поведение используется для остановки выполнения программы перед закрытием графического режима:

 repeat until graphkeypressed;

Когда выполнение программы доходит до приведенной строки, запускается цикл repeat-until, который работает до тех пор, пока условие не станет истинным, что в нашем случае произойдет только при нажатии любой клавиши.

Функция graphreadkey так же реагирует на нажатия, но в результате работы возвращает скан-код клавиши, т.е. уникальное целочисленное значение, которое соответствует коду клавиши, генерируемому контроллером клавиатуры.

 code := graphreadkey;

Особенностью это функции является то, что она блокирует исполнение программы до того момента пока не будет нажата клавиша. Если же требуется реализовать работу с клавиатурой, которая бы не останавливала работу программы, то в этом случае нужно предварительно сделать проверку на нажатие клавиши с помощью graphkeypressed:

if graphkeypressed then
    code := graphreadkey; 

Напишем программу, которая опрашивает клавиатуру и выводит на экран коды клавиш:

uses oglgraph;
var
  gd, gm, code: smallint;
 
begin
  gd := Detect;
  gm := DetectMode;
  initgraph(gd, gm, '');
 
  while true do
  begin
     if graphkeypressed then
     begin
        code := graphreadkey; 
        writeln(code);
     end;   
  end;
  closegraph;
end.

Примечания

Все параметры графических процедур и функций — целые числа.

Ось Y направлена вниз. Следовательно, координаты левого верхнего угла - (0, 0).

Все процедуры и функции можно разбить на три группы.

Функции и процедуры, позволяющие узнать текущие настройки, начинаются с «get…» (getcolor и др.).

Процедуры, устанавливающие параметры рисования — с «set…» (setcolor и др.).

Процедуры, осуществляющие рисование и все остальные, называются кто во что горазд, но более или менее осмысленно (circle, floodfill …). «Рисующие» процедуры пользуются ранее установленными настройками или настройками по умолчанию. При изменении настроек, ранее сделанные рисунки не меняются.

pascal/graph.txt · Последние изменения: 18/03/2016 10:49 — ybezrukov
CC Attribution-Noncommercial 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0