Skip to content

Instantly share code, notes, and snippets.

@JoshCheek
Last active May 25, 2019 09:43
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/f1d044067cd37ae774b4cb1989b0bf16 to your computer and use it in GitHub Desktop.
Save JoshCheek/f1d044067cd37ae774b4cb1989b0bf16 to your computer and use it in GitHub Desktop.
Tweetable Mandelbrot Set
# The first version was one I made in 2017 for Graphics,
# it has much better resolution but isn't animated:
# https://twitter.com/josh_cheek/status/846199094519443456
# https://gist.github.com/JoshCheek/dbb07c35e46d45f57c33579e03095f1c
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.
def mandelbrot(x, y, iterations)
c,z=x+y*1i,0
iterations.times.find do |i|
z = z*z+c
2<z.magnitude
end
end
require 'io/console'
h, w = $stdin.winsize
# x_target = -0.7453
# y_target = 0.1127
# x_target = -1.0396344968890008
# y_target = 0.3588067730189076
x_target = -1.0051487086372168
y_target = 0.29104801319928053
xr = w/4.0
yr = h/2.0
num_samples = 20
loop do
xs = x_target - xr
ys = y_target - yr
xf = x_target + xr
yf = y_target + yr
crnt_width = (xf-xs)
crnt_height = (yf-ys)
$><< "\e[H"+h.times.map do |v|
w.times.map do |u|
x = xs+crnt_width*u/w
y = ys+crnt_height*v/h.to_f
depth = mandelbrot(x, y, num_samples) || 0
"\e[48;2;#{(255*depth/num_samples/2).to_i};0;0m "
end*""
end*"\n"
xr *= 0.9
yr *= 0.9
num_samples += 1
# print "\e[H" + {x:x_target,y:y_target,xr:xr,yr:yr}.inspect
# char = $stdin.raw { $stdin.readpartial 100 }
# case char
# when ?\C-c
# break
# when ?h then x_target -= xr/20
# when ?l then x_target += xr/20
# when ?j then y_target += yr/20
# when ?k then y_target -= yr/20
# end
end
# @initial_width = 5
# @initial_height = 2
# @target = [w/2, h/2]
# @center = [0, 0]
# mb = MandelBrot.new w, h
# 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 = 0.5
# pixel_height = 1
# x_iterations = (w/pixel_width).ceil
# y_iterations = (h/pixel_height).ceil
# h.times do |y|
# initial_y = y * ∆y / w + start_y
# w.times do |x|
# initial_x = x * ∆x / y + start_x
# n = if depth = mandelbrot(y/h.to_f, x/w.to_f, 20)
# depth*255/20
# else
# 0
# end
# print "\e[#{y+1};#{h+1}H\e[48;2;#{depth};0;0m "
# end
# end
# 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
# # 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
def mandelbrot(x, y, iterations)
c,z=x+y*1i,0
iterations.times.find do |i|
z = z*z+c
2<z.magnitude
end
end
require 'io/console'
h, w = $stdin.winsize
x_target=-1.0051487086372168
y_target=0.29104801319928053
xr=w/4.0
yr=h/2.0
num_samples = 20
loop do
xs = x_target - xr
ys = y_target - yr
xf = x_target + xr
yf = y_target + yr
crnt_width = (xf-xs)
crnt_height = (yf-ys)
$><< "\e[H"+h.times.map do |v|
w.times.map do |u|
x = xs+crnt_width*u/w
y = ys+crnt_height*v/h.to_f
depth = mandelbrot(x, y, num_samples) || 0
"\e[48;2;#{(255*depth/num_samples/2).to_i};0;0m "
end*""
end*"\n"
xr *= 0.9
yr *= 0.9
num_samples += 1
end
require 'io/console'
h,w = $stdin.winsize
x_target=-1.0051487086372168
y_target=0.29104801319928053
xr=w/4.0
yr=h/2.0
num_samples = 20
loop do
xs = x_target - xr
ys = y_target - yr
xf = x_target + xr
yf = y_target + yr
crnt_width = (xf-xs)
crnt_height = (yf-ys)
$><< "\e[H"+h.times.map do |v|
w.times.map do |u|
x = xs+crnt_width*u/w
y = ys+crnt_height*v/h
c,z=x+y*1i,0
depth = num_samples.times.find do |i|
z = z*z+c
2<z.magnitude
end || 0
"\e[48;2;#{(255*depth/num_samples/2).to_i};0;0m "
end*""
end*"\n"
xr*=0.9
yr*=0.9
num_samples += 1
end
require 'io/console'
h,w = $stdin.winsize
xt=-1.0051487086372168
yt=0.29104801319928053
xr=w/4.0
yr=h/2.0
n = 20
loop{
xs=xt-xr
ys=yt-yr
xf=xt+xr
yf=yt+yr
crnt_width = (xf-xs)
crnt_height = (yf-ys)
$><< "\e[H"+h.times.map do |v|
w.times.map do |u|
x = xs+crnt_width*u/w
y = ys+crnt_height*v/h
c,z=x+y*1i,0
depth = n.times.find do |i|
z = z*z+c
2<z.magnitude
end || 0
"\e[48;2;#{(255*depth/n/2).to_i};0;0m "
end*""
end*"\n"
xr*=0.9
yr*=0.9
n += 1
}
require 'io/console'
h,w = $stdin.winsize
xt=-1.0051487086372168
yt=0.29104801319928053
xr=w/4.0/9
yr=h/2.0/9
n=10
loop{
crnt_width = 2*xr
crnt_height = 2*yr
$><< "\e[H"+h.times.map do |v|
w.times.map do |u|
x = (xt-xr)+crnt_width*u/w
y = (yt-yr)+crnt_height*v/h
c,z=x+y*1i,0
depth = n.to_i.times.find do |i|
z = z*z+c
2<z.magnitude
end || 0
"\e[48;5;#{232+(24*depth/n).to_i}m "
end*""
end*"\n"
xr*=0.9
yr*=0.9
n += 0.5
}
require 'io/console'
h,w = $stdin.winsize
xt=-1.0051487086372168
yt=0.29104801319928053
xr=w/4.0/9
yr=h/2.0/9
n=10
loop{
crnt_width = 2*xr
crnt_height = 2*yr
$><< "\e[H"+h.times.map do |v|
w.times.map do |u|
x = (xt-xr)+crnt_width*u/w
y = (yt-yr)+crnt_height*v/h
c,z=x+y*1i,0
depth = n.to_i.times.find do |i|
z = z*z+c
2<z.magnitude
end || 0
"\e[48;5;#{232+(24*depth/n).to_i}m "
end*""
end*"\n"
xr*=0.9
yr*=0.9
n += 0.5
}
ruby -e h,w=$LINES,$COLUMNS'
xt=-1.0051487086372168
yt=0.29104801319928053
xr=w/18.0
yr=h/9.0
n=10
loop{
$><<"\e[H"+h.times.map{|v|
w.times.map{|u|
x=(xt-xr)+2*xr*u/w
y=(yt-yr)+2*yr*v/h
c,z=x+y*1i,0
depth = n.to_i.times.find{|i|
z=z*z+c
2<z.magnitude
}||0
"\e[48;5;#{232+(24*depth/n).to_i}m "
}*""
}*?\n
xr*=0.9
yr*=0.9
n += 0.6
}'
# 13 away
ruby -e h,w=$LINES,$COLUMNS'
a=w/18.0
b=h/9.0
n=10
loop{$><<"\e[H"+h.times. map{|v|w.times. map{|u|
x=(-1.0051487086372168-a)+2*a*u/w
y=(0.29104801319928053-b)+2*b*v/h
c,z=x+y*1i,0
"\e[48;5;#{232+(24*(n. to_i.times.find{|i|z=z*z+c;2<z.magnitude}||0)/n).to_i}m "}*""}*?\n
a*=0.9
b*=0.9
n+=0.6}'
ruby -eh,w=$LINES,$COLUMNS'
a=w/9.0
b=h/4.5
n=9
loop{$><<"\e[H"+h.times.map{|v|w.times.map{|u|c,z=2*a*u/w-1.005148708637216-a+(2*b*v/h+0.291048013199280-b)*1i,0
"\e[48;5;#{(232+24*(n.to_i.times.find{|i|z=z*z+c;2<z.magnitude}||0)/n).to_i}m "}*""}*?\n
a*=0.9
b*=0.9
n+=0.6}'
# FINAL:
ruby -eh,w=$LINES,$COLUMNS'
a=w/9.0
b=h/4.5
n=9
loop{$><<"\e[H"+h.times. map{|v|w.times. map{|u|c,z=2*a*u/w-1.005148708637216-a+(2*b*v/h+0.291048013199280-b)*1i,0
"\e[48;5;#{(232+24*(n. to_i.times.find{|i|z=z*z+c;2<z.magnitude}||0)/n).to_i}m "}*""}*?\n
a*=0.99
b*=0.99
n+=0.06}'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment