Решение на Трета задача от Мария Терзиева

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

Към профила на Мария Терзиева

Резултати

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

Код

module Graphics
class Renderers
class Ascii
def self.render(canvas)
pixels = Array.new(canvas.width * canvas.height, "-")
canvas.full_pixels.each { |x, y| pixels[y * canvas.width + x] = "@" }
output = ""
pixels.each_slice(canvas.width) { |row| output << row.join("") << "\n" }
output.chomp("\n")
end
end
class Html
BEGINNING = <<-HTML_BEGINNING
<!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">
HTML_BEGINNING
ENDING = <<-HTML_ENDING
</div>
</body>
</html>
HTML_ENDING
def self.render(canvas)
pixels = Array.new(canvas.width * canvas.height, "<i></i>")
canvas.full_pixels.each { |x, y| pixels[y * canvas.width + x] = "<b></b>" }
output = ""
pixels.each_slice(canvas.width) { |row| output << row.join("") << "<br>" }
body = output.chomp("<br>")
[BEGINNING, body, ENDING].join("")
end
end
end
class Canvas
attr_reader :width, :height, :full_pixels
def initialize(width, height)
@width = width
@height = height
@full_pixels = []
end
def set_pixel(x, y)
@full_pixels << [x, y]
end
def pixel_at?(x, y)
@full_pixels.include? [x, y]
end
def draw(figure)
@full_pixels += figure.rasterize
end
def render_as(renderer)
renderer.render self
end
end
class Point
attr_reader :x, :y
alias_method :eql?, :==
def initialize(x, y)
@x = x
@y = y
end
def coordinates
[@x, @y]
end
def rasterize
[coordinates]
end
def hash
[@x, @y].hash
end
def ==(other)
@x == other.x and @y == other.y
end
end
class Bresenham
def initialize(line)
@x, @y, @end_x, @end_y = *line.from.coordinates, *line.to.coordinates
@pixels = []
@delta_x, @delta_y = (@end_x - @x).abs, (@end_y - @y).abs
@signum_x, @signum_y = @end_x <=> @x, @end_y <=> @y
@error = 2 * @delta_y - @delta_x
@swap = false
end
def swap
if @delta_x < @delta_y
@delta_x, @delta_y = @delta_y, @delta_x
@swap = true
end
end
def next_pixel
if @error > 0
@swap ? @x += @signum_x : @y += @signum_y
@error -= 2 * @delta_x
end
@swap ? @y += @signum_y : @x += @signum_x
@error += 2 * @delta_y
end
def rasterize
swap
@delta_x.times do
@pixels << [@x, @y]
next_pixel
end
@pixels << [@end_x, @end_y]
end
end
class Line
alias_method :eql?, :==
def initialize(from, to)
@from = from
@to = to
end
def from
if @from.x == @to.x
@from.y < @to.y ? @from : @to
else
@from.x < @to.x ? @from : @to
end
end
def to
if @from.x == @to.x
@from.y < @to.y ? @to : @from
else
@from.x < @to.x ? @to : @from
end
end
def hash
[from.hash, to.hash].hash
end
def ==(other)
from == other.from and to == other.to
end
def rasterize
bresenham = Bresenham.new self
bresenham.rasterize
end
end
class Rectangle
attr_reader :left, :right, :top_left
alias_method :eql?, :==
def initialize(left, right)
@left = Line.new(left, right).from
@right = Line.new(left, right).to
@top_left = Point.new([left.x, right.x].min, [left.y, right.y].min)
@width = (left.x - right.x).abs
@height = (left.y - right.y).abs
end
def hash
[top_left.hash, bottom_right.hash].hash
end
def ==(other)
top_left == other.top_left and bottom_right == other.bottom_right
end
def top_right
Point.new @top_left.x + @width, @top_left.y
end
def bottom_left
Point.new @top_left.x, @top_left.y + @height
end
def bottom_right
Point.new @top_left.x + @width, @top_left.y + @height
end
def border
lines = Line.new(top_left, top_right).rasterize
lines += Line.new(top_left, bottom_left).rasterize
lines += Line.new(bottom_left, bottom_right).rasterize
lines += Line.new(bottom_right, top_right).rasterize
end
def rasterize
if left == right
left.rasterize
elsif left.x == right.x or left.y == right.y
Line.new(left, right).rasterize
else
border
end
end
end
end

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

