Решение на Трета задача от Цветан Иванов

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

Към профила на Цветан Иванов

Резултати

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

Код

module Graphics
class Point
attr_reader :x, :y
def initialize(x, y)
@x, @y = x, y
end
def eql? (other_point)
@x.eql?(other_point.x) and @y.eql? (other_point.y)
end
def draw(canvas)
canvas.set_pixel(@x, @y)
end
def ==(other_point)
eql?(other_point)
end
def hash
@x.hash & @y.hash
end
end
class Line
attr_reader :first_point, :second_point
def initialize(first_point,second_point)
@first_point, @second_point = first_point, second_point
end
def from
if @first_point.x == @second_point.x
return @first_point.y > @second_point.y ? @second_point : @first_point
end
return @first_point.x > @second_point.x ? @second_point : @first_point
end
def to
if @first_point.x == @second_point.x
return @first_point.y < @second_point.y ? @second_point : @first_point
end
return @first_point.x < @second_point.x ? @second_point : @first_point
end
def eql? (other_line)
is_first_equal_first = @first_point.eql?(other_line.first_point)
is_second_equal_second = @second_point.eql?(other_line.second_point)
is_first_equal_second = @first_point.eql?(other_line.second_point)
is_second_equal_first = @second_point.eql?(other_line.first_point)
(is_first_equal_first and is_second_equal_second) or
(is_first_equal_second and is_second_equal_first)
end
def ==(other_line)
eql?(other_line)
end
def hash
@first_point.hash & @second_point.hash
end
def draw(canvas)
bresenham_algorithm = BresenhamAlgorithm.new(@first_point, @second_point)
points = bresenham_algorithm.calculate
points.each { |point| canvas.set_pixel(point.x, point.y) }
end
end
class Rectangle
attr_reader :first_point, :second_point, :points
def initialize(first_point, second_point)
@first_point = first_point
@second_point = second_point
@third_point = Point.new(first_point.x, second_point.y)
@fourth_point = Point.new(second_point.x, first_point.y)
@points = [@first_point, @second_point, @third_point, @fourth_point]
end
def get_left_point(first_point, second_point)
if first_point.x == second_point.x
return first_point.y > second_point.y ? second_point : first_point
end
return first_point.x > second_point.x ? second_point : first_point
end
def left
get_left_point @first_point, @second_point
end
def right
if @first_point.x == @second_point.x
return @first_point.y < @second_point.y ? @second_point : @first_point
end
return @first_point.x < @second_point.x ? @second_point : @first_point
end
def top_left
sorted_points = @points.sort do |first_point, second_point|
first_point.x > second_point.x ? 1 : first_point.y <=> second_point.y
end
sorted_points[0]
end
def bottom_left
sorted_points = @points.sort do |first_point, second_point|
first_point.x > second_point.x ? 1 : second_point.y <=> first_point.y
end
sorted_points[0]
end
def bottom_right
sorted_points = @points.sort do |first_point, second_point|
first_point.y < second_point.y ? 1 : second_point.x <=> first_point.x
end
sorted_points[0]
end
def top_right
sorted_points = @points.sort do |first_point, second_point|
first_point.y > second_point.y ? 1 : second_point.x <=> first_point.x
end
sorted_points[0]
end
def eql? (other_rectangle)
top_left.eql?(other_rectangle.top_left) and
top_right.eql?(other_rectangle.top_right) and
bottom_left.eql?(other_rectangle.bottom_left) and
bottom_right.eql?(other_rectangle.bottom_right)
end
def ==(other_rectangle)
eql?(other_rectangle)
end
def hash
top_left.hash & top_right.hash & bottom_left.hash & bottom_right.hash
end
def draw(canvas)
Line.new(top_left, top_right).draw(canvas)
Line.new(top_right, bottom_right).draw(canvas)
Line.new(bottom_right, bottom_left).draw(canvas)
Line.new(bottom_left, top_left).draw(canvas)
end
end
class BresenhamAlgorithm
def initialize(first_point, second_point)
@first_point_x, @first_point_y = first_point.x, first_point.y
@second_point_x, @second_point_y = second_point.x, second_point.y
initialize_step
initialize_coordinates
initialize_deltas
end
def initialize_step
difference_y = (@second_point_y - @first_point_y).abs
difference_x = (@second_point_x - @first_point_x).abs
@steep = difference_y > difference_x
end
def initialize_deltas
@delta_x = @second_point_x - @first_point_x
@delta_y = (@second_point_y - @first_point_y).abs
@error = @delta_x / 2
@step_y = @first_point_y < @second_point_y ? 1 : -1
end
def initialize_coordinates
if @steep
@first_point_x, @first_point_y = @first_point_y, @first_point_x
@second_point_x, @second_point_y = @second_point_y, @second_point_x
end
if @first_point_x > @second_point_x
@first_point_x, @second_point_x = @second_point_x, @first_point_x
@first_point_y, @second_point_y = @second_point_y, @first_point_y
end
end
def calculate
points = []
@first_point_x.upto(@second_point_x) do |x|
points << (@steep ? Point.new(@first_point_y, x) : Point.new(x, @first_point_y))
increment_position
end
points
end
def increment_position
@error = @error - @delta_y
if @error <= 0
@first_point_y = @first_point_y + @step_y
@error = @error + @delta_x
end
end
end
class Canvas
attr_reader :width, :height
def initialize(width, height)
@width = width
@height = height
@field = Array.new(height){ Array.new(width){ false } }
end
def set_pixel(x, y)
@field[y][x] = true
end
def pixel_at?(x, y)
@field[y][x]
end
def draw(figure)
figure.draw(self)
end
def render_as(renderer_class)
renderer = renderer_class.new
renderer.render(@field)
end
end
module Renderers
class Renderer
def render(field, full_pixel, blank_pixel, line_break_symbol)
rendered_field = ''
field.each_with_index do |row, index_row|
row.each_with_index do |pixel, index_pixel|
rendered_field << find_pixel(pixel, full_pixel, blank_pixel)
end
rendered_field << line_break_symbol
end
rendered_field
end
def find_pixel(pixel, full_pixel, blank_pixel)
if pixel
full_pixel
else
blank_pixel
end
end
end
class Ascii < Renderer
def render(field)
super(field, "@", "-", "\n").chop
end
end
class Html < Renderer
START_HTML = <<-eos
<!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">
eos
END_HTML = <<-eos
</div>
</body>
</html>
eos
def render(field)
rendered_field = super(field, "<b></b>", "<i></i>", "<br>")
"" << START_HTML << rendered_field[0..-5] << END_HTML
end
end
end
end

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

