Файл: jourdain_spravochnik_programmista.docx

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 04.07.2020

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

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

OUT DX,AL ;посылаем данные

;---поиск цвета

MOV AX,0A000H ;адрес видеобуфера

MOV ES,AX ;

MOV BX,12 ;смещение в буфере

MOV AL,ES:[BX] ;читаем позицию буфера

CMP AL,0 ;установлены биты?

JNZ FOUND_IT ;если да, то ищем у какой точки




4.4.5 Рисование линий на экране.




Простейший способ нарисовать линию на экране состоит в том,

чтобы вычислить следующую точку этой линии и изменить биты соот-

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

нельзя избежать. Если это возможно, то лучше вычислить область

точек экрана, которые имеют одинаковый цвет. Тогда требуемые

операции над битами можно проделать только над одним байтом, а

затем этот байт может быть помещен в область соответствующих

позиций видеобуфера.


Высокий уровень.


Бейсик позволяет рисовать прямые линии с помощью оператора

LINE. LINE (20,10)-(40,30) рисует линию от столбца 20 и строки 10

к столбцу 40 и строке 30. И строки и столбцы нумеруются от нуля.

Вы можете опустить координаты первой точки, в этом случае линия

будет начинаться с последней точки, которая была ранее выведена

графическим оператором. Вторая пара координат может задаваться

также относительно первой, с помощью конструкции LINE -STEP(xoff-

set,yoffset).

Оператор LINE может указывать также цвет и стиль линии. Код

цвета следует сразу за списком координат; LINE (50,50)-(60,60),2

выводит линию цветом 2. Когда цвет не указан, то по умолчанию

берется цвет 3. Возможность выбора стиля линии предполагает ука-

зание чередования ее точек. Образец может даваться как в десятич-

ной, так и в шестнадцатиричной форме. Например, образец

1010101010101010, который соответствует &HAAAA, дает линию, точки

которой имеют по очереди данный цвет и фоновый. Стиль линии опре-

деляется третьим параметром после координат. Например, LINE

(30,30)-(40,40),3,,&HAAAA выводит линию с указанным стилем цветом

3.

Бейсик предоставляет также процедуры для рисования прямоуголь-

ников и окружностей. Прямоугольники выводятся с помощью оператора

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

правый нижний угол рамки. Надо просто указать B (box - т.е. рам-

ка) в качестве второго параметра за координатами. LINE

(50,50)-(100,100),1,B,&HAAAA рисует квадрат со стороной 50 точек

цветом 1 палетты, используя вышеописанный стиль. Для вывода пря-

моугольника, заполненного определенным цветом надо использовать

параметр BF (при этом стиль линии указывать не надо).

Окружности рисуются оператором CIRCLE. Их вывод основывается

на формуле CIRCLE (x,y),r,цвет,нач-угол,кон-угол,аспект. Коорди-

наты x,y дают адрес центра окружности на экране, а r - радиус

окружности в точках; вся остальная информация необязательна. Цвет

- это код цвета, который по умолчанию берется равным 3. Если

необходимо вывести только дугу окружности, то можно указать

нач-угол и кон-угол (когда они опущены, то выводится целая окруж-


ность). Углы измеряются как положительные или отрицательные ве-

личины, отсчитываемые от направления по горизонтали вправо. Они

измеряются в радианах (в 360 градусах содержится 6.292 радиан, а

один градус = 0.0174532 радиан). Аспект это отношение горизон-

тальных и вертикальных размеров. Круглая окружность получается на

дисплее, когда Вы укажете его равным 5/6 для умеренного разреше-



ния и 5/12 для высокого разрешения. Меньшие значения приводят к

эллипсам, вытянутым по горизонтали, а большие - по вертикали. Для

примера PI=3.14159: CIRCLE(200,50),30,2,PI/2,PI,6 выводит дугу,

центр которой находится в точке 50,200, с радиусом 30 точек цве-

том 2, причем будет выведен только левый верхний квадрант верти-

кально вытянутого эллипса.

