GTK+で落書き 4(Ruby)

引き続き Gem 'oekaki' で落書きです。
oekaki | RubyGems.org | your community gem host
GTK+でお絵かきしてみた(Ruby) - Camera Obscura



Ruby コード。

require 'oekaki'
include Math

L = 300; O = L / 2
R = 140
step = 20

i = 0

Oekaki.app width: L, height: L do
  draw do
    color(0, 0, 0)
    rectangle(true, 0, 0, L, L)
    color(0x87 * 256, 0xce * 256, 0xeb * 256)    #skyblue
    arc(false, O - R, O - R, R * 2, R * 2, 0, 64 * 360)
  end
  
  id = timer(500) do
    ar = []
    θ = i * step * PI / 180
    x = R * cos(θ)
    y = R * sin(θ)
    ar << [O + x, O - y]
    3.times do
      x, y = -y, x
      ar << [O + x, O - y]
    end
    color(0x22 * 256, 0x8b * 256, 0x22 * 256)    #forestgreen
    polygon(false, ar)
    i += 1
    Gtk.timeout_remove(id) if i * step > 180
    true
  end
end

GTK+ でぽちぽち遊び(Ruby)

キャンバス上でマウスクリックして下さい。ぽちぽち円が描かれます。


右クリックで終了ボタンが出ます。


Ruby コード。

require 'oekaki'

L = 500; R = 25

Oekaki.app width: L, height: L do
  draw do
    color(0, 0, 0)
    rectangle(true, 0, 0, L, L)
  end
  
  quit_window = proc do
    make_window do |w|
      w.title = ""
      b = button do
        set_size_request(120, 40)
        add(Gtk::Label.new.set_markup('<span size="x-large">Quit!</span>'))
        signal_connect("clicked") {Gtk.main_quit}
      end
      add(b)
    end
  end

  mouse_button do |w, e|
    quit_window.call if e.button != 1
    color(rand(65536), rand(65536), rand(65536))
    arc(true, e.x - R, e.y - R, R * 2, R * 2, 0, 64 * 360) 
  end
end

 
Gem 'oekaki'(かつての 'mygtk')については
GTK+でお絵かきしてみた(Ruby) - Camera Obscura
メソッド Event#mouse_button, Event#make_window, Gtk::Window#button を加えました。
oekaki | RubyGems.org | your community gem host

複素フィボナッチ数列と GTK+ お絵かき

GTK+でお絵かきしてみた(Ruby) - Camera Obscura
これまで mygtk.rb と言っていた GTK+ お絵かきモジュールを、Gem 'oekaki' として RubyGems.org に登録いたしました。よろしかったら使ってやって下さい。
oekaki | RubyGems.org | your community gem host
その簡単な記録が
最小限度の Ruby Gem 作成と公開 - Marginalia
であります。


それとちょっと関係してといいますか、いつも拝読しているブログ「完全無欠で荒唐無稽な夢」の記事に、複素フィボナッチ数列というおもしろそうな題材がありましたので、お絵かきしてみました。数列を複素平面にプロットしただけであります。ただし、ものすごい勢いで原点から遠ざかったりもするので、原点からの距離は対数をとってあります。
複素フィボナッチ数列の件 - 完全無欠で荒唐無稽な夢

複素フィボナッチ数列とは,
  
というものですね。

まず、
  
の場合。

わかりにくいけれど、螺旋ですね。

上ブログ記事にあった、
  
の場合。

あんまり変わらないですかね。


Ruby のコード。

require 'oekaki'

L = 400
a = Complex(1, -1)
b = Complex(1,  1)

Oekaki.app width: L, height: L do
  draw do
    color(0, 0, 0)
    rectangle(true, 0, 0, L, L)
  end
  
  plot = lambda do |a|
    x1 = a.real
    y1 = a.imaginary
    r = Math.sqrt(x1 ** 2 + y1 ** 2)
    l = Math.log(r) * 2.5
    x = L / 2 + 1 + x1 * l / r
    y = L / 2 + 1 - y1 * l / r
    color(0, 65535, 0)
    arc(false, x, y, 3, 3, 0, 64 * 360) rescue return
  end  
  
  timer(20) do
    plot.call(a)
    a, b = b, b + Complex::I * a
  end
  
  key_in do |w, e|
    Gtk.main_quit if e.keyval == Gdk::Keyval::GDK_Return
  end
end

リターンキーで画面が閉じます。

Ruby Gem できた

野良 Gem の作り方(Ruby) - Camera Obscura
以前「野良 Gem」(「野良」なのは、僕が RubyGems.org に登録していないからです)を作ったのですが、いいかげんなやり方だったので、書き直してみます。

gem 'mygtk' を作ってみます。git が必要なので、なければインストールして下さい。
GitHub のアカウントに mygtk というリポジトリを作っておきます。
また、以下 Bundler を使うので、インストールしておいて下さい。


好きなディレクトリで

$ bundle gem mygtk

