| Inicial | Temas | Manuales | Ejercicios | Exámenes | Documentación

Tema 26: Programación de fractales en Haskell

Índice

1. Introducción

  • Un fractal es un objeto geométrico cuya estructura básica, fragmentada o irregular, se repite a diferentes escalas.
  • El término fue propuesto por el matemático Benoît Mandelbrot en 1975 y deriva del Latín fractus, que significa quebrado o fracturado.
  • Muchas estructuras naturales son de tipo fractal. Por ejemplo, el romanescu (un híbrido de brécol)
    Romanescu.jpg

2. Ejemplo simple: el fractal del árbol

  • El fractal árbol es
    Arbol_coloreado_6.png

2.1. Tronco de un árbol

  • Dibujo
    Tronco.png
  • Programa Tronco.hs

    import Graphics.Gloss
    
    main :: IO ()
    main = display (InWindow "Tronco de arbol" (700,800) (20,20)) black dibujo
    
    dibujo :: Picture
    dibujo = Color aquamarine (Translate 0 (-300) tronco)
    
    tronco :: Picture
    tronco = Polygon [(30,0), (15,300), (-15,300), (-30,0)]
    

2.2. Tronco de árbol con ramas

  • Dibujo
    TroncoConRama.png
  • Programa TroncoConRamas.hs

    import Graphics.Gloss
    
    main :: IO ()
    main = display (InWindow "Tronco y ramas" (700,800) (20,20)) black dibujo
    
    dibujo :: Picture
    dibujo = Color green (Translate 0 (-300) troncoConRamas)
    
    tronco :: Picture
    tronco = Polygon [(30,0), (15,300), (-15,300), (-30,0)]
    
    troncoConRamas :: Picture
    troncoConRamas =
      Pictures [ tronco,
                 Translate 0 300 rama,
                 Translate 0 240 (Rotate 20    rama),
                 Translate 0 180 (Rotate (-20) rama),
                 Translate 0 120 (Rotate 40    rama),
                 Translate 0  60 (Rotate (-40) rama)
               ]
      where rama = Scale 0.5 0.5 tronco
    

2.3. Construcción iterada de un árbol

  • Dibujo
    Arbol.png
  • Programa Arbol.hs

    import Graphics.Gloss
    
    main :: IO ()
    main = display (InWindow "Arbol" (700,800) (20,20)) black dibujo
    
    dibujo :: Picture
    dibujo = Color green (Translate 0 (-300) arbol)
    
    tronco :: Picture
    tronco = Polygon [(30,0), (15,300), (-15,300), (-30,0)]
    
    troncoConRamas :: Picture
    troncoConRamas =
      Pictures [ tronco,
                 Translate 0 300 rama,
                 Translate 0 240 (Rotate 20    rama),
                 Translate 0 180 (Rotate (-20) rama),
                 Translate 0 120 (Rotate 40    rama),
                 Translate 0  60 (Rotate (-40) rama)
               ]
      where rama = Scale 0.5 0.5 tronco
    
    arbol :: Picture
    arbol =
      Pictures [ tronco,
                 Translate 0 300 ramas,
                 Translate 0 240 (Rotate 20    ramas),
                 Translate 0 180 (Rotate (-20) ramas),
                 Translate 0 120 (Rotate 40    ramas),
                 Translate 0  60 (Rotate (-40) ramas)
               ]
      where ramas = Scale 0.5 0.5 troncoConRamas
    

2.4. Árbol como un fractal (recursión sobre el paso)

  • Objetivo: Definir una única función con un argumento (el paso) que pinte los siguientes dibujos.
    • Árbol fractal, paso 0
      Arbol_fractal_0.png
    • Árbol fractal, paso 1
      Arbol_fractal_1.png
    • Árbol fractal, paso 2
      Arbol_fractal_2.png
    • Árbol fractal, paso 3
      Arbol_fractal_3.png
    • Árbol fractal, paso 4
      Arbol_fractal_4.png
    • Árbol fractal, paso 5
      Arbol_fractal_5.png
    • Árbol fractal, paso 6
      Arbol_fractal_6.png
  • Programa ArbolFractal.hs

    import Graphics.Gloss
    import System.IO
    
    main :: IO ()
    main = do
      hSetBuffering stdout NoBuffering
      putStr "Árbol fractal.  Introduce el paso [0..6]: "
      paso <- readLn
      display (InWindow "Arbol fractal" (700,800) (20,20)) black (dibujo paso)
    
    dibujo :: Int -> Picture
    dibujo paso = Color green (Translate 0 (-300) (arbol paso))
    
    tronco :: Picture
    tronco = Polygon [(30,0), (15,300), (-15,300), (-30,0)]
    
    arbol :: Int -> Picture
    arbol 0 = tronco
    arbol n = Pictures [tronco,
                        Translate 0 300 menor,
                        Translate 0 240 (Rotate 20    menor),
                        Translate 0 180 (Rotate (-20) menor),
                        Translate 0 120 (Rotate 40    menor),
                        Translate 0  60 (Rotate (-40) menor) ]
        where menor = Scale 0.5 0.5 (arbol (n-1))
    

