Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

722

.pdf
Скачиваний:
5
Добавлен:
15.11.2022
Размер:
450.3 Кб
Скачать

расширение Video BIOS, предложенное VESA. Драйвер VESA или загружается, или содержится в ROM Video BIOS.

Контексты устройств (Device Contexts - DC)

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

Перечислим атрибуты, связанные с каждыми из этих объектов.

Графический объект

Атрибуты

Точечный рисунок

Размер, в байтах; протяженности (в пикселях);

 

цветовой формат; схема сжатия; и т. д.

Кисть

Стиль, цвет, форма, и начало координат

Палитра

Цвета и размер (или число цветов)

Шрифт

Название Шрифта, ширина, высота, размер,

 

набор символов, и т. д.

Перо

Стиль, ширина, и цвет

Область

Расположение и габариты

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

Графические режимы

Windows поддерживает пять графических режимов, которые позволяют приложению определить, как смешивать цвета, где размещать вывод, как выполнять масштабирование и т. д. Вот эти режимы:

Фоновый режим Определяет, как цвета фона смешиваются с существующими оконными

или экранными цветами для растровых и текстовых операций. Режим рисования

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

Режим отображения Определяет, как графический образ отображается из логического представления на окно, экран, или бумагу принтера.

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

Режим растяжения Определяет, как растровые цвета смешаны с существующими оконными или экранными цветами при сжатии рисунка.

Приложение может определять заданные по умолчанию режимы,

вызывая соответственно функции GetBkMode, GetROP2, GetMapMode,

GetPolyFillMode, GetStretchBltMode. Для изменения режимов используют функции SetBkMode, SetROP2, SetMapMode, SetPolyFillMode, SetStretchBltMode.

Типы DC

Win32 API поддерживает четыре типа контекста устройств: дисплей, принтер, память и информация. Каждый тип обеспечивает работу с определенным объектом:

Дисплей

Поддерживает операции рисования на дисплее.

Принтер

Поддерживает операции рисования на принтере или

 

графопостроителе (плоттере).

Память

Поддерживает операции рисования на точечном рисунке.

Информация

Поддерживает поиск данных устройства.

 

DC дисплея (Display DC - DDC)

Windows предоставляет три типа контекста устройства для дисплеев: класс, общий и частный. Класс и частные контексты используются в приложениях САПР, издательских системах и т. п. Общие контексты используются в прикладных программах, которые выполняют нечастые операции рисования.

Приложение получает DDС, вызывая функцию BeginPaint или GetDC и идентифицируя окно, в котором предполагается вывод. Как правило, приложение получает контекст устройства только для рисования на клиентской области окна. Когда приложение заканчивает рисование, оно должно освободить контекст устройства, вызывая функцию EndPaint или ReleaseDC.

Класс DC

Класс DC поддерживается только для совместимости с предыдущими версиями Windows. При разработке 32-хразрядных приложений используют частный контекст устройства.

Общие DC

Общие DC - это DDC, стандартно управляемые оконными средствами Win32 API. Приложение получает дескриптор (handle), идентифицирующий один из доступных общих DC, вызывая GetDC, GetDCEx, или функцию BeginPaint. Перед возвращением этого дескриптора Windows инициализирует общий контекст устройства с заданными по умолчанию объектами, атрибутами и режимами.

Частные DC

Частные DC, в отличие от общих, сохраняют любые изменения заданных по умолчанию данных даже после вызовов из прикладной программы функций ReleaseDC или EndPaint. Частные контексты устройства не входят в кэш администратора оконного режима и поэтому не должны освобождаться после использования. Администратор автоматически удаляет частный контекст устройства после того, как связанное с ним последнее окно будет разрушено.

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

Операции с DC

Приложению доступны следующие операции:

11

·Перечисление существующих графических объектов.

·Выбор новых графических объектов.

·Удаление существующих объектов.

·Сохранение текущих графических объектов, их атрибутов и графических режимов.

·Восстановление предварительно сохраненных графических объектов, атрибутов и режимов.

Закрашивание и рисование

Почти все прикладные программы используют экран, чтобы отобразить данные, которыми они манипулируют.

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

Приложение рисует в окне в следующих случаях: при создании окна, при изменении размера окна, при наложении окон, при свертке или максимизировании окна, при отображении данных из открытого файла, при прокрутке, изменении или выборе части отображенных данных. Windows управляет действиями типа перемещения и установления размеров окна. Если оказывается воздействие на содержимое окна, Windows отмечает поврежденную часть окна как готовую к обновлению и при первой возможности посылает сообщение WM_PAINT. Некоторые действия управляются приложением, например, отображение открытых файлов и выбор отображенных данных.

Во всех случаях приложение может рисовать в окне, как только оно создано. Чтобы рисовать в окне, приложение должно сначала отыскать дескриптор DDC для окна. Обычно приложение выполняет большинство операций рисования в течение обработки сообщений WM_PAINT. В этом случае приложение отыскивает DDC, вызывая функцию BeginPaint. Сначала устанавливается область отсечения для DC, равная пересечению части окна, которое нуждается в обновлении и части, которая является видимой пользователю. Повторно выводятся только те части окна, которые изменились.

Windows может также посылать диспетчеру сообщения WM_NCPAINT и WM_ERASEBKGND. Эти сообщения направляют приложение, чтобы обновить неклиентскую область и фон окна. Неклиентская область - часть окна, которая находится вне клиентской области. Эта область включает области заголовка, меню окна (системное меню), и линейки прокрутки. Большинство прикладных программ полагается на заданную по умолчанию функцию окна DefWindowProc для вывода этой области. Фон окна - цвет или текстура, которым заполняется окно прежде, чем начинаются другие операции рисования. Фон закрывает любые объекты в окне.

Область обновления

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

Синхронное и асинхронное рисование

Рисование, выполненное в течение обработки WM_PAINT асинхронно: то есть имеется задержка между моментом выдачи запроса на обновление и посылкой WM_PAINT. В течение задержки приложение обычно выбирает сообщения из очереди и выполняет другие задачи. Причина для задержки в том, что Windows вообще обрабатывает рисование в окне как операцию с низким приоритетом и пропускает вперед сообщения ввода пользователя и сообщения, которые могут воздействовать на позицию или размер окна.

