martes, 21 de julio de 2015

Planeta fractal

(es) Planeta fractal

(eo) Fraktalplanedo

Planeta fractal

http://dx.doi.org/10.13140/RG.2.2.34092.90243

Descripción artística:

Un mundo fractal.

Motivación:

Una revisión de las diferentes variantes conocidas de fractales de la familia Mándelbrot.

Descripción técnica:

Una vista de alta resolución de un conjunto fractal similar al de Mándelbrot, pero con ecuación recursiva z n+1 = exp ( z n 2 -1,00001 z n c 3 ) .
El conjunto de Mándelbrot es el conjunto M de todos los puntos c del plano complejo tal que la sucesión z n+1 = z n 2 +c (con z 0 =0+0i ) no diverge (es decir, tal que es acotada).
El criterio usado para determinar si las sucesiones divergen o no, es si z k , con kN , tiene un módulo mayor que 2, es decir | z k |2 (procedimiento estándar para los conjuntos de Julia y de Mándelbrot). Puesto que no puede evaluarse hasta el infinito, se usa una cota: N . Si la sucesión no “diverge” antes de llegar al N -ésimo término de las sucesiones, se considera que no diverge, es decir que es acotada.

Archivos

Código (Python):

#!/usr/bin/env python
# coding: utf-8

# Copyright 2015 Eduardo Adam Navas López
# Este programa es Software Libre liberado bajo la licencia GNU GPLv3 o su versión más reciente:
# http://www.gnu.org/licenses/gpl.html

"""Este programa genera una imagen en pantalla o en archivo, según
el valor de la variable global 'prueba'.
La imagen generada es una variante del conjunto de Mandelbrot
"""

import cmath
import pygame
#import escala
import datetime

prueba = True
#prueba = False #Hay que descomentar esta línea para una versión 'final'

if prueba:
 TAM = 200
else:
 TAM = 8000
ANCHO = TAM
ALTO  = TAM

MAXPASOS = 40

LIMITEMODULO = 2.0
LIMITEMODULO2 = 4.0

SUPERIOR_DER = (0.93, 0.93)
INFERIOR_IZQ = (-0.93,-0.93)

COLOR_ADENTRO = (255,255,255) 
COLOR_AFUERA = (0,0,0)
COLOR_AFUERA2 = (128,128,128)

ROJO   = (255,0,0)
VERDE  = (0,255,0)
AZUL   = (0,0,255)
BLANCO = (255,255,255)
NEGRO  = (0,0,0)

def mundo(z,c):
 "mundo"
 return cmath.exp((z**2-1.00001*z)/c**3)


def dibujar(lienzo):
 #Dibujar imagen:
 pantalla.fill(BLANCO)
 
 if prueba:
  porcentajes = [(x+1)/100.0 for x in range(99)]
 else:
  porcentajes = [(x+1)/500.0 for x in range(500)]
 porcentajes.reverse()

 print "Iniciando cálculo de puntos"
 print "0%"
 for y in xrange(ALTO):
  c_i = (INFERIOR_IZQ[1]-SUPERIOR_DER[1])*float(y)/ALTO + SUPERIOR_DER[1]
  for x in xrange(ANCHO):
   c_r = (SUPERIOR_DER[0]-INFERIOR_IZQ[0])*float(x)/ANCHO + INFERIOR_IZQ[0]
   
   c = c_r + c_i*1j

   z = 0+0j
   numPasos = 0
   while numPasos<MAXPASOS and (z.real*z.real+z.imag*z.imag)<LIMITEMODULO2:
    try:
     z= mundo(z,c)
    except OverflowError:
     break
    except ZeroDivisionError:
     break
    numPasos += 1
   if numPasos==MAXPASOS: #Sí converge
    lienzo.set_at((x,y),COLOR_ADENTRO)
   else:
    col = int(255*float(numPasos)/MAXPASOS)
    color = [col,col,col]
    color[numPasos%3]=255
    lienzo.set_at((x,y),tuple(color))

  #Para cantidades grandes de TAM...
  if len(porcentajes)>0 and float(y)/TAM>porcentajes[-1]:
   print "{:2}%".format(porcentajes.pop()*100)
 print "100%"

 #Actualizar o guardar:
 if prueba:
  pygame.display.flip()
 else:
  fin = datetime.datetime.today()
  nombrearchivo = "mundo-{:02}{:02}{:02}{:02}{:02}{:02}.png".format(fin.year, fin.month, fin.day, fin.hour, fin.minute, fin.second)
  pygame.image.save(pantalla, nombrearchivo)


if __name__ == "__main__":
 pygame.init()

 if prueba:
  pantalla = pygame.display.set_mode((ANCHO, ALTO))
  pygame.display.set_caption("Mundo")
 else:
  pantalla = pygame.Surface((ANCHO, ALTO))

 #e = escala.Escala((ANCHO, ALTO), INF_IZQ, SUP_DER)
 dibujar(pantalla)
 
 corriendo = True
 if prueba:
  while corriendo:
   for evento in pygame.event.get():
    if evento.type == pygame.QUIT:
     corriendo = False

No hay comentarios:

Publicar un comentario