2.5. Árbol como un fractal coloreado (recursión sobre el paso y el color)

  • Objetivo: Definir una única función con un argumento (el paso) que pinte los siguientes dibujos.
    • Dibujo paso 0
      Arbol_fractal_coloreado_0.png
    • Dibujo paso 1
      Arbol_fractal_coloreado_1.png
    • Dibujo paso 2
      Arbol_fractal_coloreado_2.png
    • Dibujo paso 3
      Arbol_fractal_coloreado_3.png
    • Dibujo paso 4
      Arbol_fractal_coloreado_4.png
    • Dibujo paso 5
      Arbol_fractal_coloreado_5.png
    • Dibujo paso 6
      Arbol_fractal_coloreado_6.png
  • Programa ArbolFractalColoreado.hs

    import Graphics.Gloss
    import System.IO
    
    main :: IO ()
    main = do
      hSetBuffering stdout NoBuffering
      putStr "Árbol fractal.  Introduce el paso [0..6]: "
      paso <- readLn
      display (InWindow "Arbol fractal" (700,800) (20,20)) black (dibujo paso)
    
    dibujo :: Int -> Picture
    dibujo paso = Translate 0 (-300) (arbol paso marron)
    
    tronco :: Color -> Picture
    tronco color = Color color (Polygon [(30,0), (15,300), (-15,300), (-30,0)])
    
    arbol :: Int -> Color -> Picture
    arbol 0 color = tronco color
    arbol n color = Pictures [tronco color,
                              Translate 0 300 arbolMenor,
                              Translate 0 240 (Rotate   20  arbolMenor),
                              Translate 0 180 (Rotate (-20) arbolMenor),
                              Translate 0 120 (Rotate   40  arbolMenor),
                              Translate 0  60 (Rotate (-40) arbolMenor) ]
      where arbolMenor = Scale 0.5 0.5 (arbol (n-1) (masVerde color))
    
    marron :: Color
    marron = makeColorI 139 100  35 255
    
    -- (masVerde c) es el color obtenido mezclando los colores c y verde en
    -- las proporciones 1 y 0.1.
    masVerde :: Color -> Color
    masVerde color = mixColors 1.0 0.1 color green
    

3. Fractal de la curva de Koch

  • La curva de Koch es un fractal descrito por el matemático sueco Helge von Koch en 1904.
  • Construcción:
    • Se inicia con un segmento.
    • Se divide en tres partes iguales, se remplaza la parte central por dos partes de igual longitud haciendo un ángulo de 60 grados.
    • Luego, con los cuatro segmentos, se procede de la misma manera, lo que da lugar a 16 segmentos más pequeños en la segunda iteración.
    • Y así sucesivamente.
  • El paso es
    Curva_de_Koch_paso.png
  • Representación de los seis primeras pasos de la construcción.
    • Curva de Koch, paso 0
      Curva_de_Koch_0.png
    • Curva de Koch, paso 1
      Curva_de_Koch_1.png
    • Curva de Koch, paso 2
      Curva_de_Koch_2.png
    • Curva de Koch, paso 3
      Curva_de_Koch_3.png
    • Curva de Koch, paso 4
      Curva_de_Koch_4.png
    • Curva de Koch, paso 5
      Curva_de_Koch_5.png
    • Curva de Koch, paso 6
      Curva_de_Koch_6.png
  • Programa Curva_de_Koch.hs

    import Graphics.Gloss
    import System.IO
    
    main :: IO ()
    main = do
      hSetBuffering stdout NoBuffering
      putStr "Curva de Koch. Introduce el paso [0..6]: "
      paso <- readLn
      display (InWindow ("Curva de Koch - Paso " ++ show paso)
                        (500,500) (20,20)) black (dibujo paso)
    
    -- Longitud de los lados del triángulo inicial
    longitud = 360 :: Float
    
    dibujo :: Int -> Picture
    dibujo paso =
      Color aquamarine $                                  -- colorea
      Translate (-longitud/2) (-(longitud * sqrt 3)/6) $  -- centra el fractal
      curva paso
    
    curva :: Int -> Picture
    curva 0 = Line [(0, 0), (longitud, 0)]
    curva n =
      Pictures [nuevaCurva,
                Translate (longitud/3) 0                        (Rotate (-60) nuevaCurva),
                Translate (longitud/2) ((longitud * sqrt 3)/6)  (Rotate   60  nuevaCurva),
                Translate (2 * longitud/3) 0                    nuevaCurva ]
      where nuevaCurva = Scale (1/3) (1/3) (curva (n-1))
    