Иногда необходимо вывести синхронно, то есть рисовать окно немедленно. Например, немедленно выводится главное окно приложения после его запуска. Windows выводит синхронно некоторые окна управления , типа кнопок, потому что они служат фокусом ввода пользователя. Синхронные функции UpdateWindow и RedrawWindow обеспечивают эту возможность. Они посылают сообщение WM_PAINT прямо окну, если область обновления не пуста.

Рисование без сообщения WM_PAINT

Иногда более эффективно выводить прямо в окно без ожидания WM_PAINT. Это может быть полезно, когда пользователь нуждается в немедленной обратной связи, как при перемещении или установлении размеров объекта. В таких случаях приложение обычно выводит в окно при обработке сообщений мыши или клавиатуры. Чтобы рисовать в окне без использования WM_PAINT, приложение вызывает функции GetDC или GetDCEx, чтобы отыскать DDC для окна.

Графическая подсистема Borland C++ Builder

Разработчики Borland C++ Builder уделили большое внимание возможностям работы с деловой графикой: простота и удобство ее использования напрямую сказывается на простоте и удобстве созданных приложений. Вместо дебрей графического интерфейса Windows разработчик получил несколько инструментов, сколь понятных, столь же и мощных.

Другой бич работы с графикой в Windows - проблема рационального использования ресурсов. Для больших программных комплексов она стала в последнее время нешуточной. Такие монстры, как Microsoft Office, потребляют во время работы львиную долю ресурсов. В Borland C++ Builder ресурсами GDI незримо для пользователя "заведуют" специальные менеджеры, ведущие списки всех размещенных кистей, перьев, шрифтов и т. п. и управляющие их использованием.

Обязательным для любого объекта, связанного с графикой в Borland C++ Builder является событие

__property Classes::TNotifyEvent OnChange = {read=FOnChange, write=FOnChange};

Его обработчик вызывается всякий раз, когда изменились какие-то характеристики объекта, влияющие на его внешний вид.

В стандартном GDI основой для рисования служит дескриптор контекста устройства hDC и связанные с ним шрифт, перо и кисть. В состав VCL входят объектно-ориентированные надстройки над последними, назначением которых является удобный доступ к свойствам инструментов и прозрачная для пользователя обработка всех их изменений. Сначала опишем три этих класса.

Класс TFont

Класс инкапсулирует шрифт Windows. В Borland C++ Builder допускаются только горизонтально расположенные шрифты. В конструк-

12

торе объекта по умолчанию принимается шрифт System цвета clWindowText размера 10 пунктов.

Свойства класса приведены в таблице:

-----------------------------------------------------------------

Handle

Содержит дескриптор шрифта.

 

 

 

Name

Содержит

имя

(начертание)

 

шрифта,

 

например, Arial

 

 

 

 

 

Style

Содержит

 

стиль

(особенности

 

начертания) шрифта: жирный, курсив,

 

подчеркнутый и перечеркнутый.

 

 

Color

Определяет цвет шрифта.

 

 

 

 

Pitch

Определяет

способ

установки

ширины

 

символов шрифта. Значение fpFixed

со

 

ответствует

моноширинным

шрифтам;

 

fpVariable - шрифтам с переменной

 

шириной символа. Установка fpDefault

 

означает принятие того способа,

 

который определен начертанием.

 

 

Height

Содержит значение высоты шрифта в

 

пикселах.

 

 

 

 

 

 

 

PixelsPerInch

Определяет

число

точек

 

на

дюйм.

 

Первоначально

равно числу

точек

на

 

дюйм

в контексте экрана. Программист

 

не

должен изменять это свойство,

т.

 

к.

оно

используется

системой

для

 

приведения

изображения на

экране

и

 

принтере к одному виду

 

 

 

 

Size

Содержит

размер

шрифта

в

 

пунктах

 

(принято в Windows). Это свойство

 

связано с Height соотношением.

 

 

 

Font->Size = -Font->Height * 72 /

 

 

 

 

 

Font->PixelsPerInch;

 

-----------------------------------------------------------------

Класс ТРеn

Инкапсулирует перо. В конструкторе по умолчанию создается непрерывное (psSolid) черное перо шириной в один пиксел. Свойства класса приведены в таблице:

-----------------------------------------------------------------

Handle

Содержит дескриптор пера.

 

 

Color

Определяет цвет пера.

 

 

Mode

Содержит

идентификатор одной

из

 

растровых

 

операций,

которые

 

определяют взаимодействие пера

с

 

поверхностью.

Эти

операции

 

соответствуют

стандартным,

 

определенным в Windows

 

 

Style

Определяет стиль линии,

рисуемой

 

пером.

Соответствующие

стили

 

также определены в Windows

Width

Содержит значение толщины пера в

 

пикселах

-----------------------------------------------------------------

Класс TBrush

Инкапсулирует кисть. Первоначально создается белая сплошная (bsSolid) кисть. Свойства класса приведены в таблице:

-----------------------------------------------------------------

Handle

Содержит дескриптор кисти.

 

Color

Определяет цвет кисти.

 

 

Style

Содержит

стиль кисти

(фактуру

 

закраски).

 

 

 

Bitmap

Содержит

битовую

карту,

 

определенную пользователем

для

 

закраски поверхностей. Если это

 

свойство определено, то

Color

и

 

Style недействительны

 

 

-----------------------------------------------------------------

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

Класс TCanvas

Этот класс - сердцевина графической подсистемы Borland C++ Builder. Он объединяет в себе и "холст" (контекст конкретного устройства GDI), и рабочие инструменты" (перо, кисть, шрифт) и даже "подмастерьев" (набор функций по рисованию типовых геометрических фигур).

В дальнейшем для обозначения этого класса мы будем пользоваться термином 'канва". Канва не является компонентом, но она входит в качестве свойства во многие другие компоненты, которые должны уметь нарисовать себя и отобразить какую-либо информацию. Дескриптор контекста устройства, над которым "построена" канва, может быть востребован для различных низкоуровневых операций. Он задается свойством:

__property HDC Handle = {read =GetHandle, write=SetHandle, nodefault};

Для рисования канва включает в себя шрифт, перо и кисть:

