class UnicodePlot::Canvas

Constants

CANVAS_CLASS_MAP

Attributes

height[R]
origin_x[R]
origin_y[R]
pixel_height[R]
pixel_width[R]
plot_height[R]
plot_width[R]
width[R]
x_pixel_per_char[R]
y_pixel_per_char[R]

Public Class Methods

create(canvas_type, width, height, **kw) click to toggle source
# File lib/unicode_plot/canvas.rb, line 7
def self.create(canvas_type, width, height, **kw)
  canvas_class = CANVAS_CLASS_MAP[canvas_type]
  case canvas_class
  when Class
    canvas_class.new(width, height, **kw)
  else
    raise ArgumentError, "unknown canvas type: #{canvas_type}"
  end
end
new(width, height, pixel_width, pixel_height, fill_char, origin_x: 0, origin_y: 0, plot_width: 1, plot_height: 1, x_pixel_per_char: 1, y_pixel_per_char: 1) click to toggle source
# File lib/unicode_plot/canvas.rb, line 17
def initialize(width, height, pixel_width, pixel_height, fill_char,
               origin_x: 0,
               origin_y: 0,
               plot_width: 1,
               plot_height: 1,
               x_pixel_per_char: 1,
               y_pixel_per_char: 1)
  @width = width
  @height = height
  @pixel_width = check_positive(pixel_width, :pixel_width)
  @pixel_height = check_positive(pixel_height, :pixel_height)
  @origin_x = origin_x
  @origin_y = origin_y
  @plot_width = plot_width
  @plot_height = plot_height
  @x_pixel_per_char = x_pixel_per_char
  @y_pixel_per_char = y_pixel_per_char
  @grid = Array.new(@width * @height, fill_char)
  @colors = Array.new(@width * @height, COLOR_ENCODE[:normal])
end

Public Instance Methods

char_at(x, y) click to toggle source
# File lib/unicode_plot/canvas.rb, line 71
def char_at(x, y)
  @grid[index_at(x, y)]
end
color_at(x, y) click to toggle source
# File lib/unicode_plot/canvas.rb, line 75
def color_at(x, y)
  @colors[index_at(x, y)]
end
index_at(x, y) click to toggle source
# File lib/unicode_plot/canvas.rb, line 79
def index_at(x, y)
  return nil unless 0 <= x && x < width && 0 <= y && y < height
  y * width + x
end
line!(x1, y1, x2, y2, color) click to toggle source

digital differential analyzer algorithm

# File lib/unicode_plot/canvas.rb, line 112
def line!(x1, y1, x2, y2, color)
  if (x1 < origin_x && x2 < origin_x) ||
      (x1 > origin_x + plot_width && x2 > origin_x + plot_width)
    return color
  end
  if (y1 < origin_y && y2 < origin_y) ||
      (y1 > origin_y + plot_height && y2 > origin_y + plot_height)
    return color
  end

  toff = x1 - origin_x
  px1 = toff.fdiv(plot_width) * pixel_width
  toff = x2 - origin_x
  px2 = toff.fdiv(plot_width) * pixel_width

  toff = y1 - origin_y
  py1 = pixel_height - toff.fdiv(plot_height) * pixel_height
  toff = y2 - origin_y
  py2 = pixel_height - toff.fdiv(plot_height) * pixel_height

  dx = px2 - px1
  dy = py2 - py1
  nsteps = dx.abs > dy.abs ? dx.abs : dy.abs
  inc_x = dx.fdiv(nsteps)
  inc_y = dy.fdiv(nsteps)

  cur_x = px1
  cur_y = py1
  pixel!(cur_x.floor, cur_y.floor, color)
  1.upto(nsteps) do |i|
    cur_x += inc_x
    cur_y += inc_y
    pixel!(cur_x.floor, cur_y.floor, color)
  end
  color
end
lines!(x, y, color = :normal) click to toggle source
# File lib/unicode_plot/canvas.rb, line 149
def lines!(x, y, color = :normal)
  if x.length != y.length
    raise ArgumentError, "x and y must be the same length"
  end
  unless x.length > 0
    raise ArgumentError, "x and y must not be empty"
  end
  (0 ... (x.length - 1)).each do |i|
    line!(x[i], y[i], x[i+1], y[i+1], color)
  end
end
point!(x, y, color) click to toggle source
# File lib/unicode_plot/canvas.rb, line 84
def point!(x, y, color)
  unless origin_x <= x && x <= origin_x + plot_width &&
         origin_y <= y && y <= origin_y + plot_height
    return color
  end

  plot_offset_x = x - origin_x
  pixel_x = plot_offset_x.fdiv(plot_width) * pixel_width

  plot_offset_y = y - origin_y
  pixel_y = pixel_height - plot_offset_y.fdiv(plot_height) * pixel_height

  pixel!(pixel_x.floor, pixel_y.floor, color)
end
points!(x, y, color = :normal) click to toggle source
# File lib/unicode_plot/canvas.rb, line 99
def points!(x, y, color = :normal)
  if x.length != y.length
    raise ArgumentError, "x and y must be the same length"
  end
  unless x.length > 0
    raise ArgumentError, "x and y must not be empty"
  end
  (0 ... x.length).each do |i|
    point!(x[i], y[i], color)
  end
end
print(out) click to toggle source
show(out) click to toggle source
# File lib/unicode_plot/canvas.rb, line 49
def show(out)
  b = BorderMaps::BORDER_SOLID
  border_length = width

  print_border_top(out, "", border_length, :solid, color: :light_black)
  out.puts
  (0 ... height).each do |row_index|
    print_styled(out, b[:l], color: :light_black)
    print_row(out, row_index)
    print_styled(out, b[:r], color: :light_black)
    out.puts
  end
  print_border_bottom(out, "", border_length, :solid, color: :light_black)
end

Private Instance Methods

check_positive(value, name) click to toggle source
# File lib/unicode_plot/canvas.rb, line 161
        def check_positive(value, name)
  return value if value > 0
  raise ArgumentError, "#{name} has to be positive"
end