注意
このファイルを使う際には、必ず同じ階層に「colorName.csv」を配置してください。
配置していない場合、カーラネームでの色の指定ができません。
設定用関数
設定用関数です。
描画には関係ありません。
init関数
[引数] スクリーンサイズ x座標(デフォルト 1980), スクリーンサイズ y座標(デフォルト 1080)
[説明]
初期化用関数。draw関数内で必ず最初に使用してください。
デフォルトサイズ 1980x1080
pset関数
[引数] 点を打つ x座標, 点を打つ y座標, 色(デフォルト 0, 0, 0), 透明度(0.0)
[説明]
指定した座標に指定した色、透明度で点を打ちます。
writeimage関数
[引数] 書き込むファイル名
[説明]
データをppmファイルに書き込みます。ppmファイルのみ指定できます。
計算用関数
描画に使う計算をするための関数です。
deg2rad関数
[引数] 弧度法に変換したい角度(度数法)
[説明]
度数法(deg)を弧度法(rad)に変換します。
Math.sin, Math.cosなどの引数に度数法を指定したいときに使用します。
getColor関数
[引数] カラーコード(文字列)
[説明]
カラーコードもしくはカラーネームをrgbに変換します。「#ffffff」のような形で指定してください。
カラーネームについては
https://www.webcreatorbox.com/webinfo/color-name
を参照してください。
描画用関数
図形を描画するための関数です。
background関数
[引数] 色(デフォルト 0, 0, 0), 透明度(0.0)
[説明]
背景を描画します。
line関数
[引数] 開始 x座標, 開始 y座標, 終点 x座標, 終点 y座標, 幅, 色(デフォルト 0, 0, 0), 透明度(0.0)
[説明]
線を描画します。
circle関数
[引数] 中心 x座標, 中心 y座標, 半径, 色(デフォルト 0, 0, 0), 透明度(0.0)
[説明]
塗りつぶされた円を描画します。
枠線を描画したい場合はdonut関数を使用して下さい。
ellipse関数
[引数] 中心 x座標, 中心 y座標, 横(x軸方向)の半径, 縦(y軸方向)の半径, 回転角度(度数法)(デフォルト 0.0), 色(デフォルト 0, 0, 0), 透明度(0.0)
[説明]
塗りつぶされた楕円を描画します。
回転角度には度数法を指定します。
donut関数
[引数] 中心 x座標, 中心 y座標, 半径1, 半径2 色(デフォルト 0, 0, 0), 透明度(0.0)
[説明]
ドーナツ型を描画します。
半径2 < 半径1となるように引数を指定してください
triangle関数
[引数] 頂点 x座標1, 頂点 y座標1, 頂点 x座標2, 頂点 y座標2, 頂点 x座標3, 頂点 y座標3, 色(デフォルト 0, 0, 0), 透明度(0.0)
[説明]
三角形を描画します。
rect関数
[引数] 中心 x座標, 中心 y座標, 幅, 高さ, 色(デフォルト 0, 0, 0), 透明度(0.0)
[説明]
長方形を描画します。
trapezoid関数
[引数] 中心 x座標, 中心 y座標, 上底の長さ, 下底の長さ, 高さ, 色(デフォルト 0, 0, 0), 透明度(0.0)
[説明]
台形を描画します。
rhombus関数
[引数] 中心 x座標, 中心 y座標, 幅, 高さ, 色(デフォルト 0, 0, 0), 透明度(0.0)
[説明]
ひし形を描画します。
star関数
[引数] 中心 x座標, 中心 y座標, 外接円の半径, 頂点の数, 回転角度(弧度法)(デフォルト 0.0) 色(デフォルト 0, 0, 0), 透明度(0.0)
[説明]
星形を描画します。
回転角度には弧度法を指定してください。
[参考] http://blog.livedoor.jp/reona396/archives/54602822.html
polygon関数
[引数] 中心 x座標, 中心 y座標, 外接円の半径, 頂点の数, 回転角度(弧度法)(デフォルト 0.0) 色(デフォルト 0, 0, 0), 透明度(0.0)
[説明]
正多角形を描画します。
回転角度には弧度法を指定してください。
[参考] http://blog.livedoor.jp/reona396/archives/54602822.html
convex関数
[引数] 頂点 x座標の配列, 頂点 y座標の配列, 回転角度(弧度法)(デフォルト 0.0) 色(デフォルト 0, 0, 0), 透明度(0.0)
[説明]
凸多角形を描画します。
凹みがある場合は描写できません。
#メイン関数
描画用の処理を書くための関数です。
draw関数
[説明]
init関数を一番最初に記述してください。
最後にwriteimage関数で画像を描画します。
ファイルのダウンロード
右上の緑の「Code」から「Download ZIP」を選択するとダウンロードできます。
全体のプログラム
# drawImg.rb
#
# ========== settings ==========
#
require "csv"
Pixel = Struct.new(:r, :g, :b)
# init func
# [args] screenSizeX, screenSizeY
def init(screenSizeX = 1980, screenSizeY = 1080)
# create colorNameArray
# [Reference] https://www.webcreatorbox.com/webinfo/color-name
$colorName = CSV.read("colorName.csv")
# default screenSize
$screenX = screenSizeX
$screenY = screenSizeY
# default var draw area
$i0 = 0
$i1 = $screenX
$j0 = 0
$j1 = $screenY
# define goldenRatio
$goldenRatio = 1.618
# create imgArray
$img = Array.new($screenY) do
Array.new($screenX) do
Pixel.new(255, 255, 255)
end
end
end
# pointSet func
# [args] x, y, color, a
def pset(x, y, color = [255, 255, 255], a = 0.0)
# error
if x < 0 || x >= $screenX || y < 0 || y >= $screenY
return
end
r = color[0]
g = color[1]
b = color[2]
$img[y][x].r = ($img[y][x].r * a + r * (1.0 - a)).to_i
$img[y][x].g = ($img[y][x].g * a + g * (1.0 - a)).to_i
$img[y][x].b = ($img[y][x].b * a + b * (1.0 - a)).to_i
end
# writeImage func
# [args] filename
def writeimage(name)
s = "P6\n" + $screenX.to_s + " " + $screenY.to_s + "\n255"
open(name, "wb") do |f|
f.puts(s)
$img.each do |a|
a.each do |p|
f.write(p.to_a.pack("ccc"))
end
end
end
return true
end
#
# ========== calc func ==========
#
# deg => rad func
# [args] theta(deg)
def deg2rad(theta)
return theta * Math::PI / 180.0
end
# judge isinside func
# [args] x, y, arrayX, arrayY
# [Reliance] oprod
def isinside(x, y, ax, ay)
(ax.length-1).times do |i|
if oprod(ax[i+1]-ax[i], ay[i+1]-ay[i], x-ax[i], y-ay[i]) < 0
return false
end
end
return true
end
# get outer product
# [args] a, b, c, d
def oprod(a, b, c, d)
return a*d - b*c
end
# getColor (colorCode to rgba)
# [args] colorCode
def getColor(colorCode)
rgb = Array.new()
# colorName check
$colorName.each_index do |i|
if colorCode === $colorName[i][0]
colorCode = $colorName[i][1]
break
end
end
# convert colorCode
if colorCode[0] === "#"
1.step(6, 2) do |i|
str = colorCode[i] + colorCode[i+1]
rgb.push(str.to_i(16))
end
else
rgb.push(0)
rgb.push(0)
rgb.push(0)
end
return rgb
end
# set draw area func
# [args] x0, x1, y0, y1
def setDrawArea(x0, x1, y0, y1)
$i0 = x0.to_i
$i1 = x1.to_i
$j0 = y0.to_i
$j1 = y1.to_i
end
#
# ========== draw shape func ==========
#
# draw background func
# [args] color, a
def background(color = [0, 0, 0], a = 0.0)
$screenY.times do |j|
$screenX.times do |i|
pset(i, j, color, a)
end
end
end
# draw line
# [args] startX, startY, endX, endY, width, color, a
# [Reliance] convex
def line(x0, y0, x1, y1, w, color = [0, 0, 0], a = 0.0)
dx = y1 - y0
dy = x0 - x1
n = 0.5 * w / Math.sqrt(dx**2 + dy**2)
dx *= n
dy *= n
convex([x0-dx, x0+dx, x1+dx, x1-dx, x0-dx], [y0-dy, y0+dy, y1+dy, y1-dy, y0-dy], color, a)
end
# draw circle func
# [args] centerX, centerY, radius, color, a
def circle(x, y, rad, color = [0, 0, 0], a = 0.0)
setDrawArea(x-rad, x+rad, y-rad, y+rad)
$j0.step($j1) do |j|
$i0.step($i1) do |i|
if (i - x)**2 + (j - y)**2 < rad**2
if block_given?
yield(i, j)
else
pset(i, j, color, a)
end
end
end
end
end
# draw ellipse func
# [args] centerX, centerY, radiusX, radiusY, rotateTheta(deg), color, a
def ellipse(x, y, radX, radY, theta = 0.0, color = [0, 0, 0], a = 0.0)
d = (if radX > radY then radX else radY end)
setDrawArea(x-d, x+d, y-d, y+d)
thetaRad = theta * Math::PI / 180
$j0.step($j1) do |j|
$i0.step($i1) do |i|
dx = i - x
dy = j - y
px = dx * Math.cos(thetaRad) - dy * Math.sin(thetaRad)
py = dx * Math.sin(thetaRad) + dy * Math.cos(thetaRad)
if (px/radX)**2 + (py/radY)**2 < 1.0
if block_given?
yield(i, j)
else
pset(i, j, color, a)
end
end
end
end
end
# draw donut func
# [args] centerX, centerY, radius1, radius2, color, a
def donut(x, y, rad1, rad2, color = [0, 0, 0], a = 0.0)
setDrawArea(x-rad1, x+rad1, y-rad1, y+rad1)
$j0.step($j1) do |j|
$i0.step($i1) do |i|
d = (i - x)**2 + (j - y)**2
if rad2**2 < d && d < rad1**2
if block_given?
yield(i, j)
else
pset(i, j, color, a)
end
end
end
end
end
# draw triangle func
# [args] x0, y0, x1, y1, x2, y2, color, a
# [Reliance] convex
def triangle(x0, y0, x1, y1, x2, y2, color = [0, 0, 0], a = 0.0)
convex([x0, x1, x2, x0], [y0, y1, y2, y0], color, a)
convex([x0, x2, x1, x0], [y0, y2, y1, y0], color, a)
end
# draw rect func
# [args] centerX, centerY, width, height, color, a
def rect(x, y, w, h, color = [0, 0, 0], a = 0.0)
setDrawArea(x-0.5*w, x+0.5*w, y-0.5*h, y+0.5*h)
$j0.step($j1) do |j|
$i0.step($i1) do |i|
if block_given?
yield(i, j)
else
pset(i, j, color, a)
end
end
end
end
# draw trapezoid func
# [args] centerX, centerY, topLength, bottomLength, height, color, a
# [Reliance] convex
def trapezoid(x, y, u, b, h, color = [0, 0, 0], a = 0.0)
convex([x+u/2, x+b/2, x-b/2, x-u/2, x+u/2], [y-h/2, y+h/2, y+h/2, y-h/2, y-h/2], color, a)
end
# draw rhombus func
# [args] centerX, centerY, width, height, color, a
# [Reliance] convex
def rhombus(x, y, w, h, color = [0, 0, 0], a = 0.0)
convex([x, x+w, x, x-w, x], [y-h, y, y+h, y, y-h], color, a)
end
# draw star func
# [args] centerX, centerY, radius, vertexNum, theta, color, a
# [Reliance] convex
# [Reference] http://blog.livedoor.jp/reona396/archives/54602822.html
def star(x, y, rad, vertexNum, theta = 0.0, color = [0, 0, 0], a = 0.0)
rOut = rad
rIn = rad / 2.0
vertexNum *= 2
(vertexNum/2).times do |i|
x1 = rOut * Math.cos(deg2rad((360 / vertexNum * i * 2) - 90 + theta).to_f) + x
x2 = rIn * Math.cos(deg2rad((360 / vertexNum * (i * 2 + vertexNum + 1)) - 90 + theta).to_f) + x
x3 = x
x4 = rIn * Math.cos(deg2rad((360 / vertexNum * (i * 2 + vertexNum - 1)) - 90 + theta).to_f) + x
y1 = rOut * Math.sin(deg2rad((360 / vertexNum * i * 2) - 90 + theta).to_f) + y
y2 = rIn * Math.sin(deg2rad((360 / vertexNum * (i * 2 + vertexNum + 1)) - 90 + theta).to_f) + y
y3 = y
y4 = rIn * Math.sin(deg2rad((360 / vertexNum * (i * 2 + vertexNum - 1)) - 90 + theta).to_f) + y
convex([x1, x2, x3, x4, x1], [y1, y2, y3, y4, y1], color, a)
end
end
# draw polygon func
# [args] centerX, centerY, radius, vertexNum, theta, color, a
# [Reliance] convex
# [Reference] http://blog.livedoor.jp/reona396/archives/54602822.html
def polygon(x, y, rad, vertexNum, theta = 0.0, color = [0, 0, 0], a = 0)
ax = Array.new()
ay = Array.new()
vertexNum.times do |i|
ax.push(rad * Math.cos(deg2rad((360 / vertexNum * i) - 90).to_f) + x)
ay.push(y1 = rad * Math.sin(deg2rad((360 / vertexNum * i) - 90).to_f) + y)
end
ax.push(rad * Math.cos(deg2rad(-90 + theta).to_f) + x)
ay.push(rad * Math.sin(deg2rad(-90 + theta).to_f) + y)
convex(ax, ay, color, a)
end
# draw convex func
# [args] arrayX, arrayY, r, g, b, a
# [!Caution!] Enter counterclockwise
# [Reliance] isinside
def convex(ax, ay, color = [0, 0, 0], a = 0.0)
setDrawArea(ax.min, ax.max, ay.min, ay.max)
$j0.step($j1) do |j|
$i0.step($i1) do |i|
if isinside(i, j, ax, ay)
if block_given?
yield(i, j)
else
pset(i, j, color, a)
end
end
end
end
end
# draw func (drawPicture)
# [args] none
def draw
#init
init()
# ここに処理を記述
# write
writeimage("img.ppm")
return true
end
draw()