__property TFont* Font = {read=FFont, write=SetFont}; __property TPen* Pen = {read=FPen, write =SetPen}; __property TBrush* Brush = {read=FBrush, write=SetBrush};

Кроме того, можно рисовать и поточечно, получив доступ к каждому пикселу. Значение свойства

__property TColor Pixels[int X][int Y] = {read=GetPixel, write=SetPixel};

соответствует цвету точки с координатами (X,Y).

Канва содержит методы-надстройки над всеми основными функциями рисования GDI Windows и свойства, которые приведены ниже в таблице. При их рассмотрении имейте в виду, что все геометрические фигуры рисуются текущим пером. Те из них, которые можно зак-

13

рашивать, закрашиваются с помощью текущей кисти. Кисть и перо при этом имеют текущий цвет.

------------------------------------------------------------------

void

__fastcall Arc(int X1,

int¦Метод

рисует сегмент

эллипса.

Y1, int X2, int Y2, int X3,

int¦Эллипс

определяется описывающим

Y3, int X4, int Y4);

 

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

(X1,Y1)

-

 

 

 

 

 

¦(X2,Y2);

его

 

размеры

должны

 

 

 

 

 

¦лежать в диапазоне от 2 до 32767

 

 

 

 

 

¦точек. Начальная точка

сегмента

 

 

 

 

 

¦лежит на

пересечении эллипса

и

 

 

 

 

 

¦луча, проведенного из его центра

 

 

 

 

 

¦через

точку

(X3,Y3). Конечная

 

 

 

 

 

¦точка

сегмента

 

лежит

 

на

 

 

 

 

 

¦пересечении

 

эллипса

 

и

луча,

 

 

 

 

 

¦проведенного из его центра через

 

 

 

 

 

¦точку (X4,Y4). Сегмент

рисуется

 

 

 

 

 

¦против часовой стрелки.

 

 

 

void

__fastcall

Chord(int

X1,¦Рисует

хорду

и

 

заливает

int

Y1, int X2, int Y2, int

X3,¦отсекаемую

ею

часть

 

эллипса.

int Y3, int X4, int Y4);

 

¦Эллипс,

начальная

и

конечная

 

 

 

 

 

¦точки определяются, как в методе

 

 

 

 

 

¦Arc.

 

 

 

 

 

 

 

 

 

void

__fastcall Ellipse(int

X1,¦Рисует

и

закрашивает

эллипс,

int Y1, int X2, int Y2);

 

¦вписанный в прямоугольник (X1

 

 

 

 

 

¦,Y1) - (X2,Y2).

 

 

 

 

 

void

__fastcall

LineTo(int

X,¦Проводит

линию текущим пером из

int Y);

 

 

 

¦текущей точки в (X,Y).

 

 

 

void

__fastcall

MoveTo(int

X,¦Перемещает

текущее

 

положение

int Y);

 

 

 

¦пера

(свойство PenPos) в

точку

 

 

 

 

 

¦(X,Y).

 

 

 

 

 

 

 

 

void __fastcall BrushCopy(const¦Производит

 

 

 

специальное

Windows::TRect &Dest,

TBitmap*¦копирование.

 

 

Прямоугольник

Bitmap,

const

Windows::TRect¦Source

из битовой карты

Bitmap

&Source, TColor Color);

 

¦копируется в прямоугольник Dest

 

 

 

 

 

¦на

канве;

при этом

цвет Color

 

 

 

 

 

¦заменяется на цвет текущей кисти

 

 

 

 

 

¦(Brush->Color). С

помощью этого

 

 

 

 

 

¦метода

 

можно

 

нарисовать

 

 

 

 

 

¦"прозрачную" картинку. Для этого

 

 

 

 

 

¦нужно выбрать

 

соответствующий

 

 

 

 

 

¦фону цвет кисти и затем заменить

 

 

 

 

 

¦на

него

фоновый

или

наиболее

 

 

 

 

 

¦часто встречающийся цвет битовой

 

 

 

 

 

¦карты (см. TransparentColor).

 

void

__fastcall

CopyRect(const¦Производит

 

 

 

копирование

Windows::

TRect &Dest,

TCanvas*¦прямоугольника Source

 

из

канвы

Canvas,

const

Windows::TRect¦Canvas

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

Dest

в

&Source);

 

 

 

¦области самого объекта.

 

 

 

void

__fastcall

FillRect(const¦Производит

 

 

 

 

заливку

Windows:: TRect &Rect);

 

¦прямоугольника (текущей кистью).

void __fastcall FrameRect(const¦Производит,

 

 

оконтуривание

Windows:: TRect &Rect);

 

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

цветом

текущей

 

 

 

 

 

¦кисти (без заполнения).

 

 

 

void

__fastcall Draw(int X,

int¦Осуществляет

 

 

 

 

рисование

Y, TGraphic* Graphic);

 

¦графического

 

объекта

 

Graphic

 

 

 

 

 

¦(точнее,

вызов

метода

 

его

 

 

 

 

 

¦рисования) в области

с

верхним

 

 

 

 

 

¦левым углом (X,Y).

 

 

 

 

void __fastcall

 

 

¦Осуществляет рисование

объекта

StretchDraw(const Windows::TRect ¦Graphic

 

 

в

 

 

заданном

&Rect, TGraphic* Graphic);

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

Rect.

 

Если

 

 

 

 

 

 

¦размеры их не совпадают, Graphic

 

 

 

 

 

 

¦масштабируется.

 

 

 

 

void

 

 

 

 

__fastcall¦Производит

 

 

отрисовку

DrawFocusRect(const

 

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

из

точек

Windows::TRect &Rect);

¦(как

на элементе, имеющем фокус

 

 

 

 

 

 

¦ввода).

 

Поскольку

метод

 

 

 

 

 

 

¦использует логическую

операцию

 

 

 

 

 

 

¦xor (исключающее ИЛИ), повторный

 

 

 

 

 

 

¦вызов для того же прямоугольника

 

 

 

 

 

 

¦приводит

изображение

 

к

 

 

 

 

 

 

¦начальному виду.

 

 

 

 

void __fastcall FloodFill(int

X,¦Производит

заливку

области

int

Y,

TColor Color, TFillStyle¦текущей

 

кистью.

 

Процесс

FillStyle);

 

 

 