..........F...F...................F..............F...........F.......

Failures:

  1) 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:
       @@ -2,4 +2,6 @@
        @---
        -@@-
        ----
       +
       +@
     # /tmp/d20131223-4637-1bmak4i/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-1bmak4i/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)>'

  2) 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:
       
       
       @@ -1,11 +1,11 @@
        ----------
        -@--------
       --@--------
        --@-------
       ---@-------
       ---@-------
       ---@-------
        ---@------
       +---@------
       +---@------
       +---@------
       +----@-----
        ---@------
        ----------
     # /tmp/d20131223-4637-1bmak4i/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-1bmak4i/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)>'

  3) Graphics shapes Point comparison for equality works for eql? as well
     Failure/Error: a1.should eql a2
       
       expected: #<Graphics::Point:0xb90925a4 @x=4, @y=5>
            got: #<Graphics::Point:0xb90925f4 @x=4, @y=5>
       
       (compared using eql?)
       
       Diff:
       @@ -1,2 +1,2 @@
       -#<Graphics::Point:0xb90925a4 @x=4, @y=5>
       +#<Graphics::Point:0xb90925f4 @x=4, @y=5>
     # /tmp/d20131223-4637-1bmak4i/spec.rb:356: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 shapes Line comparison for equality works with eql? as well
     Failure/Error: a.should eql b
       
       expected: #<Graphics::Line:0xb9067124 @from=#<Graphics::Point:0xb90671b0 @x=1, @y=1>, @to=#<Graphics::Point:0xb9067188 @x=10, @y=14>>
            got: #<Graphics::Line:0xb90671d8 @from=#<Graphics::Point:0xb9067250 @x=1, @y=1>, @to=#<Graphics::Point:0xb9067214 @x=10, @y=14>>
       
       (compared using eql?)
       
       Diff:
       @@ -1,4 +1,4 @@
       -#<Graphics::Line:0xb9067124
       - @from=#<Graphics::Point:0xb90671b0 @x=1, @y=1>,
       - @to=#<Graphics::Point:0xb9067188 @x=10, @y=14>>
       +#<Graphics::Line:0xb90671d8
       + @from=#<Graphics::Point:0xb9067250 @x=1, @y=1>,
       + @to=#<Graphics::Point:0xb9067214 @x=10, @y=14>>
     # /tmp/d20131223-4637-1bmak4i/spec.rb:457: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 works with eql? as well
     Failure/Error: a.should eql b
       
       expected: #<Graphics::Rectangle:0xb902fb48 @left=#<Graphics::Point:0xb902fbc0 @x=1, @y=1>, @right=#<Graphics::Point:0xb902fb98 @x=10, @y=14>, @top_left=#<Graphics::Point:0xb902fa44 @x=1, @y=1>, @width=9, @height=13>
            got: #<Graphics::Rectangle:0xb902fcc4 @left=#<Graphics::Point:0xb902fd14 @x=1, @y=1>, @right=#<Graphics::Point:0xb902fcec @x=10, @y=14>, @top_left=#<Graphics::Point:0xb902fbfc @x=1, @y=1>, @width=9, @height=13>
       
       (compared using eql?)
       
       Diff:
       
       @@ -1,7 +1,7 @@
       -#<Graphics::Rectangle:0xb902fb48
       +#<Graphics::Rectangle:0xb902fcc4
         @height=13,
       - @left=#<Graphics::Point:0xb902fbc0 @x=1, @y=1>,
       - @right=#<Graphics::Point:0xb902fb98 @x=10, @y=14>,
       - @top_left=#<Graphics::Point:0xb902fa44 @x=1, @y=1>,
       + @left=#<Graphics::Point:0xb902fd14 @x=1, @y=1>,
       + @right=#<Graphics::Point:0xb902fcec @x=10, @y=14>,
       + @top_left=#<Graphics::Point:0xb902fbfc @x=1, @y=1>,
         @width=9>
     # /tmp/d20131223-4637-1bmak4i/spec.rb:548: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.09698 seconds
