Учебник по программированию.

Первые шаги. Язык программирования PascalABC.

Предыдущий параграф Назад в содержание Следующий параграф


Глава V. Графика.

Программирование под ОС Windows.


В данной главе мы изучим принципы работы с графикой. Для этих целей в PascalABC.NET специально был создан модуль GraphABC. Так же стоит сказать, что изучение программирования под операционную систему DOS у нас закончилось, и мы начнём создавать программы под операционную систему Windows.


§20. Модуль GraphABC.

Создадим новую программу, ничего не выполняющую, и подключим к ней модуль GraphABC. Сделать это можно с помощью шаблона наберите gr и нажмите «Shift+Пробел». Получим следующий код:


uses GraphABC;


begin

 

end.


Теперь после запуска такой программы мы увидим не консольное приложение, а обычное Windows-овское окно:



В этом и заключается преимущество  PascalABC.NET (в смысле обучения) над другими интегрированными средами разработки. Нам нет необходимости писать код для создания окна, достаточно просто подключить модуль GraphABC к программе, и окно будет появляться автоматически. В таком случае мы можем сосредоточиться на изучении именно графики, а не проходить параллельно курс программирования под операционную систему Windows.

Внимательно посмотрите на окно. Вверху окна вы увидите четыре стандартных кнопки одна слева и три справа. При нажатии левой кнопки появляется меню с командами:



О назначении трёх правых вы наверняка знаете не хуже меня это свернуть, развернуть и закрыть.

По краям окна находится синяя окантовка или бордюр. Большая часть окна заполнена белым цветом это клиентская часть. Именно в этой части окна мы и будем выводить наши графические рисунки.

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

Вся клиентская часть нашего окна поделена на точки (пиксели), которые имеют свои собственные координаты. Отчёт точек начинается с верхнего левого угла. Для того, что бы было понятно можно условно провести с лева на право ось Х, и с верху в низ ось У. Наглядно это демонстрирует следующий рисунок, на котором изображена буква Т:


На рисунке закрашенными в чёрный цвет являются пиксели со следующими координатами: (2;2), (3;2), (4;2), (5;2), (6;2), (4;3), (4;4), (4;5), (4;6). Здесь можно провести следующую аналогию: в консольном окне символы тоже имеют свои координаты, только там не оси Х и Y, а порядковый номер символа в строчке и номер строчки соответственно.

Здесь же стоит отметить, что если вы не сделали ни каких инициализирующих действий, то размер клиентской части нашего окна по умолчанию будет иметь размер 640х480 точек.

В данной главе изучение модуля GraphABC начнём с так называемых графических примитивов. К ним  относятся следующие элементы: текст, точка, отрезок (линия), круг, окружность, дуга, прямоугольник, прямоугольник со скруглёнными краями и эллипс. Остальные возможности этого модуля будут приведены в виде обзора в 32 параграфе.

Текст. Текст рисуется с помощью следующей процедуры:

procedure TextOut(x,y: integer; s: string); выводит строку s в прямоугольник с координатами левого верхнего угла (x,y). Пример:


uses GraphABC;

begin

  TextOut(10,10,'Привет всем!');

end.


Шрифт текста, который рисуется с помощью данной процедуры можно менять следующими подпрограммами:

procedure SetFontSize(size: integer); устанавливает размер шрифта в пунктах.

function FontSize: integer; возвращает размер шрифта в пунктах.

procedure SetFontName(name: string); устанавливает имя шрифта.

function FontName: string; возвращает имя шрифта.

procedure SetFontColor(c: Color); устанавливает цвет шрифта. О цветах поговорим отдельно в следующем подразделе.

function FontColor: Color; возвращает цвет шрифта.

procedure SetFontStyle(fs: integer); устанавливает стиль шрифта.

function FontStyle: integer; возвращает стиль шрифта.

В модуле GraphABC определены следующие константы для установки стилей шрифта:

  • fsNormal обычный;
  • fsBold жирный;
  • fsItalic наклонный;
  • fsBoldItalic жирный наклонный;
  • fsUnderline подчеркнутый;
  • fsBoldUnderline жирный подчеркнутый;
  • fsItalicUnderline наклонный подчеркнутый;
  • fsBoldItalicUnderline жирный наклонный подчеркнутый.

function TextWidth(s: string): integer; возвращает ширину строки s в пикселях при текущих настройках шрифта.

function TextHeight(s: string): integer; возвращает высоту строки s в пикселях при текущих настройках шрифта.

Пример:


program HellowWord;

uses GraphABC;

var x,y,//Координаты для вывода текста

    xTemp,yTemp:byte;//Координаты для вывода второй строки


begin

//Настраиваем шрифт

  SetFontSize(30);

  SetFontName('Times New Roman');

  SetFontStyle(fsBoldItalicUnderline);

  SetFontColor(clRed);

  x:=100; y:=10;

//Выводим первую строку

  TextOut(x,y,'Привет всем!');

//Формируем координату для второй строки 

  xTemp:=x+Round(TextWidth('Привет всем!')/2)-

                                   Round(TextWidth('Дорогие друзья!')/2);

  yTemp:=y+TextHeight('П');

//Выводим вторую строку 

  TextOut(xTemp,yTemp,'Дорогие друзья!');

end.

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

Так же обратите внимание на то, что в данном примере мы вывели первую строку, используя координаты x,y. Координаты для второй строки были рассчитаны относительно этих же координат. В таком случае можно менять координаты x и y, и при этом строки относительно друг друга своё положение не изменят. Так же можно менять размер и стиль шрифта. Например, если сделаем x=10,y=20, размер шрифта равным 10 и стиль шрифта fsBold, то получим следующий результат:



Здесь координаты x,y являются абсолютными, а xTem, yTemp относительными. Очень часто заранее неизвестно, где будет находиться тот или иной элемент изображения. Поэтому необходимо во время выполнения программы вычислять его координаты относительно какого-либо другого элемента. Отсюда и название относительные координаты.


Цвета. Всего в модуле GraphABC определено 141 константа для установки цвета. Все они начинаются с префикса cl, поэтому, набрав этот префикс, вам всплывёт подсказка, в которой вы увидите весь список доступных цветов. Для этого должна быть включена подсказка по нажатию клавиш. Об этом речь шла в 16-ом параграфе. Так же про цвета вы можете узнать в справке в пункте: «Стандартные модули -> Модуль GraphABC -> GraphABC: цветовые константы».

Плюсом к вышесказанному о цветах предлагаю написать небольшую программку, которая будет выводить цвет и его название:


uses GraphABC;

var  mC:array [1..141] of Color;


begin

    mC[1]:=clAquamarine;

    mC[2]:=clAzure;

..................................

    mC[140]:=clYellow;

    mC[141]:=clYellowGreen ;

 

  SetFontSize(10);

  var x,y:integer;

      x:=5; y:=5;

  for var i:=1 to 141 do

    begin

      SetBrushColor(mC[i]);

      Rectangle(x,y,x+100,y+10);

      SetBrushColor(clWhite);

      TextOut(x,y+10,mC[i].Name);

      x:=x+105;

      if x>1200 then begin x:=5; y:=y+35 end;

    end;

end.


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

Так же стоит сказать, что тип Color структурированный тип запись. Поэтому он имеет поле Name, в котором содержится имя цвета. Для того, что бы использовать этот цвет в программе к этому имени необходимо добавить префикс cl.

В предыдущем абзаце было сказано, что тип Color  тип запись. Это не совсем верно. В дальнейшем, когда будем изучать ООП, мы узнаем что такое на самом деле тип Color. На данном этапе предлагаю воспринимать его, как тип запись.


Точка. Для того, что бы нарисовать или стереть точку имеется следующая процедура:

procedure SetPixel(x,y: integer; c: Color);  закрашивает пиксель с координатами (x,y) цветом c.