Более сложные линии могут выводиться с помощью оператора DRAW,

который необычайно гибок. За оператором DRAW следует строка (зак-

люченная в скобки), в которой закодирована последовательность

ориентаций и длин сегментов, составляющих линию. Например, DRAW

"E12F12G12H12" выводит бубну. Начальная точка устанавливается

оператором PSET (обсуждаемым в [4.4.2]); в противном случае, по

умолчанию берется центр экрана. Основные коды состоят из буквы,

за которой следует длина сегмента в точках. Коды следующие:


Ux вверх (на x точек)

Dx вниз

Rx вправо

Lx влево

Ex по диагонали вверх и вправо

Fx по диагонали вниз и вправо

Gx по диагонали вниз и влево

Hx по диагонали вверх и влево


При умеренном разрешении 100 точек по горизонтали и 100 точек по

вертикали дают отрезки примерно одинаковой длины (на самом деле

отношение y к x равно 5/6). При высоком разрешении горизонтальная

линия будет приблизительно вдвое меньше, чем вертикальная. Из-за

большего расстояния между точками диагональ прямоугольника содер-

жит ровно столько же точек, сколько и максимальная сторона пря-

моугольника, хотя сам отрезок длиннее.

Для рисования диагоналей с углами, отличными от 45 градусов,

используется кодовая буква M. Этот код рисует следующий сегмент

линии в абсолютную или относительную позицию экрана. Чтобы ука-

зать абсолютную позицию надо указать координаты x и y. DRAW

"M50,60" проведет линию в точку, имеющую координаты столбца 50 и

строки 60. Для указания относительных координат добавьте знаки +

или - перед числами. Если текущее значение координаты x равно

100, то +50 продолжит линию до столбца 150, а -50 - до столбца

50. Чтобы сдвинуться из 100,100 в 120,70 напишите DRAW

"M+20,-30".

Линия не обязана быть непрерывной. Когда перед кодом указана

буква B, то указатель перемещается как указано, но сегмент линии

при этом не рисуется. Например, DRAW "L10BU5R10" рисует две пара-

ллельные горизонтальные линии. Чтобы из одной точки начиналось

несколько сегментов надо указать перед кодом букву N. В этом

случае указатель будет возвращаться в начальную точку после выво-

да сегмента.


Имеется ряд специальных кодов, которые будучи помещенными

внутри строки, действуют на все последующие коды (пока следующий

аналогичный код не укажет другое действие). Цвет сегмента линии

устанавливается буквой C, за которой следует код цвета. DRAW

"C2D5" рисует линию, направленную вниз цветом 2. Установка масш-

табного фактора меняет масштаб, в котором будет выводиться фигура



или ее часть. Надо добавить к строке букву S, за которой следует

фактор. Фактор это число, которое для получения масштаба делится

на 4. Обычно фактор равен 4, что соответствует масштабу 1:1.

Изменение фактора на 8 приведет к тому, что размер выводимой

фигуры будет вдвое больше. Для этого напишите DRAW "S8U12D12" и

т.д.

Используя один их двух кодов Вы можете вращать оси координат-

ной системы. Кодовая буква A вращает оси против часовой стрелки с

90-градусными инкриментами. A0 не вращет оси вообще. A1 - повора-

чивает их на 90 градусов, A2 - на 180 градусов и A3 - на 270

градусов. Аналогично, код TA поворачивает оси на указанное число

градусов от 0 до 360 (против часовой стрелки) и от 0 до -360 (по

часовой стрелке). DRAW "A1L10" и DRAW "TA90L10" приведут к тому,

что линия, которая должна была быть направленной влево будет

вместо этого нарисована повернутой на 90 градусов и направлена

вниз.

Оператор DRAW может включать строковые переменные, которые

состоят из набора допустимых кодов. Это свойство позволяет прог-

рамме повторно использовать части фигур в различных рисунках. В

операторе DRAW имя строки должно быть помещено за буквой X и за

ним должны следовать точка с запятой. Например:


100 S$ = "U12R15U45L32"

110 DRAW "XS$;"


В одном операторе DRAW может содержаться несколько строк, переме-

жаемых другими кодами. Отметим, что любые числа, используемые с

кодами в операторах DRAW могут сами быть переменными. Таким обра-

зом с помощью одного оператора DRAW могут выводиться фигуры,

отличающиеся по форме, цвету, масштабу и ориентации. Надо помес-

тить знак равенства между буквенным кодом и именем переменной, а

за именем поместить точку с запятой. Например, чтобы установить

код цвета, определяемый переменной, напишите DRAW "C=PCOLOR;".

Компилятор Бейсика требует, чтобы ссылка на эти переменные осу-

ществлялась с помощью функции VARPTR$. В этом случае такой опера-

тор будет иметь вид DRAW "X" + VARPTR$(S$) или DRAW "C=" +

VARPTR$(PCOLOR). Сложные рисунки могут быть сохранены в массиве и

затем возвращены на экран в любой момент. Обсуждение этого вопро-

са см. в [4.4.6].


Низкий уровень.


Нижеприведенная процедура использует алгоритм Брезенхэма для

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

функцию BIOS установки точек и ее можно убыстрить если заменить

эту функцию на встроенную процедуру, использующую прямое отобра-

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

избегает операций умножения и деления. Линия рассматривается как


набор сегментов двух типов: тех которые расположены диагонально и

тех, которые расположены горизонтально или вертикально. Для линий

с наклоном больше 1 прямые сегменты вертикальны, в противном

случае они горизонтальны; первая задача алгоритма состоит в вы-

числении наклона. Затем вычисляется выравнивающий фактор, который

следит чтобы некоторое число прямых сегментов имело большую дли-



ну, чем остальные. И, наконец, сложный цикл поочередно выводит

диагональные и прямые сегменты. BX поочередно принимает то поло-

жительные, то отрицательные значения, отмечая какой тип сегмента

выводится. Ниже готовятся данные для вывода диагонали из одного

угла экрана в противоположный:


;---в сегменте данных

START_X DW 0

END_X DW 319

START_Y DW 0

END_Y DW 199

COLOR DB 2

DIAGONAL_Y_INCREMENT DW ?

DIAGONAL_X_INCREMENT DW ?

SHORT_DISTANCE DW ?

STRAIGHT_X_INCREMENT DW ?

STRAIGHT_Y_INCREMENT DW ?

STRAIGHT_COUNT DW ?

DIAGONAL_COUNT DW ?


;---установка режима дисплея

MOV AH,0 ;функция установки режима

MOV AL,4 ;цветной 320*200

INT 10H ;установка режима

;---установка начальных инкрементов для каждой позиции точки

MOV CX,1 ;инкремент для оси x

MOV DX,1 ;инкремент для оси y

;---вычисление вертикальной дистанции

MOV DI,END_Y ;вычитаем координату начальной

SUB DI,START_Y ;точки из координаты конечной

JGE KEEP_Y ;вперед если наклон < 0

NEG DX ;иначе инкремент равен -1

NEG DI ;а дистанция должна быть > 0

KEEP_Y: MOV DIAGONAL_Y_INCREMENT,DX

;---вычисление горизонтальной дистанции

MOV SI,END_X ;вычитаем координату начальной

SUB SI,START_X ;точки из координаты конечной

JGE KEEP_X ;вперед если наклон < 0

NEG CX ;иначе инкремент равен -1

NEG SI ;а дистанция должна быть > 0

KEEP_X: MOV DIAGONAL_Y_INCREMENT,CX

;---определяем горизонтальны или вертикальны прямые сегменты

CMP SI,DI ;горизонтальные длиннее?

JGE HORZ_SEG ;если да, то вперед

MOV CX,0 ;иначе для прямых x не меняется

XCHG SI,DI ;помещаем большее в CX

JMP SAVE_VALUES;сохраняем значения

HORZ_SEG: MOV DX,0 ;теперь для прямых не меняется y

