funkcionalno programiranje

30
Funkcionalno programiranje Rad sa grafičkim elementima - nastavak

Upload: kendra

Post on 08-Jan-2016

73 views

Category:

Documents


4 download

DESCRIPTION

Funkcionalno programiranje. Rad sa grafi čkim elementima - nastavak. Zadaci. Nacrtati prikazanu sliku. Napisati funkciju perimeter:: Shape->Float koja ra čuna obim oblika tipa Shape. Tip podataka Region. data Region = Shape Shape -- primitive shape - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Funkcionalno programiranje

Funkcionalno programiranje

Rad sa grafičkim elementima - nastavak

Page 2: Funkcionalno programiranje

Zadaci

Nacrtati prikazanu sliku. Napisati funkciju perimeter:: Shape->Float

koja računa obim oblika tipa Shape.

Page 3: Funkcionalno programiranje

Tip podataka Region

data Region = Shape Shape -- primitive shape | Translate Vector Region -- translated region | Scale Vector Region -- scaled region | Complement Region -- inverse of region | Region `Union` Region -- union of regions | Region `Intersect` Region -- intersection of

regions | Empty deriving Show

type Vector = (Float, Float)

Page 4: Funkcionalno programiranje

Funkcija contains

containsR :: Region -> Vertex -> Bool

containsS :: Shape -> Vertex -> Bool

Page 5: Funkcionalno programiranje

Contains: pravougaonik

Rectangle s1 s2 `containsS` (x,y)= let t1 = s1/2 t2 = s2/2 in -t1<=x && x<=t1 && -t2<=y && y<=t2

s1

s2t1 t2

Page 6: Funkcionalno programiranje

Contains: elipsa

Ellipse r1 r2 `containsS` (x,y) = (x/r1)^2 + (y/r2)^2 <= 1

r1

r2

Page 7: Funkcionalno programiranje

Contains: poligon

a = (ax,ay)

b = (bx,by)Za vektor čija je početna tačka aa krajnja b, tačka p leži levo od vektorakada:

isLeftOf :: Coordinate -> Ray -> Bool(px,py) `isLeftOf` ((ax,ay),(bx,by)) = let (s,t) = (px-ax, py-ay) (u,v) = (px-bx, py-by) in s*v >= t*utype Ray = (Coordinate, Coordinate)

p = (px,py)

Page 8: Funkcionalno programiranje

Contains: poligon

Tačka p je unutar (konveksnog) poligona ako je svakoj njegovoj stranici sa leve strane, pri čemu su stranice usmerene u smeru suprotnom od kazaljke na satu.

p

Polygon pts `containsS` p

= let shiftpts = tail pts ++ [head pts]

leftOfList = map isLeftOfp (zip pts shiftpts)

isLeftOfp p' = isLeftOf p p'

in and leftOfList

Page 9: Funkcionalno programiranje

Contains: pravougli trougao

RtTriangle s1 s2 `containsS` p = Polygon [(0,0),(s1,0),(0,s2)] `containsS` p

s1(0,0)

(0,s2)

(s1,0)

s2

Page 10: Funkcionalno programiranje

Zadatak

Koristeći definisanu funkciju containsS, definisati funkciju

containsR :: Region -> Vertex -> Bool

Page 11: Funkcionalno programiranje

Primer

Regions.hs

Page 12: Funkcionalno programiranje

Tip podataka Picture

data Picture = Region Color Region | Picture `Over` Picture | EmptyPic

deriving Show

Page 13: Funkcionalno programiranje

G.Region

Tip podataka G.Region je dvodimenzioni niz (bit-map) koji čuva binarnu vrednost za svaki od piksela

Page 14: Funkcionalno programiranje

Bitmap operatori

Postoje ugrađene funkcije za kombinovanje bitmap slika. Na primer, za uniju:

+ =

Ove funkcije su brze ali zahtevaju dosta prostora

Page 15: Funkcionalno programiranje

G.Region Interface

createRectangle :: Point -> Point -> IO G.Region createEllipse :: Point -> Point -> IO G.Region createPolygon :: [Point] -> IO G.Region

andRegion :: G.Region -> G.Region -> IO G.Region orRegion :: G.Region -> G.Region -> IO G.Region xorRegion :: G.Region -> G.Region -> IO G.Region diffRegion :: G.Region -> G.Region -> IO G.Region deleteRegion :: G.Region -> IO ()

drawRegion :: G.Region -> Graphic

Funkcije definisane u Graphics.SOE biblioteci.

Page 16: Funkcionalno programiranje

Crtanje G.Region-a

drawRegionInWindow :: Window -> Color -> Region -> IO ()

drawRegionInWindow w c r = drawInWindow w (withColor c (drawRegion (regionToGRegion r)))

Page 17: Funkcionalno programiranje

Crtanje Picture-sa

drawPic :: Window -> Picture -> IO ()

drawPic w (Region c r) = drawRegionInWindow w c rdrawPic w (p1 `Over` p2) = do drawPic w p2 drawPic w p1drawPic w EmptyPic = return ()

Page 18: Funkcionalno programiranje

Region -> G.Region

Pokušajmo najpre sa manjim problemom: suzimo tipove Region i Shape:

data Region = Shape Shape | Scale Vector Region

data Shape = Rectangle x ydata NewRegion = Rect Side Side -- abstracts

G.Region

Page 19: Funkcionalno programiranje

Pojednostavljena verzija

regToNReg :: Region -> NewRegion---------------------------------------------------regToNReg (Shape (Rectangle sx sy)) = Rect sx sy---------------------------------------------------regToNReg (Scale (x,y) r) = regToNReg (scaleReg (x,y) r) where scaleReg (x,y) (Shape (Rectangle sx sy)) = Shape (Rectangle (x*sx) (y*sy)) scaleReg (x,y) (Scale s r) = Scale s (scaleReg (x,y) r)

