Skip to content

Instantly share code, notes, and snippets.

@JoshCheek
Last active March 27, 2017 04:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JoshCheek/dbb07c35e46d45f57c33579e03095f1c to your computer and use it in GitHub Desktop.
Save JoshCheek/dbb07c35e46d45f57c33579e03095f1c to your computer and use it in GitHub Desktop.
Static image of Mandelbrot
# 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