SAVE_VALUES: MOV SHORT_DISTANCE,DI ;меньшее расстояние

MOV STRAIGHT_X_INCREMENT,CX ;один из них 0,

MOV STRAIGHT_Y_INCREMENT,DX ;а другой - 1.



;---вычисляем выравнивающий фактор

MOV AX,SHORT_DISTANCE ;меньшее расстояние в AX

SHL AX,1 ;удваиваем его

MOV STRAIGHT_COUNT,AX ;запоминаем его

SUB AX,SI ;2*меньшее - большее

MOV BX,AX ;запоминаем как счетчик цикла

SUB AX,SI ;2*меньшее - 2*большее

MOV DIAGONAL_COUNT,AX ;запоминаем

;---подготовка к выводу линии

MOV CX,START_X ;начальная координата x

MOV CX,START_Y ;начальная координата y

INC SI ;прибавляем 1 для конца

MOV AL,COLOR ;берем код цвета

;---теперь выводим линию

MAINLOOP: DEC SI ;счетчик для большего расстояния

JZ LINE_FINISHED ;выход после последней точки


MOV AH,12 ;функция вывода точки

INT 10H ;выводим точку

CMP BX,0 ;если BX < 0, то прямой сегмент

JGE DIAGONAL_LINE ;иначе диагональный сегмент

;---выводим прямые сегменты

ADD CX,STRAIGHT_X_INCREMENT ;определяем инкре-

ADD DX,STRAIGHT_Y_INCREMENT ;менты по осям

ADD BX,STRAIGHT_COUNT ;фактор выравнивания

JMP SHORT MAINLOOP ;на следующую точку

;---выводим диагональные сегменты

DIAGONAL_LINE: ADD CX,DIAGONAL_X_INCREMENT ;определяем инкре-

ADD DX,DIAGONAL_Y_INCREMENT ;менты по осям

ADD BX,DIAGONAL_COUNT ;фактор выравнивания

JMP SHORT MAINLOOP ;на следующую точку

LINE_FINISHED:




4.4.6 Заполнение областей экрана.




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

медлительности, которая свойственна многим программам заполнения

областей для графического экрана. Когда заполнение основано на

простых вычислениях, которые действуют по очереди для каждой

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

Более экономный код может определять все ли битовые позиции опре-

деленного байта видеобуфера должны иметь один и тот же цвет и

когда это условие выполняется, то этому байту присваивается зара-

нее заготовленное значение, которое устанавливает все точки в

правильный цвет. При этом нет необходимости повторять операции

над одним и тем же байтом, каждый раз устанавливая биты только

для одной из точек, информацию о которой содержит данный байт.

В [4.3.4] объяснено как создать описание символа в виде матри-

цы 8*8 точек, имеющего требуемый Вам вид. Хотя такие символы

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

использование может существенно облегчить заполнение графиков.

Образец высвечивающий все 8*8 точек может быть выведен в интерва-

ле нескольких строк и столбцов, заполняя область намного быстрее,

чем это достигается при поточечной зарисовке. Этот тип графичес-

ких символов может использоваться совместно с точечной графикой.

Псевдографические символы могут использоваться также для вывода

вращающихся или колеблющихся объектов.


Высокий уровень.


Бейсик предоставляет оператор PAINT для заполнения замкнутой

фигуры произвольной формы. Вам необходимо указать только точку

внутри области, а об остальном позаботится процедура. Может быть

указан цвет палетты, которым надо заполнить область, например,

PAINT (100,110),2 заполняет область цветом 2 палетты. Закраска

ведется начиная от указанной точки до тех пор, пока не встретятся

точки с цветом, отличающимся от фонового. Вы можете, наоборот,

указать цвет границы и закраска будет продолжаться во всех нап-

равлениях, пока не будут встречены точки указанного цвета. При

такой закраске линии других цветов, находящиеся внутри границы,

могут быть также закрашены. Код цвета границы следует за кодом

цвета заполнения, таким образом PAINT (100,180),2,3 закрашивает