Tema 25: Programación de dibujos con Gloss

1 Introducción

2 Instalación de Gloss

> cabal update
> cabal install gloss

3 Representación de dibujos

type Point = (Float, Float)
type Path = [Point]

4 El TDA de los dibujos

4.1 Elementos básicos del TDA de los dibujos

data Picture = Line    Path
             | Polygon Path
             | Text    String

4.2 Ejemplo de líneas

import Graphics.Gloss
    
main :: IO ()
main = display (InWindow "Dibujo" (300,300) (20,20)) white cuadrado
    
cuadrado :: Picture 
cuadrado = Line [(72,72),(144,72),(144,144),(72,144),(72,72)]
> runhaskell lineas.hs

4.3 Ejemplo de poligono

import Graphics.Gloss
    
main :: IO ()
main = display (InWindow "Dibujo" (300,300) (20,20)) white cuadrado
    
cuadrado :: Picture 
cuadrado = Polygon [(72,72),(144,72),(144,144),(72,144),(72,72)]
> runhaskell poligono.hs

4.4 Ejemplo de texto

import Graphics.Gloss
    
main :: IO ()
main = display (InWindow "Dibujo" (800,300) (20,20)) white texto
    
texto :: Picture
texto = Text "Figura"
> runhaskell texto.hs

5 Ampliaciones del TDA de dibujos

5.1 Ampliación del TDA para incluir listas de dibujos

data Picture = ...
             | Pictures [Picture]
dibujo :: Picture
dibujo = Pictures [cuadrado1, cuadrado2]
    
cuadrado1 :: Picture
cuadrado1 = Line [(72,72),(144,72),(144,144),(72,144),(72,72)]
    
cuadrado2 :: Picture
cuadrado2 = Line [(0,0),(100,0),(100,100),(0,100),(0,0)]
> runhaskell dosCuadrados.hs

5.2 Ampliación del TDA para incluir transformaciones

data Picture = ...
             | Translate Float Float   Picture
             | Rotate    Float Picture
             | Scale     Float Float   Picture
+ `Translate` distancia-x distancia-y
+ `Rotate` grados en sentido horario alrededor del origen
+ `Scale` factor-x factor-y
Translate 0 200 (Rotate 20 (Scale 0.5 0.3 algo))
Translate 0 200 $ Rotate 20 $ Scale 0.5 0.3 algo
import Graphics.Gloss
    
main :: IO ()
main = display (InWindow "Dibujo" (300,300) (20,20)) white dibujo
    
dibujo :: Picture
dibujo = Pictures [cuadrado, titulo]
    
cuadrado :: Picture
cuadrado = Line [(72,72),(144,72),(144,144),(72,144),(72,72)]
    
titulo :: Picture
titulo = Rotate (-10) $
         Translate (-70) 0 $ 
         Scale 0.2 0.2 $ 
         Text "Un cuadrado"

genera

5.3 Ampliación del TDA para incluir colores

data Picture = ...
             | Color Color Picture
data Color = RGBA Float Float Float Float
import Graphics.Gloss
    
main :: IO ()
main = display (InWindow "Dibujo" (300,300) (20,20)) white dibujo
    
dibujo :: Picture
dibujo = Pictures [cuadrado2, cuadrado1]
    
cuadrado1 :: Picture
cuadrado1 = Color red $ Polygon [(72,72),(144,72),(144,144),(72,144),(72,72)]

genera

6 Capas de dibujos

Pictures [capa1, capa2, capa3, ...]
Pictures [cuadrado2, cuadrado1]

por eso se pintaba primero el verde y encima el rojo. Si se cambia el orden de las capas por

Pictures [cuadrado1, cuadrado2]

el dibujo que se obtiene es

7 Dibujos predefinidos en Graphics.Gloss.Data.Picture

7.1 Círculos

circle 100

genera

circleSolid 100

genera

thickCircle 100 30

genera

7.2 Arcos circulares

arc 0 90 100

genera

arcSolid 0 90 100

genera

thickArc 0 90 100 50

genera

sectorWire 0 90 100

genera

7.3 Bucles

lineLoop [(-123,-99),(15,17),(107,-73)]

genera

7.4 Rectángulos

ghci> rectanglePath 200 100
[(-100.0,-50.0),(-100.0,50.0),(100.0,50.0),(100.0,-50.0)]
rectangleWire 200 100

genera

rectangleSolid 200 100

genera

ghci> rectangleUpperPath 200 100
[(-100.0,0.0),(-100.0,100.0),(100.0,100.0),(100.0,0.0)]
rectangleUpperWire 200 100

genera

rectangleUpperSolid 200 100

genera

8 Dibujos con listas de comprensión

8.1 Círculos concéntricos

import Graphics.Gloss
    
main :: IO ()
main = display (InWindow "Dibujo" (300,300) (20,20)) white dibujo
    
dibujo :: Picture
dibujo = pictures [ circle x | x <- [10,20..100] ]

8.2 Círculos trasladados

import Graphics.Gloss
    
main :: IO ()
main = display (InWindow "Dibujo" (500,300) (20,20)) white dibujo
    
dibujo :: Picture
dibujo = pictures [translate x 0 (circle 80) | x <- [-100,-60..100]]

8.3 Circulos trasladados y ampliados

import Graphics.Gloss
    
main :: IO ()
main = display (InWindow "Dibujo" (500,300) (20,20)) white dibujo
    
