Казахстан |
Алгоритмы растеризации отрезков, окружностей и эллипсов
3.4. Изображение окружностей
Для начала перейдем к канонической системе координат, в которой центр окружности совпадает с началом координат. Тогда можно заметить, что в силу симметрии окружности относительно прямых, разделяющих октанты, достаточно построить растровое представление в одном октанте, а затем с помощью симметрий получить изображения в других октантах (см. рис. 3.7). Будем пользоваться заданием окружности в виде неявной функции: x2 + y2 - R2 = 0.
Пусть f(x, y) = x2 + y2 - R2. Будем рисовать часть окружности в 4 -м октанте, начиная с точки (-R, 0) (см. рис. 3.7, показано стрелкой).
Пусть , тогда
. Пусть функция plot8(x, y) отображает на растре все 8 точек, полученных из (x, y) с помощью симметрий.
Алгоритм Брезенхема
Будем рассуждать подобно алгоритму Брезенхема для отрезков (с соответствующими поправками на 4 -й октант) [17]. Из двух возможных пикселов в 4 -м октанте (соответствующих вертикальному и диагональному смещениям, которые обозначаются аналогично прежним s и d, см. рис. 3.10) будем выбирать тот, расстояние от окружности до которого меньше.
Для того чтобы выбрать один из двух возможных пикселей, будем сравнивать расстояния от них до окружности: где расстояние меньше - тот пиксел и будет искомым. В примере на рис. 3.8 сравниваются расстояния от точек S(xs, ys) и D(xd, yd) до окружности с радиусом R. Из евклидовой метрики получаем:
![\Delta R_s = \sqrt{x_s^2 + y_s^2} - R; \\
\Delta R_d = R -\sqrt{x_d^2 + y_d^2}.](/sites/default/files/tex_cache/52576bcaeb90f44a8c1f38afdd815b69.png)
Но вычисление квадратного корня - вычислительно трудоемкая операция, поэтому при достаточно больших R мы будем заменять сравнение расстояний сравнением приближенных значений их квадратов (см. рис. 3.9):
![(\Delta R_s)^2-(\Delta R_d)^2 = x_s^2 + y_s^2 - 2R\sqrt{x_s^2 + y_s^2}+R^2 - x_d^2 - y_d^2 + \\+ 2R\sqrt{x_d^2 + y_d^2} - R^2.](/sites/default/files/tex_cache/2cbda2851c59cb43f943530e504c0aba.png)
Уменьшим два слагаемых на приблизительно одинаковые величины:
заменим на
,
заменим на
получим
![(\Delta R_s)^2-(\Delta R_d)^2 \approx x_s^2 + y_s^2 - 2R \cdot R + R^2 - \\
- x_d^2 - y_d^2 + 2\sqrt{x_d^2 + y_d^2} \cdot \sqrt{x_d^2 + y_d^2} - R^2 = \\
= x_s^2 + y_s^2 + x_d^2 + y_d^2 - 2R^2.](/sites/default/files/tex_cache/f1137f0493eb78873944714dc3c32a18.png)
Таким образом, приближенно
-
D ближе к окружности, чем S
-
S ближе к окружности, чем D
Пусть (x, y) - текущий пиксель. Обозначим
![F_s = f(x, y + 1) = x^2 + {(y + 1)}^2 - R^2 > 0, \\
F_d = f(x + 1, y + 1) = {(x + 1)}^2 + {(y + 1)}^2 - R^2 < 0, \\
F = F_s + F_d;](/sites/default/files/tex_cache/bfa826cf127f10e65d2793a584e0d486.png)
![\Delta F(s) = ( \Delta F \text{ при переходе }s\colon (x, y) \to (x, y + 1) ) = \\
= f(x, y + 2) + f(x + 1, y + 2) - f(x, y + 1)- \\
- f(x + 1, y + 1)\\
= 4y + 6,](/sites/default/files/tex_cache/78b80133d600cf9938044de9f1d04c22.png)
![\Delta F(d) = ( \Delta F \text{ при переходе } d\colon (x, y) \to (x + 1, y + 1) ) = \\
= f(x + 1, y + 2) + f(x + 2, y + 2) - f(x, y + 1)- \\
- f(x + 1, y + 1) \\
= 4x + 4y + 10.](/sites/default/files/tex_cache/8eb7dc4877627bdf9f1472d252a35922.png)
Тогда из двух возможных смещений d и s выберем.
-
, т.е. (x + 1, y + 1) ближе к окружности, чем (x, y + 1):
d: Переходим в (x + 1, y + 1) и придаем соответствующие приращения F,
,
:
-
, т.е. (x, y+1) ближе к окружности, чем (x + 1, y + 1):
s: Переходим в (x, y + 1) и придаем соответствующие приращения F,
,
:
Если мы начинаем из (-R, 0), то начальные значения будут следующими:
![F = F_s + F_d = ({(-R)}^2 + 1^2 - R^2) + ({(-R + 1)}^2 + 1^2 - R^2) \\
= 1 + (-2R + 1 + 1) = 3 - 2R, \\
\Delta F(s) = 4 \cdot 0 + 6 = 6, \\
\Delta F(d) = 4 \cdot (-R) + 4 \cdot 0 + 10 = 10 - 4R.](/sites/default/files/tex_cache/9a77ed7b980d2a8a768d4ce50b2631c4.png)
Легко видеть, что в алгоритме все величины, связанные с F, кроме F начального, будут кратны 2. Но, если мы поделим все эти величины на 2 (в дальнейшем значения всех величин уже понимаются в этом смысле), то . Так как приращения F могут быть только целочисленными, то
, где
; т.е. если отнять
от всех значений, то знак F не изменится для всех T, кроме T = 0. Для того чтобы результат сравнения остался прежним, будем считать, что F = 0 теперь соответствует смещению s.
x = -r; y = 0; F = 1-r; delta_Fs = 3; delta_Fd = 5-2*r; while( x + y < 0 ) { plot8( x, y ); if( F > 0 ) { // d: Диагональное смещение F += delta_Fd; x++; y++; delta_Fs += 2; delta_Fd += 4; } else { // s: Вертикальное смещение F += delta_Fs; y++; delta_Fs += 2; delta_Fd += 2; } }Листинг 3.5. Алгоритм Брезенхема для окружности
Размерность вычислений этого алгоритма (т.е. отношение максимальных модулей значений величин, с которыми он оперирует к модулям исходных данных (в данном случае R )) равна 2.