Решение на Трета задача от Ангел Цанев

Обратно към всички решения

Към профила на Ангел Цанев

Резултати

  • 5 точки от тестове
  • 0 бонус точки
  • 5 точки общо
  • 52 успешни тест(а)
  • 17 неуспешни тест(а)

Код

module Graphics
class Canvas
attr_reader :width, :height, :pixels
def initialize(width, height)
@height = height
@width = width
@pixels = {}
end
def set_pixel(x, y)
@pixels["#{x},#{y}"] = true
end
def pixel_at?(x, y)
@pixels.has_key?("#{x},#{y}")
end
def draw(geometric_object)
geometric_object.draw_on(self)
end
def render_as(argument)
argument.render(self)
end
end
module Renderers
class Ascii
attr_reader :ascii_text
def self.render(canvas)
@ascii_text = ''
0.upto(canvas.height).each do |row|
0.upto(canvas.width).each do |column|
set_character(canvas, column, row)
end
@ascii_text << "\n"
end
@ascii_text
end
private
def self.set_character(canvas, x, y)
canvas.pixel_at?(x, y) ? @ascii_text << '@' : @ascii_text << '-'
end
end
class Html
attr_reader :html_body
HEADER =
'<!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">'
FOOTER =
' </div>
</body>
</html>'
def self.render(canvas)
@html_body = ''
0.upto(canvas.height).each do |row|
0.upto(canvas.width).each do |column|
set_character(canvas, column, row)
end
@html_body << '<br>'
end
HEADER + @html_body + FOOTER
end
private
def self.set_character(canvas, x, y)
canvas.pixel_at?(x, y) ? @html_body << '<b></b>' : @html_body << '<i></i>'
end
end
end
class Point
attr_reader :x, :y
def initialize(x, y)
@x = x
@y = y
end
def draw_on(canvas)
canvas.set_pixel(x,y)
end
def == (other)
self.x == other.x and self.y == other.y
end
def eql?(other)
self.hash.eql?(other.hash)
end
def hash
"X#{x}Y#{y}"
end
end
class Line
attr_reader :first_point, :second_point, :current_x, :current_y
def initialize(first_point, second_point)
@first_point = first_point
@second_point = second_point
@error = (to.x - from.x).abs - (to.y - from.y).abs
end
def from
if @first_point.x == @second_point.x
@first_point.y <= @second_point.y ? @first_point : @second_point
else
@first_point.x <= @second_point.x ? @first_point : @second_point
end
end
def to
if @first_point.x == @second_point.x
@first_point.y <= @second_point.y ? @second_point : @first_point
else
@first_point.x <= @second_point.x ? @second_point : @first_point
end
end
def draw_on(canvas)
@current_x = from.x
@current_y = from.y
draw_line(canvas)
end
def == (other)
self.from == other.from and self.to == other.to
end
def eql?(other)
self.hash.eql?(other.hash)
end
def hash
"FX#{from.x}FY#{from.y}TX#{to.x}TY#{to.y}"
end
private
def draw_line(canvas)
while true
canvas.set_pixel(@current_x, @current_y)
break if reach_last?
compute_next_x
canvas.set_pixel(@current_x, @current_y) if reach_last?
compute_next_y
end
end
def reach_last?
@current_x == to.x and @current_y == to.y
end
def compute_next_x
if (2 * @error >= -(to.y - from.y).abs)
@error -= (to.y - from.y).abs
from.x < to.x ? @current_x += 1 : @current_y -= 1
end
end
def compute_next_y
if (2 * @error < (to.x - from.x).abs)
@error += (to.x - from.x).abs
from.y < to.y ? @current_y += 1 : @current_y -= 1
end
end
end
class Rectangle
attr_reader :first_vertex, :second_vertex
def initialize(one_vertex, other_vertex)
@first_vertex = one_vertex
@second_vertex = other_vertex
end
def left
if @first_vertex.x == @second_vertex.x
@first_vertex.y <= @second_vertex.y ? @first_vertex : @second_vertex
else
@first_vertex.x <= @second_vertex.x ? @first_vertex : @second_vertex
end
end
def right
if @first_vertex.x == @second_vertex.x
@first_vertex.y <= @second_vertex.y ? @second_vertex : @first_vertex
else
@first_vertex.x <= @second_vertex.x ? @second_vertex : @first_vertex
end
end
def top_left
x_coordinate = [@first_vertex.x, @second_vertex.x].min
y_coordinate = [@first_vertex.y, @second_vertex.y].min
Point.new(x_coordinate, y_coordinate)
end
def top_right
x_coordinate = [@first_vertex.x, @second_vertex.x].max
y_coordinate = [@first_vertex.y, @second_vertex.y].min
Point.new(x_coordinate, y_coordinate)
end
def bottom_left
x_coordinate = [@first_vertex.x, @second_vertex.x].min
y_coordinate = [@first_vertex.y, @second_vertex.y].max
Point.new(x_coordinate, y_coordinate)
end
def bottom_right
x_coordinate = [@first_vertex.x, @second_vertex.x].max
y_coordinate = [@first_vertex.y, @second_vertex.y].max
Point.new(x_coordinate, y_coordinate)
end
def == (other)
self.top_left == other.top_left and self.bottom_right == other.bottom_right
end
def eql?(other)
self.hash.eql?(other.hash)
end
def hash
x = top_left.x
y = top_left.y
width = (@first_vertex.x - @second_vertex.x).abs
height = (@first_vertex.y - @second_vertex.y).abs
"X#{x}Y#{y}W#{width}H#{height}"
end
def draw_on(canvas)
canvas.draw (Line.new(top_left, top_right))
canvas.draw (Line.new(top_left, bottom_left))
canvas.draw (Line.new(bottom_left, bottom_right))
canvas.draw (Line.new(top_right, bottom_right))
end
end
end

Лог от изпълнението

........F.FFFFFFFFFFFFFF.FF..........................................

