Материал: Конспект лекций по дисциплине «Компьютерная графика». Лейкин М.А

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

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

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

Источник: https://studfile.net/preview/16564466/