4. Fractal del copo de nieve de Koch

  • Construcción: Tres curvas de Koch unidas forman el copo de nieve de Koch.
  • Representación de los seis primeras pasos de la construcción.
    • Copo de nieve, paso 0
      Copo_de_nieve_0.png
    • Copo de nieve, paso 1
      Copo_de_nieve_1.png
    • Copo de nieve, paso 2
      Copo_de_nieve_2.png
    • Copo de nieve, paso 3
      Copo_de_nieve_3.png
    • Copo de nieve, paso 4
      Copo_de_nieve_4.png
    • Copo de nieve, paso 5
      Copo_de_nieve_5.png
    • Copo de nieve, paso 6
      Copo_de_nieve_6.png
  • Programa Copo_de_nieve_de_Koch.hs

    import Graphics.Gloss
    import System.IO
    
    main :: IO ()
    main = do
      hSetBuffering stdout NoBuffering
      putStr "Fractal copo de nieve. Introduce el paso [0..6]: "
      paso <- readLn
      display (InWindow "Fractal copo de nieve" (500,500) (20,20)) black (dibujo paso)
    
    -- Longitud de los lados del triángulo inicial
    longitud = 360 :: Float
    
    dibujo :: Int -> Picture
    dibujo paso =
      Color aquamarine $                                  -- colorea
      Translate (-longitud/2) ((longitud * sqrt 3)/6) $   -- centra el fractal
      copoDeNieve paso
    
    curva :: Int -> Picture
    curva 0 = Line [(0,0), (longitud, 0)]
    curva n =
      Pictures [nuevaCurva,
                Translate (longitud/3)     0                        (Rotate (-60) nuevaCurva),
                Translate (longitud/2)     ((longitud * sqrt 3)/6)  (Rotate   60  nuevaCurva),
                Translate (2 * longitud/3) 0                        nuevaCurva]
      where nuevaCurva = Scale (1/3) (1/3) (curva (n-1))
    
    copoDeNieve :: Int -> Picture
    copoDeNieve n =
      Pictures [unaCurva ,
                Translate longitud     0                          (Rotate   120  unaCurva),
                Translate (longitud/2) (-((longitud * sqrt 3)/2)) (Rotate (-120) unaCurva)]
      where unaCurva = curva n
    

5. Triángulo de Sierpinski

  • El triángulo de Sierpinski es un fractal que se puede construir a partir de un triángulo equilátero.
  • Construcción
    • El inicio es un triángulo equilátero.
    • A partir de los puntos medios de cada lado se construye un triángulo equilátero invertido de lado 1/2. Se recorta.
    • El proceso se repite con cada uno de los tres triángulos de lado 1/2 que quedan. Así que esta vez se recortan tres triángulos invertidos de lado 1/4.
    • Se repite el proceso.
  • El paso es
    Sierpinski_paso.png)
  • Representación de los seis primeras pasos de la construcción.
    • Sierpinski, paso 0
      Sierpinski_0.png
    • Sierpinski, paso 1
      Sierpinski_1.png
    • Sierpinski, paso 2
      Sierpinski_2.png
    • Sierpinski, paso 3
      Sierpinski_3.png
    • Sierpinski, paso 4
      Sierpinski_4.png
    • Sierpinski, paso 5
      Sierpinski_5.png
    • Sierpinski, paso 6
      Sierpinski_6.png
  • Programa Sierpinski.hs

    import Graphics.Gloss
    import System.IO
    
    main :: IO ()
    main = do
      hSetBuffering stdout NoBuffering
      putStr "Sierpinski. Introduce el paso [0..6]: "
      paso <- readLn
      display (InWindow ("Sierpinski - Paso " ++ show paso)
                        (500,500) (20,20)) black (dibujo paso)
    
    dibujo :: Int -> Picture
    dibujo paso = Color aquamarine (Translate (-150) (-125) (sierpinski paso))
    
    -- Longitud del lado inicial
    longitud = 300 :: Float
    
    sierpinski :: Int -> Picture
    sierpinski 0 =
      Polygon [(0,0),
               (longitud/2, longitud * sqrt 3 /2),
               (longitud, 0)]
    sierpinski n =
      Pictures [nuevoSierpinski,
                Translate (longitud/2) 0 nuevoSierpinski,
                Translate (longitud/4) (longitud * sqrt 3 /4) nuevoSierpinski]
      where nuevoSierpinski = Scale 0.5 0.5 (sierpinski (n-1))
    

6. Curva del dragón

  • La curva del dragón se puede construir plegando un papel como se muestra en el siguiente vídeo
  • Representación de los seis primeras pasos de la construcción.
    • Curva del dragón, paso 0
      Dragon_0.png
    • Curva del dragón, paso 1
      Dragon_1.png
    • Curva del dragón, paso 2
      Dragon_2.png
    • Curva del dragón, paso 3
      Dragon_3.png
    • Curva del dragón, paso 4
      Dragon_4.png
    • Curva del dragón, paso 5
      Dragon_5.png
    • Curva del dragón, paso 6
      Dragon_6.png
  • Se propone como ejercicio programar la curva del dragón.

7. Referencias


| Inicial | Temas | Manuales | Ejercicios | Exámenes | Documentación

José A. Alonso Jiménez

Sevilla, 07 de abril del 2024

Licencia: Creative Commons.