Class: GraphImageDrawer
- Inherits:
-
Object
- Object
- GraphImageDrawer
- Defined in:
- lib/technical_graph/graph_image_drawer.rb
Overview
options parameters: :width - width of image :height - height of image :x_min, :x_max, :y_min, :y_max - default or fixed ranges :xy_behaviour:
-
:default - use them as default ranges
-
:fixed - ranges will not be changed during addition of layers
Constant Summary collapse
- DEFAULT_WIDTH =
default sizes
1600- DEFAULT_HEIGHT =
1200- ONE_LAYER_LEGEND_SPACER =
height of 1 layer without font size
5
Instance Attribute Summary collapse
-
#drawer ⇒ Object
readonly
Returns the value of attribute drawer.
-
#technical_graph ⇒ Object
readonly
Returns the value of attribute technical_graph.
Instance Method Summary collapse
- #antialias ⇒ Object
- #axis_font_size ⇒ Object
-
#best_output_format ⇒ Object
Best output image format, used for testing.
-
#calc_bitmap_x(_x) ⇒ Object
Calculate image X position.
-
#calc_bitmap_y(_y) ⇒ Object
Calculate image Y position.
-
#crate_blank_graph_image ⇒ Object
Create background image.
-
#data_processor ⇒ Object
Calculate everything.
- #draw_legend? ⇒ Boolean
-
#drawing_class ⇒ Object
Which type of drawing class use?.
-
#graph_axis ⇒ Object
Axis processing.
- #height ⇒ Object
- #height=(h) ⇒ Object
-
#initialize(technical_graph) ⇒ GraphImageDrawer
constructor
A new instance of GraphImageDrawer.
-
#layers ⇒ Object
Accessor for DataLayer Array.
- #legend_auto_position ⇒ Object
- #legend_height ⇒ Object
- #legend_margin ⇒ Object
- #legend_width ⇒ Object
- #legend_x ⇒ Object
- #legend_y ⇒ Object
- #logger ⇒ Object
- #one_layer_legend_height ⇒ Object
-
#options ⇒ Object
Accessor for options Hash.
-
#post_dot_drawn(bx, by) ⇒ Object
Used for auto position for legend.
-
#pre_image_create_calculations ⇒ Object
Everything that must be done before creating image.
-
#recalculate_legend_position ⇒ Object
Choose best location.
-
#recalculate_legend_size ⇒ Object
Enlarge legend’s width using legend labels sizes.
-
#render_data_layer(l) ⇒ Object
Render data layer, calculate coords and execute proxy.
-
#render_data_legend ⇒ Object
Render legend on graph.
-
#rmagick_installed? ⇒ Boolean
Check if rmagick is installed.
-
#save_to_file(file) ⇒ Object
Save output to file.
-
#to_format(format) ⇒ Object
Export image.
-
#to_png ⇒ Object
Return binary PNG.
- #to_svg ⇒ Object
- #to_svgz ⇒ Object
- #truncate_string ⇒ Object
- #width ⇒ Object
- #width=(w) ⇒ Object
Constructor Details
#initialize(technical_graph) ⇒ GraphImageDrawer
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 120 121 122 123 124 125 126 127 128 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 84 def initialize(technical_graph) @technical_graph = technical_graph t = Time.now # drawer type #options[:drawer_class] ||= :rmagick [:drawer_class] ||= :rasem [:width] ||= DEFAULT_WIDTH [:height] ||= DEFAULT_HEIGHT [:axis_value_and_param_labels] = true if [:axis_value_and_param_labels].nil? [:axis_zero_labels] = true if [:axis_zero_labels].nil? [:adjust_axis_to_zero] = true if [:adjust_axis_to_zero].nil? # colors [:background_color] ||= 'white' [:background_hatch_color] ||= 'lightcyan2' [:axis_color] ||= '#000000' # antialias [:antialias] = false if [:antialias].nil? # font sizes [:axis_font_size] ||= 10 [:layers_font_size] ||= 10 [:axis_label_font_size] ||= 10 [:legend_font_size] ||= 10 # legend [:legend] = false if [:legend].nil? [:legend_auto] = true if [:legend_auto].nil? [:legend_x] ||= 50 [:legend_y] ||= 50 [:legend_width] ||= 100 [:legend_margin] ||= 50 # array of all points drawn on graph, used for auto positioning of legend @drawn_points = Array.new logger.debug "initializing #{self.class}" logger.debug " TIME COST #{Time.now - t}" end |
Instance Attribute Details
#drawer ⇒ Object (readonly)
Returns the value of attribute drawer.
209 210 211 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 209 def drawer @drawer end |
#technical_graph ⇒ Object (readonly)
Returns the value of attribute technical_graph.
45 46 47 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 45 def technical_graph @technical_graph end |
Instance Method Details
#antialias ⇒ Object
146 147 148 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 146 def antialias [:antialias] == true end |
#axis_font_size ⇒ Object
75 76 77 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 75 def axis_font_size [:axis_font_size] end |
#best_output_format ⇒ Object
Best output image format, used for testing
41 42 43 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 41 def best_output_format @technical_graph.best_output_format end |
#calc_bitmap_x(_x) ⇒ Object
Calculate image X position
179 180 181 182 183 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 179 def calc_bitmap_x(_x) l = data_processor.x_max - data_processor.x_min offset = _x - data_processor.x_min return (offset.to_f * width.to_f) / l.to_f end |
#calc_bitmap_y(_y) ⇒ Object
Calculate image Y position
186 187 188 189 190 191 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 186 def calc_bitmap_y(_y) l = data_processor.y_max - data_processor.y_min #offset = _y - data_processor.y_min offset = data_processor.y_max - _y return (offset.to_f * height.to_f) / l.to_f end |
#crate_blank_graph_image ⇒ Object
Create background image
200 201 202 203 204 205 206 207 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 200 def crate_blank_graph_image # reset color banks GraphColorLibrary.instance.reset # calculate some stuff :] pre_image_create_calculations # create drawing proxy @drawer = drawing_class.new(self) end |
#data_processor ⇒ Object
Calculate everything
58 59 60 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 58 def data_processor @technical_graph.data_processor end |
#draw_legend? ⇒ Boolean
150 151 152 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 150 def draw_legend? [:legend] end |
#drawing_class ⇒ Object
Which type of drawing class use?
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 19 def drawing_class if [:drawer_class] == :rmagick and rmagick_installed? require 'technical_graph/graph_image_drawer_rmagick' return GraphImageDrawerRmagick end if [:drawer_class] == :rasem require 'technical_graph/graph_image_drawer_rasem' return GraphImageDrawerRasem end # default require 'technical_graph/graph_image_drawer_rasem' return GraphImageDrawerRasem end |
#graph_axis ⇒ Object
Axis processing
63 64 65 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 63 def graph_axis @technical_graph.axis end |
#height ⇒ Object
134 135 136 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 134 def height [:height].to_i end |
#height=(h) ⇒ Object
142 143 144 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 142 def height=(h) [:height] = h.to_i if h.to_i > 0 end |
#layers ⇒ Object
Accessor for DataLayer Array
53 54 55 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 53 def layers @technical_graph.layers end |
#legend_auto_position ⇒ Object
162 163 164 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 162 def legend_auto_position [:legend_auto] end |
#legend_height ⇒ Object
170 171 172 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 170 def legend_height [:legend_height] end |
#legend_margin ⇒ Object
174 175 176 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 174 def legend_margin [:legend_margin] end |
#legend_width ⇒ Object
166 167 168 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 166 def legend_width [:legend_width] end |
#legend_x ⇒ Object
154 155 156 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 154 def legend_x [:legend_x] end |
#legend_y ⇒ Object
158 159 160 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 158 def legend_y [:legend_y] end |
#logger ⇒ Object
67 68 69 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 67 def logger @technical_graph.logger end |
#one_layer_legend_height ⇒ Object
256 257 258 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 256 def one_layer_legend_height [:legend_font_size] + ONE_LAYER_LEGEND_SPACER end |
#options ⇒ Object
Accessor for options Hash
48 49 50 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 48 def @technical_graph. end |
#post_dot_drawn(bx, by) ⇒ Object
Used for auto position for legend
247 248 249 250 251 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 247 def post_dot_drawn(bx, by) if legend_auto_position @drawn_points << { :x => bx, :y => by } end end |
#pre_image_create_calculations ⇒ Object
Everything that must be done before creating image
194 195 196 197 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 194 def pre_image_create_calculations # check axis density and enlarge if this option is on graph_axis.axis_distance_image_enlarge end |
#recalculate_legend_position ⇒ Object
Choose best location
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 271 def recalculate_legend_position return unless legend_auto_position logger.debug "Auto position calculation, drawn points #{@drawn_points.size}" # check 8 places: positions = [ { :x => legend_margin, :y => 0 + legend_margin }, # top-left { :x => width/2, :y => 0 + legend_margin }, # top-center { :x => width - legend_margin - legend_width, :y => 0 + legend_margin }, # top-right { :x => legend_margin, :y => height/2 }, # middle-left { :x => width - legend_margin - legend_width, :y => height/2 }, # middle-right { :x => legend_margin, :y => height - legend_margin - legend_height }, # bottom-left { :x => width/2, :y => height - legend_margin - legend_height }, # bottom-center { :x => width - legend_margin - legend_width, :y => height - legend_margin - legend_height }, # bottom-right ] t = Time.now # calculate nearest distance of all drawn points positions.each do |p| p[:distance] = (width ** 2 + height ** 2) ** 0.5 # max distance, diagonal of graph @drawn_points.each do |dp| # calculate drawn point distance to being checked now legend position two_points_distance = ((p[:x] - dp[:x]) ** 2 + (p[:y] - dp[:y]) ** 2) ** 0.5 # modify only if distance is closer if p[:distance] > two_points_distance p[:distance] = two_points_distance end end end logger.debug "auto legend best position distance calc." logger.debug " TIME COST #{Time.now - t}" t = Time.now # chose position with highest distance positions.sort! { |a, b| a[:distance] <=> b[:distance] } best_position = positions.last [:legend_x] = best_position[:x] [:legend_y] = best_position[:y] logger.debug "Best position x #{options[:legend_x]}, y #{options[:legend_y]}, distance #{best_position[:distance]}" logger.debug " TIME COST #{Time.now - t}" end |
#recalculate_legend_size ⇒ Object
Enlarge legend’s width using legend labels sizes
261 262 263 264 265 266 267 268 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 261 def recalculate_legend_size layers.each do |l| w = l.label.size * [:legend_font_size] [:legend_width] = w if w > legend_width end [:legend_height] = layers.size * one_layer_legend_height end |
#render_data_layer(l) ⇒ Object
Render data layer, calculate coords and execute proxy
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 212 def render_data_layer(l) layer_data = l.processed_data t = Time.now # calculate coords, draw text, and then lines and circles coords = Array.new (0...(layer_data.size - 1)).each do |i| ax = layer_data[i].x ax = calc_bitmap_x(ax).round ay = layer_data[i].y ay = calc_bitmap_y(ay).round bx = layer_data[i+1].x bx = calc_bitmap_x(bx).round by = layer_data[i+1].y by = calc_bitmap_y(by).round coords << { :ax => ax, :ay => ay, :bx => bx, :by => by, :dy => layer_data[i].y } end logger.debug "rendering layer of size #{layer_data.size}, bitmap position calculation" logger.debug " TIME COST #{Time.now - t}" t = Time.now # draw using proxy drawer.render_data_layer(l, coords) end |
#render_data_legend ⇒ Object
Render legend on graph
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 317 def render_data_legend return unless draw_legend? recalculate_legend_size recalculate_legend_position x = legend_x y = legend_y legend_data = Array.new layers.each do |l| h = Hash.new h[:color] = l.color h[:label] = l.label h[:x] = x h[:y] = y legend_data << h y += one_layer_legend_height end drawer.legend(legend_data) end |
#rmagick_installed? ⇒ Boolean
Check if rmagick is installed
36 37 38 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 36 def rmagick_installed? return Gem.source_index.find_name('rmagick').size > 0 end |
#save_to_file(file) ⇒ Object
Save output to file
342 343 344 345 346 347 348 349 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 342 def save_to_file(file) t = Time.now drawer.save(file) logger.debug "saving image" logger.debug " TIME COST #{Time.now - t}" end |
#to_format(format) ⇒ Object
Export image
352 353 354 355 356 357 358 359 360 361 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 352 def to_format(format) t = Time.now blob = drawer.to_format(format) logger.debug "exporting image as string" logger.debug " TIME COST #{Time.now - t}" return blob end |
#to_png ⇒ Object
Return binary PNG
364 365 366 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 364 def to_png drawer.to_png end |
#to_svg ⇒ Object
368 369 370 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 368 def to_svg drawer.to_svg end |
#to_svgz ⇒ Object
372 373 374 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 372 def to_svgz drawer.to_svgz end |
#truncate_string ⇒ Object
71 72 73 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 71 def truncate_string [:truncate_string] end |
#width ⇒ Object
130 131 132 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 130 def width [:width].to_i end |
#width=(w) ⇒ Object
138 139 140 |
# File 'lib/technical_graph/graph_image_drawer.rb', line 138 def width=(w) [:width] = w.to_i if w.to_i > 0 end |