69 examples, 5 failures

Failed examples:

rspec /tmp/d20131223-4637-1bmak4i/spec.rb:51 # Graphics Canvas drawing of shapes and rasterization of points works for multiple ones
rspec /tmp/d20131223-4637-1bmak4i/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-1bmak4i/spec.rb:355 # Graphics shapes Point comparison for equality works for eql? as well
rspec /tmp/d20131223-4637-1bmak4i/spec.rb:452 # Graphics shapes Line comparison for equality works with eql? as well
rspec /tmp/d20131223-4637-1bmak4i/spec.rb:543 # Graphics shapes Rectangle comparison for equality works with eql? as well

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

Мария обнови решението на 22.12.2013 15:49 (преди почти 11 години)

+module Graphics
+ class Renderers
+ class Ascii
+ def self.render(canvas)
+ matrix = Array.new(canvas.width * canvas.height, "-")
+ canvas.set_pixels.each { |x, y| matrix[y * canvas.width + x] = "@" }
+ output = ""
+ matrix.each_slice(canvas.width) { |slice| output << slice.join("") << "\n" }
+ output.chomp("\n")
+ end
+ end
+
+ class Html
+ BEGINNING = <<-HTML_BEGINNING
+ <!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">
+ HTML_BEGINNING
+
+ ENDING = <<-HTML_ENDING
+ </div>
+ </body>
+ </html>
+ HTML_ENDING
+
+ def self.render(canvas)
+ matrix = Array.new(canvas.width * canvas.height, "<i></i>")
+ canvas.set_pixels.each { |x, y| matrix[y * canvas.width + x] = "<b></b>" }
+ output = ""
+ matrix.each_slice(canvas.width) { |slice| output << slice.join("") << "<br>" }
+ body = output.chomp("<br>")
+ [BEGINNING, body, ENDING].join("")
+ end
+ end
+ end
+
+ class Canvas
+ attr_reader :width, :height, :set_pixels
+
+ def initialize(width, height)
+ @width = width
+ @height = height
+ @set_pixels = []
+ end
+
+ def set_pixel(x, y)
+ @set_pixels << [x, y]
+ end
+
+ def pixel_at?(x, y)
+ @set_pixels.include? [x, y]
+ end
+
+ def draw(figure)
+ @set_pixels += figure.rasterize
+ end
+
+ def render_as(renderer)
+ renderer.render(self)
+ end
+ end
+
+ class Point
+ attr_reader :x, :y
+
+ def initialize(x, y)
+ @x = x
+ @y = y
+ end
+
+ def coordinates
+ [@x, @y]
+ end
+
+ def rasterize
+ [coordinates]
+ end
+
+ def hash
+ [@x, @y].hash
+ end
+
+ def ==(other)
+ @x == other.x and @y == other.y
+ end
+
+ alias_method :eql?, :==
+ end
+
+ class Bresenham
+ def initialize(line)
+ @x, @y, @line_end = line.from.x, line.from.y, [line.to.x, line.to.y]
+ @pixels = []
+ @dx, @dy = (line.to.x - @x).abs, (line.to.y - @y).abs
+ @signum_x, @signum_y = line.to.x <=> @x, line.to.y <=> @y
+ @error = 2 * @dy - @dx
+ @swap = false
+ end
+
+ def swap
+ if @dx < @dy
+ @dx, @dy = @dy, @dx
+ @swap = true
+ end
+ end
+
+ def next_pixel
+ if @error > 0
+ @swap ? @x += @signum_x : @y += @signum_y
+ @error -= 2 * @dx
+ end
+ @swap ? @y += @signum_y : @x += @signum_x
+ @error += 2 * @dy
+ end
+
+ def rasterize
+ swap
+ @dx.times do
+ @pixels << [@x, @y]
+ next_pixel
+ end
+ @pixels << @line_end
+ end
+ end
+
+ class Line
+ def initialize(from, to)
+ @from = from
+ @to = to
+ end
+
+ def from
+ if @from.x == @to.x
+ @from.y < @to.y ? @from : @to
+ else
+ @from.x < @to.x ? @from : @to
+ end
+ end
+
+ def to
+ if @from.x == @to.x
+ @from.y < @to.y ? @to : @from
+ else
+ @from.x < @to.x ? @to : @from
+ end
+ end
+
+ def hash
+ [from.hash, to.hash].hash
+ end
+
+ def ==(other)
+ from == other.from and to == other.to
+ end
+
+ def rasterize
+ bresenham = Bresenham.new(self)
+ bresenham.rasterize
+ end
+
+ alias_method :eql?, :==
+ end
+
+ class Rectangle
+ attr_reader :left, :right, :top_left
+
+ def initialize(left, right)
+ @left = Line.new(left, right).from
+ @right = Line.new(left, right).to
+ @top_left = Point.new([left.x, right.x].min, [left.y, right.y].min)
+ @width = (left.x - right.x).abs
+ @height = (left.y - right.y).abs
+ end
+
+ def hash
+ [top_left.hash, bottom_right.hash].hash
+ end
+
+ def ==(other)
+ top_left == other.top_left and bottom_right == other.bottom_right
+ end
+
+ def top_right
+ Point.new(@top_left.x + @width, @top_left.y)
+ end
+
+ def bottom_left
+ Point.new(@top_left.x, @top_left.y + @height)
+ end
+
+ def bottom_right
+ Point.new(@top_left.x + @width, @top_left.y + @height)
+ end
+
+ def border
+ lines = Line.new(top_left, top_right).rasterize
+ lines += Line.new(top_left, bottom_left).rasterize
+ lines += Line.new(bottom_left, bottom_right).rasterize
+ lines += Line.new(bottom_right, top_right).rasterize
+ end
+
+ def rasterize
+ if left == right
+ left.coordinates
+ elsif left.x == right.x or left.y == right.y
+ Line.new(left, right).rasterize
+ else
+ border
+ end
+ end
+
+ alias_method :eql?, :==
+ end
+end