Если необходимо стереть точку, то на её месте можно нарисовать точку цвета окружающего фона. Для того что бы узнать цвет окружающего фона есть процедура, которая позволяет узнать цвет точки в определённом месте:

function GetPixel(x,y: integer): Color; возвращает цвет пикселя с координатами (x,y).

С помощью процедуры SetPixel удобно рисовать графики всевозможных функций. Например, следующий код демонстрирует вывод синусоидальной функции на экран:


Uses GraphABC;

begin

  for var i:=1 to 640 do

    SetPixel(i,Round(Sin(i/8)*10*(-1)+20),clBlack);

end.


Здесь хочу заострить ваше внимание на следующем  нюансе: для формирования координаты Y, написано следующее выражение:


Sin(i/8)*10*(-1)+20


Поделив i на 8, мы увеличили период, т.е. растянули график по оси Х. Помножив на 10, мы увеличили амплитуду. Т.е. растянули график по оси У. Т.к. обычно ось Y всегда направлена снизу вверх, то пользователю будет нелепо видеть, что синусоидальная функция вначале убывает, а потом возрастает. Поэтому нам необходимо было помножить получившееся значение на -1 для того что бы перевернуть график. Добавив 20, мы сместили график в низ на 20 пикселей. При этом мы получили довольно красивую картинку.

Без этих манипуляций, т.е. просто написав Round(sin(i)), мы бы получили не работающую программу т.к. получили бы отрицательные значения по оси Y, а т.к. пикселей с отрицательными координатами нет, то программа во время выполнения закрылась бы с ошибкой. Но даже если мы добавим 20 и тем самым сместим график вниз, то всё равно получится не со всем то, что бы хотел увидеть пользователь:


К чему все эти рассуждения. Дело в том, что при выводе результатов каких либо вычислений на экран, вам придётся заботиться о том, что бы они были удобными для восприятия пользователем.


Отрезок. Самая простая процедура для рисования отрезка это:

procedure Line(x1,y1,x2,y2: integer; c: Color); рисует отрезок от точки (x1,y1) до точки (x2,y2) цветом c. Думаю, что здесь всё понятно, никаких дополнительных пояснений не требуется.

Есть ещё одна процедура:

procedure LineTo(x,y: integer; c: Color); рисует отрезок от текущей позиции до точки (x,y) цветом c. Текущая позиция при этом переносится в точку (x,y) . Здесь стоит остановиться на том, что такое текущая позиция. Так же как и при работе с типизированными файлами существует некая переменная, которая хранит в себе координаты текущей позиции. Текущую позицию можно изменить с помощью следующей процедуры:

procedure MoveTo(x,y: integer); устанавливает текущую позицию рисования в точку (x,y).

С помощью процедуры LineTo удобно рисовать непрерывную ломаную линию:


Uses GraphABC;


begin

  for var i:=1 to 64 do

     LineTo(i*10,Random(1,29),clBlack);

  MoveTo(1,30);

  for var i:=1 to 64 do

     LineTo(i*10,Random(30,59),clBlack);

end.


При вызове процедур Line и LineTo цвет в качестве параметра можно не указывать. Тогда рисование линии будет происходить цветом, который установлен в свойствах пера. Здесь стоит отметить, что рисование линий и контуров других примитивов происходит как бы пером, поэтому цвет, толщина линии и стиль линии зависят от того как настроено перо.

Подпрограммы для настройки пера.

procedure SetPenColor(c: Color);  устанавливает цвет пера.

function PenColor: Color; возвращает цвет пера.

procedure SetPenWidth(Width: integer); устанавливает ширину пера в пикселях.

function PenWidth: integer;  возвращает ширину пера в пикселях.

procedure SetPenStyle(style: DashStyle); устанавливает стиль пера.

function PenStyle: DashStyle; возвращает стиль пера.

Стили пера бывают следующие:

  • psSolid  сплошное перо;
  • psClear  прозрачное перо;
  • psDash  штриховое перо;
  • psDot  пунктирное перо;
  • psDashDot штрихпунктирное перо;
  • psDashDotDot  альтернативное штрихпунктирное перо.

