/** * fractalbiscuit * * Copyright (C) 2008 by Andy Balaam * * A snackish way to explore the Mandelbrot set. * * Released under the GNU General Public License * with ABSOLUTELY NO WARRANTY. * * See the file COPYING for more information. */ /* Hungarian notation: s - screen position (unzoomed) z - screen position (zoomed) c - co-ordinate on the complex plane */ int zSizeX = 500; int zSizeY = 500; int initial_zoom = 1; int num_iterations = 200; double min_re = -1.5; double max_re = 0.5; double min_im = -1; double max_im = 1; double prev_min_iterations = 200; int zoom = initial_zoom; int sSizeX; int sSizeY; double cur_min_iterations; double cWidth; double cHeight; double cCentreX; double cCentreY; double mult_x; double mult_y; int zDragX = 0; int zDragY = 0; int zZoomY = 0; boolean anything_changed = true; boolean drawing = false; void setup() { size( zSizeX, zSizeY ); loadPixels(); do_update_pixels( false ); } void draw() { cWidth = max_re - min_re; cHeight = max_im - min_im; sSizeX = zSizeX / zoom; sSizeY = zSizeY / zoom; if( anything_changed ) { cur_min_iterations = num_iterations; mult_x = cWidth / (double)sSizeX; mult_y = cHeight / (double)sSizeY; do_update_pixels( true ); draw_crosshair(); } anything_changed = update_view(); if( anything_changed ) { zoom = initial_zoom; } else if( zoom > 1 ) { zoom = 1; anything_changed = true; } if( anything_changed ) { frameRate( 50 ); } else { frameRate( 10 ); } } void mousePressed() { if( mouseButton == CENTER ) { println( cCentreX + " + " + cCentreY + "i" ); println( "width = " + (max_re - min_re) ); } } void mouseDragged() { if( mouseButton == RIGHT ) { zZoomY += mouseY - pmouseY; } else { zDragX += mouseX - pmouseX; zDragY += mouseY - pmouseY; } } void draw_crosshair() { int zSizeXOver2 = (zSizeX) / 2; int zSizeYOver2 = (zSizeY) / 2; stroke( 255, 0, 0, 75 ); line( zSizeXOver2, zSizeYOver2 - 20, zSizeXOver2, zSizeYOver2 - 5 ); line( zSizeXOver2, zSizeYOver2 + 20, zSizeXOver2, zSizeYOver2 + 5 ); line( zSizeXOver2 - 20, zSizeYOver2, zSizeXOver2 - 5, zSizeYOver2 ); line( zSizeXOver2 + 20, zSizeYOver2, zSizeXOver2 + 5, zSizeYOver2 ); } void do_update_pixels( boolean really_draw ) { int pixelcounter = 0; for( int y = 0; y < sSizeY; ++y ) { int zY = y*zoom; for( int x = 0; x < sSizeX; ++x ) { int zX = x*zoom; double coord_x = min_re + ( mult_x * x ); double coord_y = min_im + ( mult_y * y ); color col = get_pixel_color( coord_x, coord_y ); if( really_draw ) { if( zoom == 1 ) { pixels[pixelcounter] = col; ++pixelcounter; } else { stroke( col, 255 ); fill( col, 255 ); rect( zX, zY, zoom - 1, zoom - 1 ); } } } } if( zoom == 1 ) { updatePixels(); } prev_min_iterations = cur_min_iterations; } color get_pixel_color( double c_re, double c_im ) { double z_re = 0; double z_im = 0; int it; for( it = 0; it < num_iterations; ++it ) { double z_re_new = (z_re*z_re) - (z_im*z_im) + c_re; z_im = (2*z_re*z_im) + c_im; z_re = z_re_new; if( z_re < -2 || z_re > 2 || z_im < -2 || z_im > 2 ) { break; } } if( it == num_iterations ) { return color( 0, 0, 0 ); } else { if( it < cur_min_iterations ) { cur_min_iterations = it; } int color_fade = (int)( 255.0 * ( (double)(it-prev_min_iterations) / (double)(num_iterations-prev_min_iterations) ) ); return color( color_fade, color_fade, 255 ); } } boolean update_view() { double cOldMaxX = max_re; double cOldMinX = min_re; double cOldMaxY = max_im; double cOldMinY = min_im; double cWidthOver2 = cWidth / 2; double cHeightOver2 = cHeight / 2; cCentreX = min_re + ( cWidthOver2 ); cCentreY = min_im + ( cHeightOver2 ); double cDragX = ( (double)zDragX / (double)(zSizeX) ) * cWidth; double cDragY = ( (double)zDragY / (double)(zSizeY) ) * cHeight; cCentreX -= cDragX; cCentreY -= cDragY; double cZoom = 1.0 + ( 2.0 * ( (double)zZoomY/(double)zSizeY ) ); double cNewWidthOver2 = cWidthOver2 * cZoom; double cNewHeightOver2 = cHeightOver2 * cZoom; max_re = cCentreX + cNewWidthOver2; min_re = cCentreX - cNewWidthOver2; max_im = cCentreY + cNewHeightOver2; min_im = cCentreY - cNewHeightOver2; zDragX = 0; zDragY = 0; zZoomY = 0; return ( cOldMaxX != max_re || cOldMinX != min_re || cOldMaxY != max_im || cOldMinY != min_im ); }