dibujo :: Picture
dibujo = pictures [translate x 0 (circle x) | x <- [10,20..100]]

8.4 Rectángulos girados

import Graphics.Gloss
    
main :: IO ()
main = display (InWindow "Dibujo" (500,300) (20,20)) white dibujo
    
dibujo :: Picture
dibujo = pictures [rotate x (rectangleWire 200 200) | x <- [0,10..90]]

8.5 Rectángulos girados y trasladados

import Graphics.Gloss
    
main :: IO ()
main = display (InWindow "Dibujo" (500,300) (20,20)) white dibujo
    
dibujo :: Picture
dibujo = pictures [translate x 0 (rotate x (rectangleWire 200 200)) | 
                   x <- [-45,-35..45]]

8.6 Círculos en cuadrado

import Graphics.Gloss
    
main :: IO ()
main = display (InWindow "Dibujo" (500,300) (20,20)) white dibujo
    
dibujo :: Picture
dibujo = pictures [translate x y (circle 10) | 
                   x <- [-200,-100..200],
                   y <- [-200,-100..200]]

8.7 Círculos en estrella

import Graphics.Gloss
    
main :: IO ()
main = display (InWindow "Dibujo" (500,300) (20,20)) white dibujo
    
dibujo :: Picture
dibujo = pictures [rotate angulo (translate x 0 (circle 10))
                  | x      <- [50,100..200],
                    angulo <- [ 0, 45..360]]

8.8 Círculos expandiéndose

import Graphics.Gloss
    
main :: IO ()
main = display (InWindow "Dibujo" (500,300) (20,20)) white dibujo
    
dibujo :: Picture
dibujo = pictures [rotate angulo (translate (5*x) 0 (circle x))
                  | x      <- [10,20.. 40],
                    angulo <- [ 0,45..360]]

9 Gráficas de funciones

El programa para dibujar la siguiente parábola (y = x^2):

es parabola.hs

import Graphics.Gloss
    
main  :: IO ()
main  =  display (InWindow "y = x^2" (500,500) (20,20)) white dibujo
    
dibujo :: Picture 
dibujo = Color red (Translate 0 (-200) parabola)
    
parabola :: Picture
parabola = Line (map puntosParabola [-200, -190 .. 200]) 
    where puntosParabola x = (x, x^2/100)

10 Dibujos programados (diseño descendente)

10.1 Elefante

import Graphics.Gloss
        
main :: IO ()
main = display (InWindow "Dibujo" (500,300) (20,20)) white dibujo
    
dibujo :: Picture
dibujo = elefante
    
elefante = 
  pictures 
   [rotate 20 (scale 3 2 (translate 30 40 (circleSolid 25))),  -- cabeza
    translate 150 (-20) (rectangleSolid 40 80),                -- trompa
    translate (-10) 40 (scale 1.5 1 (circleSolid 80)),         -- cuerpo
    translate 50 (-50)(rectangleSolid 40 70),                  -- pata delantera
    translate (-60) (-50) (rectangleSolid 40 70),              -- pata trasera
    translate (-140) 50 (rotate (-100) (rectangleSolid 10 40)) -- cola
   ]

10.2 Plato de comida

import Graphics.Gloss
    
main :: IO ()
main = display (InWindow "Dibujo" (500,500) (20,20)) white dibujo
    
dibujo :: Picture
dibujo = plato_con_comida
    
plato_con_comida = 
  pictures [ mesa,
             plato,
             comida,
             translate ( 200) 0 tenedor,
             translate (-200) 0 cuchillo ]
    
mesa = color marron (rectangleSolid 500 500)
plato = 
  pictures [ color gris      (circleSolid 175),
             color grisClaro (circleSolid 150) ]
    
comida = 
  pictures [ translate (-50) ( 50) (rotate   45  zanahoria),
             translate (-20) (-40) (rotate   20  brocoli),
             translate ( 60) (-30) (rotate (-10) brocoli) ]
    
zanahoria = 
  color orange 
        (polygon [(-5,-40),(-20,40),(20,40),(5,-40) ])
    
brocoli = 
  color (dark green) 
        (pictures [ translate (  0) (-15) (rectangleSolid 30 50), -- base
                    translate (-15) (  0) (circleSolid 25),       -- flor
                    translate ( 15) (  0) (circleSolid 25),       -- flor
                    translate (  0) ( 15) (circleSolid 25)        -- flor
                  ])
    
tenedor = 
  color grisClaro 
        (pictures [rectangleSolid 10 250,                        -- mango
                   translate (  0) ( 80) (rectangleSolid 40 10), -- base
                   translate (-15) (100) (rectangleSolid 10 45), -- diente izquierdo
                   translate ( 15) (100) (rectangleSolid 10 45)  -- diente derecho
                  ])
    
cuchillo = 
  color grisClaro 
        (pictures [translate 0 (-25) (rectangleSolid 30 200),    -- mango
                   polygon [ (-15,  75),
                             ( -5, 105),
                             ( 15, 125),
                             ( 15,  75) ]                        -- hoja
                  ])
    
-- Algunos colores usados en el dibujo:
marron    = dark orange
grisClaro = dark white
gris      = dark grisClaro


Universidad de Sevilla

José A. Alonso Jiménez
Grupo de Lógica Computacional
Dpto. de Ciencias de la Computación e I.A.
Universidad de Sevilla