Опубликован: 20.10.2007 | Доступ: свободный | Студентов: 4580 / 1391 | Оценка: 4.38 / 3.99 | Длительность: 12:07:00
ISBN: 978-5-94774-654-9
Специальности: Программист
Лекция 8:

Растровое преобразование графических примитивов

< Лекция 7 || Лекция 8: 123 || Лекция 9 >

Алгоритмы Брезенхема растровой дискретизации окружности и эллипса

Алгоритм изображения окружности несколько сложнее, чем построение отрезка. Мы рассмотрим его для случая окружности радиуса r с центром в начале координат. Перенесение его на случай произвольного центра не составляет труда. При построении растровой развертки окружности можно воспользоваться ее симметрией относительно координатных осей и прямых y=\pm x. Необходимо сгенерировать лишь одну восьмую часть окружности, а остальные ее части можно получить путем отображений симметрии. За основу можно взять часть окружности от 0 до 45 \deg в направлении по часовой стрелке с исходной точкой построения (r,0). В этом случае координата окружности x является монотонно убывающей функцией координаты y.

Ближайший пиксель при движении по окружности

Рис. 8.7. Ближайший пиксель при движении по окружности

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

\begin{gathered}
d_h=|s_h|, \quad d_v=|s_v|, \quad d_d=|s_d|, \\
s_h=(x+1)^2+y^2-r^2, \quad s_v=x^2+(y-1)^2-r^2, \quad\\ s_d=(x+1)^2+(y-1)^2-r^2.
\end{gathered}

Алгоритм можно упростить, перейдя к анализу знаков величин s_h, s_v, s_d. При s_d<0 диагональная точка лежит внутри окружности, поэтому ближайшими точками могут быть только диагональная и правая. Теперь достаточно проанализировать знак выражения \Delta=d_v-d_d. Если \Delta\le 0, выбираем горизонтальный шаг, в противном случае - диагональный. Если же s_d>0, то определяем знак \Delta^1=d_d-d_v, и если \Delta^1\le 0, выбираем диагональный шаг, в противном случае - вертикальный. Затем вычисляется новое значение s_d, причем желательно минимизировать вычисления не только этой величины, но и величин \Delta,\Delta^1 на каждом шаге алгоритма. Путем несложных преобразований можно получить для первого шага алгоритма, что \Delta=2(s_d+y)-1, \quad \Delta^1=2(s_d+x)-1.

После перехода в точку (x',y'),\:x'=x+1,\:y'=y+1 по диагонали новое значение s_d вычисляется по формуле s'_d=s_d+2x'-2y'+2, при горизонтальном переходе (x'=x+1,y'=y)\quad s'_d=s_d+2x'+1, при вертикальном (x'=x,y'=y-1) - s'_d=s_d-2y'+1.

Таким образом, алгоритм рисования этой части окружности можно считать полностью описанным (блок-схема его приведена на рис. 8.8). Все оставшиеся ее части строятся параллельно: после получения очередной точки (x',y') можно инициализировать еще семь точек с координатами (-x',y'),\;(-x',-y'),\;(x',-y'),\;(y',x'),\;(y',-x'),\;(-y',-x'),\;(-y',x').

Для построения растровой развертки эллипса с осями, параллельными осям координат, и радиусами a,b воспользуемся каноническим уравнением

\frac{x^2}{a^2}+\frac{y^2}{b^2}=1,
которое перепишем в виде
f(x,y)\equiv b^2 x^2+a^2 y^2 -a^2 b^2 =0.

В отличие от окружности, для которой было достаточно построить одну восьмую ее часть, а затем воспользоваться свойствами симметрии, эллипс имеет только две оси симметрии, поэтому придется строить одну четверть всей фигуры. За основу возьмем дугу, лежащую между точками (0,b) и (a,0) в первом квадранте координатной плоскости.

Блок-схема построения восьмой части окружности

Рис. 8.8. Блок-схема построения восьмой части окружности

В каждой точке (x,y) эллипса существует вектор нормали, задаваемый градиентом функции f. Дугу разобьем на две части: первая - с углом между нормалью и горизонтальной осью больше 45 \deg (тангенс больше 1) и вторая - с углом, меньшим 45 \deg (рис. 8.9). Движение вдоль дуги будем осуществлять в направлении по часовой стрелке, начиная с точки (0,b). Вдоль всей дуги координата является монотонно убывающей функцией от x, но в первой части она убывает медленнее, чем растет аргумент, а во второй - быстрее. Поэтому при построении растрового образа в первой части будем увеличивать x на единицу и искать соответствующее значение y, а во второй - сначала уменьшать значение y на единицу и определять соответствующее значение x.

Направление нормали соответствует вектору

grad(x,y)=
\left(
\frac{\partial f}{\partial x},\frac{\partial f}{\partial y}
\right)
=(2b^2 x, 2a^2 y).
Отсюда находим тангенс угла наклона вектора нормали: t=a^2 y/b^2 x. Приравнивая его единице, получаем, что координаты точки деления дуги на вышеуказанные части удовлетворяют равенству b^2 x=a^2 y. Поэтому критерием того, что мы переходим ко второй области в целочисленных координатах, будет соотношение a^2(y-1/2)\le b^2(x+1), или, переходя к целочисленным операциям, a^2(2y-1)\le 2b^2(x+1).

Две области на участке эллипса

Рис. 8.9. Две области на участке эллипса
Схема перехода в первой и второй областях дуги эллипса

Рис. 8.10. Схема перехода в первой и второй областях дуги эллипса

При перемещении вдоль первого участка дуги мы из каждой точки переходим либо по горизонтали, либо по диагонали, и критерий такого перехода напоминает тот, который использовался при построении растрового образа окружности. Находясь в точке (x,y), мы будем вычислять значение \Delta=f(x+1,y-\frac12). Если это значение меньше нуля, то дополнительная точка (x+1,y-\frac12) лежит внутри эллипса, следовательно, ближайшая точка растра есть (x+1,y), в противном случае это точка (x+1,y-1) (рис. 8.10а).

На втором участке дуги возможен переход либо по диагонали, либо по вертикали, поэтому здесь сначала значение координаты y уменьшается на единицу, затем вычисляется \Delta=f(x+\frac12,y-1) и направление перехода выбирается аналогично предыдущему случаю (рис. 8.10б).

Остается оптимизировать вычисление параметра \Delta, умножив его на 4 и представив в виде функции координат точки. Тогда для первой половины дуги имеем

\begin{gathered}
\widetilde{\Delta}(x,y)\equiv 4\Delta(x,y)=4b^2(x+1)^2+a^2(2y-1)^2-4a^2 b^2, \\
\widetilde{\Delta}(x+1,y)=\widetilde{\Delta}(x,y)+4b^2(2x+3), \\
\widetilde{\Delta}(x+1,y-1)=\widetilde{\Delta}(x,y)+4b^2(2x+3)-8a^2(y-1).
\end{gathered}
Для второй половины дуги получим
\begin{gathered}
\widetilde{\Delta}(x,y)\equiv 4\Delta(x,y)=b^2(2x+1)^2+4a^2(y-1)^2-4a^2 b^2, \\
\widetilde{\Delta}(x+1,y)=\widetilde{\Delta}(x,y)+8b^2(x+1), \\
\widetilde{\Delta}(x+1,y-1)=\widetilde{\Delta}(x,y)+8b^2(x+1)-4a^2(2y+3).
\end{gathered}

Все оставшиеся дуги эллипса строятся параллельно: после получения очередной точки (x',y'), можно инициализировать еще три точки с координатами (-x',y'),\;(-x',-y'),\;(x',-y'). Блок-схему не приводим ввиду прозрачности алгоритма.

< Лекция 7 || Лекция 8: 123 || Лекция 9 >
Сабина Бахриддинова
Сабина Бахриддинова
Дмитрий Трефилов
Дмитрий Трефилов