public
Description: Shoes Tutorial Note : HTML version
Homepage:
Clone URL: git://github.com/ashbb/shoes_tutorial_html.git
shoes_tutorial_html / mdowns / 01130_Fancy_Gallery_11-15.mdown
100644 256 lines (185 sloc) 6.487 kb

Fancy Gallery 11-15

Gallery No.11

I read the book: Simple Brain, Complex 'I'. (Japanese book) and knew Kohonen's Self Organizing Feature Maps.

My Shoes app uses the following very simplistic approach (rules):

  1. create 20 x 20 cells with random color
  2. create the base-color at random
  3. find a cell with the closest color from 400 cells
  4. taint the base-color a little to the cell and nearby 8 cells
  5. repeat 2 - 4 many times

then the cells will be organized some color groups.

Look at online demo. (20 x 20 cells version)

# gallery11.rb
# Kohonen's Self Organizing Feature Maps
# http://www.ai-junkie.com/ann/som/som1.html
N = 20
W = 20

Shoes.app :width => 400, :height => 450, :title => 'Self Organizing Map v0.1' do
  nostroke
  @nodes = []

  def base_color
    [rand(256), rand(256), rand(256)]
  end

  def mix node, *rgb
    r0, g0, b0 = rgb
    x, y = node.left / W, node.top / W
    [y - 1, y, y +1].each do |j|
      [x - 1, x, x + 1].each do |i|
        begin
          n = j * N + i
          r, g, b = @nodes[n].style[:color]
          #r, g, b = (r + r0) / 2, (g + g0) / 2, (b + b0) / 2
          r, g, b = r + (r0 - r) / 5, g + (g0 - g) / 5, b + (b0 - b) / 5
          @nodes[n].fill = rgb(r, g, b)
          @nodes[n].style :color => [r, g, b]
          @nodes[n].show
        end unless (i == -1 or i == N or j == -1 or j == N)
      end
    end
  end

  def som
    r0, g0, b0 = base_color
    node = @nodes.sort_by do |n|
      r, g, b = n.style[:color]
      ::Math::sqrt((r - r0) * (r - r0) + (g - g0) * (g - g0) + (b - b0) * (b - b0))
    end.shift

    mix node, r0, g0, b0
  end

  N.times do |j|
    N.times do |i|
      r, g, b = base_color
      @nodes << rect(i*W, j*W, W, W, :fill => rgb(r, g, b), :color => [r, g, b])
    end
  end

  msg  = para 0, :left => 100, :top => 420

  button 'start', :left => 20, :top => 420 do
    animate(36){|i| som; msg.text = i}
  end
end

gallery11.png

gallery11.png

Starting map. (40 x 40 cells version)

gallery11-1.png

gallery11-1.png

The map repeated 3571 times.


Tips

Paul Harris confirmed running this tiny Shoes app on his kubuntu 9.04.

At first it didn't appear to work. But tried to slow animate loop down to 10, it displayed. And finally, he found the good solution:

  • Changed to 30x30 and it runs fine on animate 5.

Thank you, Paul! :)


References


Gallery No.12

Finding Photos on Flickr.
Look at IndianGuru's Sinatra app. It's cool!
I was inspired and wrote a tiny Shoes app. Flickr's photos are so beautiful. I like it. :)

# gallery12.rb
require 'gallery12-flickr'

Shoes.app :width => 300, :height => 300, :title => 'Finding Photos on Flickr v0.1' do
  extend FindingFlickr

  para "Find: "
  @input = para('panda', :weight => 'bold')

  @star = image :left => 275, :top => 3, :width => 20, :height => 20 do
    star 10, 10, 12, 10, 7, :fill => deepskyblue, :stroke => orange
  end

  def show_flickr
    finding_flickr @input.text do |photos|
      @photo = image photos[0], :left => 30, :top => 40
      @e = every 10 do |i|
        @photo.remove
        @photo = image photos[(i + 1) % photos.length], :left => 30, :top => 40
      end
    end
  end

  def clear_flickr
    @e.remove
    @photo.remove
  end

  keypress do |k|
    case k
      when String
        @input.text += k
      when :backspace
        @input.text = @input.text[0..-2]
      else
    end
  end

  show_flickr
  @star.click{clear_flickr; show_flickr}
end

GET request is:

http://www.flickr.com/search/?w=all&q=********&m=text

You can replace ******** to search words like this: dog+cat.

# gallery12-flickr.rb
module FindingFlickr
  require 'hpricot'

  PATH = 'http://www.flickr.com/search/?w=all&q=***&m=text'

  def finding_flickr terms
    return if terms.strip.empty?
    download PATH.sub('***', terms.split.join('+')) do |dl|
      photos = []
      doc = Hpricot dl.response.body
      (doc/"img.pc_img").each do |e|
        e.to_s =~ /src=\"(.*.jpg)/
        photos << $1
      end

      yield photos
    end
  end  
end

gallery12.png

gallery12.png


Gallery No.13

Mandelbrot Set

What a mysterious pattern! Impossible drawing by hand.

Note: the following snippet is so heavy to run. Need big power of cpu.

# gallery13.rb
# Mandelbrot Set No.007

Shoes.app :width => 300, :height => 302, :title => 'Mandelbrot v0.1' do
  MAX, W, H = 200, 300, 300
  x0, y0, w = 1.768606, -0.002229, 0.0000014
  a0, a1 = x0 - w, x0 + w
  b0, b1 = y0 - w, y0 + w

  def mandelbrot a, b
    x, y = 0.0, 0.0
    MAX.times do |i|
      x, y = x * x - y * y - a, 2.0 * x * y - b
      return [x, y, i] if (x * x + y * y) > 4.0
    end
    [x, y, false]  
  end  

  nostroke
  image :width => W, :height => H do
    H.times do |j|
      W.times do |i|
        a, b = a0 + i * (a1 - a0) / W, b0 + j * (b1 - b0) / H
        x, y, diverged = mandelbrot(a, b)
        #oval(i, j, 1) unless diverged
        color = diverged ? rgb(255 - diverged, x.abs, y.abs) : black
        oval i, j, 1, :fill => color
      end
    end
  end
end

gallery13.png

gallery13.png


References

Policeman

Gallery 11 and 13 worked well with Shoes-0.r1263. But Gallery 12 didn't... so far.