summaryrefslogtreecommitdiff
path: root/ext/mandel/tkmandel.rb
diff options
context:
space:
mode:
Diffstat (limited to 'ext/mandel/tkmandel.rb')
-rw-r--r--ext/mandel/tkmandel.rb172
1 files changed, 172 insertions, 0 deletions
diff --git a/ext/mandel/tkmandel.rb b/ext/mandel/tkmandel.rb
new file mode 100644
index 0000000..5ebe90f
--- /dev/null
+++ b/ext/mandel/tkmandel.rb
@@ -0,0 +1,172 @@
+# require "complex"
+require "mandel"
+require "tkclass"
+
+DefaultMaxDepth = 30
+DefaultSX = -2.25
+DefaultSY = 1.75
+DefaultEX = 1.25
+DefaultEY = -1.75
+
+def reset
+ $max_depth = DefaultMaxDepth
+ $s_re = DefaultSX
+ $s_im = DefaultSY
+ $e_re = DefaultEX
+ $e_im = DefaultEY
+ $dx = ($e_re - $s_re).abs / Width
+ $dy = ($e_im - $s_im).abs / Height
+ $photo.blank
+end
+
+
+Width = 400
+Height = 400
+
+$c = Canvas.new {
+ width Width
+ height Height
+ }
+$c.pack
+
+$c_rect = Rectangle.new($c, 0, 0, Width+1, Height+1)
+$c_rect.fill "white"
+
+$colors = []
+
+def colors_init
+ $colors = []
+ for i in 0 .. 125
+ $colors.push(format("#%02x%02x%02x", 250 - (i*2), i*2, 0))
+ end
+ for i in 0 .. 125
+ $colors.push(format("#%02x%02x%02x", 0, 250 - (i*2), i*2))
+ end
+ $color_max = $colors.size - 1
+end
+
+def zoom(a, b, c, d)
+ center_x = (a + c) / 2
+ center_y = (b + d) / 2
+ size = (c - a).abs
+ size = (d - b).abs if (size < (d - b).abs)
+ size = 1 if (size < 1)
+ zoom_rate = ((Width + Height) / 2).to_f / size
+ $max_depth = ($max_depth.to_f * Math.sqrt(Math.sqrt(Math.sqrt(zoom_rate)))).to_i
+
+ move_x_rate = (center_x - (Width / 2)).to_f / (Width / 2)
+ move_y_rate = (center_y - (Height / 2)).to_f / (Height / 2)
+
+ center_re = ($s_re + $e_re) / 2
+ center_im = ($s_im + $e_im) / 2
+ c_size_re = ($e_re - $s_re).abs
+ c_size_im = ($e_im - $s_im).abs
+
+ center_re = center_re + (move_x_rate * (c_size_re / 2))
+ center_im = center_im - (move_y_rate * (c_size_im / 2))
+
+ $s_re = center_re - ((c_size_re / 2) / zoom_rate)
+ $s_im = center_im + ((c_size_im / 2) / zoom_rate)
+ $e_re = center_re + ((c_size_re / 2) / zoom_rate)
+ $e_im = center_im - ((c_size_im / 2) / zoom_rate)
+
+ $dx = ($e_re - $s_re).abs / Width
+ $dy = ($e_im - $s_im).abs / Height
+ p [$s_re, $dx, $s_im, $dy]
+end
+
+
+def mandel(x, y)
+ re = $s_re + ($dx * x)
+ im = $s_im - ($dy * y)
+# z = c = Complex(re, im)
+# for i in 0 .. $max_depth
+# z = (z * z) + c
+# break if z.abs > 2
+# end
+# return i
+ return Mandel.mandel(re, im, $max_depth)
+end
+
+$buf = "{"+" "*Width+"}"
+def calc
+ $c.update
+ return if $current_rect
+ depth = 0
+
+ for x in 0 .. Width - 1
+ depth = mandel(x, $calc_y)
+ if depth >= $max_depth
+ $buf[x*8+1,7] = "#000000"
+ else
+ $buf[x*8+1,7] = $colors[$color_max * depth / $max_depth]
+ end
+ end
+ $photo.put($buf, 0, $calc_y)
+
+ $calc_y += 1
+ if (($calc_y % 20) == 0)
+ print "#{($calc_y * 100 / Height)}% done. -- depth #{$max_depth}\n"
+# $mandel.image $photo
+ end
+
+ if ($calc_y > Height - 1)
+ $calc_y = StartCalcY
+ $calc_on = false
+# exit
+ end
+
+ if $calc_on
+ Tk.after(1) { calc() }
+ end
+end
+
+$photo = TkPhotoImage.new({'width'=>Width, 'height'=>Height})
+$mandel = TkcImage.new($c, Width/2, Height/2) { image $photo }
+reset()
+colors_init()
+$calc_y = StartCalcY = 0
+$calc_on = true
+calc()
+
+def clear
+# $mandel.destroy if $mandel
+ $calc_y = StartCalcY
+end
+
+$start_x = $start_y = 0
+$current_rect = nil
+
+def do_press(x, y)
+ $start_x = x
+ $start_y = y
+ $current_rect = Rectangle.new($c, x, y, x, y) { outline "white" }
+end
+
+def do_motion(x, y)
+ if $current_rect
+ $current_rect.coords $start_x, $start_y, x, y
+ end
+end
+
+def do_release(x, y)
+ if $current_rect
+ $current_rect.coords $start_x, $start_y, x, y
+ $current_rect.destroy
+ $current_rect = nil
+ clear()
+ $calc_on = true
+ zoom($start_x, $start_y, x, y)
+ calc()
+ end
+end
+
+$c.bind("1", proc{|e| do_press e.x, e.y})
+$c.bind("B1-Motion", proc{|x, y| do_motion x, y}, "%x %y")
+$c.bind("ButtonRelease-1", proc{|x, y| do_release x, y}, "%x %y")
+
+begin
+ Tk.mainloop
+ensure
+# File.delete("#tmpmandel#.gif")
+end