Skip to content

Instantly share code, notes, and snippets.

@trpfrog
Last active November 14, 2019 18:53
Show Gist options
  • Save trpfrog/38667e64a8484167b1b429301e60d458 to your computer and use it in GitHub Desktop.
Save trpfrog/38667e64a8484167b1b429301e60d458 to your computer and use it in GitHub Desktop.
つまみアイコンを出力します。
WIDTH = 500
HEIGHT = 500
Pixel = Struct.new(:r,:g,:b)
$img = Array.new(HEIGHT) do
Array.new(WIDTH) do Pixel.new(255,255,255) end
end
def clear
$img = Array.new(HEIGHT) do
Array.new(WIDTH) do Pixel.new(255,255,255) end
end
write_canvas()
end
def pset(x,y,colorset)
unless colorset.length == 3 || colorset.length == 4
raise "Invalid colorset"
return
end
if colorset.length == 4
old_color = [$img[y][x].r, $img[y][x].g, $img[y][x].b]
t = colorset[3]
3.times do |i|
colorset[i] = (1-t) * old_color[i] + t * colorset[i]
end
end
colorset.each do |i|
return if (i<0 || 255<i)
end
if (0<=x && x < WIDTH) && (0 <= y && y < HEIGHT)
$img[y][x].r = colorset[0]
$img[y][x].g = colorset[1]
$img[y][x].b = colorset[2]
end
end
def write_image(name)
open(name,"wb") do |f|
s = "P6\n"+WIDTH.to_s+" "+HEIGHT.to_s+"\n255"
f.puts(s)
max_idx = $img.length-1
$img.each_index do |i|
$img[max_idx-i].each do |p|
f.write(p.to_a.pack("ccc"))
end
end
end
return name+" has been drawn."
end
#-------------------------------------------#
def overlay(img)
img.each_index do |y|
img[y].each_index do |x|
pix = img[y][x]
color = [pix.r,pix.g,pix.b]
pset(x,y,color)
end
end
return "drawn"
end
def marge_map(map_under,map_over,opacity)
map_under.each_index do |y|
map_under.each_index do |x|
colorset = [map_over[y][x].r,map_over[y][x].g,map_over[y][x].b]
next unless valid_color?(colorset)
if opacity != 1
old_color = [map_under[y][x].r, map_under[y][x].g, map_under[y][x].b]
t = colorset[3]
3.times do |i|
colorset[i] = (1-t) * old_color[i] + t * colorset[i]
end
end
map_under[y][x] = Pixel.new(colorset[0],colorset[1],colorset[2])
end
end
return map_under
end
def valid_color?(colorset)
colorset.each do |i|
return false if (i<0 || 255<i) && colorset != [-5,-5,-5]
end
return true
end
def get_layer
layer = Array.new(HEIGHT) do
Array.new(WIDTH) do
Pixel.new(-1,-1,-1)
end
end
return layer
end
def filled_circle(x,y,r,color)
map = get_layer()
for x1 in (x-r.round)..(x+r.round) do
for y1 in (y-r.round)..(y+r.round) do
next if x1 < 0 || WIDTH <= x1 || y1 < 0 || HEIGHT <= y1
if (x1-x)**2 + (y1-y)**2 <= r**2
map[y1][x1] = Pixel.new(color[0],color[1],color[2])
end
end
end
return map
end
def filled_polygon(dots,colorset)
#x,y座標の最大値最小値を設定
x_max = 0; x_min = WIDTH
y_max = 0; y_min = HEIGHT
dots.each do |p|
x_max = p[0] if x_max < p[0]
x_min = p[0] if x_min > p[0]
y_max = p[1] if y_max < p[1]
y_min = p[1] if y_min > p[1]
end
map = get_layer()
invisible = Pixel.new(-1,-1,-1)
marker = Pixel.new(-2,-2,-2)
ignore = Pixel.new(-3,-3,-3)
color = Pixel.new(colorset[0],colorset[1],colorset[2])
l = dots.length
#枠線を描く
dots.each_index do |i|
x1 = dots[i%l][0]; y1 = dots[i%l][1]
x2 = dots[(i+1)%l][0]; y2 = dots[(i+1)%l][1]
if x1 > x2
x1,x2 = x2,x1
y1,y2 = y2,y1
end
next if WIDTH <= x1 || x1 == x2
m = (y1-y2)/(x1-x2).to_f
for j in x1..x2 do
y = (m*(j-x1)+y1).round
next if y<0 || HEIGHT<=y || j<0
map[m*(j-x1)+y1][j] = marker
end
end
#無視する頂点に印をつける
dots.each_index do |i|
x0 = dots[(i-1)%l][0]
x1 = dots[i%l][0]
x2 = dots[(i+1)%l][0]
next if (x0 < x1 && x1 < x2)||(x2 < x1 && x1 < x0)
if x0==x1||x1==x2
2.times do |j|
if dots[(i+j-1)%l][0]==dots[(i+j)%l][0]
y0 = dots[(i+j-1)%l][1]
y1 = dots[(i+j)%l][1]
y0,y1 = y1,y0 if y0 > y1
for y in y0..y1 do
map[y][x1] = ignore
end
end
end
end
map[dots[i][1]][dots[i][0]] = ignore
end
#縦のスキャンラインで塗る
for x in x_min..x_max do
brush = invisible
for y in y_min..y_max do
next if map[y][x]==ignore
if map[y][x]==marker
brush = (brush == color) ? invisible : color
next
end
map[y][x] = brush
end
end
#枠線と頂点を塗る
for x in x_min..x_max do
for y in y_min..y_max do
next unless (map[y][x] == ignore || map[y][x] == marker)
map[y][x] = color
end
end
return map
end
def linear_transfrom(map,matrix,origin)
a = matrix[0][0]; b = matrix[0][1]; c = matrix[1][0]; d = matrix[1][1]
delta_x = origin[0]; delta_y = origin[1]
empty_map = get_layer()
map.each_index do |y|
map[y].each_index do |x|
x1 = (a*(x-delta_x) + b*(y-delta_y) + delta_x).round
y1 = (c*(x-delta_x) + d*(y-delta_y) + delta_y).round
if 0 <= x1 && x1 < WIDTH && 0 <= y1 && y1 < HEIGHT
empty_map[y1][x1] = map[y][x]
end
end
end
return empty_map
end
def pie_kone(map)
empty_map = get_layer()
map.each_index do |y|
map[y].each_index do |x|
if x <= WIDTH/2
x1 = 2*x; y1 = y/2
else
x1 = 2*x-WIDTH; y1 = (y+HEIGHT)/2
end
if 0 <= x1 && x1 < WIDTH && 0 <= y1 && y1 < HEIGHT
empty_map[y1][x1] = map[y][x]
empty_map[y1][x1-1] = map[y][x]
empty_map[y1][x1+1] = map[y][x]
end
end
end
return empty_map
end
def fill_and_line(dots,fillcolor,linecolor,thickness)
fill(dots,fillcolor)
closed_line(dots,linecolor,thickness)
return "drawn"
end
def gradation_polygon(dots,start,goal)
map = filled_polygon(dots,GRADTION_MARKER)
gradation_fill(map,start,goal)
end
GRADTION_MARKER = Pixel.new(-5,-5,-5)
def gradation_fill(map,start,goal)
dots = []
map.each_index do |y|
map[y].each_index do |x|
dots.push([x,y]) if map[y][x]==GRADTION_MARKER
end
end
x_max = 0; x_min = WIDTH
y_max = 0; y_min = HEIGHT
dots.each do |p|
x_max = p[0] if x_max < p[0]
x_min = p[0] if x_min > p[0]
y_max = p[1] if y_max < p[1]
y_min = p[1] if y_min > p[1]
end
steps = y_max - y_min
delta = Array.new(start.length)
delta.each_index do |i|
delta[i] = (goal[i]-start[i]).to_f/steps
end
for y in y_min..y_max
delta.each_index do |i|
start[i] += delta[i]
end
brush = Pixel.new(start[0].round, start[1].round, start[2].round)
for x in x_min..x_max
if map[y][x] == GRADTION_MARKER
map[y][x] = brush
end
end
end
return map
end
def line(start,goal,color,thickness,generation_direction=6)
map = get_layer()
x1 = start[0]; y1 = start[1]
x2 = goal[0]; y2 = goal[1]
steep_slope = (x1 != x2) ? (y1-y2)/(x1-x2).to_f.abs > 1 : true
if(steep_slope)
x1,y1 = y1,x1
x2,y2 = y2,x2
end
if x1 > x2
x1,x2 = x2,x1
y1,y2 = y2,y1
end
m = (y1-y2)/(x1-x2).to_f
for j in x1..x2 do
y = (m*(j-x1)+y1).round
break if j > (steep_slope ? WIDTH : HEIGHT)
next if y<0 || (steep_slope ? WIDTH : HEIGHT) <=y || j<0
unless(steep_slope)
map[y][j] = Pixel.new(color[0],color[1],color[2])
else
map[j][y] = Pixel.new(color[0],color[1],color[2])
end
end
if thickness != 0
delta = steep_slope ? [1,0] : [0,1]
thickness -= 1
if(generation_direction%2==0)
start_1 = [start[0]+delta[0],start[1]+delta[1]]
goal_1 = [goal[0]+delta[0],goal[1]+delta[1]]
marge_map(map,line(start_1,goal_1,color,thickness,2),1)
end
if(generation_direction%3==0)
start_2 = [start[0]-delta[0],start[1]-delta[1]]
goal_2 = [goal[0]-delta[0],goal[1]-delta[1]]
marge_map(map,line(start_2,goal_2,color,thickness,3),1)
end
end
return map
end
def circle_end_line(start,goal,color,thickness)
map = get_layer
map = line(start,goal,color,thickness)
map = marge_map(map,filled_circle(start[0],start[1],thickness,color),1)
map = marge_map(map,filled_circle(goal[0],goal[1],thickness,color),1)
return map
end
def closed_line(dots,color,thickness)
l = dots.length
dots.each_index do |i|
line(dots[i%l],dots[(i+1)%l],color,thickness)
end
end
def background()
puts "Drawing background..."
phase = [499,375,250,100,0]
color = [[0,166,255],[116,209,244],[171,247,255],[255,241,105],[255,241,105]]
map = get_layer()
(phase.length-1).times do |i|
vertexes = [[0,phase[i]],[WIDTH-1,phase[i]],[WIDTH-1,phase[i+1]],[0,phase[i+1]]]
map = marge_map(map,gradation_polygon(vertexes,[color[i+1][0],color[i+1][1],color[i+1][2]],[color[i][0],color[i][1],color[i][2]]),1)
end
overlay(map)
end
def frame()
puts "Drawing frame..."
circle = filled_circle(250,240,250,[255,255,255])
circle = linear_transfrom(circle,[[0.9,0],[0,0.93]],[250,250])
overlay(circle)
map = get_layer()
white = [255,255,255]
front_box = filled_polygon([[183,169],[463,190],[453,0],[189,0]],white)
left_box = filled_polygon([[183,169],[37,160],[47,0],[189,0]],white)
box_wing = filled_polygon([[183,169],[37,160],[0,200],[0,220],[132,230]],white)
back_wing = filled_polygon([[463,190],[450,180],[448,250],[500,500-244],[500,500-259]],white)
magnification = 1.05
ref_point = [[250,100],[249,99],[251,101]]
ref_point.each_index do |i|
map = marge_map(map,linear_transfrom(front_box,[[magnification,0],[0,magnification]],ref_point[i]),1)
map = marge_map(map,linear_transfrom(left_box,[[magnification,0],[0,magnification]],ref_point[i]),1)
map = marge_map(map,linear_transfrom(box_wing,[[magnification,0],[0,magnification]],ref_point[i]),1)
map = marge_map(map,linear_transfrom(back_wing,[[magnification,0],[0,magnification]],ref_point[i]),1)
end
overlay(map)
end
def back_wing()
puts "Drawing back wing..."
overlay(filled_polygon([[463,190],[450,180],[448,250],[500,500-244],[500,500-259]],[176,135,0]))
end
def face()
puts "Drawing ball..."
#c_coord = relative_coord(0.5,0.48)
circle = filled_circle(250,240,240,GRADTION_MARKER)
gradation_fill(circle,[144,226,0],[144,255,0])
circle = linear_transfrom(circle,[[0.9,0],[0,0.93]],[250,250])
puts "Drawing face..."
eye_coord = [[208,325,17],[341,337,16]]
eye_coord.each do |eye|
eye_map = filled_circle(eye[0],eye[1],eye[2],GRADTION_MARKER)
eye_map = gradation_fill(eye_map,[0,0,0],[10,10,10])
circle = marge_map(circle,eye_map,1)
end
circle = marge_map(circle,circle_end_line([254,307-20],[311,310-18],[0,0,0],3),1)
overlay(circle)
end
def box()
puts "Drawing box..."
front_box = filled_polygon([[183,169],[463,190],[453,0],[189,0]],[224,195,154])
left_box = filled_polygon([[183,169],[37,160],[47,0],[189,0]],[179,132,94])
box_wing = filled_polygon([[183,169],[37,160],[0,200],[0,220],[132,230]],[134,84,0])
front_tape = filled_polygon([[303,178],[342,500-319],[350,0],[312,0]],[215,167,0])
left_tape = filled_polygon([[114,500-335],[90,500-337],[96,0],[121,0]],[132,100,0])
wing_tape = filled_polygon([[114,500-335],[90,500-337],[34,500-278],[59,500-276]],[100,61,0])
map = get_layer()
map = marge_map(map,front_box,1)
map = marge_map(map,left_box,1)
map = marge_map(map,front_tape,1)
map = marge_map(map,left_tape,1)
map = marge_map(map,box_wing,1)
map = marge_map(map,wing_tape,1)
overlay(map)
end
def draw()
background()
frame()
back_wing()
face()
box()
write_image("trpfrog.ppm")
end
draw()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment