Pro názornost ještě uvádím zdrojové texty v C pro některé mně
sympatické případy. Všechny varianty předpokládají existenci funkce:
void putpixel(short x, short y, char c); /* Nakreslí barvou c *
* bod na souřadnicích *
* [x, y] *
* doporučuji inline */
Zde je asi nejvýhodnější (když to přepíšete do assembleru) varianta
na kreslení obyčejné úsečky. Je jí metoda se čtyřmi samostatnými
případy (2.)
void bres_line_2 (short x1, short y1, short x2, short y2, char c)
/* Tato funkce ilustruje použití 2. metody implementace *
* bresenhamova algoritmu. (čtyři varianty) */
{
register short deltax, deltay, d;
deltax = (x2 > x1) ? (x2 - x1) : (x1 - x2);
deltay = (y2 > y1) ? (y2 - y1) : (y1 - y2);
/* CO TO JE? Chacha! Tohle neznáš, pascalisto, co?! */
if(deltax >= deltay) {
/* Řídící proměnná byla vybrána X */
if(x1 > x2) { /* Jestli jsme v opačném směru */
x1 ^= x2; x2 ^= x1; x1 ^= x2; /* Swap pomocí XOR */
y1 ^= y2; y2 ^= y1; y1 ^= y2; /* Instrukce XCHG... */
/* Poznámka pro pascalisty: ^= je xorrovnáse */
}
if(y2 > y1) {
/* Přičítáme Y */
for(d = -(deltax >> 1); x1 <= x2; x1++, d += deltay) {
if(d > 0) {d -= deltax; y1++;};
putpixel(x1, y1, c);
};
} else {
/* Odčítáme Y */
for(d = -(deltax >> 1); x1 <= x2; x1++, d += deltay) {
if(d > 0) {d -= deltax; y1--;};
putpixel(x1, y1, c);
};
};
} else {
/* Řídící proměnná byla vybrána Y */
if(y1 > y2) { /* Jestli jsme v opačném směru */
y1 ^= y2; y2 ^= y1; y1 ^= y2; /* Stejné prohození */
x1 ^= x2; x2 ^= x1; x1 ^= x2;
}
if(x2 > x1) {
/* Přičítáme X */
for(d = -(deltay >> 1); y1 <= y2; y1++, d += deltax) {
if(d > 0) {d -= deltay; x1++;};
putpixel(x1, y1, c);
};
} else {
/* Odčítáme X */
for(d = -(deltay >> 1); y1 <= y2; y1++, d += deltax) {
if(d > 0) {d -= deltay; x1--;};
putpixel(x1, y1, c);
};
};
};
} /* Konec funkce */
V assembleru je tahle varianta asi nejvýhodnější. V Céčku se asi ale
myslím lépe hodí varianta 3 s přičítací proměnou. Tu si však doufám
dokážete snadno odvodit sami.
A ještě bych chtěl ukázat rutinu pro kreslení čáry s barevným
přechodem. Něco velmi podobného stylu dostanete při psaní gouroud
shadingu:
void bres_shade_line (short x1, short y1, short x2, short y2,
unsigned char c1, unsigned char c2)
/* Tato funkce ilustruje kombinaci 3. a 4. metody implementace *
* bresenhamova algoritmu pro vykreslení úsečky s barevným *
* přechodem */
{
short deltax, deltay, deltac, dcoo, dcol, addcoo, addcol;
/* deltax = abs(x2 - x1), deltay = abs(y2 - y1) *
* deltac = abs(c2 - c1), dcoo = rozh. prom. souřadnice *
* dcol = rozh. prom. barvy addcoo = znaménko souřadnice *
* addcol = znaménko přičítání barvy */
deltax = (x2 > x1) ? (x2 - x1) : (x1 - x2);
deltay = (y2 > y1) ? (y2 - y1) : (y1 - y2);
deltac = (c2 > c1) ? (c2 - c1) : (c1 - c2);
if(deltax >= deltay) {
/* Řídící proměnná X */
if(x1 > x2) { /* Jestli jsme v opačném směru */
x1 ^= x2; x2 ^= x1; x1 ^= x2; /* Swap pomocí XOR */
y1 ^= y2; y2 ^= y1; y1 ^= y2; /* Instrukce XCHG... */
c1 ^= c2; c2 ^= c1; c1 ^= c2;
};
addcoo = (y2 > y1) ? 1 : -1;
addcol = (c2 > c1) ? 1 : -1;
for(dcoo = -(deltax >> 1), dcol = -(deltax >> 1); x1 <= x2;
dcoo += deltay, dcol += deltac, x1++) {
if(dcoo > 0) {dcoo -= deltax; y1 += addcoo;};
while(dcol > 0) {dcol -= deltax; c1 += addcol;};
/* vidíte ten rozdíl if/while? */
putpixel(x1, y1, c1);
};
} else {
/* Řídící proměnná Y */
if(y1 > y2) { /* Jestli jsme v opačném směru */
y1 ^= y2; y2 ^= y1; y1 ^= y2; /* Stejné prohození */
x1 ^= x2; x2 ^= x1; x1 ^= x2;
c1 ^= c2; c2 ^= c1; c1 ^= c2;
};
addcoo = (x2 > x1) ? 1 : -1;
addcol = (c2 > c1) ? 1 : -1;
for(dcoo = -(deltay >> 1), dcol = -(deltay >> 1); y1 <= y2;
dcoo += deltax, dcol += deltac, y1++) {
if(dcoo > 0) {dcoo -= deltay; x1 += addcoo;};
while(dcol > 0) {dcol -= deltay; c1 += addcol;};
putpixel(x1, y1, c1);
};
};
}
Poznámka ke zdrojákům: Možná tam můžou bejt překlepy nebo dokonce
chyby. Jestli jo, tak mě opravte.
Poznámka k poznámce: S hláškama typu: "Není to zoptimalizovaný" a
"Je to prasárna" na mě nechoďte. Zoptimalizovaný to není a prasárna
to je.
Poznámka pro pascalisty: Nemám rád pascal, ale protože znám lidi, co
nic jiného neumí, tady je pascalský zdroják. (Jenom ten první. Ten
druhý je skoro stejný, tak doufám, že ho všichni pochopí.)
- Bulb -
výheň