Raszteres grafika

Egyenes rajzolása

Kör rajzolása

Ellipszis rajzolása

Raszteres grafika


Feladat:
grafikai primitíveket (pl. vonalat, síkidomot) ábrázolni kép-mátrixszal
meghatározni azokat a képpontokat, amelyek a primitív pontjai, vagy közel vannak a primitívhez
modell:







képpont (= körlap), amely a négyzetháló csúcspontjaiban helyezhető el
koordináták: egész számok

      
Vissza a lap tetejére

Egyenes rajzolása:


Tfh.: "vékony" egyenes y = mx + B

meredeksége: 0 < m < 1
(m = 0,1,... triviális speciális esetek)
más esetekben 0 < m < 1 -re visszavezetjük



legyen: x0 < x1 , y0 < y1



1. Alap inkrementális algoritmus

haladjunk balról jobbra x = 1 növekménnyel, válasszuk a legközelebbi képpontot:
(xi, [yi+0.5]) = (xi, [mxi+B+0.5])

a szorzás kiküszöbölhető inkrementálással:
yi+1 = mxi+1+B = m(xi+x)+B = yi+mx = yi+m


Algoritmus:
(ha |m|>1, akkor x-et cseréljük y-nal)

procedure Line(
     x0,y0,
     x1,y1,
     value : integer);
var
     x : integer;
     dy,dx,y,m : real;
begin
     dy := y1-y0;
     dx := x1-x0;
     m := dy/dx;
     y := y0;
     for x := x0 to x1 do
       begin
         WritePixel (x, Round(y), value);
         y := y+m 
       end
     end; {Line}


2. Felezőpont algoritmus egyenesre

egész aritmetika elegendő (Bresenham)



elv:
azt a képpontot válasszuk NE és E közül, amelyik közelebb van a Q metszésponthoz, azaz, hogy Q az M felezéspont melyik oldalán van, az döntsön a választásban.

tfh.: x0< x1 , y0< y1

legyen F(x,y) = ax+by+c = 0
dx = x1-x0
dy = y1-y0
F(x,y) = dy·x-dx·y+B·dx = 0

  > 0, ha (x,y) az egyenes alatt van,
F(x,y) = 0, ha (x,y) az egyenesen van,
  < 0, ha (x,y) az egyenes fölött van.

felezőpont kritérium:
              választás:
  > 0, ha M alul, NE
d = F(M) = F(xp+1,yp+1/2) = 0, ha M rajta, NE vagy E
(d : döntési változó) < 0, ha M fölül E

következő pontnál:
ha E-t választottuk, akkor
        E = dúj-drégi = F(xp+2,yp+1/2)-F(xp+1,yp+1/2) = dy,
ha NE-t választottuk, akkor
        NE = F(xp+2,yp+3/2)-F(xp+1,yp+1/2) = dy-dx.
kezdés:
        dstart = F(x0+1,y0+1/2) = F(x0,y0)+dy-dx/2 = dy = dx/2
azért, hogy egész aritmetikával számolhassunk, használjuk inkább az
        F(x,y) = 2·(dy·x-dx·y+B·dx) = 0
függvényt.

procedure MidpointLine(x0,y0,x1,y1,value : integer);
var
    dx,dy,incrE,incrNE,d,x,y : integer;
begin
    dx := x1-x0;
    dy := y1-y0;
    d := 2*dy-dx;
    incrE := 2*dy;
    incrNE := 2*(dy-dx);
    x := x0;
    y := y0;
    WritePixel(x,y,value);
    while x < x1 do
      begin
        if d <= 0 then
           begin
             d := d + incrE;
             x := x + 1
           end
        else
           begin
             d := d + incrNE;
             x := x + 1;
             y := y + 1
           end;
        WritePixel(x,y,value)
      end {while}
end; {MidpointLine}

eredmény: pl.









tulajdonságok:

- csak összeadás és kivonás
- általánosítható körre, ellipszisre


Problémák:
1. Különböző pontsorozat lesz az eredmény ha balról jobbra, vagy ha jobbról balra haladunk.

    legyen a választás:
        balról jobbra: d = 0 E-t választani
        jobbról balra: d = 0 SW-t választani
(megjegyzés: nem mindig lehet csak balról jobbra haladva rajzolni az egyeneseket - pl. szaggatott vonallal rajzolt zárt poligon)

2. A vonal pontjainak a sűrűsége függ a meredekségétől

megoldás:
intenzitás változtatása
kitöltött téglalapnak tekinteni az egyenest



Vissza a lap tetejére

Kör rajzolása:


x2+y2 = R2                 R : egész

1.
elég egy kör-negyedet megrajzolni (a többi rész a szimmetria alapján transzformációkkal - pl. tükrözés - előáll)

x   0-tól R-ig növekszik,
y =

drága eljárás (szorzás, gyökvonás),
nem egyenletes

2. polárkoordinátás alak
x = R·cos                    0°-tól 90°-ig növekszik
y = R·sin

drága eljárás (sin, cos)

Elég egy nyolcad kört kiszámítani:


procedure Circlepoints(x,y,value: integer);
begin
  WritePixel (x, y, value);
  WritePixel (y, x, value);
  WritePixel (y, -x, value);
  WritePixel (x, -y, value);
  WritePixel (-x, -y, value);
  WritePixel (-y, -x, value);
  WritePixel (-y, x, value);
  WritePixel (-x, y, value);
end; {CirclePoints}

3. Felezőpont algoritmus körre
x     0-tól     R/-ig

elv:
azt a pontot választjuk E és SE közül, amelyikhez a körív metszéspontja közelebb van

  > 0, ha (x,y) kívül van,
