Last active
November 14, 2019 18:53
-
-
Save trpfrog/38667e64a8484167b1b429301e60d458 to your computer and use it in GitHub Desktop.
つまみアイコンを出力します。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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