巷ではシダを生やすのが流行っているようですが、
意外にも Ruby での投稿がなかったようなのでやってみました。
shida.rb
require "RMagick"
require "open3"
class ShidaGenerator
include Magick
N = 20
DEFAULT_WIDTH = 500
DEFAULT_HEIGHT = 500
FILE_NAME = "shida.jpg"
W1x = -> (x, y) { 0.836 * x + 0.044 * y }
W1y = -> (x, y) { -0.044 * x + 0.836 * y + 0.169 }
W2x = -> (x, y) { -0.141 * x + 0.302 * y }
W2y = -> (x, y) { 0.302 * x + 0.141 * y + 0.127 }
W3x = -> (x, y) { 0.141 * x - 0.302 * y }
W3y = -> (x, y) { 0.302 * x + 0.141 * y + 0.169 }
W4x = -> (x, y) { 0 }
W4y = -> (x, y) { 0.175337 * y }
def initialize(width = DEFAULT_WIDTH, height = DEFAULT_HEIGHT)
@width = width
@height = height
end
def self.show(width = DEFAULT_WIDTH, height = DEFAULT_HEIGHT)
self.new(width, height).show
end
def generate
image = Magick::Image.new(@width, @height)
f = -> (k, x, y) do
if 0 < k
f.(k - 1, W1x.(x, y), W1y.(x, y))
f.(k - 1, W2x.(x, y), W2y.(x, y)) if Random.rand < 0.3
f.(k - 1, W3x.(x, y), W3y.(x, y)) if Random.rand < 0.3
f.(k - 1, W4x.(x, y), W4y.(x, y)) if Random.rand < 0.3
else
xx = (x * 490 + @width * 0.5).to_i
yy = (@height - y * 490).to_i
image.store_pixels(xx, yy, 1, 1, [green_pixel])
end
end
-> (k, x, y) { f.(k, x, y) }.(N, 0, 0)
image
end
def show
self.generate.write(image_path)
system("open -a Preview #{image_path}") if open_command_exists?
end
private
def green_pixel
@pixel ||= Magick::Pixel.new(0, 128 * 256, 0)
end
def image_path
current_dir = File.expand_path(File.dirname(__FILE__))
File.join(current_dir, FILE_NAME)
end
def open_command_exists?
Open3.capture3("which open").first.empty?.!
end
end
exit unless __FILE__ == $0
ShidaGenerator.show
当初は ShidaGenerator#render メソッドを再帰的に呼んで描画処理を行っていたのですが、
インスタンスメソッドを再帰的に呼ぶのが嫌だったので、メソッド内で lambda を再帰的に呼ぶことで実現しました。
それと、本当は tk を使って GUI で表示したかったんですが、何時間か試しても実現できませんでした…。
そのため妥協案として JPEG 画像を生成して Mac の場合はそれをプレビューで表示するようにしました。
結果
元ネタ
- プログラムでシダを描画する - 強火で進め
- 「プログラムでシダを描画する」をDartで描画する - Qiita
- 「プログラムでシダを描画する」をGoで描画する - Qiita
- Clojure - プログラムでシダを描画する - Qiita
- 「プログラムでシダを描画する」をPythonで描画する - Qiita
- 「プログラムでシダを描画する」をJavaScript+Canvasで描画する - Qiita
- 「プログラムでシダを描画する」をPHPで描画する - Qiita
- 「プログラムでシダを描画する」をEmacs Lispで描画する
- 「プログラムでシダを描画する」をSass(CSS)で描画する