F(x,y) = x2+y2-R2 = 0, ha (x,y) rajta van,
  < 0, ha (x,y) belül van.

  > 0 SE-t választani
d = F(M) = F(xp+1, yp-1/2) = 0 SE vagy E
  < 0 E-t választani

dúj = F(xp+2, yp- 3/2)   SE = 2xp-2yp+5
       
dúj = F(xp+2, yp-1/2)   E = 2xp+3

tehát az iterációs lépések:
1. a döntési változó előjele alapján kiválasztjuk a következő képpontot
2. d = d + (a választástól függően) SE vagy E
kezdés:
kezdőpont: (0,R)
felezőpont: (1,R-1/2)
d = F(1,R-1/2) = 5/4 -R

procedure MidpointCircle (radius, value : integer);
var
    x, y : integer; d: real;
begin
    x := 0;
    y := radius;
    d := 5/4-radius;
    CirclePoints (x,y,value);

    while y>x do
      begin
        if d<0 then
          begin
            d := d+2*x+3;
            x := x+1
          end
        else
          begin
            d := d+2*(x-y)+5;
            x := x+1;
            y := y-1
          end;
        CirclePoints (x,y,value)
      end {while}
end; {MidpointCircle}


nem egész aritmetika, ezért legyen h új döntési változó:
h = d-1/4                 h+1/4 = d < 0
                               h < -1/4

ekkor kezdéskor
                                                           h = 1-R
igaz, hogy d < 0 helyett h < 1/4-et kellene vizsgálni, de ez ekvivalens h < 0-val,
tehát egész aritmetika használható: (a sugár is egész)

procedure MidpointCircle (radius, value : integer);
var
   x,y,d : integer;
begin
   x := 0;
   y := radius;
   d := 1-radius;
   CirclePoints (x,y,value);

   while y>x do
     begin
       if d<0 then
         begin
           d := d+2*x+3;
           x := x+1
         end
       else
         begin
           d := d+2*(x-y)+5;
           x := x+1;
           y := y-1
         end;
       CirclePoints (x,y,value)
     end {while}
end; {MidpointCircle}


4. Másodrendű differenciák
stratégia:
egy függvény értéke becsülhető két pontban felvett értékei különbségét használva
(ami polinomok esetében alacsonyabb fokszámú lesz).
használjunk első- és másodrendű parciális differenciákat

tudjuk, hogy
E(xp,yp) = 2·xp+3
SE(xp,yp) = 2·xp-2·yp+5,
akkor, ha E-t választottuk (xp,yp) (xp+1,yp), akkor
E új-E régi = 2,   SE új-SE régi = 2;
           ha SE-t választottuk (xp,yp) (xp+1,yp-1)
E új-E régi = 2,   SE új-SE régi = 4.
tehát az iterációs lépések:
1) d előjele alapján a következő képpont kiválasztása
2) d = d+ (a választástól függően E vagy SE)
3) E és SE módosítása (a választástól függően)

procedure MidpointCircle (radius,value : integer);
var
   x,y,d,deltaE,deltaSE : integer;
begin
   x := 0;
   y := radius;
   d := 1-radius;
   deltaE := 3;
   deltaSE := -2*radius+5;
   CirclePoints(x,y,value);

   while y>x do
     begin
       if d<0 then
         begin
           d := d+deltaE;
           deltaE := deltaE+2;
           deltaSE := deltaSE+2;
           x := x+1
         end
       else
         begin
           d := d+deltaSE;
           deltaE := deltaE+2;
           deltaSE := deltaSE+4;
           x := x+1;
           y := y-1
         end;
       CirclePoints(x,y,value)
     end {while}
end; {MidpointCircle}




Vissza a lap tetejére

Ellipszis rajzolása


   a,b egész
                              F(x,y) = b2x2 + a2y2 - a2b2 = 0

szimmetria miatt: elég az első síknegyedben megrajzolni

DaSilva algoritmusa (felezőpont módszer)
bontsuk a negyedet két tartományra:

1. tartománynak vége, ha
      a2(yp-1/2) b2(xp+1)

1. tartományban:
  0 SE-t választjuk  
d1 = F(xp+1,yp-1/2)  
  < 0 E-t választjuk

  drégi = F(xp+1,yp-1/2),  dúj = F(xp+2,yp-3/2)  
 
  drégi = F(xp+1,yp-1/2),  dúj = F(xp+2,yp-1/2)

  SE = b2(2xp+3) + a2(-2yp+2)
 
  E = b2(2xp+3)
2. tartományban:


megoldása házi feladat otthon


kezdés:
kezdőpont:  (0,b)
felezőpont: (1,b-1/2)
d = F(1,b-1/2) = b2+a2(-b+1/4)


procedure MidpointEllipse (a,b,value : integer);
var
   x,y: integer; d1,d2: real;
begin
   x := 0;
   y := b;
   d1 := b2-a2b+a2/4;
   EllipsePoints (x,y,value);

   while (a2(y-1/2) > b2(x+1)) do
     begin
       if d1<0 then
         begin
           d1 := d1+b2(2x+3);
           x := x+1
         end
       else
         begin
           d1 := d1+b2(2x+3)+a2(-2y+2);
           x := x+1;
           y := y-1
         end
       EllipsePoints (x,y,value)
     end; {Region1}

   d2 := b2(x+1/2)2+a2(y-1)2-a2b2;
   while (y>0) do
     begin
       if d2<0 then
         begin
           d2 := d2+b2(2x+2)+a2(-2y+3);
           x := x+1;
           y := y-1
         end
       else
         begin
           d2 := d2+a2(-2y+3);
           y := y-1
         end;
       EllipsePoints (x,y,value)
     end {Region2}

end; {MidpointEllipse}


Vissza a lap tetejére