Page 20: Funkcionalno programiranje

Problem

Posmatrajmo

(Scale (x1,y1) (Scale (x2,y2) (Scale (x3,y3) ... (Shape (Rectangle

sx sy)) ... )))

Ako je skaliranje n nivoa duboko, koliko će se puta izvršiti regToNReg nad čitavim Region drvetom?

Page 21: Funkcionalno programiranje

Sličan problem

Kod funkcije reverse:

reverse [] = [] reverse (x:xs) = (reverse xs) ++ [x] where [] ++ zs = zs (y:ys) ++ zs = y : (ys ++ zs)

Uvođenjem parametra za akumulaciju:

reverse xs = revhelp xs [] where revhelp [] zs = zs revhelp (x:xs) zs = revhelp xs (x:zs)

Page 22: Funkcionalno programiranje

Sa akumulirajućim faktorom

regToNReg2 :: Region -> NewRegion

regToNReg2 r = rToNR (1,1) r where rToNR :: (Float,Float) -> Region -> NewRegion

rToNR (x1,y1) (Shape (Rectangle sx sy))

= Rect (x1*sx) (y1*sy) rToNR (x1,y1) (Scale (x2,y2) r) = rToNR (x1*x2,y1*y2) r

Page 23: Funkcionalno programiranje

Konačna verzija

regToGReg1 :: Vector -> Vector -> Region -> G.Region

regToGReg1 loc sca (Shape s) = shapeToGRegion loc sca s

regToGReg1 (x,y) sca (Translate (u,v) r) = regToGReg1 (x+u, y+v) sca rregToGReg1 loc (x,y) (Scale (u,v) r) = regToGReg1 loc (x*u, y*v) rregToGReg1 loc sca Empty = createRectangle (0,0)

(0,0)regToGReg1 loc sca (r1 `Union` r2) = let gr1 = regToGReg1 loc sca r1 gr2 = regToGReg1 loc sca r2 in orRegion gr1 gr2

Page 24: Funkcionalno programiranje

Apstrakcija

primGReg loc sca r1 r2 op

= let gr1 = regToGReg loc sca r1

gr2 = regToGReg loc sca r2

in op gr1 gr2

Ovaj šablon će nam se javljati i kod unije i kod preseka pa je zato pogodno izdvojiti ga

Page 25: Funkcionalno programiranje

Konačna verzija sa izmenama

regToGReg :: Vector -> Vector -> Region -> G.RegionregToGReg (loc@(x,y)) (sca@(a,b)) shape = case shape of Shape s -> shapeToGRegion loc sca s Translate (u,v) r -> regToGReg (x+u, y+v) sca r Scale (u,v) r -> regToGReg loc (a*u, b*v) r Empty -> createRectangle (0,0) (0,0) r1 `Union` r2 -> primGReg loc sca r1 r2 orRegion r1 `Intersect` r2 -> primGReg loc sca r1 r2 andRegion Complement r -> primGReg loc sca winRect r

diffRegion where winRect :: Region winRect = Shape (Rectangle (pixelToInch xWin) (pixelToInch yWin))regionToGRegion :: Region -> G.RegionregionToGRegion r = regToGReg (0,0) (1,1) r

Page 26: Funkcionalno programiranje

Shape to G.Region: Rectangle

shapeToGRegion

:: Vector -> Vector -> Shape -> IO G.Region

shapeToGRegion (lx,ly) (sx,sy) (Rectangle s1 s2)

= createRectangle (trans(-s1/2,-s2/2)) (trans (s1/2,s2/2))

where trans (x,y) = ( xWin2 + inchToPixel (lx+x*sx),

yWin2 - inchToPixel (ly+y*sy) )

( xWin2, yWin2)

( xWin, yWin )

s1

s2s1/2

S2/2

Page 27: Funkcionalno programiranje

Ellipse

shapeToGRegion1 (lx,ly) (sx,sy) (Ellipse r1 r2) = createEllipse (trans (-r1,-r2)) (trans ( r1, r2)) where trans (x,y) = ( xWin2 + inchToPixel (lx+x*sx), yWin2 - inchToPixel (ly+y*sy) )

r1r2

Page 28: Funkcionalno programiranje

Polygon and RtTriangle

shapeToGRegion1 (lx,ly) (sx,sy) (Polygon pts) = createPolygon (map trans pts) where trans (x,y) = ( xWin2 + inchToPixel (lx+x*sx), yWin2 - inchToPixel (ly+y*sy) )------------------------------------------------------------------

shapeToGRegion1 (lx,ly) (sx,sy) (RtTriangle s1 s2) = createPolygon (map trans [(0,0),(s1,0),(0,s2)]) where trans (x,y) =

( xWin2 + inchToPixel (lx+x*sx), yWin2 - inchToPixel (ly+y*sy) )

Page 29: Funkcionalno programiranje

Konačna verzija

shapeToGRegion (lx,ly) (sx,sy) s = case s of Rectangle s1 s -> createRectangle (trans (-s1/2,-s2/2)) (trans( s1/2, s2/2))

Ellipse r1 r2 -> createEllipse (trans (-r1,-r2)) (trans ( r1, r2))

Polygon pts -> createPolygon (map trans pts)

RtTriangle s1 s2 -> createPolygon (map trans [(0,0),(s1,0),(0,s2)])

where trans (x,y) = ( xWin2 + inchToPixel (lx+x*sx), yWin2 - inchToPixel (ly+y*sy) )

Page 30: Funkcionalno programiranje

Primer

picture.hs