¦начинается

с точки

(X,Y). Если

 

 

 

 

 

 

¦режим FillStyle равен fsSurface,

 

 

 

 

 

 

¦то

он продолжается до тех

пор,

 

 

 

 

 

 

¦пока

есть

соседние

точки

с

 

 

 

 

 

 

¦цветом Color. В режиме

fsBorder

 

 

 

 

 

 

¦закрашивание,

 

наоборот,

 

 

 

 

 

 

¦прекращается

при

 

выходе

на

 

 

 

 

 

 

¦границу с цветом Color.

 

 

void

__fastcall Pie(int X1,

int¦Рисует

 

сектор

 

эллипса,

Y1,

int X2, int Y2, int X3,

int¦описываемого

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

Y3, int X4, int Y4);

 

¦(X1,Y1)

-

(X2,Y2).

Стороны

 

 

 

 

 

 

¦сектора

лежат

на

лучах,

 

 

 

 

 

 

¦проходящих

из центра

эллипса

 

 

 

 

 

 

¦через точки (X3,Y3) и (X4,Y4).

void __fastcall Polygon(const¦Строит

многоугольник, используя

tagPOINT

*

Points,

const

int¦массив

координат точек

Points.

Points_Size);

 

 

 

¦При

 

этом

последняя

точка

 

 

 

 

 

 

¦соединяется

с

 

первой

и

 

 

 

 

 

 

¦внутренняя область закрашивается

void

__fastcall

Polyline(const¦Строит

ломаную линию, используя

tagPOINT

*

Points,

const

int¦массив координат точек Points.

Points_Size);

 

 

 

¦

 

 

 

 

 

 

 

void

__fastcall

 

Rectangle(int¦Рисует

прямоугольник с верхним

X1, int Y1, int X2, int Y2);

¦левым

углом в (X1, Y1) и нижним

 

 

 

 

 

 

¦правым в (X2, Y2).

 

 

 

 

void

__fastcall

 

RoundRect(int¦Рисует

 

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

с

X1, int Y1, int X2, int Y2,

int¦закругленными углами. Координаты

X3, int Y3);

 

 

 

¦вершин - те же, что и в

методе

 

 

 

 

 

 

¦Rectangle. Закругления

рисуются

 

 

 

 

 

 

¦как сегменты эллипса с размерами

 

 

 

 

 

 

¦осей по

горизонтали и вертикали

 

 

 

 

 

 

¦X3 и Y3.

 

 

 

 

 

int

__fastcall

TextHeight(const¦Возвращает высоту строки

Text в

System:: AnsiString Text);

¦пикселах.

 

 

 

 

 

int

__fastcall

TextWidth(const¦Возвращает ширину строки

Text в

System:: AnsiString Text);

¦пикселах.

 

 

 

 

 

void

__fastcall

TextOut(int

X,¦Производит вывод строки Text.

int

Y,

const System::AnsiString¦Левый

верхний угол помещается в

Text);

 

 

 

 

¦точку канвы (X.Y).

 

 

 

 

void

__fastcall

TextRect(const¦Производит

вывод

 

текста

с

Windows::

TRect

&Rect, int

X,¦отсечением. Как и в

TextOut,

int

Y,

const System::AnsiString¦строка

Text выводится с позиции

Text);

 

 

 

 

¦(X,Y);

при

этом

часть текста,

 

 

 

 

 

 

¦лежащая

 

вне

 

 

пределов

 

 

 

 

 

 

¦прямоугольника Rect,

отсекается

 

 

 

 

 

 

¦и не будет видна.

 

 

 

 

14

__property tagPOINT

PenPos =¦Содержит

текущую

позицию пера

{read

=GetPenPos,¦канвы

(изменяется

посредством

write=SetPenPos};

¦метода MoveTo).

 

-----------------------------------------------------------------

Метод

void __fastcall Refresh(void);

сбрасывает текущие шрифт, перо и кисть, заменяя их на стандарт-

ные, заимствованные из Windows (BLACK_PEN, HOLLOW_BRUSH, SYS-

TEM_FONT). Предусмотрено два события дня пользовательской реакции на изменение канвы: OnChange и OnChanging . Эти события возникают при изменениях свойств и вызовах методов TCanvas, меняющих вид канвы (то есть при любом рисовании. В MoveTo, например, они не возникают). Отличие их в том, что OnChanging вызывается до начала изменений, a OnChange - после их завершения.

Идентификатор (код) растровой операции при копировании прямоугольных блоков содержится в свойстве CopyMode и определяет правило сочетания пикселов, копируемых на канву, с ее текущим содержимым. При этом можно создавать разные изобразительные эффекты. В Borland C++ Builder определены следующие константы кодов: cmBlackness, cmDstInvert. cmMergeCopy, cmMergePaint, cmNotSrcCopy, cmNotSrcErase, cmPatCopy, cmPatInvert, cmPatPaint, cmSrcAnd, cmSrcCopy, cmSrcErase, cmSrcInvert, cmSrcPaint, cmWhiteness. Все они стандартно определены в Windows, и подробное их описание можно найти в документации по GDI. Значением CopyMode по умолчанию является cmSrcCopy - копирование пикселов источника поверх существующих.

Помимо графических примитивов, таких как линии и фигуры, на канве можно разместить готовые изображения. Для их описания создан класс TGraphic. Этот абстрактный класс является родительским для трех видов изображений, общепринятых в графике Windows - значка (класс TIcon), метафайла (класс TMetafile) и растровой картинки (класс TBitmap).

Работая над приложением в Borland C++ Builder, вы никогда не будете создавать объекты класса TGraphic, но переменной этого типа вы можете присваивать указатель на любой из классов-потомков.

Метод

virtual void __fastcall Assign(Classes:: TPersistent* Source);

переопределяет одноименный метод предка, позволяя полиморфное присваивание графических объектов (см. ниже).

Загрузку и выгрузку графики в поток осуществляют методы

virtual void __fastcall LoadFromStream(Classes:: TStream* Stream); virtual void __fastcall SaveToStream(Classes::TStream* Stream);

а загрузку и выгрузку в файл:

virtual void __fastcall LoadFromFile(const System:: AnsiString Filename);

virtual void __fastcall SaveToFile(const System:: AnsiString Filename);

Эти методы создают соответствующий файловый поток и затем вызывают методы LoadFromStream / SaveToStream.

Два метода осуществляют взаимодействие с буфером обмена: virtual void __fastcall LoadFromClipboardFormat(Word AFormat,

int AData, HPALETTE APalette);

virtual void __fastcall SaveToClipboardFormat(Word &Format,

int &Data, HPALETTE &APalette);

Здесь AFormat - используемый графический формат; AData и APalette - данные и палитра (если она требуется). Потомок должен иметь свой формат и уметь обрабатывать данные, представленные в нем. Свойство Empty устанавливается в true, если графический объект пуст (в него не загружались данные).

Высота и ширина графического объекта: Height, Width. Для каждого дочернего типа значения этих свойств вычисляются своим способом. Наконец, логическое свойство Modified показывает, модифицировался ли данный графический объект. Это свойство устанавливается в true внутри обработчика события OnChange.

Класс TPicture

Класс-надстройка над TGraphic, точнее - над его потомками. Он содержит поле Graphic, которое может содержать TBitmap, TIcon

иTMetafile. Предназначение TPicture - управлять вызовами соответствующих методов, скрывая при этом хлопоты с определением типа

идетали их реализации.

Кроме того, на уровне TPicture определены возможности по регистрации и использованию других - определенных пользователем - классов графических объектов, порожденных от TGraphic. Доступ к графическому объекту осуществляется посредством свойства: Graphic. Если графический объект имеет один из трех предопределенных типов, то к нему можно обратиться и как к одному из свойств Bitmap, Icon или Metafile.

Если в поле Graphic хранился объект одного класса, а затребован - другого, то прежний объект уничтожается, а вместо него создается пустой объект нужного класса.

Все три разновидности графических объектов имеют свои системы кэширования. Это означает, что на один реально существующий в системе дескриптор могут одновременно ссылаться несколько объектов. Более простым является кэширование для TIcon и TMetafile, которые умеют только отображать себя и не предназначены для редактирования (создатели Borland C++ Builder считают, что дескриптор графического объекта дается программисту не для того, чтобы ковыряться в нем на уровне двоичных кодов). Гораздо сложнее устроен механизм кэширования для TBitmap, который имеет свою канву для рисования.

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

Кого-то может удивить отсутствие объявленных методов рисова-

ния вроде Draw у TIcon, TMetafile и TBitmap. Такие методы есть,

но они недоступны. Все рисование должно осуществляться через вызовы методов Draw и StretchDraw канвы, содержащей графику, ибо канва несет тот контекст, в котором должна осуществляться операция. Рассмотрим предопределенные графические классы.

Класс TMetaflle

Инкапсулирует свойства стандартного метафайла Windows. В нем перекрываются методы Assign, LoadFromStream, SaveToStream, LoadFromClipboardFormat, SaveToClipboardFormat. В буфер обмена объект помещает свое содержимое в формате CF_METAFILEPICT. Помимо общих, класс имеет свойства:

15

-----------------------------------------------------------------

Handle

Дескриптор метафайла.

 

 

Inch

Число точек

на

дюйм

в

 

координатной системе

метафайла.

 

Связано с установленным режимом

 

отображения.

 

 

 

-----------------------------------------------------------------

Класс TIcon Инкапсулирует значок Windows.

Не пытайтесь изменить размеры значка - они постоянны (равны

GetSystemMetrics(SM_CXICON) и GetSystemMetrics(SM_CYICON)), и при попытке присвоить новые значения возникает исключительная ситуация EInvalidGraphicOperation. Значок нельзя также читать и писать в буфер обмена так как в Windows нет соответствующего формата. В этом классе перекрываются методы класса ТGraphiс: Assign, LoadFromStream и SaveToStream. Дополнительно также определены:

-----------------------------------------------------------------

Handle

Дескриптор значка.

 

ReleaseHandle

Метод

"отдает"

дескриптор

 

- возвращает его значение,

 

обнуляя ссылку на него в объекте

-----------------------------------------------------------------

Класс TBitmap

Класс соответствует битовой карте, зависимой от устройства

(Device - dependent bitmap, DDB). В нем перекрываются методы Assign LoadFromClipboardFormat, LoadFromStream, SaveToClipboardFormat, SaveToStream. Объект взаимодействует с буфером обмена в фор-

мате CF_BITMAP.

Канва битовой карты доступна через свойство Canvas. Обратите внимание на то, что другие потомки TGraphic канвы

не имеют. С ее помощью можно рисовать на поверхности изображения. Дескрипторы битовой карты и ее палитры доступны как свойства

Handle и Palette.

Два метода

HBITMAP __fastcall ReleaseHandle(void);

HPALETTE __fastcall ReleasePalette(void);

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

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

void __fastcall Dormant(void); - выгружает изображение в поток и уничтожает дескрипторы битовой карты и палитры,

void __fastcall FreeImage(void); - "освобождает" дескриптор бито-

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

Битовая карта может быть монохромной и цветной, что определено логическим свойством Monochrome. Значение true соответствует монохромной битовой карте. При его изменении происходит преобразование содержимого к требуемому виду.

"Фоновый" цвет битовой карты:

__property TColor TransparentColor = {read=GetTransparentColor, write=SetTransparentColor, stored=TransparentColorStored, nodefault};

Это тот цвет, который можно отменить в операции BrushCopy, чтобы она выглядела прозрачной. Для монохромной карты этот цвет - белый.

Функции для работы с графикой

-------------------------------------------------------------------

extern

 

PACKAGE¦Эту функцию

удобно

использовать

System::AnsiString

__fastcall¦вместе

с

диалогами

открытия

и

GraphicFilter(System::

 

¦закрытия

файла.

Для

заданного

TMetaClass* GraphicClass);

¦класса

 

GraphicClass

она

вернет

 

 

¦строку,

 

которую

сразу

можно

 

 

¦присвоить

 

свойству

 

Filter

 

 

¦диалога.

Например,

для

TBitmap

 

 

¦она

вернет

строку

 

'Bitmaps

 

 

¦(.ВМР)|*.ВМР'

 

 

 

 

 

extern

 

PACKAGE¦Возвращает

строку,

