#!ruby -Ks # -*- mode: ruby; encoding: sjis -*- # Last updated: <2014/05/29 06:26:19 +0900> # # Xiaolin Wu's line algorithm - Rosetta Code # http://rosettacode.org/wiki/Xiaolin%5FWu%27s%5Fline%5Falgorithm require 'dxruby' class XiaolinWuDraw def XiaolinWuDraw.draw_line(img, x1, y1, x2, y2, colour) if x1 == x2 and y1 == y2 # not line. this is a dot. img[x1, y1] = colour return end dx, dy = x2 - x1, y2 - y1 steep = (dy.abs > dx.abs)? true : false x1, y1, x2, y2, dx, dy = y1, x1, y2, x2, dy, dx if steep x1, y1, x2, y2 = x2, y2, x1, y1 if x1 > x2 gradient = dy.to_f / dx.to_f # handle the first endpoint xend = x1.round yend = y1 + gradient * (xend - x1) fp = (x1 + 0.5) - (x1 + 0.5).truncate rfp = 1.0 - fp xgap = rfp xpxl1 = xend ypxl1 = yend.truncate fp = yend - yend.truncate rfp = 1.0 - fp XiaolinWuDraw.put_colour(img, xpxl1, ypxl1, colour, steep, rfp * xgap) XiaolinWuDraw.put_colour(img, xpxl1, ypxl1 + 1, colour, steep, fp * xgap) itery = yend + gradient # handle the second endpoint xend = x2.round yend = y2 + gradient * (xend - x2) fp = (x2 + 0.5) - (x2 + 0.5).truncate rfp = 1.0 - fp xgap = rfp xpxl2 = xend ypxl2 = yend.truncate fp = yend - yend.truncate rfp = 1.0 - fp XiaolinWuDraw.put_colour(img, xpxl2, ypxl2, colour, steep, rfp * xgap) XiaolinWuDraw.put_colour(img, xpxl2, ypxl2 + 1, colour, steep, fp * xgap) # in between (xpxl1 + 1).upto(xpxl2 - 1).each do |x| itt = itery.truncate fp = itery - itery.truncate rfp = 1.0 - fp XiaolinWuDraw.put_colour(img, x, itt, colour, steep, rfp) XiaolinWuDraw.put_colour(img, x, itt + 1, colour, steep, fp) itery = itery + gradient end end def XiaolinWuDraw.put_colour(img, x, y, col, steep, c) return if c == 0.0 or col[0] == 0 x, y = y, x if steep o = img[x, y] n = Array.new(4) if o[0] >= 255 # Bg Alpha = 255 n[0] = 255 for i in 1..3 do n[i] = (col[i] * c + o[i] * (1.0 - c)).round end elsif o[0] == 0 # Bg Alpha = 0 n[0] = (255 * c).round for i in 1..3 do n[i] = col[i] end else na = (255 * c).round n[0] = (na > o[0])? na : o[0] for i in 1..3 do n[i] = (col[i] * c + o[i] * (1.0 - c)).round end end img[x, y] = n end end # ---------------------------------------- # test if $0 == __FILE__ font = Font.new(14) w, h = 500, 500 bgcol = [0, 0, 255] # blue (R,G,B) fgcol = [255, 255, 255, 0] # Yellow (A,R,G,B) fgcol2 = [255, 0, 255, 0] # Green (A,R,G,B) p = [] 10.step(460, 30) do |a| p.push([10, 10, 490, a, fgcol]) p.push([10, 10, a, 490, fgcol]) end p.push([10, 10, 490, 490, fgcol]) img0 = Image.new(w, h) # img0.fill(bgcol) p.each do |d| x1, y1, x2, y2, col = d XiaolinWuDraw.draw_line(img0, x1, y1, x2, y2, col) end # img0.save("test.png") img1 = Image.new(w, h) p.each do |d| x1, y1, x2, y2, col = d img1.line(x1, y1, x2, y2, col) end img2 = Image.new(640, 480) Window.bgcolor = bgcol Window.loop do break if Input.keyPush?(K_ESCAPE) # Push A key aa_enable = (Input.keyDown?(K_A))? false : true img2.clear x1, y1 = 320, 240 x2, y2 = Input.mousePosX, Input.mousePosY if aa_enable XiaolinWuDraw.draw_line(img2, x1, y1, x2, y2, fgcol2) Window.draw(0, 0, img0) Window.draw(0, 0, img2) else img2.line(x1, y1, x2, y2, fgcol2) Window.draw(0, 0, img1) Window.draw(0, 0, img2) end s = "#{Window.real_fps} FPS CPU: #{Window.getLoad.to_i} %" Window.drawFont(640 - 140, 2, s, font) s = "Push A key" Window.drawFont(640 - 140, 20, s, font) end end