Сияна обнови решението на 22.12.2013 16:48 (преди почти 11 години)
+module Graphics
+ class Canvas
+ attr_reader :width, :height
+ def initialize(width,height)
+ @width = width
+ @height = height
+ @canvas = Array.new(width) { Array.new(height)}
+ end
+
+ def set_pixel(x,y)
+ @canvas[x][y] = 1
+ end
+
+ def pixel_at?(x,y)
+ !@canvas[x][y].nil?
+ end
+
+ def draw (figure)
+ figure.get_coordinates.each do |coordinates|
+ self.set_pixel(coordinates[1],coordinates[0])
+ end
+ end
+
+ def render_as (renderer)
+ renderer.render(@canvas)
+ end
+ end
+
+ module Renderers
+
+ class Ascii
+ def self.render(canvas)
+ rendered_canvas = []
+ canvas.each { |column| rendered_canvas << rendered_column(column) }
+ rendered_canvas.last.chomp!
+ rendered_canvas
+ end
+
+ private
+ def self.rendered_column(column)
+ rendered_column = ""
+ column.each do |pixel|
+ pixel.nil? ? rendered_column << "_" : rendered_column << "@"
+ end
+ rendered_column.concat("\n")
+ end
+ end
+
+ class Html
+ def self.render(canvas)
+ rendered_canvas = html_heading
+ canvas.each { |column| rendered_canvas << rendered_column(column)}
+ rendered_canvas.chop!.chop!.chop!.chop!
+ rendered_canvas << "</div></body></html>"
+ File.open("html", 'w') { |file| file.write(rendered_canvas) }
+ end
+
+ private
+ def self.html_heading
+ "<!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.rendered_column(column)
+ rendered_column = ""
+ column.each do |pixel|
+ pixel.nil? ? rendered_column << "<i></i>" : rendered_column << "<b></b>"
+ end
+ rendered_column.concat("<br>")
+ end
+ end
+ end
+
+ class Point
+ attr_reader :x, :y
+ def initialize(x,y)
+ @x = x
+ @y = y
+ end
+
+ def get_coordinates
+ [[@x,@y]]
+ end
+
+ def ==(other)
+ x == other.x and y == other.y
+ end
+
+ alias_method :eql?, :==
+
+ def hash
+ [x,y].hash
+ end
+ end
+
+ class Line
+ def initialize(point_one, point_two)
+ @point_one = point_one
+ @point_two = point_two
+ end
+
+ def from
+ if @point_one.x == @point_two.x
+ [@point_one,@point_two].min_by {|point| point.y}
+ else
+ [@point_one,@point_two].min_by {|point| point.x}
+ end
+ end
+
+ def to
+ if @point_one.x == @point_two.x
+ [@point_one,@point_two].max_by {|point| point.y}
+ else
+ [@point_one,@point_two].max_by {|point| point.x}
+ end
+ end
+
+ def get_coordinates
+ x_one, y_one = self.from.x, self.from.y
+ x_two, y_two = self.to.x, self.to.y
+ steep = (y_two - y_one).abs > (x_two - x_one).abs
+ x_one, y_one, x_two, y_two = y_one, x_one, y_two, x_two if steep
+ y_step = y_one < y_two ? 1 : -1
+ coordinates(x_1,x_2,y_1,steep,(y_2 - y_1).abs,x_2 - x_1,(x_2 - x_1)/2, y_step)
+ end
+
+ def ==(other)
+ (from == other.from and to == other.to) or (from == other.to and to == other.from)
+ end
+
+ alias_method :eql?, :==
+
+ def hash
+ [from.x,from.y,to.x,to.y].hash
+ end
+
+ private
+ def coordinates(x_one,x_two,y,steep,delta_y,delta_x,error,y_step)
+ coordinates = []
+ x_one.upto(x_two) do |x|
+ coordinates << (steep ? [y,x] : [x,y])
+ error -= deltay
+ y, error = y + y_step, delta_x + error if error < 0
+ end
+ coordinates
+ end
+ end
+
+ class Rectangle
+ def initialize(point_one, point_two)
+ @point_one = point_one
+ @point_two = point_two
+ end
+
+ def left
+ if @point_one == @point_two
+ [@point_one,@point_two].min_by {|point| point.y}
+ else
+ [@point_one,@point_two].min_by {|point| point.x}
+ end
+ end
+
+ def right
+ if @point_one == @point_two
+ [@point_one,@point_two].max_by {|point| point.y}
+ else
+ [@point_one,@point_two].max_by {|point| point.x}
+ end
+ end
+
+ def top_left
+ x = [@point_one.x,@point_two.x].min.to_i
+ y = [@point_one.y,@point_two.y].min.to_i
+ Point.new(x,y)
+ end
+
+ def top_right
+ x = [@point_one.x,@point_two.x].min.to_i
+ y = [@point_one.y,@point_two.y].max.to_i
+ Point.new(x,y)
+ end
+
+ def bottom_left
+ x = [@point_one.x,@point_two.x].max.to_i
+ y = [@point_one.y,@point_two.y].min.to_i
+ Point.new(x,y)
+ end
+
+ def bottom_right
+ x = [@point_one.x,@point_two.x].max.to_i
+ y = [@point_one.y,@point_two.y].max.to_i
+ Point.new(x,y)
+ end
+
+ def get_coordinates
+ a = Graphics::Line.new(self.top_left,self.top_right).get_coordinates
+ b = Graphics::Line.new(self.bottom_left,self.bottom_right).get_coordinates
+ c = Graphics::Line.new(self.top_left,self.bottom_left).get_coordinates
+ d = Graphics::Line.new(self.top_right,self.bottom_right).get_coordinates
+ a + b + c + d
+ end
+
+ def ==(other)
+ left == other.left and right == other.right
+ end
+
+ alias_method :eql?, :==
+
+ def hash
+ [left.x,left.y,right.x,right.y].hash
+ end
+
+ end
+
+end
+
+