содержащую

System::AnsiString

__fastcall¦расширение, которое встречается

у

GraphicExtension(System::

¦файлов

 

в формате

GraphicClass.

TMetaClass* GraphicClass);

¦Например,

GraphicExtension(TIcon)

 

 

¦равно строке 'ICO'.

 

 

 

 

extern PACKAGE int

__fastcall¦Преобразует

значение типа

TColor

ColorToRGB(Tcolor Color);

¦в формат RGB.

 

 

 

 

 

extern PACKAGE bool __fastcall¦Функции взаимного преобразования

ColorToIdent(int

Color,¦цвета

в

строку с его

названием.

System::AnsiString &Ident);

¦Например,

ColorToIdent(clWhite,

extern PACKAGE bool __fastcall¦AString)

присвоит

 

AString

IdentToColor(const

 

¦значение

"clWhite".

В

случае

System::AnsiString

Ident,

int¦неуспеха возвращается false

 

&Color);

 

¦

 

 

 

 

 

 

extern PACKAGE

 

¦Назначение

 

аналогично

двум

System::AnsiString __fastcall

¦предыдущим

 

функциям.

 

При

ColorToString(TColor Color);

¦отсутствии

цвета Color

в списке

extern PACKAGE TColor __fastcall¦предопределенных

 

цветов

StringToColor(const

 

¦возвращается

строка

 

с

его

System::AnsiString S);

¦значением

в

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

 

 

¦формате.

При отсутствии

цвета

с

 

 

¦именем

S

том

же

списке)

 

 

¦делается

попытка преобразовать

 

 

¦строку

в число, в случае

неудачи

 

 

¦возникает

 

исключительная

 

 

¦ситуация.

 

 

 

 

 

extern PACKAGE void __fastcall¦Производит

вызов

определенной

GetColorValues(Classes::TGetStrP ¦пользователем процедуры

Proc

для

roc &Proc);

 

¦всех имеющихся в списке цветов.

В

 

 

¦качестве

параметра

в

такую

 

 

¦процедуру

передается

строка

с

 

 

¦именем цвета.

 

 

 

 

--------------------------------------------------------------------

Для преобразования битовой карты из зависимого от устройства формата DDB в независимый (DIB) предназначены две функции:

--------------------------------------------------------------------

extern PACKAGE void

__fastcall¦Возвращает

размер

заголовка

GetDIBSizes(HBITMAP

Bitmap, int¦изображения

и размер

самого

&InfoHeaderSize,

int¦изображения.

 

Значение

&ImageSize);

¦InfoHeaderSize

равно

размеру

 

¦структуры TBitmapInfoHeader плюс,

16

 

¦при

необходимости,

размеру

 

¦палитры (каждый элемент которой

 

¦TRGBQuad занимает 4 байта).

В

 

¦ImageSize

возвращается количество

 

¦байт,

которое нужно

отвести

для

 

¦получения изображения в формате

 

¦DIB.

 

 

 

 

 

¦

 

 

 

 

extern PACKAGE bool __fastcall¦Преобразует

DDB (определенную

GetDIB(HBITMAP Bitmap, HPALETTE¦через Bitmap и Palette) в DIB.

Palette,

void *BitmapInfo, void¦Заголовок

помещается

в

*Bits);

¦BitmapInfo,

а сами

данные

- в

 

¦Bits.

 

 

 

 

-------------------------------------------------------------------

Визуальные компоненты для работы с графическими объектами

Компонент TPaintBox

Самой простой надстройкой над канвой служит компонент TPaintBox, предназначенный для рисования. Можно даже рассматривать его как канву, снабженную атрибутами компонента. Она представлена свойством Canvas.

Помимо канвы, компонент имеет свой цвет (фона) Color и шрифт Font. Изобразить на канве компонента что-либо можно, предусмотрев обработчик события OnPaint.

Компонент TShape

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

__property TShapeType

Shape = {read = FShape, write=SetShape,

 

 

 

default=0};

Рисуемая фигура - одна из предопределенных в множестве:

enum

TShapeType

{

stRectangle, stSquare, stRoundRect,

stRoundSquare, stEllipse, stCircle };

Размеры фигуры соответствуют размерам компонента. Если задан квадрат или круг, а ширина и высота компонента не равны между собой, то сторона или диаметр фигуры будут равны длине меньшей стороны компонента.

Кисть и перо, которыми рисуется и закрашивается фигура, представлены свойствами Brush и Pen.

Компонент TImage

Этот компонент служит надстройкой над классом TPicture и замыкает всю иерархию графических объектов VCL. Он предназначен для показа на форме изображения: битовой карты (TBitmap), метафайла

(TMetafile), значка (TIcon).

Свойство

__property Graphics::TPicture* Picture = {read=FPicture, write=SetPicture};

служит контейнером для графического объекта одного из перечисленных классов.

В качестве канвы используется канва объекта Graphic - только если поле Graphic ссылается на объект класса Tbitmap.

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

Следующие три свойства определяют, как именно TPicture располагается в рабочей области компонента:

__property bool AutoSize = {read=FAutoSize, write=SetAutoSize, default=0}; - означает, что размеры компонента настраиваются по размерам содержащегося в нем графического объекта. Устанавливать его в True нужно перед загрузкой изображения из файла или буфepa обмена;

__property bool Stretch = {read=FStretch, write=SetStretch, default=0}; - если это свойство установлено в True, то изображение "натягивается" на рабочую область, при необходимости уменьшая или увеличивая свои размеры. Если оно установлено в False, то играет роль следующее свойство;

__property bool Center = {read=FCenter, write=SetCenter, default=0}; - если это свойство установлено в True, изображение центрируется в пределах рабочей области. В противном случае - располагается в ее верхнем левом углу.

Графическое представление результатов расчета с помощью визуального компонента VCL CHART FX

Создание простой диаграммы

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

Изначально на диаграмме отображаются случайные данные. Поэтому как только Вы создали диаграмму, необходимо по крайней мере определить данные, которые должны быть отображены.

Чтобы определить данные, которые будут показаны, следует использовать свойство Value - массив с плавающей точкой:

Chart1->Value[nPoint] = dValue;

т.е. dValue является значением точки nPoint в серии, указанной свойством ThisSerie.

// Серия 0 , Точка 3 , Значение 10.5

Chart1->ThisSerie = 0;

Chart1->Value[3] = 10.5;

Однако перед использованием этого свойства Вы должны убедиться, что канал связи к библиотеке должным образом открыт. Это реализуется парой методов OpenDataEx и CloseData.

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

//Открыть канал ЗНАЧЕНИЙ, определяющий 2 серии и 7 точек

Chart1->OpenDataEx(COD_VALUES,2, 7);

//Код, чтобы установить данные

Chart1->ThisSerie = 0;

for (i = 0; i < 7; ++i)

17

Chart1->Value[i] = 9;

Chart1->ThisSerie = 1;

for (i = 0; i < 7; ++i) Chart1->Value[i] = 15;

// Закрыть канал ЗНАЧЕНИЙ

Chart1->CloseData(COD_VALUES);

Изменение данных существующей диаграммы

Как только диаграмма создана, Вы можете изменять любое из отображенных значений, используя свойства, описанные ранее: OpenDataEx, Value, CloseData.

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

//Открыть канал ЗНАЧЕНИЙ, определяющий 4 серии и 8 точек

Chart1->OpenDataEx(COD_VALUES, 4, 8);

//Код, чтобы установить данные

for (i = 0; i < 4; ++i)

{

Chart1->ThisSerie = i; for (j = 0; j < 8; ++j)

Chart1->Value[j] = 12;

}

// Закрыть канал ЗНАЧЕНИЙ

Chart1->CloseData(COD_VALUES);

Если Вы только хотите изменить значения без изменения числа точек или серий, можно использовать флажок COD_UNCHANGE:

Chart1->OpenDataEx(COD_VALUES,COD_UNCHANGE COD_UNCHANGE);

// Изменяют произвольную точку

Chart1->ThisSerie = 1;

Chart1->Value[4] = 10.5;

// Закрыть канал ЗНАЧЕНИЙ

Chart1->CloseData(COD_VALUES);

Изменение условных обозначений и заголовков

Чтобы изменять заголовки диаграммы, Вы можете устанавливать свойство Title с кодом заголовка в индексе, как показано ниже:

// Устанавливает или Изменяет заголовки диаграммы

Chart1->Title[CHART_LEFTTIT] = "Revenues"; Chart1->Title[CHART_BOTTOMTIT] = "Months";

Чтобы изменять легенды диаграммы, используется свойство Legend для описания легенды аргумента X и свойство SerLeg для легенды серии:

Chart1->Legend[0] = "Jan";

Chart1->Legend[1] = "Feb";

Chart1->Legend[2] = "Mar";

Chart1->Legend[3] = "Apr";

Chart1->SerLeg[0] = "Sales";

Chart1->SerLeg[1] = "Revenues";

Хотя библиотека Chart FX разрешает пользователю менять заголовки, это может быть ограничено двумя способами:

-Созданием диаграммы без CS_TITLES стиля.

-Использованием свойства Style.

Изменение визуальных атрибутов диаграммы

Chart FX обеспечивает 3 режима для отображения графики:

-2D режим

-3D "простой" режим

-3D с углами вращения

По умолчанию задается 2D-режим, однако Вы можете отменять это значение по умолчанию и устанавливать трехмерный "простой" режим при проектировании и времени выполнения, используя Свойства Type или Chart3D следующим образом:

// Чтобы установить трехмерный простой режим

Chart1->Chart3D = true;

Чтобы устанавливать полный трехмерный режим представления, диаграмма должна быть в трехмерном "простом" режиме и нуждается в следующих запросах:

/*

Чтобы установить 3D-режим с 30 точками по оси X и 60 точками по оси Y

*/

Chart1->View3D = true; Chart1->Angles3D = MAKELONG(30,60);

// Чтобы удалить 3D-режим

Chart1->View3D = false;

Установка цветовых схем, сетки и цветов фона

Цветовая схема описывает способ, который используется Chart FX для раскраски линий, точек, секторов круга, и т.д. Схема может быть Solid (твердые цвета), BW Patterns (черно-белые модели) и Patterns (цветные модели).

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

мы.

Цвета фона - для вывода различных фонов в диаграмме.

// Установим цветовую схему

Chart1->Scheme = CHART_CSPATTERN;

// Установим сетку

Chart1->Grid = CHART_HORZGRID;

// Установим цвета фона

Chart1->RGBBk = RGB(0,255,0); Chart1->RGB2DBk = RGB(200,20,90);

18

Chart1->RGB3DBk = RGB(200,20,90);

Изменение шрифтов

Хотя Chart FX использует по умолчанию шрифт Arial 8 для отображения заголовков, условных обозначений и других текстов в диаграмме, программист может изменять любой из шрифтов, использованных библиотекой через свойства hFont и RGBFONT. Имеются два способа, которыми программист может определить шрифт:

Ограниченный Режим (свойство Font). В этом режиме программист с помощью поразрядного ИЛИ определяет флажки, который задают шрифт: гарнитура (CF_ARIAL, CF_TIMES, и т.д.), эффекты (CF_BOLD, CF_ITALIC, и т.д.) семейство (CF_FDONTCARE, CF_FSWISS, и т.д.) и

размер шрифта в точках.

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

Windows (CreateFont и DeleteObject)

// Установка заголовка

Chart1->Title[CHART_BOTTOMTIT] = "Times Font";

// Изменение шрифта заголовка

Chart1->Font[CHART_BOTTOMFT] = CF_TIMES | CF_BOLD | 12;

// Изменение цветов для вывода шрифта

Chart1->RGBFont[CHART_BOTTOMFT] = RGB(255,0,0);

Создание инструментальных средств и других визуальных элементов

Chart FX предоставляет пользователю 4 инструментальных средства Windows, которые предлагают простой и интуитивный путь изменения некоторых из характеристик диаграммы:

Окно

Флажок

Используется для ...

ToolBar

CT_TOOL

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

 

 

типа графика, сетки и так далее.

LegendBar

CT_LEGEND

управления легендами серий и оси

 

 

аргумента X.

PaletteBar

CT_PALETTE

управления цветами

PatternBar

CT_PATTERN

управления заполнением

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

Chart1->Type_ = BAR | CT_TOOL | CT_LEGEND;