を実行します。すると mygtk フォルダが出来、色いろ他のファイルも作成されます。

$ cd mygtk

でフォルダの中に入ります。この中にある、mygtk.gemspec というファイルの中身を変更します。具体的には上のリンク先を見て下さい。spec.summary と spec.description は必ず中身を記述しなくてはなりません。また、依存する Gem があれば spec.add_dependency も記述します(標準添付ライブラリについては必要ありません)。

lib というディレクトリに入って、中の mygtk.rb を書きます(先頭に require "mygtk/version" が必要です)。これが require される Gem の本体になります。

git のインデックス(ステージ領域)に追加し、コミットします。

$ git add -A
$ git commit -m 'first commit'

Gem を作ります。

$ rake install

これで Gem が出来ているので、irb で require 'mygtk' などしてみて確認します。

リモートリポジトリ(この場合は GitHub)にファイルを上げます。

$ git remote add origin git@github.com:obelisk68/mygtk.git
$ git push -u origin master

リリースします。RubyGems.org に登録していれば、これで Gem が公開されます。登録していない場合はここでフリーズするので、しばらくして [Ctrl]+[C] で中断します。

$ rake release

これで GitHub に(野良)Gem が置かれました。終了です。


これで RubyGem に上げていれば、あとはふつうに Gem として使ってください。
「野良」の場合は、Bundler でインストールできます。Gemfile に

gem 'mygtk', github: 'obelisk68/mygtk'

と記述して、

$ bundle install

でインストールできます。使い方は以下。
GTK+でお絵かきしてみた(Ruby) - Camera Obscura


※参考
bundle gemは何をしてくれるのか? - ザリガニが見ていた...。
サルでもわかるGit入門 〜バージョン管理を使いこなそう〜 | どこでもプロジェクト管理バックログ

Ruby 実行のエラー時に n 回リトライするメソッド

n.times_retry でブロック内をエラーがあれば最大 n 回再実行し、それを超えれば停止します。エラーがないかリトライに成功すれば、そのまま次へ処理が渡されます。

引数の massage は true ならば情報を出力します(デフォルト true)。wait: n は retry の前に n秒スリーブします(デフォルトは 0)。ブロック引数の i は i 回目の実行ということです。

5.times_retry(message: true, wait: 1) do |i|
  puts i
  if i <= 3
    raise "sample error"
  end
end
puts "success"

__END__
#出力
1
Error: retry 1
times_retry.rb:23:in `block in <main>'
times_retry.rb:5:in `times_retry'
times_retry.rb:21:in `<main>'
2
Error: retry 2
times_retry.rb:23:in `block in <main>'
times_retry.rb:5:in `times_retry'
times_retry.rb:21:in `<main>'
3
Error: retry 3
times_retry.rb:23:in `block in <main>'
times_retry.rb:5:in `times_retry'
times_retry.rb:21:in `<main>'
4
success

 
メソッドのコード。

class Integer
  def times_retry(message: true, wait: 0)
    n = 1
    begin
      yield(n)
    rescue => e
      if n <= self
        puts "Error: retry #{n}" if message
        puts e.backtrace if message
        n += 1
        sleep(wait)
        retry
      end
      puts "Error: stop" if message
      raise e
    end
  end
end

GTK+で落書き 3(Ruby)


周転円みたいな。


ライブラリ「MyGtk」についてはこちら

require_relative 'mygtk'
include Math

L = 400
R1 = 150; R2 = (L - R1 * 2) / 2 - 5
STP1 = (PI / 180) * 0.5; STP2 = (PI / 180) * 10

MyGtk.app width: L, height: L do
  draw do
    color(5000, 0, 10000)
    rectangle(true, 0, 0, L, L)
  end

  i = 0
  
  id = timer(20) do
    x = L / 2 + (R1 * cos(STP1 * i) + R2 * cos(STP2 * i))
    y = L / 2 - (R1 * sin(STP1 * i) + R2 * sin(STP2 * i))
    color(0, 65535, 0)
    arc(false, x, y, 3, 3, 0, 64 * 360)
    i += 1
    Gtk.timeout_remove(id) if STP1 * i > PI * 2
    true
  end
end

コールバック関数は true を返さないといけません。

GTK+で落書き 2(Ruby)

MF / 今日の落書き Ruby/Tk で フィボナッチ配列(螺旋)
ここのパクリです。



ライブラリ「MyGtk」についてはここを参照。

require_relative 'mygtk'
include Math

ANGLE = 2 * PI * (1 + sqrt(5)) / 2

MyGtk.app width:300, height: 300, title: :Fibonacci do
  draw do
    color(0, 0, 0)
    rectangle(true, 0, 0, 300, 300)
    
    2000.times do |t|
      angle = t * ANGLE
      r = t * 0.1
      x = 147 + r * cos(angle)
      y = 147 + r * sin(angle)
      color(0, 65535, 0)
      arc(false, x, y, 3, 3, 0, 64 * 360)
    end
  end
end