Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2 курс Компьютерная Графика / Литература / Учебное пособие по КГГ для ИДО4.doc
Скачиваний:
199
Добавлен:
15.04.2015
Размер:
3.49 Mб
Скачать
  1. Растровые алгоритмы

Большинство графических устройств являются растровыми, представляя изображение в виде прямоугольной матрицы (сетки, целочисленной решетки) пикселей (растра), и большинство графических библиотек содержат внутри себя достаточное количество простейших растровых алгоритмов. На рис 2 .11 приведена система растровых алгоритмов.

Рис. 2.11.Классификация растровых алгоритмов

    1. Алгоритмы растеризации

Прежде чем перейдем к непосредственному рассмотрению возможности перевода математического описания объекта (линии и пр.) в растровую форму, рассмотрим понятие связности. Связность– возможность соединения двух пикселей растровой линией, т. е. последовательным набором пикселей. Возникает вопрос, когда пиксели (x1, y1) и (x2, y2) можно считать соседними. Для этого вводятся два понятия связности:

1. Четырехсвязность: пиксели считаются соседними, если либо ихx-координаты, либо ихy– координаты отличаются на единицу:

|x1­x2| + |y1y2| ≤ 1;

2. Восьмисвязность: пиксели считаются соседними, если ихx-координаты иy-координаты отличаются не более чем на единицу:

|x1­x2| ≤ 1, |y1y2| ≤ 1.

На рис. 2 .12 изображены четырехсвязная и восьмисвязная линии.

Рис. 2.12. Четырехсвязная и восьмисвязная линии

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

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

Рассмотрим задачу построения растрового изображения отрезка, соединяющего точки A(xa, ya)иB(xb, yb). Для простоты будем считать, что

0 ≤ yb yaxb xa. Тогда отрезок описывается уравнением:

y = ya + (x–xa), x Є [xa, xb] или y = kx + b.

Отсюда получаем простейший алгоритм растрового представления отрезка:

void line(int xa, int ya, int xb, int yb, int color)

{

double k = ((double)(yb – ya)) / (xb – xa);

double b = ya – k * xa;

for (int x = xa; x <= xb; x++)

putpixel(x, (int)(k * x + b), color);}

Вычислений значений функции y = kx + bможно избежать, используя в цикле рекуррентные соотношения, так как при измененииxна 1 значениеyменяется наk:

void line(int xa, int ya, int xb, int yb, int color)

{

double k = ((double)(yb – ya)) / (xb – xa);

double y = ya;

for (int x = xa; x <= xb; x++, y += k)

putpixel(x, (int)y, color);

}

Приведенные простейшие пошаговые алгоритмы построения отрезка имеют ряд недостатков:

  1. Выполняют операции над числами с плавающей точкой, а желательно было бы работать с целочисленной арифметикой;

  2. На каждом шаге выполняется операция округления, что также снижает быстродействие.

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

Как и в предыдущем случае, будем считать, что тангенс угла наклона отрезка принимает значение в диапазоне от 0 до 1. Рассмотрим i-й шаг алгоритма (рис. 2 .13). На этом этапе пиксельPi-1уже найден как ближайший к реальному отрезку. Требуется определить, какой из пикселов (TiилиSi) будет установлен следующим.

Рис. 2.13. i-й шаг алгоритма Брезенхейма

В алгоритме используется управляющая переменная di, которая на каждом шаге пропорциональна разности междуSиT. ЕслиS<T, тоSiближе к отрезку, иначе выбираетсяTi.

Пусть изображаемый отрезок проходит из точки (x1, y1) в точку (x2, y2). Исходя из начальных условий, точка (x1, y1) ближе к началу координат. Тогда перенесем оба конца отрезка с помощью преобразования T(­­­­­­–x1, –y1), так чтобы первый конец отрезка совпал с началом координат. Начальной точкой отрезка стала точка (0, 0), конечной точкой – (dx, dy), гдеdx = x2 – x1,dy = y2y1(рис. 2 .14).

Рис. 2.14. Вид отрезка после переноса в начало координат

Уравнение прямой в этом случае будет иметь вид:

y=x.

Обозначим координаты точки Pi-1 после переноса через (r, q). ТогдаSi = (r+1, q) иTi = (r+1, q+1).

Из подобия треугольников на рис. 2 .14 можно записать, что

=.

Выразим S:

S= (r+ 1) –q.

Tможно представить какT= 1 –S. Используем предыдущую формулу

T= 1 –S = 1 – (r+ 1) –q.

Найдем разницу ST:

ST =(r+ 1) –q1 + (r+ 1) –q = 2 (r+ 1) – 2 q1.

Помножим левую и правую часть на dx:

dx (ST) = 2 dy (r + 1) – 2 q dx – dx = 2 (r dy – q dx) + 2 dy – dx.

Величинаdxположительная, поэтому неравенствоdx(ST) < 0 можно использовать в качестве проверки при выбореSi. Обозначимdi =dx(ST), тогда

di = 2 (r dyq dx) + 2dydx.

Поскольку r=xi-1иq=yi-1, то

di = 2 xi-1 dy –2 yi-1 dx + 2 dy – dx.

Прибавляя 1 к каждому индексу найдемdi+1:

di+1 = 2 xi dy –2 yi dx + 2 dy – dx.

Вычитая di из di+1 получим

di+1di = 2 dy (xi xi-1) – 2 dx (yi yi-1).

Известно, чтоxi xi-1= 1, тогда

di+1di = 2dy– 2dx(yi yi-1).

Отсюда выразим di+1:

di+1=di+ 2dy– 2dx(yi yi-1).

Таким образом, получили итеративную формулу вычисления управляющего коэффициента di+1по предыдущему значениюdi. С помощью управляющего коэффициента выбирается следующий пиксель –SiилиTi.

Если di≥ 0, тогда выбираетсяTiиyi=yi–1+ 1,di+1= di+2 (dydx). Еслиdi< 0, тогда выбираетсяSiиyi=yi–1иdi+1= di+2dy.

Начальные значения d1с учетом того, что (x0, y0) = (0, 0),

d1 = 2dydx.

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

Реализация этого алгоритма выглядит следующим образом:

void MyLine(int x1, int y1, int x2, int y2, int c)

{

int dx, dy, inc1, inc2, d, x, y, Xend;

dx = abs(x2 - x1);

dy = abs(y2 - y1);

d = dy << 1 - dx;

inc1 = dy << 1;

inc2 = (dy - dx) << 1;

if (x1>x2)

{

x = x2;

y = y2;

Xend = x1;

}

else

{

x = x1;

y = y1;

Xend = x2;

};

putpixel(x, y, c);

while (x < Xend)

{

x++;

if (d < 0) d = d + inc1;

else

{

y++;

d = d + inc2;

};

putpixel(x, y, c);

};

}

Если dy > dx, то необходимо будет использовать этот же алгоритм, но пошагово увеличиваяyи на каждом шаге вычислятьx.

Соседние файлы в папке Литература