RMagickでサインカーブ

December 20, 2019

今後同じようなコードを何度も書きそうだったので、MagickCanvasという怪しげなクラスを用意しました。

https://github.com/tnantoka/ruby.tnantoka.com/blob/17f6b32fa974eeb4dc16f1b4f51db45570742765/rmagick/magick_canvas.rb

これを使ってサインカーブ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# frozen_string_literal: true

require_relative 'magick_canvas'

class Canvas < MagickCanvas
  AMPLITUDE = 50
  FREQUENCY = 5

  def options
    {
      directory: File.expand_path('../tmp', __dir__),
      width: 400,
      height: 200
    }
  end

  def draw(image, _frame_count)
    points = (0..width).flat_map do |x|
      [
        x,
        center.y + Math.sin(radians(x) * FREQUENCY) * AMPLITUDE
      ]
    end

    gc = Draw.new
    gc.stroke('white').stroke_width(1)
    gc.polyline(*points)
    gc.draw(image)
  end
end

Canvas.new.open

https://github.com/tnantoka/ruby.tnantoka.com/blob/17f6b32fa974eeb4dc16f1b4f51db45570742765/rmagick/sine_wave_png.rb

アニメーションGIFにも対応。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# frozen_string_literal: true

require_relative 'magick_canvas'

class Canvas < MagickCanvas
  AMPLITUDE = 50
  FREQUENCY = 5

  def options
    {
      directory: File.expand_path('../tmp', __dir__),
      width: 400,
      height: 200,
      number_of_frames: 60
    }
  end

  def draw(image, frame_count)
    range = -30.step(30, 2).to_a
    amplitude = (range + range.reverse)[frame_count]

    gc = Draw.new
    gc.stroke('white').stroke_width(1)
    gc.polyline(*points(amplitude))
    gc.draw(image)
  end

  private

  def points(amplitude)
    (0..width).flat_map do |x|
      [
        x,
        center.y + Math.sin(radians(x) * FREQUENCY) * amplitude
      ]
    end
  end
end

Canvas.new.open

https://github.com/tnantoka/ruby.tnantoka.com/blob/17f6b32fa974eeb4dc16f1b4f51db45570742765/rmagick/sine_wave_gif.rb

わりとうまく動いたのでgemにしようかな。