РАСТРОВАЯ ГРАФИКА

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

АЛГОРИТМЫ ВЫЧЕРЧИВАНИЯ ОТРЕЗКОВ

Поскольку экран растрового дисплея с электронно-лучевой

трубкой (ЭЛТ) можно рассматривать как матрицу дискретных элементов (пикселов), каждый из которых может быть подсвечен, нельзя непосредственно провести отрезок из одной точки в другую. Процесс определения пикселов, наилучшим образом аппроксимирующих заданный отрезок, называется разложением в растр. В сочетании с процессом построчной визуализации изображения он известен как преобразование растровой развертки. Для горизонтальных, вертикальных и наклоненных под углом 45° отрезков выбор растровых элементов очевиден. При любой другой ориентации выбрать нужные пикселы труднее.

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

Постоянная вдоль всего отрезка яркость достигается лишь при проведении горизонтальных, вертикальных и наклоненных под углом 45° прямых. Для всех других ориентаций разложение в растр приведет к неравномерной яркости. Даже для частных случаев яркость зависит от наклона: заметим например, что расстояние между соседними пикселами для отрезка под углом 45° больше, чем для вертикальных и горизонтальных прямых. Поэтому вертикальные и горизонтальные отрезки будут выглядеть ярче, чем наклонные. Обеспечение одинаковой яркости вдоль отрезков разных длин и ориентаций требует извлечения квадратного корня, а это замедлит вычисления. Обычным компромиссом является нахождение приближенной длины отрезка, сведение вычислений к минимуму, предпочтительное использование целой арифметики, а также реализация алгоритмов на аппаратном или микропрограммном уровне.

В большинстве алгоритмов вычерчивания отрезков для упрощения вычислений используется пошаговый метод. Приведем пример подобного алгоритма:

Простой пошаговый алгоритм позиция = начало шаг = приращение

1If позиция - конец < точность then 4 If позиция > конец then 2

позиция < конец then 3

2позиция = позиция - шаг gоto 1

3позиция = позиция + шаг goto 1

4finish

ЦИФРОВОЙ ДИФФЕРЕНЦИАЛЬНЫЙ АНАЛИЗАТОР

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

dy/dx = const

19

или

dy/dx = (Y2-Y1)/(X2-X1)

Решение представляется в виде

Yi+1 = Yi + dy

Yi+1 = Yi +(Y2-Y1)/(X2-X1) * dx

где X1, Y1 и X2, Y2концы разлагаемого отрезка и Yi - начальное значение для очередного шага вдоль отрезка. Фактически уравнение представляет собой рекуррентное соотношение для последовательных значений Y вдоль нужного отрезка. Этот метод, используемый для разложения в растр отрезков, называется цифровым дифференциальным анализатором (ЦДА). В простом ЦДА либо dx, либо dy (большее из приращений) выбирается в качестве единицы растра. Ниже приводится простой алгоритм, работающий во всех квадрантах:

/*

Предполагается, что концы отрезка (X1, Y1) и (X2, Y2) не совпадают.

Integer - функция преобразования вещественного числа в целое.

Примечание: во многих реализациях функция Integer означает округление целой части, т. е. Integer (-8.5) = -9, а не -8. В алгоритме используется именно такая функция.

Sign - функция, возвращающая -1, 0, 1 для отрицательного, нулевого и положительного аргумента соответственно

*/

// аппроксимируем длину отрезка

if abs(x2 - X1) >= abs(y2 - y1) then

Длина = abs(x2 - x1)

else

Длина = abs(y2 - y1) end if

// полагаем большее из приращений dx или dy равным единице растра

dх = (х2 - х1)/Длина dy = (y2 - y1)/Длина

/*

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

*/

х = х1 + 0.5 * Sign(dx)

y = y1 + 0.5 * Sign(dy)

// начало основного цикла i = 1

while (i <= Длина)

Plot (Integer(x), Integer(y))

х = х + dх y = y + dy i = i + 1

end while finish

АЛГОРИТМ БРЕЗЕНХЕМА

Хотя алгоритм Брезенхема был первоначально разработан для цифровых графопостроителей, однако он в равной степени подходит и для использования растровыми устройствами с ЭЛТ. Алгоритм выбирает оптимальные растровые координаты для представления отрезка. В процессе работы одна из координат - либо x либо у (в зависимости от углового коэффициента) - изменяется на единицу. Изменение другой координаты (либо на нуль, либо на единицу) зависит от расстояния между действительным положением отрезка и ближайшими координатами сетки. Такое расстояние мы назовем ошибкой. Ошибка - это интервал, отсекаемый по оси Y рассматриваемым отрезком в каждом растровом элементе. Алгоритм построен так, что требуется проверять лишь знак этой ошибки.

/*

Алгоритм Брезенхема разложения в растр отрезка для первого октанта.

Предполагается, что концы отрезка (x1,y1) и (x2,y2) не совпадают.

Integer - функция преобразования в целое.

х, y, dх, dy - целые.

е - вещественное.

*/

//инициализация переменных х = х1

y = y1

dх = х2 - х1 dy = y2 - y1

//инициализация е с поправкой на половину пиксела е = dy/dх - .5

//начало основного цикла

for i = 1 to dх Plot (х, y) while (e >= 0)

y = y + 1

е = е - 1 end while

x = x + 1

е = е + dy/dх next i

finish

ЦЕЛОЧИСЛЕННЫЙ АЛГОРИТМ БРЕЗЕНХЕМА

Алгоритм Брезенхема в том виде, как он представлен выше, требует использования арифметики с плавающей точкой и деления (для вычисления углового коэффициента и оценки ошибки). Быстродействие алгоритма можно увеличить, если использовать только целочисленную арифметику и исключить деление. Так как важен лишь знак ошибки, то простое преобразование E = 2 * е * dy превратит предыдущий алгоритм в целочисленный и позволит эффективно реализовать его на аппаратном или микропрограммном уровне. Чтобы реализация алгоритма Брезенхема была полной, необходимо брать отрезки во всех октантах. Модификацию легко сделать, учитывая в алгоритме номер квадранта, в котором лежит отрезок и его угловой коэффициент. Когда абсолютная величина углового коэффициента больше

20

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]