Мария обнови решението на 22.12.2013 18:11 (преди почти 11 години)

module Graphics
class Renderers
class Ascii
def self.render(canvas)
- matrix = Array.new(canvas.width * canvas.height, "-")
- canvas.set_pixels.each { |x, y| matrix[y * canvas.width + x] = "@" }
+ pixels = Array.new(canvas.width * canvas.height, "-")
+ canvas.pixels.each { |x, y| pixels[y * canvas.width + x] = "@" }
output = ""
- matrix.each_slice(canvas.width) { |slice| output << slice.join("") << "\n" }
+ pixels.each_slice(canvas.width) { |row| output << row.join("") << "\n" }
output.chomp("\n")
end
end
class Html
BEGINNING = <<-HTML_BEGINNING
<!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">
HTML_BEGINNING
ENDING = <<-HTML_ENDING
</div>
</body>
</html>
HTML_ENDING
def self.render(canvas)
- matrix = Array.new(canvas.width * canvas.height, "<i></i>")
- canvas.set_pixels.each { |x, y| matrix[y * canvas.width + x] = "<b></b>" }
+ pixels = Array.new(canvas.width * canvas.height, "<i></i>")
+ canvas.pixels.each { |x, y| pixels[y * canvas.width + x] = "<b></b>" }
output = ""
- matrix.each_slice(canvas.width) { |slice| output << slice.join("") << "<br>" }
+ pixels.each_slice(canvas.width) { |row| output << row.join("") << "<br>" }
body = output.chomp("<br>")
[BEGINNING, body, ENDING].join("")
end
end
end
class Canvas
- attr_reader :width, :height, :set_pixels
+ attr_reader :width, :height, :pixels
def initialize(width, height)
@width = width
@height = height
- @set_pixels = []
+ @pixels = []
end
def set_pixel(x, y)
- @set_pixels << [x, y]
+ @pixels << [x, y]
end
def pixel_at?(x, y)
- @set_pixels.include? [x, y]
+ @pixels.include? [x, y]
end
def draw(figure)
- @set_pixels += figure.rasterize
+ @pixels += figure.rasterize
end
def render_as(renderer)
- renderer.render(self)
+ renderer.render self
end
end
class Point
attr_reader :x, :y
+ alias_method :eql?, :==
def initialize(x, y)
@x = x
@y = y
end
def coordinates
[@x, @y]
end
def rasterize
[coordinates]
end
def hash
[@x, @y].hash
end
def ==(other)
@x == other.x and @y == other.y
end
-
- alias_method :eql?, :==
end
class Bresenham
def initialize(line)
- @x, @y, @line_end = line.from.x, line.from.y, [line.to.x, line.to.y]
+ @x, @y, @end_x, @end_y = *line.from.coordinates, *line.to.coordinates
@pixels = []
- @dx, @dy = (line.to.x - @x).abs, (line.to.y - @y).abs
- @signum_x, @signum_y = line.to.x <=> @x, line.to.y <=> @y
+ @dx, @dy = (@end_x - @x).abs, (@end_y - @y).abs
+ @signum_x, @signum_y = @end_x <=> @x, @end_y <=> @y
@error = 2 * @dy - @dx
@swap = false
end
def swap
if @dx < @dy
@dx, @dy = @dy, @dx
@swap = true
end
end
def next_pixel
if @error > 0
@swap ? @x += @signum_x : @y += @signum_y
@error -= 2 * @dx
end
@swap ? @y += @signum_y : @x += @signum_x
@error += 2 * @dy
end
def rasterize
swap
@dx.times do
@pixels << [@x, @y]
next_pixel
end
- @pixels << @line_end
+ @pixels << [@end_x, @end_y]
end
end
class Line
+ alias_method :eql?, :==
+
def initialize(from, to)
@from = from
@to = to
end
def from
if @from.x == @to.x
@from.y < @to.y ? @from : @to
else
@from.x < @to.x ? @from : @to
end
end
def to
if @from.x == @to.x
@from.y < @to.y ? @to : @from
else
@from.x < @to.x ? @to : @from
end
end
def hash
[from.hash, to.hash].hash
end
def ==(other)
from == other.from and to == other.to
end
def rasterize
- bresenham = Bresenham.new(self)
+ bresenham = Bresenham.new self
bresenham.rasterize
end
-
- alias_method :eql?, :==
end
class Rectangle
attr_reader :left, :right, :top_left
+ alias_method :eql?, :==
def initialize(left, right)
@left = Line.new(left, right).from
@right = Line.new(left, right).to
@top_left = Point.new([left.x, right.x].min, [left.y, right.y].min)
@width = (left.x - right.x).abs
@height = (left.y - right.y).abs
end
def hash
[top_left.hash, bottom_right.hash].hash
end
def ==(other)
top_left == other.top_left and bottom_right == other.bottom_right
end
def top_right
- Point.new(@top_left.x + @width, @top_left.y)
+ Point.new @top_left.x + @width, @top_left.y
end
def bottom_left
- Point.new(@top_left.x, @top_left.y + @height)
+ Point.new @top_left.x, @top_left.y + @height
end
def bottom_right
- Point.new(@top_left.x + @width, @top_left.y + @height)
+ Point.new @top_left.x + @width, @top_left.y + @height
end
def border
lines = Line.new(top_left, top_right).rasterize
lines += Line.new(top_left, bottom_left).rasterize
lines += Line.new(bottom_left, bottom_right).rasterize
lines += Line.new(bottom_right, top_right).rasterize
end
def rasterize
if left == right
- left.coordinates
+ left.rasterize
elsif left.x == right.x or left.y == right.y
Line.new(left, right).rasterize
else
border
end
end
-
- alias_method :eql?, :==
end
-end
+end

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