Далее пример, в котором настроенное перо рисует штриховую линию коричневого цвета, шириной в 3 пикселя:


uses GraphABC;

begin

  SetPenColor(clChocolate);

  SetPenWidth(3);

  SetPenStyle(psDash);

  for var i:=1 to 32 do

     LineTo(i*20,Random(1,29));

end.


В данном параграфе мы познакомились с модулем GraphABC. Научились выводить в графическое окно текст и линию. А так же научились закрашивать пиксель определённым цветом и настраивать перо.



Задачи.

1. Начертить графики следующих функций, в диапазоне значений параметра от 0 до 12: а); б) ; б).

2. Перечертить на экран чертёж, представленный на рисунке в относительных координатах. Так же масштаб рисунка должен задаваться константой, при этом при смене масштаба рисунок должен сохранять пропорции. Размеры и выносные линии чертить не надо.



Решение.

1.a)

program Grafik_1;

uses GraphABC;

const m=20;//Массштаб - 20 пикселей это одно реальное значение

var rX,rY:real;//реальные значения параметров функции


begin

//Чертим оси координат

  Line(20,100,285,100);

  Line(30,20,30,110);

//Стрелочки ось X

  Line(285,100,278,97); Line(285,100,278,103);

//Стрелочки ось Y

  Line(30,20,27,27); Line(30,20,33,27);

//Деления ось X 

  for var i:=1 to 12 do

    begin

      var temp:=i*m+30;

      Line(temp,90,temp,110);

      TextOut(temp-5,115,IntToStr(i));

    end;

//Деления ось Y

  for var i:=1 to 3 do

    begin

      var temp:=100-i*m;

      Line(25,temp,35,temp);

      TextOut(15,temp-8,IntToStr(i));

    end;

//График

  for var i:=30 to 12*m+30 do

    begin

      rX:=(i-30)/m;

      rY:=0.2*rX+0.5;

      SetPixel(i,Round(-m*rY+100),clRed);

    end

end.

В пунктах b и c код программы остаётся тот же, за исключением 32-ой строчки:

b) rY:=1.3*Power(rX,1/3);

c) rY:=1.3*Sin(rX)+1.5;


2.

Program Chertej;

uses GraphABC;

const m=2;//Массштаб

      X0=10;Y0=10;//Начало координат

var tp:record //Текущая позиция дл процедуры LineFT

    x,y:integer;end;


//Line From tp To x,y

//Рисует линию от текущей позиции в точку (x,y),

//которая задаётся относитльно текущей позици

procedure LineFT(x,y:integer);

begin

Line(tp.x,tp.y,tp.x+x,tp.y+y);

tp.x:=tp.x+x;

tp.y:=tp.y+y;

end;


begin

//Рисуем основной контур толстыми линиями

  SetPenWidth(2);

  tp.x:=118*m+X0+10; tp.y:=Y0;

  LineFT(0,90*m);

  LineFT(-30*m,0);

  LineFT(0,-19*m);

  LineFT(-26*m,0);

  LineFT(0,-8*m);

  LineFT(-62*m,0);

  LineFT(0,-36*m);

  LineFT(62*m,0);

  LineFT(0,-8*m);

  LineFT(26*m,0);

  LineFT(0,-19*m);

  LineFT(30*m,0);

//Дорисовываем толстые линии

  Line(X0+10+62*m,Y0+27*m,X0+10+62*m,Y0+63*m);

  Line(X0+10+88*m,Y0+19*m,X0+10+88*m,Y0+71*m);

//Рисуем ось детали

  SetPenWidth(1);

  tp.x:=X0; tp.y:=Y0+45*m;

  for var i:=1 to 6 do

    begin

      LineFT(Round(118*m/6)-15,0);

      tp.x:=tp.x+5;

      LineFT(5,0);

      tp.x:=tp.x+5

    end

  LineFT(Round(118*m/6)-15,0);

end.



Предыдущий параграф Назад в содержание Следующий параграф