Failures:

  1) Graphics Canvas drawing of shapes and rasterization renders multiple drawn shapes
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "@@@@@@@@@@@@@@@\n@-------------@\n@-@@@@@@@@@@@-@\n@-@---------@-@\n@-@------@@-@-@\n@-@---@@@---@-@\n@-@-@@------@-@\n@-@---------@-@\n@-@-@@@@----@-@\n@-@-@-------@-@\n@-@---------@-@\n@-@---------@-@\n@-@@@@@@@@@@@-@\n@-------------@\n@@@@@@@@@@@@@@@"
            got: "@@@@@@@@@@@@@@@-\n@-------------@-\n@-@@@@@@@@@@@-@-\n@-@---------@-@-\n@-@-----@@@-@-@-\n@-@--@@@----@-@-\n@-@-@-------@-@-\n@-@---------@-@-\n@-@-@@@@----@-@-\n@-@-@-------@-@-\n@-@---------@-@-\n@-@---------@-@-\n@-@@@@@@@@@@@-@-\n@-------------@-\n@@@@@@@@@@@@@@@-\n----------------\n"
       
       (compared using ==)
       
       Diff:
       @@ -1,16 +1,17 @@
       -@@@@@@@@@@@@@@@
       -@-------------@
       -@-@@@@@@@@@@@-@
       -@-@---------@-@
       -@-@------@@-@-@
       -@-@---@@@---@-@
       -@-@-@@------@-@
       -@-@---------@-@
       -@-@-@@@@----@-@
       -@-@-@-------@-@
       -@-@---------@-@
       -@-@---------@-@
       -@-@@@@@@@@@@@-@
       -@-------------@
       -@@@@@@@@@@@@@@@
       +@@@@@@@@@@@@@@@-
       +@-------------@-
       +@-@@@@@@@@@@@-@-
       +@-@---------@-@-
       +@-@-----@@@-@-@-
       +@-@--@@@----@-@-
       +@-@-@-------@-@-
       +@-@---------@-@-
       +@-@-@@@@----@-@-
       +@-@-@-------@-@-
       +@-@---------@-@-
       +@-@---------@-@-
       +@-@@@@@@@@@@@-@-
       +@-------------@-
       +@@@@@@@@@@@@@@@-
       +----------------
     # /tmp/d20131223-4637-14f8a9/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-14f8a9/spec.rb:211:in `block (4 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) Graphics Canvas drawing of shapes and rasterization of points works for multiple ones
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "@---\n@---\n-@@-\n----"
            got: "@----\n@----\n-@@--\n-----\n----@\n"
       
       (compared using ==)
       
       Diff:
       @@ -1,5 +1,6 @@
       -@---
       -@---
       --@@-
       -----
       +@----
       +@----
       +-@@--
       +-----
       +----@
     # /tmp/d20131223-4637-14f8a9/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-14f8a9/spec.rb:59:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  3) Graphics Canvas drawing of shapes and rasterization of lines works with simple horizontal lines
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "--------\n---@@@@-\n--------"
            got: "---------\n---@@@@--\n---------\n---------\n"
       
       (compared using ==)
       
       Diff:
       @@ -1,4 +1,5 @@
       ---------
       ----@@@@-
       ---------
       +---------
       +---@@@@--
       +---------
       +---------
     # /tmp/d20131223-4637-14f8a9/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-14f8a9/spec.rb:73:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  4) Graphics Canvas drawing of shapes and rasterization of lines works with vertical lines
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "-@------\n-@------\n-@------\n-@------\n-@------\n-@------\n-@------\n--------"
            got: "-@-------\n-@-------\n-@-------\n-@-------\n-@-------\n-@-------\n-@-------\n---------\n---------\n"
       
       (compared using ==)
       
       Diff:
       @@ -1,9 +1,10 @@
       --@------
       --@------
       --@------
       --@------
       --@------
       --@------
       --@------
       ---------
       +-@-------
       +-@-------
       +-@-------
       +-@-------
       +-@-------
       +-@-------
       +-@-------
       +---------
       +---------
     # /tmp/d20131223-4637-14f8a9/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-14f8a9/spec.rb:84:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  5) Graphics Canvas drawing of shapes and rasterization of lines works with lines with a small slope
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "----------\n-@@-------\n---@@@@---\n-------@@-\n----------"
            got: "-----------\n-@---------\n--@@@@-----\n------@@@--\n-----------\n-----------\n"
       
       (compared using ==)
       
       Diff:
       @@ -1,6 +1,7 @@
       -----------
       --@@-------
       ----@@@@---
       --------@@-
       -----------
       +-----------
       +-@---------
       +--@@@@-----
       +------@@@--
       +-----------
       +-----------
     # /tmp/d20131223-4637-14f8a9/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-14f8a9/spec.rb:100:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  6) Graphics Canvas drawing of shapes and rasterization of lines works with lines with a significant slope, with swapped ends
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "----------\n-@--------\n-@--------\n--@-------\n--@-------\n--@-------\n--@-------\n---@------\n---@------\n----------"
            got: "-----------\n-@---------\n-@---------\n--@--------\n--@--------\n--@--------\n--@--------\n---@-------\n---@-------\n-----------\n-----------\n"
       
       (compared using ==)
       
       Diff:
       @@ -1,11 +1,12 @@
       -----------
       --@--------
       --@--------
       ---@-------
       ---@-------
       ---@-------
       ---@-------
       ----@------
       ----@------
       -----------
       +-----------
       +-@---------
       +-@---------
       +--@--------
       +--@--------
       +--@--------
       +--@--------
       +---@-------
       +---@-------
       +-----------
       +-----------
     # /tmp/d20131223-4637-14f8a9/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-14f8a9/spec.rb:113:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  7) Graphics Canvas drawing of shapes and rasterization of lines works with multiple lines
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "-@--------\n-@@-------\n-@-@@@@---\n-@-----@@-\n----------"
            got: "-@---------\n-@---------\n-@@@@@-----\n-@----@@@--\n-----------\n-----------\n"
       
       (compared using ==)
       
       Diff:
       @@ -1,6 +1,7 @@
       --@--------
       --@@-------
       --@-@@@@---
       --@-----@@-
       -----------
       +-@---------
       +-@---------
       +-@@@@@-----
       +-@----@@@--
       +-----------
       +-----------
     # /tmp/d20131223-4637-14f8a9/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-14f8a9/spec.rb:132:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  8) Graphics Canvas drawing of shapes and rasterization of lines draws lines with two equal ends as points
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "---\n-@-\n---"
            got: "----\n-@--\n----\n----\n"
       
       (compared using ==)
       
       Diff:
       @@ -1,4 +1,5 @@
       ----
       --@-
       ----
       +----
       +-@--
       +----
       +----
     # /tmp/d20131223-4637-14f8a9/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-14f8a9/spec.rb:145:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  9) Graphics Canvas drawing of shapes and rasterization of rectangles works with simple rects
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "----------\n-@@@@@@@@-\n-@------@-\n-@@@@@@@@-\n----------"
            got: "-----------\n-@@@@@@@@--\n-@------@--\n-@@@@@@@@--\n-----------\n-----------\n"
       
       (compared using ==)
       
       Diff:
       @@ -1,6 +1,7 @@
       -----------
       --@@@@@@@@-
       --@------@-
       --@@@@@@@@-
       -----------
       +-----------
       +-@@@@@@@@--
       +-@------@--
       +-@@@@@@@@--
       +-----------
       +-----------
     # /tmp/d20131223-4637-14f8a9/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-14f8a9/spec.rb:158:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  10) Graphics Canvas drawing of shapes and rasterization of rectangles works with rects defined with their bottom left and top right points
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "----------\n-@@@@@@@@-\n-@------@-\n-@@@@@@@@-\n----------"
            got: "-----------\n-@@@@@@@@--\n-@------@--\n-@@@@@@@@--\n-----------\n-----------\n"
       
       (compared using ==)
       
       Diff:
       @@ -1,6 +1,7 @@
       -----------
       --@@@@@@@@-
       --@------@-
       --@@@@@@@@-
       -----------
       +-----------
       +-@@@@@@@@--
       +-@------@--
       +-@@@@@@@@--
       +-----------
       +-----------
     # /tmp/d20131223-4637-14f8a9/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-14f8a9/spec.rb:171:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  11) Graphics Canvas drawing of shapes and rasterization of rectangles works with rects with a zero height as a line
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "----------\n-@@@@@@@@-\n----------"
            got: "-----------\n-@@@@@@@@--\n-----------\n-----------\n"
       
       (compared using ==)
       
       Diff:
       @@ -1,4 +1,5 @@
       -----------
       --@@@@@@@@-
       -----------
       +-----------
       +-@@@@@@@@--
       +-----------
       +-----------
     # /tmp/d20131223-4637-14f8a9/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-14f8a9/spec.rb:184:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  12) Graphics Canvas drawing of shapes and rasterization of rectangles works with rects with a zero width and height as a single point
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "---\n-@-\n---"
            got: "----\n-@--\n----\n----\n"
       
       (compared using ==)
       
       Diff:
       @@ -1,4 +1,5 @@
       ----
       --@-
       ----
       +----
       +-@--
       +----
       +----
     # /tmp/d20131223-4637-14f8a9/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-14f8a9/spec.rb:195:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  13) Graphics Renderers Ascii renders a grid of the size of the canvas
     Failure/Error: lines.size.should eq 3
       
       expected: 3
            got: 4
       
       (compared using ==)
     # /tmp/d20131223-4637-14f8a9/spec.rb:240:in `block (4 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  14) Graphics Renderers Ascii renders blank canvases
     Failure/Error: canvas.render_as(ascii).should eq rendering('
       
       expected: "----\n----\n----"
            got: "-----\n-----\n-----\n-----\n"
       
       (compared using ==)
       
       Diff:
       @@ -1,4 +1,5 @@
       -----
       -----
       -----
       +-----
       +-----
       +-----
       +-----
     # /tmp/d20131223-4637-14f8a9/spec.rb:245:in `block (4 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  15) Graphics Renderers Ascii renders simple canvases
     Failure/Error: canvas.render_as(ascii).should eq rendering('
       
       expected: "@---\n----\n---@"
            got: "@----\n-----\n---@-\n-----\n"
       
       (compared using ==)
       
       Diff:
       @@ -1,4 +1,5 @@
       -@---
       -----
       ----@
       +@----
       +-----
       +---@-
       +-----
     # /tmp/d20131223-4637-14f8a9/spec.rb:256:in `block (4 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  16) Graphics Renderers Html renders a grid of the size of the canvas
     Failure/Error: lines.size.should eq 3
       
       expected: 3
            got: 4
       
       (compared using ==)
     # /tmp/d20131223-4637-14f8a9/spec.rb:283:in `block (4 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  17) Graphics Renderers Html renders simple canvases
     Failure/Error: html_rendering_of(canvas).should eq [
       
       expected: "<i></i><i></i><i></i><i></i><br><i></i><b></b><i></i><i></i><br><i></i><b></b><i></i><i></i>"
            got: "<i></i><i></i><i></i><i></i><i></i><br><i></i><b></b><i></i><i></i><i></i><br><i></i><b></b><i></i><i></i><i></i><br><i></i><i></i><i></i><i></i><i></i><br>"
       
       (compared using ==)
     # /tmp/d20131223-4637-14f8a9/spec.rb:291:in `block (4 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.0969 seconds
69 examples, 17 failures

Failed examples:

rspec /tmp/d20131223-4637-14f8a9/spec.rb:203 # Graphics Canvas drawing of shapes and rasterization renders multiple drawn shapes
rspec /tmp/d20131223-4637-14f8a9/spec.rb:51 # Graphics Canvas drawing of shapes and rasterization of points works for multiple ones
rspec /tmp/d20131223-4637-14f8a9/spec.rb:69 # Graphics Canvas drawing of shapes and rasterization of lines works with simple horizontal lines
rspec /tmp/d20131223-4637-14f8a9/spec.rb:80 # Graphics Canvas drawing of shapes and rasterization of lines works with vertical lines
rspec /tmp/d20131223-4637-14f8a9/spec.rb:96 # Graphics Canvas drawing of shapes and rasterization of lines works with lines with a small slope
rspec /tmp/d20131223-4637-14f8a9/spec.rb:109 # Graphics Canvas drawing of shapes and rasterization of lines works with lines with a significant slope, with swapped ends
rspec /tmp/d20131223-4637-14f8a9/spec.rb:127 # Graphics Canvas drawing of shapes and rasterization of lines works with multiple lines
rspec /tmp/d20131223-4637-14f8a9/spec.rb:141 # Graphics Canvas drawing of shapes and rasterization of lines draws lines with two equal ends as points
rspec /tmp/d20131223-4637-14f8a9/spec.rb:154 # Graphics Canvas drawing of shapes and rasterization of rectangles works with simple rects
rspec /tmp/d20131223-4637-14f8a9/spec.rb:167 # Graphics Canvas drawing of shapes and rasterization of rectangles works with rects defined with their bottom left and top right points
rspec /tmp/d20131223-4637-14f8a9/spec.rb:180 # Graphics Canvas drawing of shapes and rasterization of rectangles works with rects with a zero height as a line
rspec /tmp/d20131223-4637-14f8a9/spec.rb:191 # Graphics Canvas drawing of shapes and rasterization of rectangles works with rects with a zero width and height as a single point
rspec /tmp/d20131223-4637-14f8a9/spec.rb:237 # Graphics Renderers Ascii renders a grid of the size of the canvas
rspec /tmp/d20131223-4637-14f8a9/spec.rb:244 # Graphics Renderers Ascii renders blank canvases
rspec /tmp/d20131223-4637-14f8a9/spec.rb:252 # Graphics Renderers Ascii renders simple canvases
rspec /tmp/d20131223-4637-14f8a9/spec.rb:280 # Graphics Renderers Html renders a grid of the size of the canvas
rspec /tmp/d20131223-4637-14f8a9/spec.rb:287 # Graphics Renderers Html renders simple canvases

История (4 версии и 2 коментара)

Ангел обнови решението на 22.12.2013 03:10 (преди почти 11 години)

+module Graphics
+ class Canvas
+ attr_accessor :pixels
+ attr_reader :width, :height
+
+ def initialize(width, height)
+ @height = height
+ @width = width
+ @pixels = Array.new(height) { Array.new(width, false) }
+ end
+
+ def set_pixel(x, y)
+ @pixels[y][x] = true
+ end
+
+ def pixel_at?(x, y)
+ @pixels[y][x]
+ end
+
+ def draw(geometric_object)
+ geometric_object.draw(self)
+ end
+
+ def render_as(argument)
+ argument.send(:render, self)
+ end
+ end
+
+ module Renderers
+ class Ascii
+ def self.render(canvas)
+ ascii_text = canvas.pixels.map{ |row| row.map{ |pixel| pixel }.join }.join("\n")
+ ascii_text.gsub('false', '-').gsub('true', '@')
+ end
+ end
+
+ class Html
+ HEADER =
+ '<!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">
+ '
+
+ FOOTER =
+ '
+ </div>
+ </body>
+ </html>'
+
+ def self.render(canvas)
+ html_body = canvas.pixels.map{ |row| row.map{ |pixel| pixel }.join }.join('<br>')
+ HEADER + html_body.gsub('false', '<i></i>').gsub('true', '<b></b>') + FOOTER
+ end
+ end
+ end
+
+ class Point
+ attr_reader :x, :y
+
+ def initialize(x, y)
+ @x = x
+ @y = y
+ end
+
+ def draw(canvas)
+ canvas.set_pixel(x,y)
+ end
+
+ def == (other)
+ (self.x == other.x) and (self.y == other.y)
+ end
+
+ def eql?(other)
+ (self.hash == other.hash)
+ end
+
+ def hash
+ {'x' => self.x, 'y' => self.y}
+ end
+ end
+
+ class Line
+ attr_reader :first_point, :second_point
+
+ def initialize(first_point, second_point)
+ @first_point = first_point
+ @second_point = second_point
+ @current_x = from.x
+ @current_y = from.y
+ @error = (to.x - from.x).abs - (to.y - from.y).abs
+ end
+
+ def from
+ if (@first_point.x == @second_point.x)
+ (@first_point.y <= @second_point.y) ? @first_point : @second_point
+ else
+ (@first_point.x <= @second_point.x) ? @first_point : @second_point
+ end
+ end
+
+ def to
+ if (@first_point.x == @second_point.x)
+ (@first_point.y <= @second_point.y) ? @second_point : @first_point
+ else
+ (@first_point.x <= @second_point.x) ? @second_point : @first_point
+ end
+ end
+
+ def draw(canvas)
+ while(true)
+ canvas.set_pixel(@current_x, @current_y)
+
+ break if reach_last?
+
+ error_value_due_to_y
+
+ canvas.set_pixel(@current_x, @current_y) if reach_last?
+
+ error_value_due_to_x
+ end
+ end
+
+ def == (other)
+ (self.from == other.from) and (self.to == other.to)
+ end
+
+ def eql?(other)
+ (self.hash == other.hash)
+ end
+
+ def hash
+ {'from_x' => from.x, 'from_y' => from.y, 'to_x' => to.x, 'to_y' => to.y}
+ end
+
+ private
+ def reach_last?
+ @current_x == to.x and @current_y == to.y
+ end
+
+ def error_value_due_to_y
+ if (2 * @error >= -(to.y - from.y).abs)
+ @error -= (to.y - from.y).abs
+ (from.x < to.x) ? @current_x += 1 : @current_y -= 1
+ end
+ end
+
+ def error_value_due_to_x
+ if (2 * @error < (to.x - from.x).abs)
+ @error += (to.x - from.x).abs
+ (from.y < to.y) ? @current_y += 1 : @current_y -= 1
+ end
+ end
+ end
+
+ class Rectangle
+ attr_reader :first_vertex, :second_vertex
+
+ def initialize(one_vertex, other_vertex)
+ @first_vertex = one_vertex
+ @second_vertex = other_vertex
+ end
+
+ def left
+ if (@first_vertex.x == @second_vertex.x)
+ (@first_vertex.y <= @second_vertex.y) ? @first_vertex : @second_vertex
+ else
+ (@first_vertex.x <= @second_vertex.x) ? @first_vertex : @second_vertex
+ end
+ end
+
+ def right
+ if (@first_vertex.x == @second_vertex.x)
+ (@first_vertex.y <= @second_vertex.y) ? @second_vertex : @first_vertex
+ else
+ (@first_vertex.x <= @second_vertex.x) ? @second_vertex : @first_vertex
+ end
+ end
+
+ def top_left
+ x_coordinate = [@first_vertex.x,@second_vertex.x].min
+ y_coordinate = [@first_vertex.y,@second_vertex.y].min
+ Point.new(x_coordinate,y_coordinate)
+ end
+
+ def top_right
+ x_coordinate = [@first_vertex.x,@second_vertex.x].max
+ y_coordinate = [@first_vertex.y,@second_vertex.y].min
+ Point.new(x_coordinate,y_coordinate)
+ end
+
+ def bottom_left
+ x_coordinate = [@first_vertex.x,@second_vertex.x].min
+ y_coordinate = [@first_vertex.y,@second_vertex.y].max
+ Point.new(x_coordinate,y_coordinate)
+ end
+
+ def bottom_right
+ x_coordinate = [@first_vertex.x,@second_vertex.x].max
+ y_coordinate = [@first_vertex.y,@second_vertex.y].max
+ Point.new(x_coordinate,y_coordinate)
+ end
+
+ def == (other)
+ (self.top_left == other.top_left) and (self.bottom_right == other.botton_right)
+ end
+
+ def eql?(other)
+ self.hash == other.hash
+ end
+
+ def hash
+ x = top_left.x
+ y = top_left.y
+ width = (@first_vertex.x - @second_vertex.x).abs
+ height = (@first_vertex.y - @second_vertex.y).abs
+
+ {'point.x' =>x, 'point.y' => y, 'width' => width, 'height' => height}
+ end
+
+ def draw(canvas)
+ canvas.draw (Line.new(top_left, top_right))
+ canvas.draw (Line.new(top_left, bottom_left))
+ canvas.draw (Line.new(bottom_left, bottom_right))
+ canvas.draw (Line.new(top_right, bottom_right))
+ end
+ end
+end

Ангел обнови решението на 22.12.2013 03:14 (преди почти 11 години)

module Graphics
class Canvas
attr_accessor :pixels
attr_reader :width, :height
def initialize(width, height)
@height = height
@width = width
@pixels = Array.new(height) { Array.new(width, false) }
end
def set_pixel(x, y)
@pixels[y][x] = true
end
def pixel_at?(x, y)
@pixels[y][x]
end
def draw(geometric_object)
geometric_object.draw(self)
end
def render_as(argument)
argument.send(:render, self)
end
end
module Renderers
class Ascii
def self.render(canvas)
ascii_text = canvas.pixels.map{ |row| row.map{ |pixel| pixel }.join }.join("\n")
ascii_text.gsub('false', '-').gsub('true', '@')
end
end
class Html
HEADER =
'<!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">
'
FOOTER =
'
</div>
</body>
</html>'
def self.render(canvas)
html_body = canvas.pixels.map{ |row| row.map{ |pixel| pixel }.join }.join('<br>')
HEADER + html_body.gsub('false', '<i></i>').gsub('true', '<b></b>') + FOOTER
end
end
end
class Point
attr_reader :x, :y
def initialize(x, y)
@x = x
@y = y
end
def draw(canvas)
canvas.set_pixel(x,y)
end
def == (other)
(self.x == other.x) and (self.y == other.y)
end
def eql?(other)
(self.hash == other.hash)
end
def hash
{'x' => self.x, 'y' => self.y}
end
end
class Line
attr_reader :first_point, :second_point
def initialize(first_point, second_point)
@first_point = first_point
@second_point = second_point
@current_x = from.x
@current_y = from.y
@error = (to.x - from.x).abs - (to.y - from.y).abs
end
def from
if (@first_point.x == @second_point.x)
(@first_point.y <= @second_point.y) ? @first_point : @second_point
else
(@first_point.x <= @second_point.x) ? @first_point : @second_point
end
end
def to
if (@first_point.x == @second_point.x)
(@first_point.y <= @second_point.y) ? @second_point : @first_point
else
(@first_point.x <= @second_point.x) ? @second_point : @first_point
end
end
def draw(canvas)
while(true)
canvas.set_pixel(@current_x, @current_y)
break if reach_last?
error_value_due_to_y
canvas.set_pixel(@current_x, @current_y) if reach_last?
error_value_due_to_x
end
end
def == (other)
(self.from == other.from) and (self.to == other.to)
end
def eql?(other)
(self.hash == other.hash)
end
def hash
{'from_x' => from.x, 'from_y' => from.y, 'to_x' => to.x, 'to_y' => to.y}
end
private
def reach_last?
@current_x == to.x and @current_y == to.y
end
def error_value_due_to_y
if (2 * @error >= -(to.y - from.y).abs)
@error -= (to.y - from.y).abs
(from.x < to.x) ? @current_x += 1 : @current_y -= 1
end
end
def error_value_due_to_x
if (2 * @error < (to.x - from.x).abs)
@error += (to.x - from.x).abs
(from.y < to.y) ? @current_y += 1 : @current_y -= 1
end
end
end
class Rectangle
attr_reader :first_vertex, :second_vertex
def initialize(one_vertex, other_vertex)
@first_vertex = one_vertex
@second_vertex = other_vertex
end
def left
if (@first_vertex.x == @second_vertex.x)
(@first_vertex.y <= @second_vertex.y) ? @first_vertex : @second_vertex
else
(@first_vertex.x <= @second_vertex.x) ? @first_vertex : @second_vertex
end
end
def right
if (@first_vertex.x == @second_vertex.x)
(@first_vertex.y <= @second_vertex.y) ? @second_vertex : @first_vertex
else
(@first_vertex.x <= @second_vertex.x) ? @second_vertex : @first_vertex
end
end
def top_left
x_coordinate = [@first_vertex.x,@second_vertex.x].min
y_coordinate = [@first_vertex.y,@second_vertex.y].min
Point.new(x_coordinate,y_coordinate)
end
def top_right
x_coordinate = [@first_vertex.x,@second_vertex.x].max
y_coordinate = [@first_vertex.y,@second_vertex.y].min
Point.new(x_coordinate,y_coordinate)
end
def bottom_left
x_coordinate = [@first_vertex.x,@second_vertex.x].min
y_coordinate = [@first_vertex.y,@second_vertex.y].max
Point.new(x_coordinate,y_coordinate)
end
def bottom_right
x_coordinate = [@first_vertex.x,@second_vertex.x].max
y_coordinate = [@first_vertex.y,@second_vertex.y].max
Point.new(x_coordinate,y_coordinate)
end
def == (other)
- (self.top_left == other.top_left) and (self.bottom_right == other.botton_right)
+ (self.top_left == other.top_left) and (self.bottom_right == other.bottom_right)
end
def eql?(other)
self.hash == other.hash
end
def hash
x = top_left.x
y = top_left.y
width = (@first_vertex.x - @second_vertex.x).abs
height = (@first_vertex.y - @second_vertex.y).abs
{'point.x' =>x, 'point.y' => y, 'width' => width, 'height' => height}
end
def draw(canvas)
canvas.draw (Line.new(top_left, top_right))
canvas.draw (Line.new(top_left, bottom_left))
canvas.draw (Line.new(bottom_left, bottom_right))
canvas.draw (Line.new(top_right, bottom_right))
end
end
end

Ангел обнови решението на 22.12.2013 03:17 (преди почти 11 години)

module Graphics
class Canvas
- attr_accessor :pixels
+ attr_accessor :pixels
attr_reader :width, :height
def initialize(width, height)
@height = height
@width = width
@pixels = Array.new(height) { Array.new(width, false) }
end
def set_pixel(x, y)
@pixels[y][x] = true
end
def pixel_at?(x, y)
@pixels[y][x]
end
def draw(geometric_object)
geometric_object.draw(self)
end
def render_as(argument)
argument.send(:render, self)
end
end
module Renderers
class Ascii
def self.render(canvas)
ascii_text = canvas.pixels.map{ |row| row.map{ |pixel| pixel }.join }.join("\n")
ascii_text.gsub('false', '-').gsub('true', '@')
end
end
class Html
HEADER =
'<!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">
'
FOOTER =
'
</div>
</body>
</html>'
def self.render(canvas)
html_body = canvas.pixels.map{ |row| row.map{ |pixel| pixel }.join }.join('<br>')
HEADER + html_body.gsub('false', '<i></i>').gsub('true', '<b></b>') + FOOTER
end
end
end
class Point
attr_reader :x, :y
def initialize(x, y)
@x = x
@y = y
end
def draw(canvas)
canvas.set_pixel(x,y)
end
def == (other)
(self.x == other.x) and (self.y == other.y)
end
def eql?(other)
(self.hash == other.hash)
end
def hash
{'x' => self.x, 'y' => self.y}
end
end
class Line
attr_reader :first_point, :second_point
def initialize(first_point, second_point)
@first_point = first_point
@second_point = second_point
@current_x = from.x
@current_y = from.y
@error = (to.x - from.x).abs - (to.y - from.y).abs
end
def from
if (@first_point.x == @second_point.x)
(@first_point.y <= @second_point.y) ? @first_point : @second_point
else
(@first_point.x <= @second_point.x) ? @first_point : @second_point
end
end
def to
if (@first_point.x == @second_point.x)
(@first_point.y <= @second_point.y) ? @second_point : @first_point
else
(@first_point.x <= @second_point.x) ? @second_point : @first_point
end
end
def draw(canvas)
while(true)
canvas.set_pixel(@current_x, @current_y)
break if reach_last?
error_value_due_to_y
canvas.set_pixel(@current_x, @current_y) if reach_last?
error_value_due_to_x
end
end
def == (other)
(self.from == other.from) and (self.to == other.to)
end
def eql?(other)
(self.hash == other.hash)
end
def hash
{'from_x' => from.x, 'from_y' => from.y, 'to_x' => to.x, 'to_y' => to.y}
end
private
def reach_last?
@current_x == to.x and @current_y == to.y
end
def error_value_due_to_y
if (2 * @error >= -(to.y - from.y).abs)
@error -= (to.y - from.y).abs
(from.x < to.x) ? @current_x += 1 : @current_y -= 1
end
end
def error_value_due_to_x
if (2 * @error < (to.x - from.x).abs)
@error += (to.x - from.x).abs
(from.y < to.y) ? @current_y += 1 : @current_y -= 1
end
end
end
class Rectangle
attr_reader :first_vertex, :second_vertex
def initialize(one_vertex, other_vertex)
@first_vertex = one_vertex
@second_vertex = other_vertex
end
def left
if (@first_vertex.x == @second_vertex.x)
(@first_vertex.y <= @second_vertex.y) ? @first_vertex : @second_vertex
else
(@first_vertex.x <= @second_vertex.x) ? @first_vertex : @second_vertex
end
end
def right
if (@first_vertex.x == @second_vertex.x)
(@first_vertex.y <= @second_vertex.y) ? @second_vertex : @first_vertex
else
(@first_vertex.x <= @second_vertex.x) ? @second_vertex : @first_vertex
end
end
def top_left
x_coordinate = [@first_vertex.x,@second_vertex.x].min
y_coordinate = [@first_vertex.y,@second_vertex.y].min
Point.new(x_coordinate,y_coordinate)
end
def top_right
x_coordinate = [@first_vertex.x,@second_vertex.x].max
y_coordinate = [@first_vertex.y,@second_vertex.y].min
Point.new(x_coordinate,y_coordinate)
end
def bottom_left
x_coordinate = [@first_vertex.x,@second_vertex.x].min
y_coordinate = [@first_vertex.y,@second_vertex.y].max
Point.new(x_coordinate,y_coordinate)
end
def bottom_right
x_coordinate = [@first_vertex.x,@second_vertex.x].max
y_coordinate = [@first_vertex.y,@second_vertex.y].max
Point.new(x_coordinate,y_coordinate)
end
def == (other)
(self.top_left == other.top_left) and (self.bottom_right == other.bottom_right)
end
def eql?(other)
self.hash == other.hash
end
def hash
x = top_left.x
y = top_left.y
width = (@first_vertex.x - @second_vertex.x).abs
height = (@first_vertex.y - @second_vertex.y).abs
{'point.x' =>x, 'point.y' => y, 'width' => width, 'height' => height}
end
def draw(canvas)
canvas.draw (Line.new(top_left, top_right))
canvas.draw (Line.new(top_left, bottom_left))
canvas.draw (Line.new(bottom_left, bottom_right))
canvas.draw (Line.new(top_right, bottom_right))
end
end
end

Като цяло, дизайнът ти е в правилната посока. Ето някои неща, които би могъл да подобриш:

  • Помисли дали няма друг по-оптимален начин в Ruby за реализация вътрешното представяне на пано, от масив от масиви. Ruby не е C и има по-удобни структури от данни, за които дори няма нужда да require-ваш нищо :)
  • Също така, pixel_at? може да връща нещо, което се оценява като истина или лъжа; не е задължително да е true/false. Ключът за палатката се крие в отговора на въпроса нужно ли е да описваш предварително факта, че всеки пискел е "празен", като това е състоянието по подразбиране?
  • Защо ти е този attr_accessor на ред 3? Защо не само reader? Не виждам причина да даваш такъв достъп до вътрешното представяне на паното.
  • Бих кръстил метода draw(canvas) на фигурата draw_on(canvas), за по-добра четимост.
  • Защо ползваш send на ред 25? Защо не просто argument.render(self)?
  • Пробвай да пренапишеш методите за рендериране така, че да не трябва да ползваш gsub.
  • Не намирам логиката в начина, по който си идентирал HTML-кода в класа Html. Намира се на няколко интервала отстояние от левия край на редактора. Нито е залепен максимално вляво, нито е подравнен с HEADER/FOOTER, нито е вкаран едно ниво на идентация по-навътре спрямо двете константи.
  • Трябва да има интервал тук: map {, а не така: map{.
  • Класовете на фигури са ти ненужно идентирани едно ниво навътре.
  • Няма нужда от скоби на ред 92 и на други сходни места. Няма нужда от скобите в целите методи from и to на Line, например. Няма нужда от скоби на ред 132 и т.н.
  • Може да ползваш синоними на методи, за да дефинираш единия от методите на равенството на фигури.
  • Мисля, че не си разбрал какво трябва да прави методът hash. Това не е to_h или to_hash. Виж какво прави този метод (hash) на някой от вградените типове данни. Общо-взето, връща едно число.
  • Бих подравнил вертикално спрямо символа = на някои места. Например Line#initialize.
  • Какво ще стане, ако се опитам да начертая един и същи обект линия два пъти? Да кажем, на различни пана? Трябва да работи. Ще работи ли при теб?
  • error_value_due_to_x може би ще е по-добре да се казва compute_next_y или нещо от сорта.
  • Оставяй празен ред след private.
  • Не пропускай да сложиш интервал след запетая (например методите за ъгли на правоъгълник).

Ангел обнови решението на 22.12.2013 21:31 (преди почти 11 години)

module Graphics
class Canvas
- attr_accessor :pixels
- attr_reader :width, :height
+ attr_reader :width, :height, :pixels
def initialize(width, height)
@height = height
- @width = width
- @pixels = Array.new(height) { Array.new(width, false) }
+ @width = width
+ @pixels = {}
end
def set_pixel(x, y)
- @pixels[y][x] = true
+ @pixels["#{x},#{y}"] = true
end
def pixel_at?(x, y)
- @pixels[y][x]
+ @pixels.has_key?("#{x},#{y}")
end
def draw(geometric_object)
- geometric_object.draw(self)
+ geometric_object.draw_on(self)
end
def render_as(argument)
- argument.send(:render, self)
+ argument.render(self)
end
end
module Renderers
class Ascii
+ attr_reader :ascii_text
+
def self.render(canvas)
- ascii_text = canvas.pixels.map{ |row| row.map{ |pixel| pixel }.join }.join("\n")
- ascii_text.gsub('false', '-').gsub('true', '@')
+ @ascii_text = ''
+ 0.upto(canvas.height).each do |row|
+ 0.upto(canvas.width).each do |column|
+ set_character(canvas, column, row)
+ end
+ @ascii_text << "\n"
+ end
+ @ascii_text
end
+
+ private
+
+ def self.set_character(canvas, x, y)
+ canvas.pixel_at?(x, y) ? @ascii_text << '@' : @ascii_text << '-'
+ end
end
class Html
+ attr_reader :html_body
+
HEADER =
- '<!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">
- '
+ '<!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">'
- FOOTER =
- '
- </div>
- </body>
- </html>'
+ FOOTER =
+ ' </div>
+ </body>
+ </html>'
def self.render(canvas)
- html_body = canvas.pixels.map{ |row| row.map{ |pixel| pixel }.join }.join('<br>')
- HEADER + html_body.gsub('false', '<i></i>').gsub('true', '<b></b>') + FOOTER
+ @html_body = ''
+
+ 0.upto(canvas.height).each do |row|
+ 0.upto(canvas.width).each do |column|
+ set_character(canvas, column, row)
+ end
+ @html_body << '<br>'
+ end
+ HEADER + @html_body + FOOTER
end
+
+ private
+
+ def self.set_character(canvas, x, y)
+ canvas.pixel_at?(x, y) ? @html_body << '<b></b>' : @html_body << '<i></i>'
+ end
end
end
- class Point
- attr_reader :x, :y
+ class Point
+ attr_reader :x, :y
- def initialize(x, y)
- @x = x
- @y = y
- end
+ def initialize(x, y)
+ @x = x
+ @y = y
+ end
- def draw(canvas)
- canvas.set_pixel(x,y)
- end
+ def draw_on(canvas)
+ canvas.set_pixel(x,y)
+ end
- def == (other)
- (self.x == other.x) and (self.y == other.y)
- end
+ def == (other)
+ self.x == other.x and self.y == other.y
+ end
- def eql?(other)
- (self.hash == other.hash)
- end
+ def eql?(other)
+ self.hash.eql?(other.hash)
+ end
- def hash
- {'x' => self.x, 'y' => self.y}
- end
+ def hash
+ "X#{x}Y#{y}"
end
+ end
- class Line
- attr_reader :first_point, :second_point
+ class Line
+ attr_reader :first_point, :second_point, :current_x, :current_y
- def initialize(first_point, second_point)
- @first_point = first_point
- @second_point = second_point
- @current_x = from.x
- @current_y = from.y
- @error = (to.x - from.x).abs - (to.y - from.y).abs
- end
+ def initialize(first_point, second_point)
+ @first_point = first_point
+ @second_point = second_point
+ @error = (to.x - from.x).abs - (to.y - from.y).abs
+ end
- def from
- if (@first_point.x == @second_point.x)
- (@first_point.y <= @second_point.y) ? @first_point : @second_point
- else
- (@first_point.x <= @second_point.x) ? @first_point : @second_point
- end
+ def from
+ if @first_point.x == @second_point.x
+ @first_point.y <= @second_point.y ? @first_point : @second_point
+ else
+ @first_point.x <= @second_point.x ? @first_point : @second_point
end
+ end
- def to
- if (@first_point.x == @second_point.x)
- (@first_point.y <= @second_point.y) ? @second_point : @first_point
- else
- (@first_point.x <= @second_point.x) ? @second_point : @first_point
- end
+ def to
+ if @first_point.x == @second_point.x
+ @first_point.y <= @second_point.y ? @second_point : @first_point
+ else
+ @first_point.x <= @second_point.x ? @second_point : @first_point
end
+ end
- def draw(canvas)
- while(true)
- canvas.set_pixel(@current_x, @current_y)
+ def draw_on(canvas)
+ @current_x = from.x
+ @current_y = from.y
+ draw_line(canvas)
+ end
- break if reach_last?
+ def == (other)
+ self.from == other.from and self.to == other.to
+ end
- error_value_due_to_y
+ def eql?(other)
+ self.hash.eql?(other.hash)
+ end
- canvas.set_pixel(@current_x, @current_y) if reach_last?
+ def hash
+ "FX#{from.x}FY#{from.y}TX#{to.x}TY#{to.y}"
+ end
- error_value_due_to_x
- end
- end
+ private
- def == (other)
- (self.from == other.from) and (self.to == other.to)
- end
+ def draw_line(canvas)
+ while true
+ canvas.set_pixel(@current_x, @current_y)
- def eql?(other)
- (self.hash == other.hash)
- end
+ break if reach_last?
- def hash
- {'from_x' => from.x, 'from_y' => from.y, 'to_x' => to.x, 'to_y' => to.y}
- end
+ compute_next_x
- private
- def reach_last?
- @current_x == to.x and @current_y == to.y
+ canvas.set_pixel(@current_x, @current_y) if reach_last?
+
+ compute_next_y
end
+ end
- def error_value_due_to_y
- if (2 * @error >= -(to.y - from.y).abs)
- @error -= (to.y - from.y).abs
- (from.x < to.x) ? @current_x += 1 : @current_y -= 1
- end
+ def reach_last?
+ @current_x == to.x and @current_y == to.y
+ end
+
+ def compute_next_x
+ if (2 * @error >= -(to.y - from.y).abs)
+ @error -= (to.y - from.y).abs
+ from.x < to.x ? @current_x += 1 : @current_y -= 1
end
+ end
- def error_value_due_to_x
- if (2 * @error < (to.x - from.x).abs)
- @error += (to.x - from.x).abs
- (from.y < to.y) ? @current_y += 1 : @current_y -= 1
- end
+ def compute_next_y
+ if (2 * @error < (to.x - from.x).abs)
+ @error += (to.x - from.x).abs
+ from.y < to.y ? @current_y += 1 : @current_y -= 1
end
end
+ end
- class Rectangle
- attr_reader :first_vertex, :second_vertex
+ class Rectangle
+ attr_reader :first_vertex, :second_vertex
- def initialize(one_vertex, other_vertex)
- @first_vertex = one_vertex
- @second_vertex = other_vertex
- end
+ def initialize(one_vertex, other_vertex)
+ @first_vertex = one_vertex
+ @second_vertex = other_vertex
+ end
- def left
- if (@first_vertex.x == @second_vertex.x)
- (@first_vertex.y <= @second_vertex.y) ? @first_vertex : @second_vertex
- else
- (@first_vertex.x <= @second_vertex.x) ? @first_vertex : @second_vertex
- end
+ def left
+ if @first_vertex.x == @second_vertex.x
+ @first_vertex.y <= @second_vertex.y ? @first_vertex : @second_vertex
+ else
+ @first_vertex.x <= @second_vertex.x ? @first_vertex : @second_vertex
end
+ end
- def right
- if (@first_vertex.x == @second_vertex.x)
- (@first_vertex.y <= @second_vertex.y) ? @second_vertex : @first_vertex
- else
- (@first_vertex.x <= @second_vertex.x) ? @second_vertex : @first_vertex
- end
+ def right
+ if @first_vertex.x == @second_vertex.x
+ @first_vertex.y <= @second_vertex.y ? @second_vertex : @first_vertex
+ else
+ @first_vertex.x <= @second_vertex.x ? @second_vertex : @first_vertex
end
+ end
- def top_left
- x_coordinate = [@first_vertex.x,@second_vertex.x].min
- y_coordinate = [@first_vertex.y,@second_vertex.y].min
- Point.new(x_coordinate,y_coordinate)
- end
+ def top_left
+ x_coordinate = [@first_vertex.x, @second_vertex.x].min
+ y_coordinate = [@first_vertex.y, @second_vertex.y].min
+ Point.new(x_coordinate, y_coordinate)
+ end
- def top_right
- x_coordinate = [@first_vertex.x,@second_vertex.x].max
- y_coordinate = [@first_vertex.y,@second_vertex.y].min
- Point.new(x_coordinate,y_coordinate)
- end
+ def top_right
+ x_coordinate = [@first_vertex.x, @second_vertex.x].max
+ y_coordinate = [@first_vertex.y, @second_vertex.y].min
+ Point.new(x_coordinate, y_coordinate)
+ end
- def bottom_left
- x_coordinate = [@first_vertex.x,@second_vertex.x].min
- y_coordinate = [@first_vertex.y,@second_vertex.y].max
- Point.new(x_coordinate,y_coordinate)
- end
+ def bottom_left
+ x_coordinate = [@first_vertex.x, @second_vertex.x].min
+ y_coordinate = [@first_vertex.y, @second_vertex.y].max
+ Point.new(x_coordinate, y_coordinate)
+ end
- def bottom_right
- x_coordinate = [@first_vertex.x,@second_vertex.x].max
- y_coordinate = [@first_vertex.y,@second_vertex.y].max
- Point.new(x_coordinate,y_coordinate)
- end
+ def bottom_right
+ x_coordinate = [@first_vertex.x, @second_vertex.x].max
+ y_coordinate = [@first_vertex.y, @second_vertex.y].max
+ Point.new(x_coordinate, y_coordinate)
+ end
- def == (other)
- (self.top_left == other.top_left) and (self.bottom_right == other.bottom_right)
- end
+ def == (other)
+ self.top_left == other.top_left and self.bottom_right == other.bottom_right
+ end
- def eql?(other)
- self.hash == other.hash
- end
+ def eql?(other)
+ self.hash.eql?(other.hash)
+ end
- def hash
- x = top_left.x
- y = top_left.y
- width = (@first_vertex.x - @second_vertex.x).abs
- height = (@first_vertex.y - @second_vertex.y).abs
+ def hash
+ x = top_left.x
+ y = top_left.y
+ width = (@first_vertex.x - @second_vertex.x).abs
+ height = (@first_vertex.y - @second_vertex.y).abs
- {'point.x' =>x, 'point.y' => y, 'width' => width, 'height' => height}
- end
+ "X#{x}Y#{y}W#{width}H#{height}"
+ end
- def draw(canvas)
- canvas.draw (Line.new(top_left, top_right))
- canvas.draw (Line.new(top_left, bottom_left))
- canvas.draw (Line.new(bottom_left, bottom_right))
- canvas.draw (Line.new(top_right, bottom_right))
- end
+ def draw_on(canvas)
+ canvas.draw (Line.new(top_left, top_right))
+ canvas.draw (Line.new(top_left, bottom_left))
+ canvas.draw (Line.new(bottom_left, bottom_right))
+ canvas.draw (Line.new(top_right, bottom_right))
end
-end
+ end
+end