module Graphics
class Renderers
class Ascii
def self.render(canvas)
pixels = Array.new(canvas.width * canvas.height, "-")
- canvas.pixels.each { |x, y| pixels[y * canvas.width + x] = "@" }
+ canvas.full_pixels.each { |x, y| pixels[y * canvas.width + x] = "@" }
output = ""
pixels.each_slice(canvas.width) { |row| output << row.join("") << "\n" }
output.chomp("\n")
end
end
class Html
BEGINNING = <<-HTML_BEGINNING
<!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">
HTML_BEGINNING
ENDING = <<-HTML_ENDING
</div>
</body>
</html>
HTML_ENDING
def self.render(canvas)
pixels = Array.new(canvas.width * canvas.height, "<i></i>")
- canvas.pixels.each { |x, y| pixels[y * canvas.width + x] = "<b></b>" }
+ canvas.full_pixels.each { |x, y| pixels[y * canvas.width + x] = "<b></b>" }
output = ""
pixels.each_slice(canvas.width) { |row| output << row.join("") << "<br>" }
body = output.chomp("<br>")
[BEGINNING, body, ENDING].join("")
end
end
end
class Canvas
- attr_reader :width, :height, :pixels
+ attr_reader :width, :height, :full_pixels
def initialize(width, height)
@width = width
@height = height
- @pixels = []
+ @full_pixels = []
end
def set_pixel(x, y)
- @pixels << [x, y]
+ @full_pixels << [x, y]
end
def pixel_at?(x, y)
- @pixels.include? [x, y]
+ @full_pixels.include? [x, y]
end
def draw(figure)
- @pixels += figure.rasterize
+ @full_pixels += figure.rasterize
end
def render_as(renderer)
renderer.render self
end
end
class Point
attr_reader :x, :y
alias_method :eql?, :==
def initialize(x, y)
@x = x
@y = y
end
def coordinates
[@x, @y]
end
def rasterize
[coordinates]
end
def hash
[@x, @y].hash
end
def ==(other)
@x == other.x and @y == other.y
end
end
class Bresenham
def initialize(line)
@x, @y, @end_x, @end_y = *line.from.coordinates, *line.to.coordinates
@pixels = []
- @dx, @dy = (@end_x - @x).abs, (@end_y - @y).abs
+ @delta_x, @delta_y = (@end_x - @x).abs, (@end_y - @y).abs
@signum_x, @signum_y = @end_x <=> @x, @end_y <=> @y
- @error = 2 * @dy - @dx
+ @error = 2 * @delta_y - @delta_x
@swap = false
end
def swap
- if @dx < @dy
- @dx, @dy = @dy, @dx
+ if @delta_x < @delta_y
+ @delta_x, @delta_y = @delta_y, @delta_x
@swap = true
end
end
def next_pixel
if @error > 0
@swap ? @x += @signum_x : @y += @signum_y
- @error -= 2 * @dx
+ @error -= 2 * @delta_x
end
@swap ? @y += @signum_y : @x += @signum_x
- @error += 2 * @dy
+ @error += 2 * @delta_y
end
def rasterize
swap
- @dx.times do
+ @delta_x.times do
@pixels << [@x, @y]
next_pixel
end
@pixels << [@end_x, @end_y]
end
end
class Line
alias_method :eql?, :==
def initialize(from, to)
@from = from
@to = to
end
def from
if @from.x == @to.x
@from.y < @to.y ? @from : @to
else
@from.x < @to.x ? @from : @to
end
end
def to
if @from.x == @to.x
@from.y < @to.y ? @to : @from
else
@from.x < @to.x ? @to : @from
end
end
def hash
[from.hash, to.hash].hash
end
def ==(other)
from == other.from and to == other.to
end
def rasterize
bresenham = Bresenham.new self
bresenham.rasterize
end
end
class Rectangle
attr_reader :left, :right, :top_left
alias_method :eql?, :==
def initialize(left, right)
@left = Line.new(left, right).from
@right = Line.new(left, right).to
@top_left = Point.new([left.x, right.x].min, [left.y, right.y].min)
@width = (left.x - right.x).abs
@height = (left.y - right.y).abs
end
def hash
[top_left.hash, bottom_right.hash].hash
end
def ==(other)
top_left == other.top_left and bottom_right == other.bottom_right
end
def top_right
Point.new @top_left.x + @width, @top_left.y
end
def bottom_left
Point.new @top_left.x, @top_left.y + @height
end
def bottom_right
Point.new @top_left.x + @width, @top_left.y + @height
end
def border
lines = Line.new(top_left, top_right).rasterize
lines += Line.new(top_left, bottom_left).rasterize
lines += Line.new(bottom_left, bottom_right).rasterize
lines += Line.new(bottom_right, top_right).rasterize
end
def rasterize
if left == right
left.rasterize
elsif left.x == right.x or left.y == right.y
Line.new(left, right).rasterize
else
border
end
end
end
end