Last active
December 12, 2020 23:00
-
-
Save dbongo/c1070607384f464612fc001121ddf13d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # The Mandelbrot Set for Ruby by Michael Crowther | |
| # | |
| # Based on "The Mandelbrot Set" example by Daniel Shiffman for Processing 3+ | |
| # (https://processing.org/examples/mandelbrot.html) | |
| # | |
| # size(640, 360); | |
| # noLoop(); | |
| # background(255); | |
| # | |
| # // Establish a range of values on the complex plane | |
| # // A different range will allow us to "zoom" in or out on the fractal | |
| # | |
| # // It all starts with the width, try higher or lower values | |
| # float w = 4; | |
| # float h = (w * height) / width; | |
| # | |
| # // Start at negative half the width and height | |
| # float xmin = -w/2; | |
| # float ymin = -h/2; | |
| # | |
| # // Make sure we can write to the pixels[] array. | |
| # // Only need to do this once since we don't do any other drawing. | |
| # loadPixels(); | |
| # | |
| # // Maximum number of iterations for each point on the complex plane | |
| # int maxiterations = 100; | |
| # | |
| # // x goes from xmin to xmax | |
| # float xmax = xmin + w; | |
| # // y goes from ymin to ymax | |
| # float ymax = ymin + h; | |
| # | |
| # // Calculate amount we increment x,y for each pixel | |
| # float dx = (xmax - xmin) / (width); | |
| # float dy = (ymax - ymin) / (height); | |
| # | |
| # // Start y | |
| # float y = ymin; | |
| # for (int j = 0; j < height; j++) { | |
| # // Start x | |
| # float x = xmin; | |
| # for (int i = 0; i < width; i++) { | |
| # | |
| # // Now we test, as we iterate z = z^2 + c does z tend towards infinity? | |
| # float a = x; | |
| # float b = y; | |
| # int n = 0; | |
| # float max = 4.0; // Infinity in our finite world is simple, let's just consider it 4 | |
| # float absOld = 0.0; | |
| # float convergeNumber = maxiterations; // this will change if the while loop breaks due to non-convergence | |
| # while (n < maxiterations) { | |
| # // We suppose z = a+ib | |
| # float aa = a * a; | |
| # float bb = b * b; | |
| # float abs = sqrt(aa + bb); | |
| # if (abs > max) { // |z| = sqrt(a^2+b^2) | |
| # // Now measure how much we exceeded the maximum: | |
| # float diffToLast = (float) (abs - absOld); | |
| # float diffToMax = (float) (max - absOld); | |
| # convergeNumber = n + diffToMax/diffToLast; | |
| # break; // Bail | |
| # } | |
| # float twoab = 2.0 * a * b; | |
| # a = aa - bb + x; // this operation corresponds to z -> z^2+c where z=a+ib c=(x,y) | |
| # b = twoab + y; | |
| # n++; | |
| # absOld = abs; | |
| # } | |
| # | |
| # // We color each pixel based on how long it takes to get to infinity | |
| # // If we never got there, let's pick the color black | |
| # if (n == maxiterations) { | |
| # pixels[i+j*width] = color(0); | |
| # } else { | |
| # // Gosh, we could make fancy colors here if we wanted | |
| # float norm = map(convergeNumber, 0, maxiterations, 0, 1); | |
| # pixels[i+j*width] = color(map(sqrt(norm), 0, 1, 0, 255)); | |
| # } | |
| # x += dx; | |
| # } | |
| # y += dy; | |
| # } | |
| # updatePixels(); | |
| def settings | |
| full_screen | |
| end | |
| # Establish a range of values on the complex plane | |
| # A different range will allow us to "zoom" in or out on the fractal | |
| def setup | |
| sketch_title 'Mandelbrot Set' | |
| no_loop | |
| # It all starts with the width, try higher or lower values | |
| @w = 4.0 | |
| @h = ((@w * height) / width).to_f | |
| # Start at negative half the width and height | |
| @xmin = (-@w / 2.0) | |
| @ymin = (-@h / 2.0) | |
| # x goes from xmin to xmax | |
| # y goes from ymin to ymax | |
| @xmax = @xmin + @w | |
| @ymax = @ymin + @h | |
| # Calculate amount we increment x,y for each pixel | |
| @dx = ((@xmax - @xmin) / width).to_f | |
| @dy = ((@ymax - @ymin) / height).to_f | |
| # Maximum number of iterations for each point on the complex plane | |
| @maxiterations = 100 | |
| # Make sure we can write to the pixels[] array. | |
| # Only need to do this once since we don't do any other drawing. | |
| load_pixels | |
| end | |
| def draw | |
| # Start y | |
| y = @ymin.to_f | |
| for j in (0...height) do | |
| # Start x | |
| x = @xmin.to_f | |
| for i in (0...width) do | |
| a = x | |
| b = y | |
| n = 0 | |
| max = 4.0 # Infinity in our finite world is simple, just consider it 4 | |
| z_old = 0.0 | |
| converge_num = @maxiterations # his will change if the while loop breaks due to non-convergence | |
| # Now we test, as we iterate z = z^2 + c does z tend towards infinity? | |
| while n < @maxiterations do | |
| # We suppose z = a+ib | |
| aa = (a * a).to_f | |
| bb = (b * b).to_f | |
| z = sqrt(aa + bb).abs # |z| = sqrt(a^2+b^2) | |
| # Now measure how much we exceeded the maximum | |
| if z > max | |
| diff_to_last = (z - z_old).to_f | |
| diff_to_max = (max - z_old).to_f | |
| converge_num = (n + (diff_to_max / diff_to_last)) | |
| break | |
| end | |
| two_ab = (2.0 * a * b) | |
| # this operation corresponds to z -> z^2+c where z=a+ib c=(x,y) | |
| a = (aa - bb + x) | |
| b = (two_ab + y) | |
| n += 1 | |
| z_old = z | |
| end | |
| # We color each pixel based on how long it takes to get to infinity. | |
| # If we never got there, pick the color black. | |
| if n == @maxiterations | |
| pixels[i + j * width] = color(0) | |
| else | |
| # Gosh, we could make fancy colors here if we wanted | |
| norm = map1d(converge_num, (0..@maxiterations), (0..1)) | |
| pixels[i + j * width] = color( | |
| map1d(sqrt(norm), (0..1), (0..255)) | |
| ) | |
| end | |
| x += @dx | |
| end | |
| y += @dy | |
| end | |
| update_pixels | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.