gruff 0.3.6 → 0.3.7
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/.rvmrc +5 -0
- data/.travis.yml +8 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +20 -0
- data/LICENSE.txt +22 -0
- data/README.md +49 -0
- data/README.txt +3 -0
- data/Rakefile +17 -34
- data/gruff.gemspec +33 -0
- data/lib/gruff.rb +3 -0
- data/lib/gruff/base.rb +17 -14
- data/lib/gruff/line.rb +104 -11
- data/lib/gruff/mini/legend.rb +50 -23
- data/lib/gruff/pie.rb +8 -6
- data/lib/gruff/scatter.rb +268 -0
- data/lib/gruff/scene.rb +1 -1
- data/lib/gruff/side_bar.rb +13 -7
- data/lib/gruff/side_stacked_bar.rb +9 -6
- data/lib/gruff/stacked_bar.rb +3 -0
- data/lib/gruff/version.rb +3 -0
- data/test/gruff_test_case.rb +2 -0
- data/test/test_bar.rb +16 -1
- data/test/test_line.rb +102 -64
- data/test/test_mini_bar.rb +1 -1
- data/test/test_mini_pie.rb +7 -2
- data/test/test_mini_side_bar.rb +1 -2
- data/test/test_scatter.rb +233 -0
- data/test/test_scene.rb +1 -1
- data/test/test_side_bar.rb +31 -0
- metadata +41 -27
data/.gitignore
ADDED
data/.rvmrc
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Uwe Kubosch
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Gruff Graphs
|
2
|
+
|
3
|
+
A library for making beautiful graphs.
|
4
|
+
|
5
|
+
## WARNING
|
6
|
+
|
7
|
+
This is beta-quality software. It works well according to our tests,
|
8
|
+
but the API may change and other features will be added.
|
9
|
+
We are working to make Gruff production quality software.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
gem 'gruff'
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install gruff
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
See the test suite in test/line_test.rb for examples.
|
28
|
+
|
29
|
+
## Samples
|
30
|
+
|
31
|
+
http://nubyonrails.com/pages/gruff
|
32
|
+
|
33
|
+
## Documentation
|
34
|
+
|
35
|
+
http://gruff.rubyforge.org
|
36
|
+
|
37
|
+
## Contributing
|
38
|
+
|
39
|
+
== Source
|
40
|
+
|
41
|
+
The source for this project is now kept at GitHub:
|
42
|
+
|
43
|
+
http://github.com/topfunky/gruff/tree/master
|
44
|
+
|
45
|
+
1. Fork it
|
46
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
47
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
48
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
49
|
+
5. Create new Pull Request
|
data/README.txt
CHANGED
data/Rakefile
CHANGED
@@ -1,55 +1,38 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
require 'rake/clean'
|
3
6
|
$:.unshift(File.dirname(__FILE__) + "/lib")
|
4
|
-
require 'gruff'
|
5
7
|
|
6
|
-
|
7
|
-
p.name = "gruff"
|
8
|
-
p.author = "Geoffrey Grosenbach"
|
9
|
-
p.description = "Beautiful graphs for one or multiple datasets. Can be used on websites or in documents."
|
10
|
-
p.email = 'boss@topfunky.com'
|
11
|
-
p.summary = "Beautiful graphs for one or multiple datasets."
|
12
|
-
p.url = "http://nubyonrails.com/pages/gruff"
|
13
|
-
p.clean_globs = ['test/output/*.png']
|
14
|
-
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
15
|
-
p.remote_rdoc_dir = '' # Release to root
|
16
|
-
end
|
8
|
+
CLEAN << ['pkg', 'test/output/*']
|
17
9
|
|
18
|
-
desc "
|
19
|
-
task :
|
20
|
-
# An error message will be displayed if files are missing
|
21
|
-
if system %(ruby -e "require 'pkg/gruff-#{Gruff::VERSION}/lib/gruff'")
|
22
|
-
puts "\nThe library files are present"
|
23
|
-
end
|
24
|
-
raise "\n*** Gruff::Base::DEBUG must be set to false for releases ***\n\n" if Gruff::Base::DEBUG
|
25
|
-
end
|
10
|
+
desc "Run tests"
|
11
|
+
task :default => :test
|
26
12
|
|
27
|
-
|
13
|
+
Rake::TestTask.new do |t|
|
14
|
+
t.libs << 'test'
|
15
|
+
end
|
28
16
|
|
29
17
|
namespace :test do
|
30
|
-
|
31
18
|
desc "Run mini tests"
|
32
19
|
task :mini => :clean do
|
33
20
|
Dir['test/test_mini*'].each do |file|
|
34
21
|
system "ruby #{file}"
|
35
22
|
end
|
36
|
-
|
37
23
|
end
|
38
|
-
|
39
24
|
end
|
40
25
|
|
41
26
|
##
|
42
27
|
# Catch unmatched tasks and run them as a unit test.
|
43
|
-
#
|
44
28
|
# Makes it possible to do
|
45
29
|
#
|
46
30
|
# rake pie
|
47
31
|
#
|
48
32
|
# To run the +test/test_pie+ and +test/test_mini_pie+ files.
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
33
|
+
#rule '' do |t|
|
34
|
+
# # Rake::Task["clean"].invoke
|
35
|
+
# Dir["test/test_*#{t.name}*.rb"].each do |filename|
|
36
|
+
# system "ruby #{filename}"
|
37
|
+
# end
|
38
|
+
#end
|
data/gruff.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'gruff/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{gruff}
|
8
|
+
s.version = Gruff::VERSION
|
9
|
+
|
10
|
+
# s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ['Geoffrey Grosenbach', 'Uwe Kubosch']
|
12
|
+
# s.date = Date.today.to_s
|
13
|
+
s.description = %q{Beautiful graphs for one or multiple datasets. Can be used on websites or in documents.}
|
14
|
+
s.email = %q{boss@topfunky.com}
|
15
|
+
# s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
|
16
|
+
# s.files = ["History.txt", "MIT-LICENSE", "Manifest.txt", "README.txt", "Rakefile", "assets/bubble.png", "assets/city_scene/background/0000.png", "assets/city_scene/background/0600.png", "assets/city_scene/background/2000.png", "assets/city_scene/clouds/cloudy.png", "assets/city_scene/clouds/partly_cloudy.png", "assets/city_scene/clouds/stormy.png", "assets/city_scene/grass/default.png", "assets/city_scene/haze/true.png", "assets/city_scene/number_sample/1.png", "assets/city_scene/number_sample/2.png", "assets/city_scene/number_sample/default.png", "assets/city_scene/sky/0000.png", "assets/city_scene/sky/0200.png", "assets/city_scene/sky/0400.png", "assets/city_scene/sky/0600.png", "assets/city_scene/sky/0800.png", "assets/city_scene/sky/1000.png", "assets/city_scene/sky/1200.png", "assets/city_scene/sky/1400.png", "assets/city_scene/sky/1500.png", "assets/city_scene/sky/1700.png", "assets/city_scene/sky/2000.png", "assets/pc306715.jpg", "assets/plastik/blue.png", "assets/plastik/green.png", "assets/plastik/red.png", "init.rb", "lib/gruff.rb", "lib/gruff/accumulator_bar.rb", "lib/gruff/area.rb", "lib/gruff/bar.rb", "lib/gruff/bar_conversion.rb", "lib/gruff/base.rb", "lib/gruff/bullet.rb", "lib/gruff/deprecated.rb", "lib/gruff/dot.rb", "lib/gruff/line.rb", "lib/gruff/mini/bar.rb", "lib/gruff/mini/legend.rb", "lib/gruff/mini/pie.rb", "lib/gruff/mini/side_bar.rb", "lib/gruff/net.rb", "lib/gruff/photo_bar.rb", "lib/gruff/pie.rb", "lib/gruff/scene.rb", "lib/gruff/side_bar.rb", "lib/gruff/side_stacked_bar.rb", "lib/gruff/spider.rb", "lib/gruff/stacked_area.rb", "lib/gruff/stacked_bar.rb", "lib/gruff/stacked_mixin.rb", "rails_generators/gruff/gruff_generator.rb", "rails_generators/gruff/templates/controller.rb", "rails_generators/gruff/templates/functional_test.rb", "test/gruff_test_case.rb", "test/test_accumulator_bar.rb", "test/test_area.rb", "test/test_bar.rb", "test/test_base.rb", "test/test_bullet.rb", "test/test_dot.rb", "test/test_legend.rb", "test/test_line.rb", "test/test_mini_bar.rb", "test/test_mini_pie.rb", "test/test_mini_side_bar.rb", "test/test_net.rb", "test/test_photo.rb", "test/test_pie.rb", "test/test_scene.rb", "test/test_side_bar.rb", "test/test_sidestacked_bar.rb", "test/test_spider.rb", "test/test_stacked_area.rb", "test/test_stacked_bar.rb"]
|
17
|
+
s.files = `git ls-files`.split($/)
|
18
|
+
# s.has_rdoc = true
|
19
|
+
s.homepage = %q{http://nubyonrails.com/pages/gruff}
|
20
|
+
# s.rdoc_options = ["--main", "README.txt"]
|
21
|
+
s.require_paths = ["lib"]
|
22
|
+
# s.rubyforge_project = %q{gruff}
|
23
|
+
# s.rubygems_version = %q{1.3.1}
|
24
|
+
s.summary = %q{Beautiful graphs for one or multiple datasets.}
|
25
|
+
# s.test_files = ["test/test_accumulator_bar.rb", "test/test_area.rb", "test/test_bar.rb", "test/test_base.rb", "test/test_bullet.rb", "test/test_dot.rb", "test/test_legend.rb", "test/test_line.rb", "test/test_mini_bar.rb", "test/test_mini_pie.rb", "test/test_mini_side_bar.rb", "test/test_net.rb", "test/test_photo.rb", "test/test_pie.rb", "test/test_scene.rb", "test/test_side_bar.rb", "test/test_sidestacked_bar.rb", "test/test_spider.rb", "test/test_stacked_area.rb", "test/test_stacked_bar.rb"]
|
26
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
27
|
+
|
28
|
+
s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
29
|
+
|
30
|
+
# s.specification_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
31
|
+
# s.add_development_dependency(%q<hoe>, [">= 1.8.2"])
|
32
|
+
# s.add_dependency(%q<rmagick>, [">= 2.12.2"])
|
33
|
+
end
|
data/lib/gruff.rb
CHANGED
data/lib/gruff/base.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'RMagick'
|
3
|
+
require 'bigdecimal'
|
3
4
|
|
4
5
|
require File.dirname(__FILE__) + '/deprecated'
|
5
6
|
|
@@ -18,10 +19,6 @@ require File.dirname(__FILE__) + '/deprecated'
|
|
18
19
|
# See Gruff::Base#theme= for setting themes.
|
19
20
|
|
20
21
|
module Gruff
|
21
|
-
|
22
|
-
# This is the version of Gruff you are using.
|
23
|
-
VERSION = '0.3.6'
|
24
|
-
|
25
22
|
class Base
|
26
23
|
|
27
24
|
include Magick
|
@@ -34,6 +31,7 @@ module Gruff
|
|
34
31
|
DATA_LABEL_INDEX = 0
|
35
32
|
DATA_VALUES_INDEX = 1
|
36
33
|
DATA_COLOR_INDEX = 2
|
34
|
+
DATA_VALUES_X_INDEX = 3
|
37
35
|
|
38
36
|
# Space around text elements. Mostly used for vertical spacing
|
39
37
|
LEGEND_MARGIN = TITLE_MARGIN = 20.0
|
@@ -41,7 +39,7 @@ module Gruff
|
|
41
39
|
DEFAULT_MARGIN = 20.0
|
42
40
|
|
43
41
|
DEFAULT_TARGET_WIDTH = 800
|
44
|
-
|
42
|
+
|
45
43
|
THOUSAND_SEPARATOR = ','
|
46
44
|
|
47
45
|
# Blank space above the graph
|
@@ -55,10 +53,10 @@ module Gruff
|
|
55
53
|
|
56
54
|
# Blank space to the left of the graph
|
57
55
|
attr_accessor :left_margin
|
58
|
-
|
56
|
+
|
59
57
|
# Blank space below the title
|
60
58
|
attr_accessor :title_margin
|
61
|
-
|
59
|
+
|
62
60
|
# Blank space below the legend
|
63
61
|
attr_accessor :legend_margin
|
64
62
|
|
@@ -223,7 +221,7 @@ module Gruff
|
|
223
221
|
@marker_font_size = 21.0
|
224
222
|
@legend_font_size = 20.0
|
225
223
|
@title_font_size = 36.0
|
226
|
-
|
224
|
+
|
227
225
|
@top_margin = @bottom_margin = @left_margin = @right_margin = DEFAULT_MARGIN
|
228
226
|
@legend_margin = LEGEND_MARGIN
|
229
227
|
@title_margin = TITLE_MARGIN
|
@@ -698,7 +696,8 @@ module Gruff
|
|
698
696
|
@d = @d.fill(@marker_color)
|
699
697
|
@d = @d.line(@graph_left, y, @graph_right, y)
|
700
698
|
|
701
|
-
marker_label = index * @increment +
|
699
|
+
marker_label = BigDecimal(index.to_s) * BigDecimal(@increment.to_s) +
|
700
|
+
BigDecimal(@minimum_value.to_s)
|
702
701
|
|
703
702
|
unless @hide_line_numbers
|
704
703
|
@d.fill = @font_color
|
@@ -977,9 +976,10 @@ module Gruff
|
|
977
976
|
data_point
|
978
977
|
end
|
979
978
|
|
980
|
-
def significant(
|
981
|
-
return 1.0 if
|
982
|
-
|
979
|
+
def significant(i) # :nodoc:
|
980
|
+
return 1.0 if i == 0 # Keep from going into infinite loop
|
981
|
+
inc = BigDecimal(i.to_s)
|
982
|
+
factor = BigDecimal('1.0')
|
983
983
|
while (inc < 10)
|
984
984
|
inc *= 10
|
985
985
|
factor /= 10
|
@@ -1063,7 +1063,7 @@ module Gruff
|
|
1063
1063
|
# Return a formatted string representing a number value that should be
|
1064
1064
|
# printed as a label.
|
1065
1065
|
def label(value)
|
1066
|
-
label = if (@spread.to_f % @marker_count.to_f == 0) || !@y_axis_increment.nil?
|
1066
|
+
label = if (@spread.to_f % (@marker_count.to_f==0 ? 1 : @marker_count.to_f) == 0) || !@y_axis_increment.nil?
|
1067
1067
|
value.to_i.to_s
|
1068
1068
|
elsif @spread > 10.0
|
1069
1069
|
sprintf("%0i", value)
|
@@ -1072,7 +1072,7 @@ module Gruff
|
|
1072
1072
|
else
|
1073
1073
|
value.to_s
|
1074
1074
|
end
|
1075
|
-
|
1075
|
+
|
1076
1076
|
parts = label.split('.')
|
1077
1077
|
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{THOUSAND_SEPARATOR}")
|
1078
1078
|
parts.join('.')
|
@@ -1085,6 +1085,7 @@ module Gruff
|
|
1085
1085
|
# handle.
|
1086
1086
|
def calculate_caps_height(font_size)
|
1087
1087
|
@d.pointsize = font_size
|
1088
|
+
@d.font = @font if @font
|
1088
1089
|
@d.get_type_metrics(@base_image, 'X').height
|
1089
1090
|
end
|
1090
1091
|
|
@@ -1093,7 +1094,9 @@ module Gruff
|
|
1093
1094
|
# Not scaled since it deals with dimensions that the regular
|
1094
1095
|
# scaling will handle.
|
1095
1096
|
def calculate_width(font_size, text)
|
1097
|
+
return 0 if text.nil?
|
1096
1098
|
@d.pointsize = font_size
|
1099
|
+
@d.font = @font if @font
|
1097
1100
|
@d.get_type_metrics(@base_image, text.to_s).width
|
1098
1101
|
end
|
1099
1102
|
|
data/lib/gruff/line.rb
CHANGED
@@ -16,7 +16,7 @@ class Gruff::Line < Gruff::Base
|
|
16
16
|
|
17
17
|
# Draw a dashed line at the given value
|
18
18
|
attr_accessor :baseline_value
|
19
|
-
|
19
|
+
|
20
20
|
# Color of the baseline
|
21
21
|
attr_accessor :baseline_color
|
22
22
|
|
@@ -26,6 +26,10 @@ class Gruff::Line < Gruff::Base
|
|
26
26
|
|
27
27
|
# Hide parts of the graph to fit more datapoints, or for a different appearance.
|
28
28
|
attr_accessor :hide_dots, :hide_lines
|
29
|
+
|
30
|
+
#accessors for support of xy data
|
31
|
+
attr_accessor :minimum_x_value
|
32
|
+
attr_accessor :maximum_x_value
|
29
33
|
|
30
34
|
# Call with target pixel width of graph (800, 400, 300), and/or 'false' to omit lines (points only).
|
31
35
|
#
|
@@ -34,7 +38,7 @@ class Gruff::Line < Gruff::Base
|
|
34
38
|
# g = Gruff::Line.new(400, false) # 400px wide, no lines (for backwards compatibility)
|
35
39
|
#
|
36
40
|
# g = Gruff::Line.new(false) # Defaults to 800px wide, no lines (for backwards compatibility)
|
37
|
-
#
|
41
|
+
#
|
38
42
|
# The preferred way is to call hide_dots or hide_lines instead.
|
39
43
|
def initialize(*args)
|
40
44
|
raise ArgumentError, "Wrong number of arguments" if args.length > 2
|
@@ -43,20 +47,95 @@ class Gruff::Line < Gruff::Base
|
|
43
47
|
else
|
44
48
|
super args.shift
|
45
49
|
end
|
46
|
-
|
50
|
+
|
47
51
|
@hide_dots = @hide_lines = false
|
48
52
|
@baseline_color = 'red'
|
49
53
|
@baseline_value = nil
|
54
|
+
@maximum_x_value = nil
|
55
|
+
@minimum_x_value = nil
|
56
|
+
end
|
57
|
+
|
58
|
+
# This method allows one to plot a dataset with both X and Y data.
|
59
|
+
#
|
60
|
+
# Parameters are as follows:
|
61
|
+
# name: string, the title of the dataset
|
62
|
+
# x_data_points: an array containing the x data points for the graph
|
63
|
+
# y_data_points: an array containing the y data points for the graph
|
64
|
+
# color: hex number indicating the line color as an RGB triplet
|
65
|
+
#
|
66
|
+
# Notes:
|
67
|
+
# -if (x_data_points.length != y_data_points.length) an error is
|
68
|
+
# returned.
|
69
|
+
# -if the color argument is nil, the next color from the default theme will
|
70
|
+
# be used.
|
71
|
+
# -if you want to use a preset theme, you must set it before calling
|
72
|
+
# dataxy().
|
73
|
+
#
|
74
|
+
# Example:
|
75
|
+
# g = Gruff::Line.new
|
76
|
+
# g.title = "X/Y Dataset"
|
77
|
+
# g.dataxy("Apples", [1,3,4,5,6,10], [1, 2, 3, 4, 4, 3])
|
78
|
+
# g.dataxy("Bapples", [1,3,4,5,7,9], [1, 1, 2, 2, 3, 3])
|
79
|
+
# #you can still use the old data method too if you want:
|
80
|
+
# g.data("Capples", [1, 1, 2, 2, 3, 3])
|
81
|
+
# #labels will be drawn at the x locations of the 1st dataset that you
|
82
|
+
# #passed in. In this example the lables are drawn at x locations 1,4,6
|
83
|
+
# g.labels = {0 => '2003', 2 => '2004', 4 => '2005'} #labels
|
84
|
+
|
85
|
+
def dataxy(name, x_data_points=[], y_data_points=[], color=nil)
|
86
|
+
raise ArgumentError, "x_data_points is nil!" if x_data_points.length == 0
|
87
|
+
|
88
|
+
if x_data_points.all?{|p| p.size == 2}
|
89
|
+
x_data_points, y_data_points = x_data_points.map{|p| p[0]}, x_data_points.map{|p| p[1]}
|
90
|
+
end
|
91
|
+
|
92
|
+
raise ArgumentError, "x_data_points.length != y_data_points.length!" if x_data_points.length != y_data_points.length
|
93
|
+
|
94
|
+
#call the existing data routine for the y data.
|
95
|
+
self.data(name, y_data_points, color)
|
96
|
+
|
97
|
+
x_data_points = Array(x_data_points) # make sure it's an array
|
98
|
+
#append the x data to the last entry that was just added in the @data member
|
99
|
+
lastElem = @data.length()-1
|
100
|
+
@data[lastElem][DATA_VALUES_X_INDEX] = x_data_points
|
101
|
+
|
102
|
+
# Update the global min/max values for the x data
|
103
|
+
x_data_points.each_with_index do |x_data_point, index|
|
104
|
+
next if x_data_point.nil?
|
105
|
+
|
106
|
+
# Setup max/min so spread starts at the low end of the data points
|
107
|
+
if @maximum_x_value.nil? && @minimum_x_value.nil?
|
108
|
+
@maximum_x_value = @minimum_x_value = x_data_point
|
109
|
+
end
|
110
|
+
|
111
|
+
@maximum_x_value = (x_data_point > @maximum_x_value) ?
|
112
|
+
x_data_point : @maximum_x_value
|
113
|
+
@minimum_x_value = (x_data_point < @minimum_x_value) ?
|
114
|
+
x_data_point : @minimum_x_value
|
115
|
+
end
|
116
|
+
|
50
117
|
end
|
51
118
|
|
52
119
|
def draw
|
53
120
|
super
|
54
121
|
|
55
122
|
return unless @has_data
|
56
|
-
|
57
|
-
# Check to see if more than one datapoint was given. NaN can result otherwise.
|
123
|
+
|
124
|
+
# Check to see if more than one datapoint was given. NaN can result otherwise.
|
58
125
|
@x_increment = (@column_count > 1) ? (@graph_width / (@column_count - 1).to_f) : @graph_width
|
59
126
|
|
127
|
+
#normalize the x data if it is specified
|
128
|
+
@data.each_with_index do |data_row, index|
|
129
|
+
norm_x_data_points = []
|
130
|
+
if (data_row[DATA_VALUES_X_INDEX] != nil)
|
131
|
+
data_row[DATA_VALUES_X_INDEX].each do |x_data_point|
|
132
|
+
norm_x_data_points << ( (x_data_point.to_f - @minimum_x_value.to_f ) /
|
133
|
+
(@maximum_x_value.to_f - @minimum_x_value.to_f) )
|
134
|
+
end
|
135
|
+
@norm_data[index] << norm_x_data_points
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
60
139
|
if (defined?(@norm_baseline)) then
|
61
140
|
level = @graph_top + (@graph_height - @norm_baseline * @graph_height)
|
62
141
|
@d = @d.push
|
@@ -68,15 +147,22 @@ class Gruff::Line < Gruff::Base
|
|
68
147
|
@d = @d.pop
|
69
148
|
end
|
70
149
|
|
71
|
-
@norm_data.
|
150
|
+
@norm_data.each_with_index do |data_row, dr_index|
|
72
151
|
prev_x = prev_y = nil
|
73
152
|
|
74
153
|
@one_point = contains_one_point_only?(data_row)
|
75
154
|
|
76
155
|
data_row[DATA_VALUES_INDEX].each_with_index do |data_point, index|
|
77
|
-
new_x = @graph_left + (@x_increment * index)
|
78
156
|
next if data_point.nil?
|
79
157
|
|
158
|
+
x_data = data_row[DATA_VALUES_X_INDEX]
|
159
|
+
if (x_data == nil)
|
160
|
+
#use the old method: equally spaced points along the x-axis
|
161
|
+
new_x = @graph_left + (@x_increment * index)
|
162
|
+
else
|
163
|
+
new_x = getXCoord(x_data[index], @graph_width, @graph_left)
|
164
|
+
end
|
165
|
+
|
80
166
|
draw_label(new_x, index)
|
81
167
|
|
82
168
|
new_y = @graph_top + (@graph_height - data_point * @graph_height)
|
@@ -92,7 +178,7 @@ class Gruff::Line < Gruff::Base
|
|
92
178
|
circle_radius = dot_radius ||
|
93
179
|
clip_value_if_greater_than(@columns / (@norm_data.first[DATA_VALUES_INDEX].size * 2.5), 5.0)
|
94
180
|
|
95
|
-
if !@hide_lines and !prev_x.nil? and !prev_y.nil? then
|
181
|
+
if !@hide_lines and !prev_x.nil? and !prev_y.nil? then
|
96
182
|
@d = @d.line(prev_x, prev_y, new_x, new_y)
|
97
183
|
elsif @one_point
|
98
184
|
# Show a circle if there's just one_point
|
@@ -114,6 +200,14 @@ class Gruff::Line < Gruff::Base
|
|
114
200
|
super
|
115
201
|
@norm_baseline = (@baseline_value.to_f / @maximum_value.to_f) if @baseline_value
|
116
202
|
end
|
203
|
+
|
204
|
+
def sort_norm_data
|
205
|
+
super unless @data.any?{|d| d[DATA_VALUES_X_INDEX]}
|
206
|
+
end
|
207
|
+
|
208
|
+
def getXCoord(x_data_point, width, offset)
|
209
|
+
return(x_data_point * width + offset)
|
210
|
+
end
|
117
211
|
|
118
212
|
def contains_one_point_only?(data_row)
|
119
213
|
# Spin through data to determine if there is just one_value present.
|
@@ -123,10 +217,9 @@ class Gruff::Line < Gruff::Base
|
|
123
217
|
if one_point
|
124
218
|
# more than one point, bail
|
125
219
|
return false
|
126
|
-
else
|
127
|
-
# there is at least one data point
|
128
|
-
return true
|
129
220
|
end
|
221
|
+
# there is at least one data point
|
222
|
+
one_point = true
|
130
223
|
end
|
131
224
|
end
|
132
225
|
return one_point
|