Ruby Fractal Library
Posted by Ryan Baxter Thu, 03 Jul 2008 21:26:00 GMT
Last October, I wrote a small fractal rendering program in Ruby using the Shoes windowing toolkit written by why the lucky stiff. It’s sole purpose was to test Shoes. The code was painfully slow at rendering the Mandelbrot set, but it did, however, begin a small obsession of mine with fractals.
Since I couldn’t find a fractal library for Ruby, I decided to write one. Over the last two weeks I’ve written some code to generate both the Mandelbrot and Julia set fractals using the escape time algorithm. The code is still slow, but within a couple weeks I hope to replace the slow portions with inline C.
There may still be some bugs and I haven’t added any error handling, but here it is. An “almost” pure Ruby fractal library. Once this is cleaned up I’ll repost the code. I suppose a gem could be possible as well. Happy 4th!
# RB
require 'rubygems'
require 'complex'
require 'png'
module Fractals
module Fractal
attr_accessor :begin_range, :end_range
def initialize(begin_range, end_range)
@begin_range, @end_range = begin_range, end_range
end
def draw(height=250, width=250, m=1.0, save_as='fractal.png')
canvas = PNG::Canvas.new(height, width)
# Find the complex coordinate for each pixel.
0.upto(height - 1) { |y|
i = (y * (@end_range.image - @begin_range.image) / height +
@begin_range.image) * m
0.upto(width - 1) { |x|
r = (x * (@end_range.real - @begin_range.real) / width +
@begin_range.real) * m
if self.in_set?(Complex(r, i)) then
canvas[x, y] = PNG::Color::Black
else
canvas[x, y] = fetch_color(self.last_iteration, self.max_iterations)
end
}
}
png = PNG.new(canvas)
png.save(save_as)
end
private
def fetch_color(last_iteration, max_iterations)
divisor = 765*last_iteration/max_iterations
case divisor
when 0..254 then return PNG::Color.new(divisor%255, 0, 0, 255)
when 255..509 then return PNG::Color.new(255, divisor%255, 0, 255)
when 510..765 then return PNG::Color.new(255, 255, divisor%255, 255)
end
end
end
class Julia
include Fractal
attr_accessor :seed, :bailout, :max_iterations
attr_reader :last_iteration
def initialize(seed=Complex(0.36, 0.1), bailout=2, max_iterations=100,
begin_range=Complex(-2.25, -1.5), end_range=Complex(0.75, 1.5))
super(begin_range, end_range)
@seed, @bailout, @max_iterations = seed, bailout, max_iterations
end
def in_set?(z)
@max_iterations.times { |i|
z = z**2 + @seed
if z > @bailout then
@last_iteration = i
return false
end
}
return true
end
end
class Mandelbrot
include Fractal
attr_accessor :bailout, :max_iterations
attr_reader :last_iteration
def initialize(bailout=5, max_iterations=100, begin_range=Complex(-2.25,
-1.5), end_range=Complex(0.75, 1.5))
super(begin_range, end_range)
@bailout, @max_iterations = bailout, max_iterations
end
def in_set?(c)
z = 0
@max_iterations.times { |i|
z = z**2 + c
if z > @bailout then
@last_iteration = i
return false
end
}
return true
end
end
endUsing this library is as simple as the following:
require 'fractals'
mandelbrot = Fractals::Mandelbrot.new
mandelbrot.drawAny suggestions/bug fixes can be posted here. Thanks.
- Posted in Code Snippets
- Meta no trackbacks, 2 comments, permalink, rss, atom
Trackbacks
Use the following link to trackback from your own site:
http://crunchlife.com/articles/trackback/70
Comments
2 months later:
2 months later:

