Bresenhamov stredový kružnicový algoritmus (Midpoint Circle Algorithm)
Princíp algoritmu
Algoritmus predstavuje úpravu Bresenhamovho midpoint line algoritmu pre kružnicu. Vychádza z polomeru $r$ kružnice $K$ a jej stredu v začiatku súradnicovej sústavy, t.j. v bode $(x_C,y_C)=(0,0)$.
Ak sa stred $(x_C,y_C)$ nenachádza v začiatku, tak pozíciu bodu kružnice $(x,y)$ vieme vypočítať pričítaním $x_C$ k $x$-ovej súradnici a $y_C$ k $y$-ovej. Vychádzame z rovnice kružnice: $f(x,y)=x^2+y^2-r^2=0$.
Platí
- Ak $f(x,y) \lt 0$, tak bod $(x,y)$ sa nachádza vnútri kružnice $K$. Takýto bod nazývame vnútorný bod
- Ak $f(x,y) = 0$, tak bod $(x,y)$ sa nachádza na kružnici $K$
- Ak $f(x,y) \gt 0$, tak bod $(x,y)$ sa nachádza mimo kružnice $K$. Takýto bod nazývame vonkajší bod.
Opäť sa nachádzame na segmente kružnice od bodu $(0,r)$ až po bod, pre ktorý je $x_i \geq y_i$ Nech sme v bode $(x_i,y_i)$ a hľadáme nasledujúci bod. Rozhodujeme sa medzi dvoma kandidátmi $E=(x_i+1,y_i)$ a $SE=(x_i+1,y_i-1)$ (Obr. 1).
Určíme $M=stred(E,SE)=(x_i+1,y_i-\frac{1}{2})$. Budeme zisťovať, či tento bod je vnútorný alebo vonkajší. Definujeme rozhodovací parameter $p_i$:
$p_i=f(M)=(x_i+1)^2+(y_i-\frac{1}{2})^2-r^2$ a odvodíme z neho rekurentný vzorec: $p_{i+1}=f((x_{i+1}+1,y_{i+1}-\frac{1}{2})=(x_{i+1}+1)^2+(y_{i+1}-\frac{1}{2})^2-r^2$
Potom $p_{i+1}-p_i=2x_{i+1}+(y_{i+1}^2-y_{i+1})-(y_{i}^2-y_i)+1$ rekurentný predpis má tvar: $p_{i+1}=p_i+2x_{i+1}+(y_{i+1}^2-y_{i+1})-(y_i^2-y_i)+1$
Zrejme platí:
- Ak $p_i \lt 0$, vyberáme ako nasledujúci pixel $(x_{i+1},y_{i+1})=E=(x_i+1,y_i)$ a $p_{i+1}=p_i+2x_i+3$
- Ak $p_i \geq 0$, vyberáme bod $(x_{i+1},y_{i+1})=SE=(x_i+1,y_i-1)$ a teda $p_{i+1}=p_i+2(x_i-y_i)+5$
Potrebujeme ešte poznať hodnotu začiatočného parametra $p_0=(x_0+1)^2+(y_0-\frac{1}{2})^2-r^2$, ktorý pre bod $(x_0,y_0)=(0,r)$ sa rovná $p_0=\frac{5}{4}-r$. Ak je polomer špecifikovaný ako celé číslo, môžeme hodnotu $p_0$ zaokrúhliť ako $p_0=1-r$, lebo všetky prírastky sú celočíselné.
Na rozdiel od lineárnych algoritmov rasterizácie úsečky, sme v prípade kružnicových algoritmov nezískali rovnaké rozhodovacie parametre.
Postup algoritmu sme ilustrovali pre kružnicový oblúk, ktorý sa nachádza v II. oktante, avšak algoritmus je možné rovnakým spôsobom odvodiť aj pre ktorýkoľvek z ostatných oktantov. Podobne ako Bresenhamov line algoritmus, aj tento vypočítava pixely pozdĺž kružnice, používajúc pri tom len celočíselné sčítania a odčítania za predpokladu, že stred a polomer kružnice sú špecifikované v celočíselných obrazových súradniciach.
Postup výpočtu
Kroky algoritmu vieme zhrnúť nasledovne:
- Zadaj polomer $r$ a stred kružnice $(x_C,y_C)$ a urči prvý bod na kružnici so stredom v začiatku $(x_0 ,y_0)=(0, r)$.
- Vypočítaj začiatočnú hodnotu rozhodovacieho parametra ako $p_0 =1-r$ (pretože predpokladáme, že $r$ je celočíselné).
- V každej pozícii $x_i$, štartujúc v $i=0$, vykonaj nasledujúci test:
- Ak $p_i \lt 0$: nasledujúci bod pozdĺž kružnice so stredom $(0,0)$ bude $(x_{i+1}, y_{i+1})=(x_i+1,y_i)$ a $p_{i+1}=p_i+2x_i+3$.
- Inak je nasledujúci bod $(x_{i+1}, y_{i+1})=(x_i+1,y_i-1)$ a $p_{i+1}=p_i+2(x_i-y_i)+5$.
- Urči súmerné body v ostatných siedmich oktantoch.
- Posuň každú vypočítanú pixlovú pozíciu $(x, y)$ na kružnicu so stredom $(x_C ,y_C )$ a zobraz bod so súradnicami: $x=x+x_C$,$y=y+y_C$.
- Opakuj kroky 3. až 5. pokiaľ $x_i \geq y_i$.
Príklad
Na ilustráciu algoritmu si ukážeme rasterizáciu kružnice so stredom v bode $(x_C, y_C)=(1, 2)$ a polomerom $r=7$.
- $(x_0,y_0)=(0,r)=(0,7)$
- $p_0=1-r=-6$
-
- $i=0:$ $p_0 \lt 0 \Rightarrow (x_1,y_1)=(x_0+1,y_0)=(1,7)$ a $p_1=p_0+2x_0+3=-3$
- $i=1:$ $p_1 \lt 0 \Rightarrow (x_2,y_2)=(x_1+1,y_1)=(2,7)$ a $p_2=p_1+2x_1+3=2$
- $i=2:$ $p_2 \gt 0 \Rightarrow (x_3,y_3)=(x_2+1,y_2-1)=(3,6)$ a $p_3=p_2+2(x_2-y_2)+5=-3$
- $i=3:$ $p_3 \lt 0 \Rightarrow (x_4,y_4)=(x_3+1,y_3)=(4,6)$ a $p_4=p_3+2x_3+3=6$
- $i=4:$ $p_4 \gt 0 \Rightarrow (x_5,y_5)=(x_4+1,y_4-1)=(5,5)$ a $x_5\geq y_5$ teda algoritmus končí.
- Určíme súmerne položené body v ostatných oktantoch (Obr. 2).
- Posunieme každú hodnotu pixla do stredu $(1,2)$. Teda body: $(2,9),(3,9),(4,8),(5,8),(6,8), ...$
Ďalšie riešené a neriešené príklady.
Interaktívny applet
Bressenhamov stredový algoritmus pre rasterizáciu kružnice
Zobrazený raster sa nachádza v prvom kvadrante, teda v ľavom dolnom rohu sa nachádza bod (0,0).
Urči polomer a kliknutím do rastra vlož stred kružnice.
circleMidpoint(int xC, int yC, int r){
int x = 0, y = r;
int p = 1 - r;
void vykresliBodKruznice(int, int, int, int);
vykresliBodKruznice(xC, yC, x, y);
while(x < y) {
if(p < 0) p = p + (2 * x) + 3;
else {
y--;
p = p + 2* (x - y) + 5;
}
x++;
vykresliBodKruznice(xC, yC, x, y); }
}
}
void vykresliBodKruznice(int xC, int yC, int x, int y){
vykresliPixel(xC + x, yC + y);
vykresliPixel(xC - x, yC + y);
vykresliPixel(xC + x, yC - y);
vykresliPixel(xC - x, yC - y);
vykresliPixel(xC + y, yC + x);
vykresliPixel(xC - y, yC + x);
vykresliPixel(xC + y, yC - x);
vykresliPixel(xC - y, yC - x);
}
Pseudokód
Implementácia Bresenhamovho stredového kružnicového algoritmu je zhrnutá v nasledujúcom pseudokóde. Na vstupe je stred kružnice $(x_C,y_C)$ a polomer kružnice $r$.
circleMidpoint(int $x_C$, int $y_C$, int $r$) $\lbrace$
int x = 0, int y = r, int p = 1 - r;
vvoid vykresliBodKruznice(int, int, int, int);
/* Vykreslí prvý bod kružnice
vykresliBodKruznice($x_C$, $y_C$, x, y);
while(x < y) $\lbrace$
x++;
if(p < 0) p += 2 * x + 3;
else $\lbrace$
y$--$;
p += 2 * (x - y) + 5;
$\rbrace$
vykresliBodKruznice($x_C$, $y_C$, x, y);
$\rbrace$
$\rbrace$
void vykresliBodKruznice(int $x_C$, int $y_C$, int x, int y); $\lbrace$
vykresliPixel($x_C$ + x, $y_C$ + y);
vykresliPixel($x_C$ - x, $y_C$ + y);
vykresliPixel($x_C$ + x, $y_C$ - y);
vykresliPixel($x_C$ - x, $y_C$ - y);
vykresliPixel($x_C$ + y, $y_C$ + x);
vykresliPixel($x_C$ - y, $y_C$ + x);
vykresliPixel($x_C$ + y, $y_C$ - x);
vykresliPixel($x_C$ - y, $y_C$ - x);
$\rbrace$
Literatúra
Bresenhamov stredový kružnicový algoritmus je detailne spracovaný v knihe [3] od strany 98. Zo slovenskej/českej literatúry nie je uvedený ani v [1] ani v [2].