Baixe o app para aproveitar ainda mais
Prévia do material em texto
Functional Images Fun of Programming Conal Elliott Rodrigo Bonifa´cio 7 de maio de 2013 Uma biblioteca Haskell que explora uma noc¸a˜o simples de imagens como func¸o˜es. Destacando: I func¸o˜es de alta ordem I polimorfismo parametrizado I embedded DSLs Uma biblioteca Haskell que explora uma noc¸a˜o simples de imagens como func¸o˜es. Destacando: I func¸o˜es de alta ordem I polimorfismo parametrizado I embedded DSLs Como representar uma imagem em Haskell? I type Imagem = Ponto -> Cor I type Imagem a = Ponto -> a Com isso, podemos definir um tipo Regiao que correspondem imagens booleanas: type Regiao = Imagem Bool Como representar uma imagem em Haskell? I type Imagem = Ponto -> Cor I type Imagem a = Ponto -> a Com isso, podemos definir um tipo Regiao que correspondem imagens booleanas: type Regiao = Imagem Bool Como representar uma imagem em Haskell? I type Imagem = Ponto -> Cor I type Imagem a = Ponto -> a Com isso, podemos definir um tipo Regiao que correspondem imagens booleanas: type Regiao = Imagem Bool Como representar uma imagem em Haskell? I type Imagem = Ponto -> Cor I type Imagem a = Ponto -> a Com isso, podemos definir um tipo Regiao que correspondem imagens booleanas: type Regiao = Imagem Bool Exemplo 01: stripe type Imagem a = Ponto -> a type Region = Imagem Bool stripe :: Region stripe = \(x,y) -> abs x < 10 I mas temos que varrer todos os pontos da imagem; e I imprimir apenas os pontos que satisfazem ao predicado stripe type Imagem a = Ponto -> a type Region = Imagem Bool stripe :: Region stripe = \(x,y) -> abs x < 10 I mas temos que varrer todos os pontos da imagem ; e I imprimir apenas os pontos que satisfazem ao predicado stripe type Imagem a = Ponto -> a type Region = Imagem Bool stripe :: Region stripe = \(x,y) -> abs x < 10 I mas temos que varrer todos os pontos da imagem; e I imprimir apenas os pontos que satisfazem ao predicado stripe . . . fa´cil, temos a noc¸a˜o de fuc¸o˜es de alta ordem pontos :: [Ponto] pontos = [(x,y) | x <- [-(intToFloat xWin) / 2.0 .. (intToFloat xWin) / 2.0] , y <- [-(intToFloat yWin) / 2.0 .. (intToFloat yWin) / 2.0] ] main = let ps = filter stripe pontos in runGraphics ( do w <- openWindow "SOE" (xWin, yWin) sequence_ (map (\p -> drawInWindow w (withColor White (desenhaP p))) ps) spaceClose w ) Exemplo 02: tabuleiro de xadrez quadrante :: Ponto -> Float -> (Int, Int) quadrante (x, y) s = (round (x / s), round (y / s)) xadrez :: Float -> Region xadrez s = \(x,y) -> let (x1, y1) = quadrante (x, y) s in even (x1 + y1) Exemplo 03: c´ıculos alternados distO :: Ponto -> Int distO (x, y) = round $ sqrt (x*x + y * y) circulosAlternados :: Int -> Region circulosAlternados r = \p -> even $ (distO p) ‘div‘ r Em algumas situac¸o˜es, e´ conveniente definir imagens usando coordenadas polares (⇢, ✓), onde ⇢ e´ a distaˆncia de um ponto p para a origem e ✓ o aˆngulo entre o eixo X e o raio que passa pela origem e o ponto p Em algumas situac¸o˜es, e´ conveniente definir imagens usando coordenadas polares (⇢, ✓), onde ⇢ e´ a distaˆncia de um ponto p para a origem e ✓ o aˆngulo entre o eixo X e o raio que passa pela origem e o ponto p distO :: Ponto -> Float distO (x, y) = sqrt (x*x + y * y) fromPolar :: PontoPolar -> Ponto fromPolar (d, a) = (d * cos a, d * sin a) toPolar :: Ponto -> PontoPolar toPolar p@(x,y) = (distO p, atan (y/x)) polarCirculosAlternados :: Float -> Region polarCirculosAlternados r = (xadrez r) . toPolar Imagens coloridas type Imagem a = Ponto -> a type Region = Imagem Bool type ImagemColorida = Imagem (SOE.Color) xadrezC :: Float -- dimensao -> SOE.Color -- cor par -> SOE.Color -- cor impar -> ImagemColorida xadrezC s c1 c2 = \(x, y) -> if xadrez s (x,y) then c1 else c2 Hypocycloids (1/2) Hypocycloids (2/2) hypocycloid :: Float -> Float -> Region hypocycloid r k = \(x,y) -> (round x, round y) ‘elem‘ (map (\(a,b) -> (round a, round b)) hps) where hps = [(hpx t, hpy t) | t <- [0, 0.3..360.0]] hpx t = r * (k-1) * (cos t) + r * (cos ((k-1) * t)) hpy t = r * (k-1) * (sin t) - r * (sin ((k-1) * t)) A func¸a˜o hypocycloid e´ bastante custosa. Alternativa mais eficiente type ImagemPS = Imagem [Ponto] hypocycloid2 :: Float -> Float -> ImagemPS hypocycloid2 r k = \_ -> hps where hps = [(hpx t, hpy t) | t <- [0, 0.3..360.0]] hpx t = r * (k-1) * (cos t) + r * (cos ((k-1) * t)) hpy t = r * (k-1) * (sin t) - r * (sin ((k-1) * t)) Continuamos na pro´xima aula . . . I Mas podemos implementar uma func¸a˜o perimetro para figuras geome´tricas. Sendo um excelente exerc´ıcio para brincarmos com lazy evaluation. Continuamos na pro´xima aula . . . I Mas podemos implementar uma func¸a˜o perimetro para figuras geome´tricas. Sendo um excelente exerc´ıcio para brincarmos com lazy evaluation. Continuamos na pro´xima aula . . . I Mas podemos implementar uma func¸a˜o perimetro para figuras geome´tricas. Sendo um excelente exerc´ıcio para brincarmos com lazy evaluation. module Perimetro where import FiguraGeometrica perimetro :: FiguraGeometrica -> Float perimetro (Retangulo b a) = 2 * (b + a) perimetro (TrianguloRetangulo b a) = b + a + sqrt (sqr b + sqr a) perimetro (Poligono ps) = foldl (+) 0 (lados ps) perimetro (Elipse r1 r2) = lados :: [Ponto] -> [Float] lados (p1:p2:ps) = (distancia p1 p2) : (lados (p2:ps)) lados _ = [] O desafio e´ o ca´lculo do per´ımetro de uma elipse. e = p r21 � r22 r1 (1) s1 = 1 4 e2 (2) si = si�1 (2i � 1)(2i � 3) 4i2 e2, i � 2 (3) p = 2r1⇡(1� inftyX i=1 si ) (4) O desafio e´ o ca´lculo do per´ımetro de uma elipse. e = p r21 � r22 r1 (1) s1 = 1 4 e2 (2) si = si�1 (2i � 1)(2i � 3) 4i2 e2, i � 2 (3) p = 2r1⇡(1� inftyX i=1 si ) (4) Soluc¸a˜o usando as seguintes funcoes: e r1 r2 = sqrt (sqr r1 - sqr r2) / (max r1 r2) serieInfinita f b i = [f v | v <- [b, (b + i) ..]]
Compartilhar