Иван обнови решението на 22.12.2013 22:49 (преди почти 11 години)
+module Graphics
+ module Renderers
+ module Renderer
+ def self.render (canvas, pixel, empty_pixel, new_line)
+ get_pixel = -> (x,y) { canvas.pixel_at?(x,y) ? pixel : empty_pixel }
+ render_line = -> y { canvas.width.times.map { |x| get_pixel.(x, y) }*"" }
+ rendered_text = canvas.height.times.map { |y| render_line.(y) << new_line }*""
+ rendered_text.gsub /#{Regexp.quote(new_line)}$/, ""
+ end
+ end
+
+ module Ascii
+ def self.render canvas
+ Renderer.render canvas, '@', '-', "\n"
+ end
+ end
+
+ module Html
+ MARKUP = "<!DOCTYPE html>
+ <html>
+ <head>
+ <title>Rendered Canvas</title>
+ <style type=\"text/css\">
+ .canvas {
+ font-size: 1px;
+ line-height: 1px;
+ }
+ .canvas * {
+ display: inline-block;
+ width: 10px;
+ height: 10px;
+ border-radius: 5px;
+ }
+ .canvas i {
+ background-color: #eee;
+ }
+ .canvas b {
+ background-color: #333;
+ }
+ </style>
+ </head>
+ <body>
+ <div class=\"canvas\">
+ PLACEHOLDER
+ </div>
+ </body>
+ </html>"
+
+
+ def self.render canvas
+ MARKUP.sub "PLACEHOLDER", Renderer.render(canvas, "<b></b>", "<i></i>", "<br>")
+ end
+ end
+ end
+
+ module Algorithms
+ module Bresenham
+ def self.set_next
+ if @@err_2 >= @@d_y
+ @@err += @@d_y
+ @@x_0 += @@step_x
+ end
+ if @@err_2 <= @@d_x
+ @@err += @@d_x
+ @@y_0 += @@step_y
+ end
+ end
+
+ def self.bresenham(canvas)
+ @@err_2 = 2 * @@err
+ set_next()
+ canvas.set_pixel(@@x_0, @@y_0)
+ bresenham(canvas) if (@@x_0 != @@x_1 || @@y_0 != @@y_1)
+ end
+
+ def self.initialize_internal(x_0, y_0, x_1, y_1)
+ @@d_x = (x_1 - x_0).abs
+ @@d_y = -(y_1 - y_0).abs
+ @@step_x = x_0 < x_1 ? 1 : -1
+ @@step_y = y_0 < y_1 ? 1 : -1
+ end
+
+ def self.initialize_class_variables(x_0, y_0, x_1, y_1)
+ @@err = @@d_x + @@d_y
+ @@x_0 = x_0
+ @@y_0 = y_0
+ @@x_1 = x_1
+ @@y_1 = y_1
+ end
+
+ def self.draw_line (x_0, y_0, x_1, y_1, canvas)
+ canvas.set_pixel(x_0, y_0)
+ initialize_internal x_0, y_0, x_1, y_1
+ initialize_class_variables x_0, y_0, x_1, y_1
+
+ bresenham(canvas)
+ end
+ end
+ end
+
+ class Point
+ attr_reader :x,:y
+
+ def initialize(x, y)
+ @x = x
+ @y = y
+ end
+
+ def eql?(other)
+ other.instance_of?(self.class) && @x == other.x && @y == other.y
+ end
+
+ def ==(other)
+ self.eql?(other)
+ end
+
+ def draw (canvas)
+ canvas.set_pixel(x,y)
+ end
+ end
+
+ class LinearFigure
+ def initialize(point_1, point_2)
+ if(point_1.x == point_2.x) then
+ @left = point_1.y <= point_2.y ? point_1 : point_2
+ else
+ @left = point_1.x <= point_2.x ? point_1 : point_2
+ end
+
+ @right = @left == point_1 ? point_2 : point_1
+ end
+
+ def eql?(other)
+ other.instance_of?(self.class) && @left == other.left && @right == other.right
+ end
+
+ def ==(other)
+ self.eql?(other)
+ end
+
+ protected
+ attr_reader :left, :right
+ end
+
+ class Line <LinearFigure
+ attr_reader :from, :to
+
+ def draw (canvas, algorithm = Algorithms::Bresenham)
+ algorithm.draw_line from.x, from.y, to.x, to.y, canvas
+ end
+
+ alias_method :from, :left
+ alias_method :to, :right
+ end
+
+ class Rectangle <LinearFigure
+ attr_reader :left, :right
+
+ def top_left
+ Point.new(left.x, [left.y, right.y].min)
+ end
+
+ def top_right
+ Point.new(right.x, [left.y, right.y].min)
+ end
+
+ def bottom_left
+ Point.new(left.x, [left.y, right.y].max)
+ end
+
+ def bottom_right
+ Point.new(right.x, [left.y, right.y].max)
+ end
+
+ def draw (canvas)
+ (top_left.x..top_right.x).each{ |x| canvas.set_pixel(x, top_left.y) }
+ (bottom_left.x..bottom_right.x).each{ |x| canvas.set_pixel(x, bottom_left.y) }
+ (top_left.y..bottom_left.y).each{ |y| canvas.set_pixel(top_left.x, y) }
+ (top_right.y..bottom_right.y).each{ |y| canvas.set_pixel(bottom_right.x, y)}
+ end
+
+ def eql? (other)
+ other.instance_of?(self.class) &&
+ top_left == other.top_left &&
+ top_right == other.top_right &&
+ bottom_left == other.bottom_left &&
+ bottom_right == other.bottom_right
+ end
+ end
+
+ class Canvas
+ attr_reader :width, :height
+
+ def initialize(width, height)
+ @width = width
+ @height = height
+ @matrix = Array.new(height) { Array.new(width) }
+ end
+
+ def set_pixel(x, y)
+ @matrix[y][x] = true
+ end
+
+ def pixel_at?(x,y)
+ @matrix[y][x] == true
+ end
+
+ def draw (figure)
+ figure.draw self
+ end
+
+ def render_as (renderer)
+ renderer.render self
+ end
+
+ end
+end