Class: UnicodePlot::Canvas

Inherits:
Object
  • Object
show all
Includes:
BorderPrinter
Defined in:
src/lib/unicode_plot/canvas.rb

Direct Known Subclasses

BrailleCanvas, DensityCanvas, LookupCanvas

Constant Summary collapse

CANVAS_CLASS_MAP =
{}

Constants included from StyledPrinter

StyledPrinter::COLOR_DECODE, StyledPrinter::COLOR_ENCODE, StyledPrinter::DISABLE_TEXT_STYLE, StyledPrinter::TEXT_COLORS

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from BorderPrinter

#print_border_bottom, #print_border_top

Methods included from StyledPrinter

#print_color, #print_styled

Constructor Details

#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) ⇒ Canvas

Returns a new instance of Canvas.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'src/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

Instance Attribute Details

#heightObject (readonly)

Returns the value of attribute height.



39
40
41
# File 'src/lib/unicode_plot/canvas.rb', line 39

def height
  @height
end

#origin_xObject (readonly)

Returns the value of attribute origin_x.



42
43
44
# File 'src/lib/unicode_plot/canvas.rb', line 42

def origin_x
  @origin_x
end

#origin_yObject (readonly)

Returns the value of attribute origin_y.



43
44
45
# File 'src/lib/unicode_plot/canvas.rb', line 43

def origin_y
  @origin_y
end

#pixel_heightObject (readonly)

Returns the value of attribute pixel_height.



41
42
43
# File 'src/lib/unicode_plot/canvas.rb', line 41

def pixel_height
  @pixel_height
end

#pixel_widthObject (readonly)

Returns the value of attribute pixel_width.



40
41
42
# File 'src/lib/unicode_plot/canvas.rb', line 40

def pixel_width
  @pixel_width
end

#plot_heightObject (readonly)

Returns the value of attribute plot_height.



45
46
47
# File 'src/lib/unicode_plot/canvas.rb', line 45

def plot_height
  @plot_height
end

#plot_widthObject (readonly)

Returns the value of attribute plot_width.



44
45
46
# File 'src/lib/unicode_plot/canvas.rb', line 44

def plot_width
  @plot_width
end

#widthObject (readonly)

Returns the value of attribute width.



38
39
40
# File 'src/lib/unicode_plot/canvas.rb', line 38

def width
  @width
end

#x_pixel_per_charObject (readonly)

Returns the value of attribute x_pixel_per_char.



46
47
48
# File 'src/lib/unicode_plot/canvas.rb', line 46

def x_pixel_per_char
  @x_pixel_per_char
end

#y_pixel_per_charObject (readonly)

Returns the value of attribute y_pixel_per_char.



47
48
49
# File 'src/lib/unicode_plot/canvas.rb', line 47

def y_pixel_per_char
  @y_pixel_per_char
end

Class Method Details

.create(canvas_type, width, height, **kw) ⇒ Object



7
8
9
10
11
12
13
14
15
# File 'src/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

Instance Method Details

#char_at(x, y) ⇒ Object



71
72
73
# File 'src/lib/unicode_plot/canvas.rb', line 71

def char_at(x, y)
  @grid[index_at(x, y)]
end

#color_at(x, y) ⇒ Object



75
76
77
# File 'src/lib/unicode_plot/canvas.rb', line 75

def color_at(x, y)
  @colors[index_at(x, y)]
end

#index_at(x, y) ⇒ Object



79
80
81
82
# File 'src/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) ⇒ Object

digital differential analyzer algorithm



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'src/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) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
# File 'src/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) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'src/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) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
# File 'src/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


64
65
66
67
68
69
# File 'src/lib/unicode_plot/canvas.rb', line 64

def print(out)
  (0 ... height).each do |row_index|
    print_row(out, row_index)
    out.puts if row_index < height - 1
  end
end

#show(out) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'src/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