diff options
Diffstat (limited to 'ext/mandel/tkmandel.rb')
-rw-r--r-- | ext/mandel/tkmandel.rb | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/ext/mandel/tkmandel.rb b/ext/mandel/tkmandel.rb new file mode 100644 index 0000000000..5ebe90fb80 --- /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 |