Ruby Fractal Library

Posted by Ryan Baxter Thu, 03 Jul 2008 21:26:00 GMT

*Update: Version 1.1.0 of the Ruby Fractal Library has been released.

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!

fractals.rb

# 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
end

Using this library is as simple as the following:

require 'fractals'

mandelbrot = Fractals::Mandelbrot.new
mandelbrot.draw

Any suggestions/bug fixes can be posted here. Thanks.

IE7's Inanimate GIF

Posted by Ryan Baxter Wed, 11 Jun 2008 12:06:00 GMT

Animated GIFs are most often used as activity indicators in modern AJAX (asynchronous JavaScript and XML) enabled websites. I decided to use a GIF (Graphic Interchange Format) from ajaxload.info on an application that I’ve been developing at work. The application performs server-side processing on files uploaded by employees. Processing time varies depending on the size of the file. Larger files take longer.

I wanted the animated GIF to appear when the file upload button was clicked so I placed the image within a DIV tag and hid it by setting a blank CSS display property. OnClick of the upload button, a JavaScript function toggled the display value to “block”, making the DIV appear. This worked as expected in Firefox and IE6, but not in IE7. The DIV appeared in IE7, but it’s GIF wasn’t moving.

A little googling turned up a helpful comment on Rick Strahl’s blog.

I’ve run into a problem with animated gifs inside of a hidden area of a Web page that is hidden with style.display=’none’. When the area is made visible again, in Internet Explorer this causes the image to not be displayed an animated GIF whatever I try. [sic]

Apparently IE7 doesn’t like to animate hidden GIFs. User submitted comments on Rick Strahl’s blog provided many solutions, but only a couple worked in my situation. The first uses the JavaScript setTimeout method to populate the image’s SRC attribute 200 ms after the function call. The second sets the DIV’s innerHTML to a string containing an IMG tag with the animated GIF.

<script language='javascript'> 
    function ShowLoading(elementId) 
    {
        document.getElementById(elementId).style.display = "block"; 
        setTimeout('document.images["loadingImage"].src = "../images/loading.gif"', 200); 
    } 
</script>

Neither solution is ideal, but setting the element’s innerHTML felt a little bit cleaner to me.

<script language='javascript'>
    function ShowLoading(elementId)
    {   
        var element = document.getElementById(elementId);    

        element.innerHTML = "<img src='../images/loading.gif'>";    
        element.style.display = "block";
    }
</script>

*IE7 may have animations disabled. Go to Tools > Internet Options > Advanced > Multimedia. Checking “Play animations in webpages” may affect how IE7 renders your animated GIFs.

Samba Network Shares with Nautilus in Hardy Heron Part 2

Posted by Ryan Baxter Sun, 01 Jun 2008 23:07:00 GMT

Nearly a month ago I wrote about my problems connecting to the network shares of my Linksys NAS200 using Nautilus in Ubuntu, Hardy Heron. My fix was simple and it worked. Unfortunately, the solution’s WAF (Wife Acceptance Factor) was low. Apparently she didn’t think it was easy enough to execute smbmount from a Terminal window. Whatever :) I have since written a small shell script that is called from Session Startup.

Initially, the script failed to connect to my network shares because my wireless network connection hadn’t finished negotiating before the script was executed. I coded around this by creating a while loop that greps the output of a ping to my router. If successful, the mount_shares function is called. Otherwise. the thread will sleep for 10 seconds and try again.

#!/bin/bash

user="thorbardin/ryan%password"
root_dir="/home/ryan/Network Shares"

mount_shares() {
  public_dir="$root_dir"/"Public on Thorbardin"
  home_dir="$root_dir"/"Home on Thorbardin"

  [ -d "$public_dir" ] || mkdir -p "$public_dir"
  [ -d "$home_dir" ] || mkdir -p "$home_dir"

  smbmount "//192.168.1.105/public disk" "$public_dir" -o user="$user"
  smbmount "//192.168.1.105/ryan" "$home_dir" -o user="$user"
}

while [ 1 ]; do
  if ping -c2 192.168.1.1 2>&1 | grep ttl; then
    mount_shares

    exit 0   
  fi
  sleep 10
done

exit 0

I’m already thinking about rewriting this script so that it scans my network using smbtree and automatically mounts all available network shares. That’ll be Part 3!

Older posts: 1 ... 4 5 6 7 8 9