Слав обнови решението на 22.12.2013 22:48 (преди почти 11 години)
+module Graphics
+
+ module Renderers
+ class Ascii
+ def self.render(canvas)
+ to_array = canvas.table.flatten.map do |element|
+ element == true ? '@' : '-'
+ end
+ to_ascii_string = ""
+ to_array.each_slice(canvas.width) do |element|
+ to_ascii_string << element.join << "\n"
+ end
+ to_ascii_string[0..-2]
+ end
+ end
+
+ class Html
+ def self.write_beg()
+ "<!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\">"
+ end
+
+ def self.write_end()
+ string_end = "\n<div> </body> </html>"
+ end
+
+ def self.to_string_array(array)
+ array.flatten.map do |element|
+ element == true ? '<b></b>' : '<i></i>'
+ end
+ end
+
+ def self.add_end_symbol(array, width, height)
+ array.each_with_index do |item, index|
+ if (index + 1) % width == 0 and index < width * height - 1
+ item << '<br>'
+ end
+ end
+ end
+
+ def self.render(canvas)
+ string_array = to_string_array(canvas.table)
+ string_array = add_end_symbol(string_array, canvas.width, canvas.height)
+ string_mid = ''
+ string_array.each_slice(canvas.width) do |element|
+ string_mid << "\n" << element.join
+ end
+ write_beg + string_mid + write_end
+ end
+ end
+ end
+
+ class Canvas
+ attr_accessor :width, :height, :table
+
+ def initialize(width, height)
+ @width = width
+ @height = height
+ @table = Array.new(height) { |i| Array.new(width) { |j| false } }
+ end
+
+ def set_pixel(x, y)
+ @table[y][x] = true
+ end
+
+ def bigger_number(first_number, second_number)
+ first_number < second_number ? 1 : -1
+ end
+
+ def if_steep(x, y, steep)
+ if steep
+ set_pixel(y, x)
+ else
+ set_pixel(x, y)
+ end
+ end
+
+ def set_values(from, to)
+ x_0, y_0, x_1, y_1 = from.x, from.y, to.x, to.y
+ steep = ((y_1 - y_0).abs) > ((x_1 - x_0).abs)
+ x_0, y_0, x_1, y_1 = y_0, x_0, y_1, x_1 if steep
+ x_0, x_1, y_0, y_1 = x_1, x_0, y_1, y_0 if x_0 > x_1
+ delta_x, delta_y, y = x_1 - x_0, (y_1 - y_0).abs, y_0
+ [x_0, x_1, y_0, y_1, delta_x, delta_y, y, steep]
+ end
+
+ def set_line(from, to)
+ x_0, x_1, y_0, y_1, delta_x, delta_y, y, steep = set_values(from, to)
+ error, y_step = (delta_x / 2).to_i, bigger_number(y_0, y_1)
+ (x_0..x_1).each do |x|
+ if_steep(x, y, steep)
+ error -= delta_y
+ y, error = y + y_step, error + delta_x if error < 1
+ end
+ end
+
+ def pixel_at?(x, y)
+ @table[x][y]
+ end
+
+ def render_as(renderer)
+ renderer.render(self)
+ end
+
+ def draw(figure)
+ figure.draw_figure(self)
+ end
+ end
+
+ class Point
+ attr_accessor :point_hash
+
+ def initialize(x, y)
+ @point_hash = { :x => x, :y => y }
+ end
+
+ def x
+ @point_hash[:x]
+ end
+
+ def y
+ @point_hash[:y]
+ end
+
+ def ==(second_point)
+ self.point_hash == second_point.point_hash
+ end
+ alias eql? ==
+
+ def draw_figure(canvas)
+ canvas.set_pixel(self.x, self.y)
+ end
+ end
+
+ class Line
+ attr_accessor :line_hash
+
+ def check_y(first_point, second_point)
+ if(first_point.y >= second_point.y)
+ @line_hash = { :from => first_point, :to => second_point }
+ else
+ @line_hash = { :from => second_point, :to => first_point }
+ end
+ end
+
+ def initialize(first_point, second_point)
+ if(first_point.x < second_point.x)
+ @line_hash = { :from => first_point, :to => second_point }
+ elsif (first_point.x == second_point.x)
+ check_y(first_point, second_point)
+ else
+ @line_hash = { :from => second_point, :to => first_point }
+ end
+ end
+
+ def from
+ @line_hash[:from]
+ end
+
+ def to
+ @line_hash[:to]
+ end
+
+ def ==(second_line)
+ line_hash == second_line.line_hash
+ end
+ alias eql? ==
+
+ def draw_figure(canvas)
+ canvas.set_line(from, to)
+ end
+ end
+
+ class Rectangle
+ attr_accessor :rectangle_hash
+
+ def check_y(first_point, second_point)
+ if(first_point.y >= second_point.y)
+ @rectangle_hash = { :left => first_point, :right => second_point }
+ else
+ @rectangle_hash = { :left => second_point, :right => first_point }
+ end
+ end
+
+ def initialize(first_point, second_point)
+ if(first_point.x < second_point.x)
+ @rectangle_hash = { :left => first_point, :right => second_point }
+ elsif (first_point.x == second_point.x)
+ check_y(first_point, second_point)
+ else
+ @rectangle_hash = { :left => second_point, :right => first_point }
+ end
+ end
+
+ def left
+ @rectangle_hash[:left]
+ end
+
+ def right
+ @rectangle_hash[:right]
+ end
+
+ def top_left
+ if @rectangle_hash[:left].y < @rectangle_hash[:right].y
+ @rectangle_hash[:left]
+ else
+ Point.new(@rectangle_hash[:left].x, @rectangle_hash[:right].y)
+ end
+ end
+
+ def bottom_left
+ if @rectangle_hash[:left].y > @rectangle_hash[:right].y
+ @rectangle_hash[:left]
+ else
+ Point.new(@rectangle_hash[:left].x, @rectangle_hash[:right].y)
+ end
+ end
+
+ def top_right
+ if @rectangle_hash[:left].y > @rectangle_hash[:right].y
+ @rectangle_hash[:right]
+ else
+ Point.new( @rectangle_hash[:right].x, @rectangle_hash[:left].y)
+ end
+ end
+
+ def bottom_right
+ if @rectangle_hash[:left].y < @rectangle_hash[:right].y
+ @rectangle_hash[:right]
+ else
+ Point.new(@rectangle_hash[:right].x, @rectangle_hash[:left].y)
+ end
+ end
+
+ def ==(second_rectangle)
+ top_left_bottom_right = Rectangle.new(second_rectangle.top_left,
+ second_rectangle.bottom_right)
+ bottom_left_top_right = Rectangle.new(second_rectangle.top_right,
+ second_rectangle.bottom_left)
+ rectangle_hash == top_left_bottom_right.rectangle_hash or
+ rectangle_hash == bottom_left_top_right.rectangle_hash
+ end
+ alias eql? ==
+
+ def draw_figure(canvas)
+ canvas.set_line(top_left, bottom_left)
+ canvas.set_line(top_left, top_right)
+ canvas.set_line(top_right, bottom_right)
+ canvas.set_line(bottom_right, bottom_left)
+ end
+ end
+
+end