..........F..FFF...........................................FF........

Failures:

  1) Graphics Canvas drawing of shapes and rasterization of points works for multiple ones
     Failure/Error: canvas.set_pixel 4, 4
     NoMethodError:
       undefined method `[]=' for nil:NilClass
     # /tmp/d20131223-4637-ouhrb0/solution.rb:224:in `set_pixel'
     # /tmp/d20131223-4637-ouhrb0/spec.rb:57: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)>'

  2) 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----------"
       
       (compared using ==)
       
       Diff:
       @@ -1,6 +1,6 @@
        ----------
        -@@-------
       ----@@@@---
       --------@@-
       +---@@@----
       +------@@@-
        ----------
     # /tmp/d20131223-4637-ouhrb0/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-ouhrb0/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)>'

  3) 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----------"
       
       (compared using ==)
       
       Diff:
       @@ -4,7 +4,7 @@
        --@-------
        --@-------
        --@-------
       ---@-------
       +---@------
        ---@------
        ---@------
        ----------
     # /tmp/d20131223-4637-ouhrb0/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-ouhrb0/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)>'

  4) 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----------"
       
       (compared using ==)
       
       Diff:
       @@ -1,6 +1,6 @@
        -@--------
        -@@-------
       --@-@@@@---
       --@-----@@-
       +-@-@@@----
       +-@----@@@-
        ----------
     # /tmp/d20131223-4637-ouhrb0/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-ouhrb0/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)>'

  5) Graphics shapes Rectangle comparison for equality is true if rectangle points are the same, even if swapped
     Failure/Error: (a == b).should be_true
       expected: true value
            got: false
     # /tmp/d20131223-4637-ouhrb0/spec.rb:533: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 shapes Rectangle comparison for equality is true for rectangles defined with different diagonal corners
     Failure/Error: (a == b).should be_true
       expected: true value
            got: false
     # /tmp/d20131223-4637-ouhrb0/spec.rb:540: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)>'

