Class: Amaze::Formatter::Image::Polar

Inherits:
Amaze::Formatter::Image show all
Defined in:
lib/amaze/formatter/image/polar.rb

Instance Attribute Summary

Attributes inherited from Amaze::Formatter::Image

#grid, #options

Instance Method Summary collapse

Methods inherited from Amaze::Formatter::Image

#background_color, #border_width, #canvas, #cell_offset, #cell_width, colors, #distance_color, #distances, #distances_max, #gradient, #hide_walls?, #image, #initialize, #path?, #path_cell?, #path_cells, #path_color, #path_finish, #path_start, #path_width, #render, #show_grid?, #wall_color, #wall_width, #write

Constructor Details

This class inherits a constructor from Amaze::Formatter::Image

Instance Method Details

#center_coord(cell, unit = :degree) ⇒ Object



151
152
153
154
155
156
157
158
# File 'lib/amaze/formatter/image/polar.rb', line 151

def center_coord cell, unit=:degree
  radius = (cell.row + 0.5) * cell_width
  theta = 2 * Math::PI / grid.columns(cell.row).size
  angle = (cell.column + 0.5) * theta
  angle = radian2degree(angle) if unit == :degree

  [radius, angle]
end

#coord(cell, unit = :degree) ⇒ Object



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/amaze/formatter/image/polar.rb', line 130

def coord cell, unit=:degree
  inner_radius = cell.row * cell_width
  outer_radius = (cell.row + 1) * cell_width
  theta = 2 * Math::PI / grid.columns(cell.row).size
  theta_ccw = cell.column * theta
  theta_cw = (cell.column + 1) * theta
  
  # we need only the cartesian coords of the cw wall
  # ax, ay = polar2cartesian(inner_radius, theta_ccw)
  # bx, by = polar2cartesian(outer_radius, theta_ccw)
  cx, cy = polar2cartesian(inner_radius, theta_cw)
  dx, dy = polar2cartesian(outer_radius, theta_cw)
  
  if unit == :degree
    theta_ccw = radian2degree theta_ccw
    theta_cw = radian2degree theta_cw
  end
  
  [cx, cy, dx, dy, inner_radius, theta_ccw, theta_cw]
end

#image_centerObject



174
175
176
# File 'lib/amaze/formatter/image/polar.rb', line 174

def image_center
  image_width / 2
end

#image_widthObject Also known as: image_height



168
169
170
# File 'lib/amaze/formatter/image/polar.rb', line 168

def image_width
  cell_width * grid.rows * 2 + wall_width + border_width * 2 + 3 # why? +3
end

#outward_subdivided?(cell) ⇒ Boolean

Returns:

  • (Boolean)


121
122
123
124
# File 'lib/amaze/formatter/image/polar.rb', line 121

def outward_subdivided? cell
  return false if grid.rows == cell.row + 1
  grid.columns(cell.row).size != grid.columns(cell.row+1).size
end

#path_outward(cell) ⇒ Object



126
127
128
# File 'lib/amaze/formatter/image/polar.rb', line 126

def path_outward cell
  cell.outward.select {|o| cell.linked?(o) && path_cell?(o) }
end

#polar2cartesian(radius, theta) ⇒ Object



160
161
162
# File 'lib/amaze/formatter/image/polar.rb', line 160

def polar2cartesian radius, theta
  [image_center + radius * Math.cos(theta), image_center + radius * Math.sin(theta)]
end

#radian2degree(value) ⇒ Object



164
165
166
# File 'lib/amaze/formatter/image/polar.rb', line 164

def radian2degree value
  360 / (2 * Math::PI) * value
end

#render_backgroundObject



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/amaze/formatter/image/polar.rb', line 4

def render_background
  canvas.stroke_antialias true
  canvas.stroke_linecap 'butt'
  canvas.stroke_width cell_width
  canvas.fill 'none'

  grid.each_cell do |cell|
    color = distance_color cell
    next unless color
    canvas.stroke color
    _, _, _, _, _, ccw, cw = coord cell
    radius, _ = center_coord cell
    canvas.ellipse image_center, image_center, radius, radius, ccw, cw
  end
