Last active
March 27, 2017 04:49
-
-
Save JoshCheek/dbb07c35e46d45f57c33579e03095f1c to your computer and use it in GitHub Desktop.
Static image of Mandelbrot
This file contains 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
# image @ https://twitter.com/josh_cheek/status/846199094519443456 | |
require 'graphics' | |
# https://www.bowdoin.edu/~dfrancis/askanerd/mandelbrot/ | |
# | |
# Consider the code: | |
# Z = 0 | |
# C = /* some complex number */ | |
# loop { Z = Z*Z + C } | |
# | |
# The Mandelbrot Set is the set of every C | |
# where Z doesn't grow beyond the number 2. | |
# | |
# This is done by sampling values for C and iterating up to a horizon. | |
# The colours are applied to the values outside the Mandelbrot Set | |
# based on how many iterations it took them to grow beyond 2. | |
class MandelBrot < Graphics::Drawing | |
LEFT_CLICK = 1 | |
def handle_event(event, n) | |
if event.kind_of?(SDL::Event::Mouseup) && event.button == LEFT_CLICK | |
@target = [h-event.y-1, event.x] | |
else | |
super | |
end | |
end | |
end | |
def mandelbrot(x, y) | |
zx = cx = x | |
zy = cy = y | |
99.times do |i| | |
zx, zy = (zx*zx + cx - zy*zy), (2*zx*zy + cy) | |
return i if 2 < zx*zx+zy*zy | |
end | |
nil | |
end | |
w = 1440 | |
h = 900 | |
@initial_width = 5 | |
@initial_height = 2 | |
@target = [w/2, h/2] | |
@center = [0, 0] | |
mb = MandelBrot.new w, h, 24 | |
depth = 3 | |
mandelbrot_width = @initial_width / depth.to_f | |
mandelbrot_height = @initial_height / depth.to_f | |
mid_x, mid_y = @center | |
start_x = mid_x - mandelbrot_width / 2 | |
start_y = mid_x - mandelbrot_height / 2 | |
end_x = start_x + 0.04 / depth * 100 | |
end_y = start_y + 0.03 / depth * 100 | |
∆x = end_x - start_x | |
∆y = end_y - start_y | |
colors = [:red, :green, :blue, :cyan, :magenta, :yellow] | |
x_step = ∆x / w | |
y_step = ∆y / h | |
pixel_width = 1 | |
pixel_height = 1 | |
x_iterations = (w/pixel_width).ceil | |
y_iterations = (h/pixel_height).ceil | |
x_iterations.times do |x| | |
initial_x = x * ∆x / x_iterations + start_x | |
y_iterations.ceil.times do |y| | |
initial_y = y * ∆y / y_iterations + start_y | |
if depth = mandelbrot(initial_x, initial_y) | |
color = :"red#{'%02d'%depth}" | |
else | |
color = :black | |
end | |
# mb.rect x*pixel_width, y*pixel_width, pixel_width, pixel_height, color, :fill | |
mb.point x*pixel_width, y*pixel_width, color | |
end | |
end | |
# NOTE ON ZOOMING: It should zoom such that the target is in the same location | |
# on the screen after the zoom as it was before the zoom | |
mb.run |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment