Название: Программирование Часть 2 - Методические указания (Т.В. Дружинина)

Жанр: Информатика

Просмотров: 1012


Лабораторная работа № 2 основные графические функции и подпрограммы

 

В приложениях типа Standard Graphic Application и QuickWin вывод на экран может осуществляться не только в алфавитно-цифровом, но и в графическом режиме. Функции графического вывода позволяют, например, строить графики, создавать трехмерные изображения, имитировать движение и т.п. Это позволяет наглядно моделировать физические процессы и отображать работу физических устройств, что упрощает и ускоряет работу пользователя. Графические операции Фортрана реализованы в виде функций и подпрограмм, их определения находятся в библиотеке MSFLIB, поэтому, если в программе используются графические операции, библиотека должна быть подключена с помощью команды

USE MSFLIB

В графическом режиме в соответствии с принципами работы растрового дисплея экран рассматривается как система координат, в которой можно управлять состоянием (подсветкой) каждой точки (пиксела) экрана. Пиксел является минимальной адресуемой графической единицей. Для хранения состояния каждого пиксела (цвета) в памяти отводится не менее одного байта. Построение любого изображения сводится к подсветке отдельных точек экрана. Число точек по горизонтали и вертикали (разрешение) определяется техническими возможностями компьютера (в частности, графическим адаптером). Стандартным является разрешение 640 точек по горизонтали на 480 точек по вертикали. Размер пиксела обычно составляет 0,31–0,21 мм.

Графический вывод выполняется в окне, размеры которого можно менять. По умолчанию окном считается весь экран. Местоположение пиксела на экране можно определить тремя способами, в зависимости от того, какая координатная система применяется. Существует три системы координат (СК): физическая СК, СК порта просмотра и оконная СК.

В физической СК координаты точки – целочисленные положительные значения, начиная с 0 (по умолчанию координата х меняется от 0 до 639, у – от 0 до 479). Позиция текущей точки, в которой выполнялся графический вывод, сохраняется в переменной структурного типа xycoord:

Подпись:  TYPE xycoord

INTEGER(2) xcoord           !координата х

INTEGER(2) ycoord           !координата у

END TYPE

 

Начальной точкой физической СК является точка с координатами (0,0), расположенная в верхнем левом углу экрана. Координата х возрастает слева направо, координата у – сверху вниз.

СК порта просмотра (видовая СК) существует в пределах определенной пользователем области, называемой портом. Порт может занимать весь экран или его часть. За пределами порта графический вывод не осуществляется. Координаты порта являются целыми числами. Задать порт можно с помощью подпрограммы

CALL SETVIEWPORT(x1,y1,x2,y2),

где х1, у1, х2, у2 – координаты INTEGER(2) верхнего левого и нижнего правого угла прямоугольной области экрана, в которой организуется порт.

 

Исходной для СК порта является верхняя левая точка.

СК окна существует в пределах видеоокна, размеры и положение которого задаются пользователем. В отличие от физической СК и СК порта, СК окна может работать с координатами типа REAL(8), причем допускаются как положительные, так и отрицательные значения координат (см. лабораторная работа

№ 4). В данной лабораторной работе рассматривается преимущественно физическая СК.

Местоположение и размеры графических объектов можно задать с помощью констант, переменных и выражений соответствующего типа (в физической СК и СК порта - INTEGER(2)). Управление координатами возможно через аргументы функций и подпрограмм или через структуру типа xycoord. Чтобы пользоваться элементами этой структуры, в программе нужно создать переменную такого типа, после чего можно воспользоваться подпрограммой

CALL MOVETO(x,y,pos),

где х, у – координаты точки (тип INTEGER(2));

роs – переменная типа xycoord для хранения координат графического вывода.

Задать координаты точки графического вывода можно различными способами, например:

 

TYPE (xycoord) pos                            !объявляется переменная типа xycoord

Integer(2) x,y,st   

 . . . . .

CALL MOVETO(10,10,pos)                             !задается позиция графического

                                                              !вывода (10,10)