Finished in 0.10533 seconds
69 examples, 6 failures

Failed examples:

rspec /tmp/d20131223-4637-ouhrb0/spec.rb:51 # Graphics Canvas drawing of shapes and rasterization of points works for multiple ones
rspec /tmp/d20131223-4637-ouhrb0/spec.rb:96 # Graphics Canvas drawing of shapes and rasterization of lines works with lines with a small slope
rspec /tmp/d20131223-4637-ouhrb0/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-ouhrb0/spec.rb:127 # Graphics Canvas drawing of shapes and rasterization of lines works with multiple lines
rspec /tmp/d20131223-4637-ouhrb0/spec.rb:529 # Graphics shapes Rectangle comparison for equality is true if rectangle points are the same, even if swapped
rspec /tmp/d20131223-4637-ouhrb0/spec.rb:536 # Graphics shapes Rectangle comparison for equality is true for rectangles defined with different diagonal corners

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

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

+module Graphics
+ class Point
+ attr_reader :x, :y
+
+ def initialize(x, y)
+ @x, @y = x, y
+ end
+
+ def eql? (other_point)
+ @x.eql?(other_point.x) and @y.eql? (other_point.y)
+ end
+
+ def draw(canvas)
+ canvas.set_pixel(@x, @y)
+ end
+
+ def ==(other_point)
+ eql?(other_point)
+ end
+
+ def hash
+ @x.hash & @y.hash
+ end
+ end
+
+ class Line
+ attr_reader :first_point, :second_point
+
+ def initialize(first_point,second_point)
+ @first_point, @second_point = first_point, second_point
+ end
+
+ def from
+ if @first_point.x == @second_point.x
+ return @first_point.y > @second_point.y ? @second_point : @first_point
+ end
+
+ return @first_point.x > @second_point.x ? @second_point : @first_point
+ end
+
+ def to
+ if @first_point.x == @second_point.x
+ return @first_point.y < @second_point.y ? @second_point : @first_point
+ end
+
+ return @first_point.x < @second_point.x ? @second_point : @first_point
+ end
+
+ def eql? (other_line)
+ is_first_equal_first = @first_point.eql?(other_line.first_point)
+ is_second_equal_second = @second_point.eql?(other_line.second_point)
+ is_first_equal_second = @first_point.eql?(other_line.second_point)
+ is_second_equal_first = @second_point.eql?(other_line.first_point)
+
+ (is_first_equal_first and is_second_equal_second) or
+ (is_first_equal_second and is_second_equal_first)
+ end
+
+ def ==(other_line)
+ eql?(other_line)
+ end
+
+ def hash
+ @first_point.hash & @second_point.hash
+ end
+
+ def draw(canvas)
+ bresenham_algorithm = BresenhamAlgorithm.new(@first_point, @second_point)
+ points = bresenham_algorithm.calculate
+ points.each { |point| canvas.set_pixel(point.x, point.y) }
+ end
+ end
+
+ class Rectangle
+ attr_reader :first_point, :second_point, :points
+
+ def initialize(first_point, second_point)
+ @first_point = first_point
+ @second_point = second_point
+ @third_point = Point.new(first_point.x, second_point.y)
+ @fourth_point = Point.new(second_point.x, first_point.y)
+ @points = [@first_point, @second_point, @third_point, @fourth_point]
+ end
+
+ def get_left_point(first_point, second_point)
+ if first_point.x == second_point.x
+ return first_point.y > second_point.y ? second_point : first_point
+ end
+
+ return first_point.x > second_point.x ? second_point : first_point
+ end
+
+ def left
+ get_left_point @first_point, @second_point
+ end
+
+ def right
+ if @first_point.x == @second_point.x
+ return @first_point.y < @second_point.y ? @second_point : @first_point
+ end
+
+ return @first_point.x < @second_point.x ? @second_point : @first_point
+ end
+
+ def top_left
+ sorted_points = @points.sort do |first_point, second_point|
+ first_point.x > second_point.x ? 1 : first_point.y <=> second_point.y
+ end
+
+ sorted_points[0]
+ end
+
+ def bottom_left
+ sorted_points = @points.sort do |first_point, second_point|
+ first_point.x > second_point.x ? 1 : second_point.y <=> first_point.y
+ end
+
+ sorted_points[0]
+ end
+
+ def bottom_right
+ sorted_points = @points.sort do |first_point, second_point|
+ first_point.y < second_point.y ? 1 : second_point.x <=> first_point.x
+ end
+
+ sorted_points[0]
+ end
+
+ def top_right
+ sorted_points = @points.sort do |first_point, second_point|
+ first_point.y > second_point.y ? 1 : second_point.x <=> first_point.x
+ end
+
+ sorted_points[0]
+ end
+
+ def eql? (other_rectangle)
+ top_left.eql?(other_rectangle.top_left) and
+ top_right.eql?(other_rectangle.top_right) and
+ bottom_left.eql?(other_rectangle.bottom_left) and
+ bottom_right.eql?(other_rectangle.bottom_right)
+ end
+
+ def ==(other_rectangle)
+ eql?(other_rectangle)
+ end
+
+ def hash
+ top_left.hash & top_right.hash & bottom_left.hash & bottom_right.hash
+ end
+
+ def draw(canvas)
+ Line.new(top_left, top_right).draw(canvas)
+ Line.new(top_right, bottom_right).draw(canvas)
+ Line.new(bottom_right, bottom_left).draw(canvas)
+ Line.new(bottom_left, top_left).draw(canvas)
+ end
+ end
+
+ class BresenhamAlgorithm
+ def initialize(first_point, second_point)
+ @first_point_x, @first_point_y = first_point.x, first_point.y
+ @second_point_x, @second_point_y = second_point.x, second_point.y
+ initialize_step
+ initialize_coordinates
+ initialize_deltas
+ end
+
+ def initialize_step
+ difference_y = (@second_point_y - @first_point_y).abs
+ difference_x = (@second_point_x - @first_point_x).abs
+ @steep = difference_y > difference_x
+ end
+
+ def initialize_deltas
+ @delta_x = @second_point_x - @first_point_x
+ @delta_y = (@second_point_y - @first_point_y).abs
+ @error = @delta_x / 2
+ @step_y = @first_point_y < @second_point_y ? 1 : -1
+ end
+
+ def initialize_coordinates
+ if @steep
+ @first_point_x, @first_point_y = @first_point_y, @first_point_x
+ @second_point_x, @second_point_y = @second_point_y, @second_point_x
+ end
+
+ if @first_point_x > @second_point_x
+ @first_point_x, @second_point_x = @second_point_x, @first_point_x
+ @first_point_y, @second_point_y = @second_point_y, @first_point_y
+ end
+ end
+
+ def calculate
+ points = []
+
+ @first_point_x.upto(@second_point_x) do |x|
+ points << (@steep ? Point.new(@first_point_y, x) : Point.new(x, @first_point_y))
+ increment_position
+ end
+
+ points
+ end
+
+ def increment_position
+ @error -= @delta_y
+ if @error <= 0
+ @first_point_y += @step_y
+ @error += @delta_x
+ end
+ end
+ end
+
+ class Canvas
+ attr_reader :width, :height
+
+ def initialize(width, height)
+ @width = width
+ @height = height
+ @field = Array.new(height){ Array.new(width){ false } }
+ end
+
+ def set_pixel(x, y)
+ @field[y][x] = true
+ end
+
+ def pixel_at?(x, y)
+ @field[y][x]
+ end
+
+ def draw(figure)
+ figure.draw(self)
+ end
+
+ def render_as(renderer_class)
+ renderer = renderer_class.new
+ renderer.render(@field)
+ end
+ end
+
+ module Renderers
+ class Renderer
+ def render(field, full_pixel, blank_pixel, line_break_symbol)
+ rendered_field = ''
+ field.each_with_index do |row, index_row|
+ row.each_with_index do |pixel, index_pixel|
+ rendered_field<< find_pixel(pixel, full_pixel, blank_pixel)
+ end
+
+ rendered_field << line_break_symbol
+ end
+
+ rendered_field
+ end
+
+ def find_pixel(pixel, full_pixel, blank_pixel)
+ if pixel
+ full_pixel
+ else
+ blank_pixel
+ end
+ end
+ end
+
+ class Ascii < Renderer
+ def render(field)
+ super(field, "@", "-", "\n").chop
+ end
+ end
+
+ class Html < Renderer
+ START_HTML = <<-eos
+ <!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">
+ eos
+
+ END_HTML = <<-eos
+ </div>
+ </body>
+ </html>
+ eos
+
+ def render(field)
+ rendered_field = super(field, "<b></b>", "<i></i>", "<br>")
+ "" << START_HTML << rendered_field[0..-5] << END_HTML
+ end
+ end
+ end
+end

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