end

#render_gridObject



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/amaze/formatter/image/polar.rb', line 20

def render_grid
  canvas.stroke_antialias true
  canvas.stroke_linecap 'square'
  canvas.stroke 'gray90'
  canvas.stroke_width 1
  canvas.fill 'none'

  grid.each_cell do |cell|
    next if cell.row == 0
    cx, cy, dx, dy, radius, ccw, cw = coord cell

    canvas.ellipse image_center, image_center, radius, radius, ccw, cw
    canvas.line cx, cy, dx, dy
  end
  canvas.ellipse(image_center, image_center, grid.rows * cell_width, grid.rows * cell_width, 0, 360)
end

#render_pathObject



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/amaze/formatter/image/polar.rb', line 55

def render_path
  canvas.stroke_antialias true
  canvas.stroke_linecap 'square'
  canvas.fill 'none'
  canvas.stroke path_color
  canvas.stroke_width path_width

  grid.each_cell do |cell|
    next unless path_cell? cell

    unless path?(:cw, cell) || path?(:ccw, cell)
      # draw arc to close the gap if outward ring is subdivided
      # and cell is linked outwards but not cw and ccw
      # this can be the case even for cell(0,0)
      outward_cells = path_outward(cell)
      if outward_subdivided?(cell) && outward_cells.any?
        radius, angle = center_coord cell
        angles_outward_cells = outward_cells.map {|o| _, a = center_coord(o); a }
        # don't use cell(0,0) own angel, override with one of the outward cells
        angle = angles_outward_cells.first if cell.row == 0
        angle1 = [angle, *angles_outward_cells].min
        angle2 = [angle, *angles_outward_cells].max
        canvas.ellipse image_center, image_center, radius, radius, angle1, angle2 unless angle1 == angle2
      end
    end

    next if cell.row == 0
    
    if path?(:inward, cell)
      radius, theta = center_coord cell, :radian
      # center of cell
      x1, y1 = polar2cartesian(radius, theta)
      # center of inward cell, but adjusted to the same angle of the current cell
      radius_inward, _ = center_coord cell.inward, :radian
      x2, y2 = polar2cartesian(radius_inward, theta)
      canvas.line x1, y1, x2, y2
    end
    
    if path?(:cw, cell)
      radius1, angle1 = center_coord cell
      radius2, angle2 = center_coord cell.cw
      # adjust angle if outward ring is subdivided
      if outward_subdivided?(cell)
        outward_cells = path_outward(cell)
        _, angle1 = center_coord(outward_cells.first) if outward_cells.any?
        outward_cells_cw = path_outward(cell.cw)
        _, angle2 = center_coord(outward_cells_cw.first) if outward_cells_cw.any?
      end
      canvas.ellipse image_center, image_center, radius1, radius1, angle1, angle2
    end
  end
  
  # draw start and finish
  canvas.stroke_antialias true
  canvas.stroke_linecap 'square'
  canvas.fill path_color
  canvas.stroke 'none'
  [path_start, path_finish].compact.each do |cell|
    radius, theta = center_coord cell, :radian
    # adjust the angle for cell(0,0)
    _, theta = center_coord path_outward(cell).first, :radian if cell.row.zero?
    x, y = polar2cartesian(radius, theta)
    canvas.ellipse x, y, path_width*2, path_width*2, 0, 360
  end
end

#render_wallObject



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/amaze/formatter/image/polar.rb', line 37

def render_wall
  canvas.stroke_antialias true
  canvas.stroke_linecap 'square'
  canvas.stroke wall_color
  canvas.stroke_width wall_width
  canvas.fill 'none'

  grid.each_cell do |cell|
    next if cell.row == 0
    cx, cy, dx, dy, radius, ccw, cw = coord cell
    
    canvas.ellipse image_center, image_center, radius, radius, ccw, cw unless cell.linked_to?(:inward)
    canvas.line cx, cy, dx, dy unless cell.linked_to?(:cw)
  end
  
  canvas.ellipse(image_center, image_center, grid.rows * cell_width, grid.rows * cell_width, 0, 360)
end