x=20; y=30

st=LINETO(x,y+5)                               !аргументами графической функции

                                                               !являются целочисленные выражения

pos.xcoord=100                                   !непосредственное обращение к элементам

структуры

pos.ycoord=200                                  !для установки позиции графического

                                                               ! вывода (100,200)

 

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

CALL SETVIEWORG(xn,yn,pos)

где хn, уn – координаты новой точки отсчета (тип INTEGER(2));

роs – переменная типа xycoord для хранения координат графического вывода.

Например, если при разрешении экрана 640х480 задать новую исходную точку с координатами (200,100), то координата х будет меняться в пределах 200…439, у – в пределах 100…379. Тогда задаваемые координаты будут преобразованы к новой системе отсчета. Так, точка с координатами (0,0) реально будет располагаться на экране в позиции (100, 200).

Часть изображения можно скрыть с помощью подпрограммы

CALL SETCLIPRGN (x1, y1, x2, x2),

где x1, y1, x2, y2 – аргументы (INTEGER(2)), физические координаты верхнего левого и нижнего правого угла прямоугольной области вывода. За пределами заданного прямоугольника изображение не появляется. На точку отсчета эта область не влияет.

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

st=SETCOLOR(color)

st=SETCOLORRGB(color)

и цвета фона

st=SETBKCOLOR(color)

st=SETBKCOLORRGB(color)

где сolor – код цвета рисунка (INTEGER(2)) или фона (INTEGER(4)),

  st – результат (индекс предыдущего цвета рисунка (фона) или -1, если цвет не удалось установить).

Код цвета в основной 16-цветной палитре можно задать следующими способами:

 

Цвет

Способы задания

Номер

Значение в шестнадцатеричной системе

(для RGB-функций)

Символьная

константа в 16-цветном режиме

Черный

0

#000000

$BLACK

Синий

1

#200000

$BLUE

Зеленый

2

#002000

$GREEN

Цвет

Способы задания

Номер

Значение в шестнадцатеричной системе

(для RGB-функций)

Символьная

константа в 16-цветном режиме

Голубой

3

#202000

$CYAN

Красный

4

#000020

$RED

Фиолетовый

5

#200020

$MAGENTA

Коричневый

6

#002020

$BROWN

Белый

7

#303030

$WHITE

Серый

8

#202020

$GREY

Светло-синий

9

#3F0000

$LIGHTBLUE

Светло-зеленый

10

#003F00

$LIGHTGREEN

Светло-голубой

11

#3F3F00

$LIGHTCYAN

Светло-красный

12

#00003F

$LIGHTRED

Светло-фиолетовый

13

#3F003F

$LIGHTMAGENTA

Желтый

14

#003F3F

$YELLOW

Ярко-белый

15

#3F3F3F

$BRIGHTWHITE

 

Значением цвета в палитре RGB является шестнадцатеричное число, которому соответствует определенный номер. Значения и номера цветов составляют палитру. RGB – это обозначение системы задания цвета. Каждый пиксел экрана имеет три точки засветки: красную (R), зеленую (G) и синюю (B). Подсветка этих точек с различной интенсивностью определяет цвет пиксела. В трех байтах описания цвета содержатся сведения об интенсивности каждого цвета. Интенсивность кодируется шестнадцатеричным числом. Поскольку с помощью одного байта можно задать 256 различных значений, число цветов в RGB составляет 2563=16777216.

Значение цвета по составляющим интенсивности можно получить с помощью функции

result=RGBTOINTEGER(r,g,b),

где result –значение цвета (INTEGER(4));

r, g, b – параметры (INTEGER(4)), задающие интенсивность красного, зеленого и синего цвета.

Можно также по значению цвета получить его составляющие:

 

call INTEGERTORGB(color, r, g, b)

где color – значение цвета (INTEGER(4));

r, g, b – составляющие интенсивности красного, зеленого и синего цвета (INTEGER(4)).

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

use msflib

integer(4) r, g, b                                    !составляющие цвета

integer(2) st, x

