l conjunto de Mandelbrot, investigado por Beniot Mandelbrot cuando estudia la transición hacia el caos en los sistemas clásicos, es uno de los más conocidos ejemplos de fractales (estructura que se autoreplica en todas las escalas)
Se trata de una sencilla serie iterativa, aplicada en el plano complejo y que se define de esta forma:
Zn+1 = Zn2 + C
con
Z0 = 0
Se suele representar el resultado de la evolución para los valores de distintos valores de C: para los valores para los que $|Z_n| > 2$ la serie diverge y para los restantes se seuele representar con un color más claro cuánto mas tarda (el n) en empezar a diverger, o en blanco si no diverge.
Al representarlo gráfiamente nos encontramos con una figura muchísimo más compleja de lo que podíamos imaginar:
La sorpresa es aún mayor si ampliamos determinadas zonas y nos encontramos ¡pequeñas copia del conjunto de Mandelbrot completo!
Con este programa vas a poder navegar seleccionando con el ratón la zona que quieres ampliar.
- Puslando la tecla «s» se guardan las coordenadas actuales (todavía no se pueden cargar….)
- Pulsando la tecla «i» se guardar la imagen actual
import pygame import time width = 1600//2 height = 1200//2 max_iteracion = 220 factor_color = 220 // max_iteracion ROJO = (255, 0, 0) x0Min = -2.1 y0Min = -1.2 x0Max = 0.8 y0Max = 1.2 stepX = 1 stepY = stepX def resetView(): global x0Min, y0Min, x0Max, y0Max x0Min = -2.1 y0Min = -1.2 x0Max = 0.8 y0Max = 1.2 def calculateFactors(): global fx0, fy0, x0Min, y0Min, x0Max, y0Max dx0 = x0Max - x0Min dy0 = y0Max - y0Min fx0 = dx0/width fy0 = dy0/height def iteraMandelbrot(x0,y0): x, y = 0, 0 iteracion = 0 while iteracion < max_iteracion and x*x + y*y < 4 : xnew = x*x - y*y + x0 y = 2*x*y + y0 x = xnew iteracion += 1 return iteracion def init(): global screen pygame.init() creaRangoColor() screen = pygame.display.set_mode((width,height)) pygame.display.set_caption("Mandelbrot Set") colores = []; def creaRangoColor(): for i in range(max_iteracion+1): colores.append(((max_iteracion -i)*factor_color, 0, i * factor_color)) def drawMandelbrot(i0=0,j0=0,stepI=1,stepJ=1,clear = False): global screen,fx0,fy0,x0Min,y0Min if clear: screen.fill((0,0,0)) for i in range(i0,width,stepI): for j in range(j0,height,stepJ): x0 = i*fx0 + x0Min y0 = j*fy0 + y0Min iteracion = iteraMandelbrot(x0,y0) color = iteracion * factor_color screen.set_at((i,j), (color,color,color)) #screen.set_at((i,j), colores[iteracion]) pygame.display.flip() def repintaZona(): global fractal calculateFactors() screen.fill((0,0,0)) drawMandelbrot() fractal = screen.copy() def refrescaPantalla(): screen.blit(fractal, (0,0)) pygame.display.flip() def main(): init() repintaZona() running = True bDrawRect = False rectangle_draging = False rectangle = pygame.Rect(0,0,0,0) while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: running = False elif event.key == pygame.K_s: # guardamos las coordenadas actuales fichero = 'coordenas'+time.strftime('%Y%m%d-%H%M%S')+'.txt' f = open(fichero,'wt') str = f'x0Min:{x0Min}\n' + f'y0Min:{y0Min}\n' + \ f'x0Max:{x0Max}\n' + f'y0Max:{y0Max}\n' f.write(str) f.close() print(f'Datos guardados en {fichero}') elif event.key == pygame.K_i: # guardamos la imagen a fichero fichero = 'imagen'+time.strftime('%Y%m%d-%H%M%S')+'.png' pygame.image.save(screen,fichero) print(f'Salvada imagen a {fichero}') elif event.key == pygame.K_r: # volvemos al zoom original resetView() repintaZona() elif event.type == pygame.MOUSEBUTTONDOWN: if event.button == 1: if rectangle_draging == False: rectangle.x,rectangle.y = event.pos rectangle_draging = True elif event.type == pygame.MOUSEBUTTONUP: if event.button == 1: rectangle_draging = False # calculamos el rectangulos en coordenadas de pantlla x1,y1 = event.pos rectangle.width = x1 - rectangle.x rectangle.height = y1 - rectangle.y # guardamos los valores antiguos x0MinOld, y0MinOld = x0Min,y0Min # calculamos la nuevas coordenadas a dibujar x0Min = rectangle.x * fx0 + x0MinOld y0Min = rectangle.y * fy0 + y0MinOld x0Max = (rectangle.x + rectangle.width) * fx0 + x0MinOld y0Max = (rectangle.y + rectangle.height) * fy0 + y0MinOld # repintamos repintaZona() refrescaPantalla() bDrawRect = False elif event.type == pygame.MOUSEMOTION: if rectangle_draging: bDrawRect = True x1,y1 = event.pos rectangle.width = x1 - rectangle.x rectangle.height = y1 - rectangle.y if bDrawRect: screen.blit(fractal, (0,0)) pygame.draw.rect(screen, ROJO, rectangle,width = 1) pygame.display.flip() pygame.quit() if __name__ == '__main__': main()