module Graphics
class Point
attr_reader :x, :y
def initialize(x, y)
@x, @y = x, y
end
def eql? (other_point)
@x.eql?(other_point.x) and @y.eql? (other_point.y)
end
def draw(canvas)
canvas.set_pixel(@x, @y)
end
def ==(other_point)
eql?(other_point)
end
def hash
@x.hash & @y.hash
end
end
class Line
attr_reader :first_point, :second_point
def initialize(first_point,second_point)
@first_point, @second_point = first_point, second_point
end
def from
if @first_point.x == @second_point.x
return @first_point.y > @second_point.y ? @second_point : @first_point
end
return @first_point.x > @second_point.x ? @second_point : @first_point
end
def to
if @first_point.x == @second_point.x
return @first_point.y < @second_point.y ? @second_point : @first_point
end
return @first_point.x < @second_point.x ? @second_point : @first_point
end
def eql? (other_line)
is_first_equal_first = @first_point.eql?(other_line.first_point)
is_second_equal_second = @second_point.eql?(other_line.second_point)
is_first_equal_second = @first_point.eql?(other_line.second_point)
is_second_equal_first = @second_point.eql?(other_line.first_point)
(is_first_equal_first and is_second_equal_second) or
(is_first_equal_second and is_second_equal_first)
end
def ==(other_line)
eql?(other_line)
end
def hash
@first_point.hash & @second_point.hash
end
def draw(canvas)
bresenham_algorithm = BresenhamAlgorithm.new(@first_point, @second_point)
points = bresenham_algorithm.calculate
points.each { |point| canvas.set_pixel(point.x, point.y) }
end
end
class Rectangle
attr_reader :first_point, :second_point, :points
def initialize(first_point, second_point)
@first_point = first_point
@second_point = second_point
@third_point = Point.new(first_point.x, second_point.y)
@fourth_point = Point.new(second_point.x, first_point.y)
@points = [@first_point, @second_point, @third_point, @fourth_point]
end
def get_left_point(first_point, second_point)
if first_point.x == second_point.x
return first_point.y > second_point.y ? second_point : first_point
end
return first_point.x > second_point.x ? second_point : first_point
end
def left
get_left_point @first_point, @second_point
end
def right
if @first_point.x == @second_point.x
return @first_point.y < @second_point.y ? @second_point : @first_point
end
return @first_point.x < @second_point.x ? @second_point : @first_point
end
def top_left
sorted_points = @points.sort do |first_point, second_point|
first_point.x > second_point.x ? 1 : first_point.y <=> second_point.y
end
sorted_points[0]
end
def bottom_left
sorted_points = @points.sort do |first_point, second_point|
first_point.x > second_point.x ? 1 : second_point.y <=> first_point.y
end
sorted_points[0]
end
def bottom_right
sorted_points = @points.sort do |first_point, second_point|
first_point.y < second_point.y ? 1 : second_point.x <=> first_point.x
end
sorted_points[0]
end
def top_right
sorted_points = @points.sort do |first_point, second_point|
first_point.y > second_point.y ? 1 : second_point.x <=> first_point.x
end
sorted_points[0]
end
def eql? (other_rectangle)
top_left.eql?(other_rectangle.top_left) and
top_right.eql?(other_rectangle.top_right) and
bottom_left.eql?(other_rectangle.bottom_left) and
bottom_right.eql?(other_rectangle.bottom_right)
end
def ==(other_rectangle)
eql?(other_rectangle)
end
def hash
top_left.hash & top_right.hash & bottom_left.hash & bottom_right.hash
end
def draw(canvas)
Line.new(top_left, top_right).draw(canvas)
Line.new(top_right, bottom_right).draw(canvas)
Line.new(bottom_right, bottom_left).draw(canvas)
Line.new(bottom_left, top_left).draw(canvas)
end
end
class BresenhamAlgorithm
def initialize(first_point, second_point)
@first_point_x, @first_point_y = first_point.x, first_point.y
@second_point_x, @second_point_y = second_point.x, second_point.y
initialize_step
initialize_coordinates
initialize_deltas
end
def initialize_step
difference_y = (@second_point_y - @first_point_y).abs
difference_x = (@second_point_x - @first_point_x).abs
@steep = difference_y > difference_x
end
def initialize_deltas
@delta_x = @second_point_x - @first_point_x
@delta_y = (@second_point_y - @first_point_y).abs
@error = @delta_x / 2
@step_y = @first_point_y < @second_point_y ? 1 : -1
end
def initialize_coordinates
if @steep
@first_point_x, @first_point_y = @first_point_y, @first_point_x
@second_point_x, @second_point_y = @second_point_y, @second_point_x
end
if @first_point_x > @second_point_x
@first_point_x, @second_point_x = @second_point_x, @first_point_x
@first_point_y, @second_point_y = @second_point_y, @first_point_y
end
end
def calculate
points = []
@first_point_x.upto(@second_point_x) do |x|
points << (@steep ? Point.new(@first_point_y, x) : Point.new(x, @first_point_y))
increment_position
end
points
end
def increment_position
- @error -= @delta_y
+ @error = @error - @delta_y
if @error <= 0
- @first_point_y += @step_y
- @error += @delta_x
+ @first_point_y = @first_point_y + @step_y
+ @error = @error + @delta_x
end
end
end
class Canvas
attr_reader :width, :height
def initialize(width, height)
@width = width
@height = height
@field = Array.new(height){ Array.new(width){ false } }
end
def set_pixel(x, y)
@field[y][x] = true
end
def pixel_at?(x, y)
@field[y][x]
end
def draw(figure)
figure.draw(self)
end
def render_as(renderer_class)
renderer = renderer_class.new
renderer.render(@field)
end
end
module Renderers
class Renderer
def render(field, full_pixel, blank_pixel, line_break_symbol)
rendered_field = ''
field.each_with_index do |row, index_row|
row.each_with_index do |pixel, index_pixel|
- rendered_field<< find_pixel(pixel, full_pixel, blank_pixel)
+ rendered_field << find_pixel(pixel, full_pixel, blank_pixel)
end
rendered_field << line_break_symbol
end
rendered_field
end
def find_pixel(pixel, full_pixel, blank_pixel)
if pixel
full_pixel
else
blank_pixel
end
end
end
class Ascii < Renderer
def render(field)
super(field, "@", "-", "\n").chop
end
end
class Html < Renderer
START_HTML = <<-eos
<!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">
eos
END_HTML = <<-eos
</div>
</body>
</html>
eos
def render(field)
rendered_field = super(field, "<b></b>", "<i></i>", "<br>")
"" << START_HTML << rendered_field[0..-5] << END_HTML
end
end
end
end