Страница 38 из 47
Оператор 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:
|