call integertorgb(#000080,r,g,b)         !определение составляющих красного

i=1                                                           !переменная для добавления оттенка

do x=1,600,5

st=setcolorrgb(rgbtointeger(r+i,g,b+i))            !установка нового оттенка цвета

st=rectangle($gfillinterior,x,1,x+5,400)              !вывод прямоугольника нового цвета

i=i+1

enddo

end

 

Задать цвет фона можно с помощью функций

result=SETBKCOLOR(color)

result1=SETBKCOLORRGB(color1)

где color–- индекс цвета фона (INTEGER(4));

color1 – RGB-значение цвета фона (INTEGER(4));

result – индекс предыдущего цвета фона (INTEGER(4));

result1 – RGB-значение предыдущего цвета фона (INTEGER(4)).

Любое изображение может быть представлено как совокупность достаточно простых объектов (точек, линий, геометрических фигур), для вывода которых разработаны графические примитивы – функции и подпрограммы:

1. Закраска точки экрана (пиксела) или группы точек заданным цветом.

Закраска указанного пиксела текущим цветом:

result=SETCOLOR(x, y),

где х, у – координаты точки (тип зависит от СК - INTEGER(2) или REAL(8));

result – прежний цвет точки (INTEGER(2)) или -1, если функция не выполнена.

Закраска заданным цветом ряда точек с указанными координатами:

CALL SETPIXELS (n, x, y, color)

где n – число закрашиваемых точек (INTEGER(4));

x, y – массивы, содержащие координаты х и у точек (INTEGER(2));

color – массив индексов цветов точек (INTEGER(2)).

Пример. Создаются массивы координат точек синусоиды и их цветов. График выводится как набор точек.

use msflib             

integer(2)  color(1000), x1(1000), y1(1000) ,x

type (xycoord) pos

call setvieworg(200,200,pos)          !перенос исходной точки СК

x=-200                                              !начальное значение координаты х

do i = 1, 1000

x1(i) = x+i                                         !массив 1000 координат х (от -200 до 200)

y1(i) = 200 * sin(3.14/500*i)           !массив 1000 координат у (синусоида)

color(i) = mod(i,15)+1                    !массив цветов (от 1 до 16)

enddo

call setpixels(1000, x1, y1, color) !закраска точек графика

end

 

Закраска указанного пиксела цветом RGB:

result=SETPIXELRGB(x,y,color),

где х, у – координаты точки (тип зависит от СК – INTEGER(2) или REAL(8));

color – RGB-значение нового цвета точки;

result – прежний цвет точки (INTEGER(4)) или -1, если функция не выполнена.

Закраска заданным цветом RGB ряда точек:

CALL SETPIXELSRGB (n, x, y, color),

где n – число закрашиваемых точек (INTEGER(4));

 

x, y – массивы, содержащие координаты х и у точек (INTEGER(2));

color – массив RGB-значений цветов точек (INTEGER(4)).

Вывод отрезка прямой от текущей графической позиции (содержится в структуре xycoord или wxycoord) до указанной точки:

result=LINETO(x, y),

где х, у – координаты точки (тип зависит от СК – INTEGER(2) или REAL(8));

result – результат выполнения (INTEGER(2)), не равен нулю при успешном завершении.

Пример. Вывод графика функции в виде отрезков, соединяющих соседние точки графика:

use msflib

integer(2) st, x

integer(2)  x2(20), y2(20)                    !массивы координат точек графика

type (xycoord) pos                                           !текущая графическая позиция

call setvieworg(320,240,pos)              !перенос начала системы отсчета

                                                                  !в середину экрана

x=-10                                                   !начальное значение координаты х

do i=1,20                                                             !цикл заполнения массивов координат точек

x2(i)=x+i-1

y2(i)=x2(i)**2                     !график функции у=х2

enddo

call moveto(x2(1),y2(1),pos)               !установка начальной точки графика

do i=2,20

       k=lineto(x2(i),y2(i))               !вывод отрезка от предыдущей

                                                      !до текущей точки

enddo

end

 

Вывод прямоугольника заданных размеров текущего цвета:

result=RECTANGLE(control,x1,y1,x2,y2),

где х1, у1, х2, у2 – координаты верхней левой и нижней правой вершины прямоугольника (тип зависит от СК – INTEGER(2) или REAL(8));

result – результат (INTEGER(2)), не равен нулю при успешном завершении;

control – параметр закраски, может принимать следующие значения:

$GBORDER – для вывода контуров прямоугольника;

$GFILLINTERIOR – для закраски прямоугольника текущим цветом.

Пример. Заполнение экрана прямоугольниками разного цвета:

 

use msflib

integer(2) x, y

integer(4) st 

st=setcolorrgb(#00FF00)                    !установка начального цвета

do x=0,560,40                                        !цикл изменения координат х

     do y=0,440,40                   !цикл изменения координат у

                 st=setcolorrgb(getcolorrgb()+2*(x+1)*(y+1))    !новый RGB-цвет

                 st=rectangle($gfillinterior,x,y,x+40,y+40)          !закрашенный

                                                                                              !прямоугольник

     enddo

enddo

end

 

Вывод многоугольника по координатам вершин:

result = POLYGON (control, ppoints, cpoints),

где result – результат (INTEGER(2)), не равен нулю при успешном завершении;

control – параметр закраски, может принимать следующие значения:

$GBORDER – для вывода контуров многоугольника;

$GFILLINTERIOR – для закраски многоугольника текущим цветом;

рpoints – массив структур xycoord (или wxycoord при работе с оконной СК), задающий координаты вершин многоугольника;

cpoints – число вершин многоугольника INTEGER(2).

Стороны многоугольника проводятся как отрезки между вершинами в порядке перечисления вершин в массиве ppoints.

Пример. Рисование звезды (определяются координаты точек окружностей двух диаметров (внутреннего и внешнего), каждая окружность делится на 5 частей, отрезки проводятся между точками внешней и внутренней окружностей):

 

use msflib

integer(4) st 

TYPE (xycoord)  poly(11), pos    !структуры для хранения координат

call setvieworg(320,240,pos)                    !начало системы отсчета переносится

                                                      ! в середину экрана

st=setcolorrgb(#000080)               !установка текущего красного цвета

a=3.14/2.                                                       !а - угол поворота точки по окружности

do i=0,11,2                                    ! координаты 11 точек звезды, последняя

                                                       !точка совпадает с первой

   poly(i+1).xcoord = sin(a)*200         !координаты внешней окружности

                                                !(радиус 400)

   poly(i+1).ycoord = cos(a)*200

   poly(i+2).xcoord = sin(a+3.14/5.)*100 !координаты внутренней окружности

                                                !(радиус 200)

   poly(i+2).ycoord = cos(a+3.14/5.)*100

   a=a+2*3.14/5              !угол поворота увеличивается на 72°

enddo

st=POLYGON($gfillinterior,poly,11) !вывод прямоугольника по массиву точек

end

 

Вывод эллипса (окружности):

result=ELLIPSE(control, x1 ,y1, x2, y2),

где х1, у1, х2, у2 – координаты верхней левой и нижней правой точки прямоугольника, в который вписан эллипс (тип зависит от СК – INTEGER(2) или REAL(8));

result – результат (INTEGER(2)), не равен нулю при успешном завершении;

control – параметр закраски, может принимать значения $GBORDER или $GFILLINTERIOR  (см. выше).

Пример. Рисование концентрических окружностей разного цвета.

use msflib

integer(2) x,y

TYPE (xycoord)  pos

call setvieworg(320,240,pos)                                      !перенос начальной точки СК

x=0; y=0                                                         !координаты центра окружностей

do i=0,200                                                      !будет выведено 200 окружностей

 st=ellipse($gborder,x-i,y-i,x+i,y+i)       !радиусы окружностей отличаются

                                                                ! на 1

 st=setcolorrgb(getcolorrgb()+500*i)     !установка нового цвета

enddo

end

Вывод дуги (дуга является частью эллипса, ограниченной двумя векторами, проведенными из его центра):

result=ARC(x1,y1,x2,y2,x3,y3,x4,y4),

где х1,у1,х2,у2 – координаты верхней левой и нижней правой точки прямоугольника, в который вписан эллипс (тип зависит от СК – INTEGER(2) или REAL(8));

х3,у3,х4,у4 – координаты конечных точек первого и второго ограничивающего вектора (INTEGER(2) или REAL(8));

result – результат (INTEGER(2)), не равен нулю при успешном завершении.

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

use msflib

integer(2) x,y, st

st=setcolor(14)                     !установка желтого цвета

x=0; y=0                                 !координаты центра дуг

do i=1,10                                                !будет выведено 10 дуг

     st=arc(x-10*i,y-10*i,x+10*i,y+10*i,-150,0,0,150) !радиусы дуг

                                        !различаются на 10

enddo

end

 

Вывод сектора круга или эллипса:

result=PIE(control,x1,y1,x2,y2,x3,y3,x4,y4),

где х1,у1,х2,у2,х3,у3,х4,у4,result – см. п.6;

control – параметр закраски, см. пп.4, 5.

Пример. Расходящиеся по кругу лучи в закрашенных виде секторов окружности радиусом 100:

use msflib

integer(2) x1,y1,x2,y2                              !координаты векторов, ограничивающих

                                                                  !секторы

integer(4) st 

call setvieworg(320,240,pos)                                !перенос начала СК в середину экрана

st=setcolorrgb(#00FFFF)                      !установка текущего желтого цвета

ugol=0                                                      !начальный угол для вычисления

                                                                  !координат векторов

do i=1,20

  x1=int(sin(ugol)*100); y1=int(cos(ugol)*100) !вектора-радиусы окружности

  x2=int(sin(ugol+6.28/50.)*100); y2=int(cos(ugol+6.28/50.)*100)

  st=pie($Gfillinterior,-100,-100,100,100,x1,y1,x2,y2)    !вывод сектора

 

  ugol=ugol+6.28/20.                      !изменение угла для перехода к следующей

                                                        !паре векторов

enddo

end

 

Изменение стиля линий для функций LINETO, POLYGON и RECTANGLE. По умолчанию эти графические примитивы выводятся непрерывными линиями, однако характер линий можно установить подпрограммой

CALL SETLINESTYLE(mask),

где mask – аргумент (INTEGER(2)), задающий вид линии. Тип INTEGER(2) занимает 2 байта (16 битов); каждый бит в mask устанавливается в 1, если требуется закрасить соответствующую по расположению точку линии, и в 0, если закраска не выполняется. Например, если требуется вывести пунктирную линию, где штрихи имеют длину 5 пикселов, а разрывы – 3, это можно задать двоичным числом 1111100011111000, что соответствует шестнадцатеричному коду #F8F8; сплошной линии (по умолчанию) соответствует код #FFFF. Получить сведения о текущем типе линий можно с помощью функции GETLINESTYLE( ).

Пример. По диагонали экрана располагаются разноцветные квадраты, стороны которых имеют разный тип линий:

use msflib

integer(2) x,y,mask,st

st=setcolor(3)                                         !установка начального цвета

mask=#F8F8         

call setlinestyle(mask)                           !установка начального типа линий (mask)

x=0;y=0                                                    !координаты верхней левой вершины

                                                                  ! первого квадрата

do i=1,10               

     st=rectangle($gborder,x,y,x+40,y+40) !контур квадрата с длиной стороны

                                                                !40 пикселов

     x=x+64; y=y+48                             !смещение к вершине следующего квадрата

     st=setcolor(getcolor()+1) !код нового цвета на 1 больше предыдущего

     call setlinestyle(getlinestyle()-10) !новый стиль закраски вычисляется

enddo                                                         !относительно предыдущего

end

 

Закраска замкнутого контура:

result=FLOODFILL(x, y, border)

result2=FLOODFILLRGB(x, y, border2),

где x, y – аргументы (INETEGER(2)), задающие координаты любой точки внутри заполняемого контура;

border – аргумент (INTEGER(2)), индекс цвета контура;

border2 – аргумент (INTEGER(4)), RGB-значение цвета контура;

result (INTEGER(2)) и result2 (INTEGER(4)) – результат работы функции, не равен 0 при успешном завершении.

Пример. По горизонтали выводится ряд треугольников, закрашенных разными цветами (цвет контуров треугольников – одинаковый):

use msflib

integer(2) x, y, st

type (xycoord) pos

st=setcolor(2)                         !индекс цвета границы

x=30; y=200                             !координаты вершины первого треугольника

do i=1,8                                    !будет выведено 8 треугольников

call moveto(x,y,pos)              !установка вершины треугольника (начало

                                                 !первого отрезка)

st=lineto(x-30,y+30)         !вывод сторон треугольника

st=lineto(x+30,y+30)

st=lineto(x,y)

x=x+60                       !смещение к вершине следующего треугольника

enddo

x=30; y=210                              !установка точки начала закраски в первом

                                                   !треугольнике

do i=1,8                                     !цикл закраски

st=setcolor(getcolor()+1)    !установка цвета закраски (индекс на 1 больше

                                            !предыдущего)

st=floodfill(x,y,2)      !закраска текущим цветом до цвета границы

                                            !(индекс 2)

x=x+60                        !смещение начальной точки закраски

enddo

end

 

10. Установка шаблона закраски. По умолчанию закраска замкнутых контуров выполняется сплошным цветом, т. е. закрашивается каждый пиксел внутри контура. Для изменения шаблона закраски создается массив из 8 байтов, представляющий шаблон экрана 8 х 8 пикселов. Если бит установлен в 1, соответствующая по расположению точка будет закрашена текущим цветом, иначе – нет. Пример кодирования шаблона:

 

 

Для установки нового шаблона закраски используется подпрограмма

CALL SETFILLMASK(mask),

где mask – массив из 8 байтов (INTEGER(1)), задающий шаблон.

 

Пример. Два прямоугольника закрашиваются с использованием разных шаблонов (сетка и штриховка):

use msflib

integer(1) mask1(8)

mask1=(/129,66,36,24,24,36,66,129/)        !шаблон-сетка (см. табл.) в десятичном коде

call setfillmask(mask1)                               !установка шаблона-сетки

st=rectangle($gfillinterior,10,10,100,100)  !вывод закрашенного прямоугольника

                                                                    !(сетка)

mask1=(/2#00000001,2#00000010,2#00000100,2#00001000,& !шаблон-штриховка

       2#00010000,2#00100000,2#01000000,2#10000000/)   !в двоичном коде

call setfillmask(mask1)                               !установка шаблона-прямоугольника

st=rectangle($gfillinterior,100,100,210,210)!вывод заштрихованного

                                                                        ! прямоугольника

end

 

11. Очистка экрана и заполнение текущим цветом фона:

CALL CLEARSCREEN (area),

где area – аргумент, определяющий область очистки:

$GCLEARSCREEN – экран очищается полностью;

$GVIEWPORT – очистка текущего порта;

$GWINDOW – очистка текущего текстового окна

            (см. лабораторная работа № 3).

 

Варианты задания

 

Вариант 1

 

Нарисовать треугольник, закрашенный по шаблону (задать самостоятельно).

Вывести разноцветные звезды по горизонтали по середине экрана.

Вывести по краям экрана рамку из разноцветных ромбов.

Создать рисунок: солнце и облака на синем фоне.

Разработать подпрограмму для рисования "елочки" и с ее помощью вывести на экран рисунок: несколько елочек разной величины.

Вариант 2

 

Нарисовать куб с разноцветными гранями.

Задать шаблон закраски (в форме буквы "V") и нарисовать трапецию, закрашенную по шаблону.

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

Создать рисунок: ромашка с разноцветными лепестками на зеленом фоне.

Разработать подпрограмму: рисование треугольника по к