質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

2回答

1427閲覧

2次元配列を使った画像表現について

pal_rex

総合スコア12

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

0クリップ

投稿2018/11/14 03:59

2次元配列を用いて内トロコイドを描きたい。

現在学校の課題で、2次元配列を用いて図形を描けという課題が出て、私は内トロコイド(ハイポトロコイド)を描こうとし、下記のコードを書いたのですがいまいち上手に書けません。間違っているところがあれば教えてくれると幸いです。コード内のpsetはある座標に色を塗るメソッドで、hypotrochoidメソッドが内トロコイドを描くメソッドになっています。
以下の式が内トロコイドの式になります。
イメージ説明

発生している問題・エラーメッセージ

psetメソッドが「Y 座標が大きいほど下」に点を打つようになっており、「Y 座標が大きいほど上」に点を打つようになっていないため、混乱しています。

該当のソースコード

Ruby

1Pixel = Struct.new(:r, :g, :b) 2$img = Array.new(300) do 3 Array.new(300) do Pixel.new(255,255,255) end 4end 5def pset(x, y, r, g, b, a = 0.0) #ある座標に点を打つ 原点中心にする必要あり!! 6 if x < 0 || x >= 300 || y < 0 || y >= 300 then return end 7 $img[y][x].r = ($img[y][x].r * a + r * (1.0 - a)).to_i 8 $img[y][x].g = ($img[y][x].g * a + g * (1.0 - a)).to_i 9 $img[y][x].b = ($img[y][x].b * a + b * (1.0 - a)).to_i 10end 11 12def hypotrochoid(rc,rm,rd,r,g,b,a=0.0) 13 0.step(360) do |theta| 14 pset(Math.cos(theta / 180.0 * Math::PI) * (rc-rm) + rd * Math.cos((rc-rm)/rm * theta / 180.0 * Math::PI), 15 Math.sin(theta / 180.0 * Math::PI) * (rc-rm) - rd * Math.sin((rc-rm)/rm * theta / 180.0 * Math::PI), 16 r,g,b,a) 17 end 18end 19 20def writeimage(name) 21 open(name, "wb") do |f| 22 f.puts("P6\n300 200\n255") 23 $img.each do |a| 24 a.each do |p| f.write(p.to_a.pack("ccc")) end 25 end 26 end 27end 28 29def mypicture 30 hypotrochoid(180,130,250,0,0,0) 31 writeimage("t.ppm") 32end 33

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

300,300のバッファを作った時

x:-150...+149
y:-149...+150
の中央を原点とした座標系を用いる事を考えると

rb

1RGB = Struct.new(:r, :g, :b) 2Pixel = RGB 3RGBA = Struct.new(:r, :g, :b, :a) do 4 def blend(rgb) 5 new_values = rgb.each_pair.with_object({}) do |(key, val), memo| 6 memo[key] = val * a + self[key] * (1-a) 7 end 8 RGB.new(*new_values.values_at(:r, :g, :b)) 9 end 10 end 11 12class ImageArray 13 def initialize(width = 300, height = 300) 14 @img = Array.new(width) do 15 Array.new(height) do 16 Pixel.new(255, 255, 255) 17 end 18 end 19 @width = width 20 @height = height 21 @width_range = Range.new(-width/2.0, width/2.0, width.even?) 22 @height_range = Range.new(-height/2.0, height/2.0, height.even?) 23 end 24 def pset(x, y, color) 25 unless @width_range.cover?(x) && @height_range.cover?(-y) 26 raise ArgumentError.new "unexpected point of #{x},#{y}.\nexpected x:#{@width_range}, -y:#{@height_range}" 27 end 28 x = @width / 2 + x 29 y = @height / 2 - y 30 col = case color 31 when RGBA then color 32 when RGB then RGBA.new(*color.values, 0) 33 when Array 34 case color.size 35 when 3 then RGBA.new(*color, 0) 36 when 4 then RGBA.new(*color) 37 else 38 raise ArgumentError.new color 39 end 40 else 41 raise ArgumentError.new color 42 end 43 @img[x][y] = col.blend(@img[x][y]) 44 end 45 attr_reader :img 46end

使い方兼テスト

rb

1image = ImageArray.new(4,4) 2 3image.pset(0,-1, [1,1,1]) 4image.pset(0, 2, [2,2,2]) 5image.pset(1, 0, [3,3,3]) 6image.pset(-2,0, [4,4,4]) 7 8pp image.img

投稿2018/11/14 05:45

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

すみませんが具体的なコードへの指摘ではなく、一つのアイデアのコメントです。

psetメソッドが「Y 座標が大きいほど下」に点を打つようになっており、「Y 座標が大きいほど上」に点を打つようになっていないため、混乱しています。

これよくわかります。大抵の計算機のGUIシステムの座標系では水平方向はいわゆるx-y平面の座標に合致しますが、垂直方向では「多分ソフトウェアの作りの都合上」逆方向になっていることが多いと思います。

そこでコードを書く際にこうした混乱をせずにわかりやすく記述する工夫をしてみるのも一考の価値ありと思います。

psetの引数のy座標の範囲を0~300ではなくて-300~0にしてみてはいかがでしょう?psetの中でy座標の符号を逆転して扱えばコードはほとんどかわりません。またpsetを使う側のコードでは数学的なy座標の値そのもので計算論理を考えることができるようになります。ちょっとしたことのようですがやってみると「結構気持ちよくスッキリ記述できる」のではないでしょうか?

投稿2018/11/14 04:39

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問