technical_graph 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +0 -2
- data/README.md +9 -0
- data/Rakefile +13 -0
- data/VERSION +1 -1
- data/lib/technical_graph/data_layer.rb +4 -0
- data/lib/technical_graph/graph_image_drawer.rb +125 -0
- data/lib/technical_graph.rb +2 -0
- data/test/test_technical_multilayer.rb +95 -0
- metadata +12 -36
- data/.document +0 -5
- data/.idea/dictionaries/olek.xml +0 -8
- data/.rvmrc +0 -1
- data/lib/technical_graph/refactoring_backup/lib/technical_graph/axis_layer.rb +0 -151
- data/lib/technical_graph/refactoring_backup/lib/technical_graph/axis_layer_draw_module.rb +0 -145
- data/lib/technical_graph/refactoring_backup/lib/technical_graph.rb +0 -55
- data/lib/technical_graph/refactoring_backup/test/test_technical_graph.rb +0 -104
- data/lib/technical_graph/refactoring_backup/test/test_technical_graph_axis.rb +0 -306
- data/samples/1.png +0 -0
- data/samples/home_io_batt_voltage.png +0 -0
- data/technical_graph.gemspec +0 -84
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -121,6 +121,15 @@ size will be enlarged to maintain set distanced between axis.
|
|
121
121
|
* options[:x_axis_min_distance] - minimum distance between X axis, default 30 pixels
|
122
122
|
* options[:y_axis_min_distance] - minimum distance between X axis, default 50 pixels
|
123
123
|
|
124
|
+
Legend options:
|
125
|
+
|
126
|
+
* options[:legend] - draw legend, default false
|
127
|
+
* options[:legend_auto] - let legend position to be chosen by algorithm, default true
|
128
|
+
* options[:legend_width] - width used for setting proper distance while drawing on right, default 100, legend height is calculated
|
129
|
+
* options[:legend_margin] - graph margin used not to draw legend on border, default 50
|
130
|
+
* options[:legend_x] - legend X position, default 50
|
131
|
+
* options[:legend_y] - legend Y position, default 50
|
132
|
+
|
124
133
|
|
125
134
|
Layer options Hash
|
126
135
|
------------------
|
data/Rakefile
CHANGED
@@ -24,10 +24,23 @@ Jeweler::Tasks.new do |gem|
|
|
24
24
|
gem.authors = ["Aleksander Kwiatkowski"]
|
25
25
|
|
26
26
|
#gem.files = FileList["[A-Z]*", "{bin,generators,lib,test}/**/*", 'lib/jeweler/templates/.gitignore']
|
27
|
+
gem.files = FileList[
|
28
|
+
"[A-Z]*", "{bin,generators,lib,test}/**/*"
|
29
|
+
]
|
27
30
|
# dependencies defined in Gemfile
|
28
31
|
end
|
29
32
|
Jeweler::RubygemsDotOrgTasks.new
|
30
33
|
|
34
|
+
desc "Remove all images created during tests"
|
35
|
+
task :clean do
|
36
|
+
`rm *.svg`
|
37
|
+
`rm *.png`
|
38
|
+
end
|
39
|
+
|
40
|
+
desc "Clean and release"
|
41
|
+
task :clean_and_release => [:clean, :release] do
|
42
|
+
end
|
43
|
+
|
31
44
|
require 'rake/testtask'
|
32
45
|
Rake::TestTask.new(:test) do |test|
|
33
46
|
test.libs << 'lib' << 'test'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.2
|
@@ -71,6 +71,17 @@ class GraphImageDrawer
|
|
71
71
|
options[:axis_font_size] ||= 10
|
72
72
|
options[:layers_font_size] ||= 10
|
73
73
|
options[:axis_label_font_size] ||= 10
|
74
|
+
|
75
|
+
# legend
|
76
|
+
options[:legend] = false if options[:legend].nil?
|
77
|
+
options[:legend_auto] = true if options[:legend_auto].nil?
|
78
|
+
options[:legend_x] ||= 50
|
79
|
+
options[:legend_y] ||= 50
|
80
|
+
options[:legend_width] ||= 100
|
81
|
+
options[:legend_margin] ||= 50
|
82
|
+
|
83
|
+
# array of all points drawn on graph, used for auto positioning of legend
|
84
|
+
@drawn_points = Array.new
|
74
85
|
end
|
75
86
|
|
76
87
|
def width
|
@@ -93,6 +104,30 @@ class GraphImageDrawer
|
|
93
104
|
options[:font_antialias] == true
|
94
105
|
end
|
95
106
|
|
107
|
+
def draw_legend?
|
108
|
+
options[:legend]
|
109
|
+
end
|
110
|
+
|
111
|
+
def legend_x
|
112
|
+
options[:legend_x]
|
113
|
+
end
|
114
|
+
|
115
|
+
def legend_y
|
116
|
+
options[:legend_y]
|
117
|
+
end
|
118
|
+
|
119
|
+
def legend_auto_position
|
120
|
+
options[:legend_auto]
|
121
|
+
end
|
122
|
+
|
123
|
+
def legend_width
|
124
|
+
options[:legend_width]
|
125
|
+
end
|
126
|
+
|
127
|
+
def legend_margin
|
128
|
+
options[:legend_margin]
|
129
|
+
end
|
130
|
+
|
96
131
|
# Calculate image X position
|
97
132
|
def calc_bitmap_x(_x)
|
98
133
|
l = data_processor.x_max - data_processor.x_min
|
@@ -206,11 +241,101 @@ class GraphImageDrawer
|
|
206
241
|
c[:ax], c[:ay],
|
207
242
|
c[:bx], c[:by]
|
208
243
|
)
|
244
|
+
|
245
|
+
# used for auto positioning of legend
|
246
|
+
if legend_auto_position
|
247
|
+
@drawn_points << {:x => c[:ax], :y => c[:ay]}
|
248
|
+
@drawn_points << {:x => c[:bx], :y => c[:by]}
|
249
|
+
end
|
209
250
|
end
|
210
251
|
layer_line.draw(@image)
|
211
252
|
|
212
253
|
end
|
213
254
|
|
255
|
+
# height of 1 layer
|
256
|
+
ONE_LAYER_LEGEND_HEIGHT = 15
|
257
|
+
|
258
|
+
# Choose best location
|
259
|
+
def recalculate_legend_position
|
260
|
+
return unless legend_auto_position
|
261
|
+
puts "Auto position calculation, drawn points #{@drawn_points.size}"
|
262
|
+
|
263
|
+
legend_height = layers.size * ONE_LAYER_LEGEND_HEIGHT
|
264
|
+
|
265
|
+
# check 8 places:
|
266
|
+
positions = [
|
267
|
+
{:x => legend_margin, :y => 0 + legend_margin}, # top-left
|
268
|
+
{:x => width/2, :y => 0 + legend_margin}, # top-center
|
269
|
+
{:x => width - legend_margin - legend_width, :y => 0 + legend_margin}, # top-right
|
270
|
+
{:x => legend_margin, :y => height/2}, # middle-left
|
271
|
+
{:x => width - legend_margin - legend_width, :y => height/2}, # middle-right
|
272
|
+
{:x => legend_margin, :y => height - legend_margin - legend_height}, # bottom-left
|
273
|
+
{:x => width/2, :y => height - legend_margin - legend_height}, # bottom-center
|
274
|
+
{:x => width - legend_margin - legend_width, :y => height - legend_margin - legend_height}, # bottom-right
|
275
|
+
]
|
276
|
+
|
277
|
+
# calculate nearest distance of all drawn points
|
278
|
+
positions.each do |p|
|
279
|
+
p[:distance] = (width ** 2 + height ** 2) ** 0.5 # max distance, diagonal of graph
|
280
|
+
@drawn_points.each do |dp|
|
281
|
+
# calculate drawn point distance to being checked now legend position
|
282
|
+
two_points_distance = ( (p[:x] - dp[:x]) ** 2 + (p[:y] - dp[:y]) ** 2 ) ** 0.5
|
283
|
+
# modify only if distance is closer
|
284
|
+
if p[:distance] > two_points_distance
|
285
|
+
p[:distance] = two_points_distance
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
# chose position with hihest distance
|
291
|
+
positions.sort!{|a,b| a[:distance] <=> b[:distance]}
|
292
|
+
best_position = positions.last
|
293
|
+
options[:legend_x] = best_position[:x]
|
294
|
+
options[:legend_y] = best_position[:y]
|
295
|
+
|
296
|
+
puts "Best position x #{options[:legend_x]}, y #{options[:legend_y]}, distance #{best_position[:distance]}"
|
297
|
+
# puts positions.to_yaml
|
298
|
+
end
|
299
|
+
|
300
|
+
# Render legend on graph
|
301
|
+
def render_data_legend
|
302
|
+
return unless draw_legend?
|
303
|
+
|
304
|
+
recalculate_legend_position
|
305
|
+
|
306
|
+
legend_text = Magick::Draw.new
|
307
|
+
legend_text_antialias = options[:layers_font_size]
|
308
|
+
legend_text.stroke_antialias(legend_text_antialias)
|
309
|
+
legend_text.text_antialias(legend_text_antialias)
|
310
|
+
legend_text.pointsize(options[:axis_font_size])
|
311
|
+
legend_text.font_family('helvetica')
|
312
|
+
legend_text.font_style(Magick::NormalStyle)
|
313
|
+
legend_text.text_align(Magick::LeftAlign)
|
314
|
+
legend_text.text_undercolor(options[:background_color])
|
315
|
+
|
316
|
+
x = legend_x
|
317
|
+
y = legend_y
|
318
|
+
|
319
|
+
layers.each do |l|
|
320
|
+
legend_text.fill(l.color)
|
321
|
+
|
322
|
+
string_label = l.label
|
323
|
+
legend_text.text(
|
324
|
+
x, y,
|
325
|
+
string_label
|
326
|
+
)
|
327
|
+
|
328
|
+
# little dot
|
329
|
+
legend_text.circle(
|
330
|
+
x - 10, y,
|
331
|
+
x - 10 + 3, y
|
332
|
+
)
|
333
|
+
|
334
|
+
y += ONE_LAYER_LEGEND_HEIGHT
|
335
|
+
end
|
336
|
+
legend_text.draw(@image)
|
337
|
+
end
|
338
|
+
|
214
339
|
# Save output to file
|
215
340
|
def save_to_file(file)
|
216
341
|
@image.write(file)
|
data/lib/technical_graph.rb
CHANGED
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestTechnicalMultilayer < Test::Unit::TestCase
|
4
|
+
context 'initial options' do
|
5
|
+
should 'draw multilayer graph' do
|
6
|
+
@tg = TechnicalGraph.new(
|
7
|
+
{
|
8
|
+
:truncate_string => "%.1f",
|
9
|
+
|
10
|
+
:x_axis_label => 'x',
|
11
|
+
:y_axis_label => 'y',
|
12
|
+
|
13
|
+
:axis_antialias => true,
|
14
|
+
:layers_antialias => true,
|
15
|
+
:font_antialias => true,
|
16
|
+
|
17
|
+
:layers_font_size => 11,
|
18
|
+
:axis_font_size => 11,
|
19
|
+
:axis_label_font_size => 20,
|
20
|
+
|
21
|
+
#:x_axis_count => 20,
|
22
|
+
#:y_axis_count => 20,
|
23
|
+
#:x_axis_interval => 1.0,
|
24
|
+
#:y_axis_interval => 1.0,
|
25
|
+
#:x_axis_fixed_interval => false,
|
26
|
+
#:y_axis_fixed_interval => false,
|
27
|
+
|
28
|
+
#:x_min => -10.0,
|
29
|
+
#:x_max => 10.0,
|
30
|
+
#:y_min => -10.0,
|
31
|
+
#:y_max => 10.0,
|
32
|
+
|
33
|
+
#:width => 4000,
|
34
|
+
#:height => 3000,
|
35
|
+
|
36
|
+
:legend => true,
|
37
|
+
:legend_auto => true,
|
38
|
+
:legend_width => 90,
|
39
|
+
:legend_margin => 60,
|
40
|
+
:legend_x => 50,
|
41
|
+
:legend_y => 50,
|
42
|
+
}
|
43
|
+
)
|
44
|
+
|
45
|
+
max = 50
|
46
|
+
|
47
|
+
# adding simple layer
|
48
|
+
layer_params_a = {
|
49
|
+
:antialias => true,
|
50
|
+
:color => 'red',
|
51
|
+
:label => 'first'
|
52
|
+
}
|
53
|
+
layer_params_b = {
|
54
|
+
:antialias => true,
|
55
|
+
:color => 'green',
|
56
|
+
:label => 'second'
|
57
|
+
}
|
58
|
+
layer_params_c = {
|
59
|
+
:antialias => true,
|
60
|
+
:color => 'blue',
|
61
|
+
:label => 'third'
|
62
|
+
}
|
63
|
+
layer_params_d = {
|
64
|
+
:antialias => true,
|
65
|
+
:color => 'purple',
|
66
|
+
:label => 'fourth'
|
67
|
+
}
|
68
|
+
layer_data_a = Array.new
|
69
|
+
layer_data_b = Array.new
|
70
|
+
layer_data_c = Array.new
|
71
|
+
layer_data_d = Array.new
|
72
|
+
(0..max).each do |i|
|
73
|
+
layer_data_a << { :x => -10.0 + i.to_f, :y => 10.0 * Math.cos(i.to_f * (4.0 * 3.14 / max.to_f)) }
|
74
|
+
layer_data_b << { :x => -10.0 + i.to_f, :y => 10.0 * Math.cos(0.3 + i.to_f * (4.0 * 3.14 / max.to_f)) }
|
75
|
+
layer_data_c << { :x => -10.0 + i.to_f, :y => 10.0 * Math.cos(0.6 + i.to_f * (4.0 * 3.14 / max.to_f)) }
|
76
|
+
layer_data_d << { :x => -10.0 + i.to_f, :y => 10.0 * Math.cos(0.9 + i.to_f * (4.0 * 3.14 / max.to_f)) }
|
77
|
+
end
|
78
|
+
@tg.add_layer(layer_data_a, layer_params_a)
|
79
|
+
@tg.add_layer(layer_data_b, layer_params_b)
|
80
|
+
@tg.add_layer(layer_data_c, layer_params_c)
|
81
|
+
@tg.add_layer(layer_data_d, layer_params_d)
|
82
|
+
|
83
|
+
|
84
|
+
@tg.layers.last.data.size.should > 0
|
85
|
+
@tg.layers.size.should == 4
|
86
|
+
|
87
|
+
@tg.render
|
88
|
+
|
89
|
+
@tg.image_drawer.save_to_file('test_multilayer.png')
|
90
|
+
@tg.image_drawer.to_png.class.should == String
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: technical_graph
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 31
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 2
|
10
|
+
version: 0.1.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Aleksander Kwiatkowski
|
@@ -43,26 +43,12 @@ dependencies:
|
|
43
43
|
segments:
|
44
44
|
- 0
|
45
45
|
version: "0"
|
46
|
-
name:
|
46
|
+
name: shoulda
|
47
47
|
version_requirements: *id002
|
48
48
|
prerelease: false
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
50
|
type: :development
|
51
51
|
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
-
none: false
|
53
|
-
requirements:
|
54
|
-
- - ">="
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
hash: 3
|
57
|
-
segments:
|
58
|
-
- 0
|
59
|
-
version: "0"
|
60
|
-
name: shoulda
|
61
|
-
version_requirements: *id003
|
62
|
-
prerelease: false
|
63
|
-
- !ruby/object:Gem::Dependency
|
64
|
-
type: :development
|
65
|
-
requirement: &id004 !ruby/object:Gem::Requirement
|
66
52
|
none: false
|
67
53
|
requirements:
|
68
54
|
- - ~>
|
@@ -74,11 +60,11 @@ dependencies:
|
|
74
60
|
- 0
|
75
61
|
version: 1.0.0
|
76
62
|
name: bundler
|
77
|
-
version_requirements: *
|
63
|
+
version_requirements: *id003
|
78
64
|
prerelease: false
|
79
65
|
- !ruby/object:Gem::Dependency
|
80
66
|
type: :development
|
81
|
-
requirement: &
|
67
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
82
68
|
none: false
|
83
69
|
requirements:
|
84
70
|
- - ">="
|
@@ -88,11 +74,11 @@ dependencies:
|
|
88
74
|
- 0
|
89
75
|
version: "0"
|
90
76
|
name: rspec
|
91
|
-
version_requirements: *
|
77
|
+
version_requirements: *id004
|
92
78
|
prerelease: false
|
93
79
|
- !ruby/object:Gem::Dependency
|
94
80
|
type: :development
|
95
|
-
requirement: &
|
81
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
96
82
|
none: false
|
97
83
|
requirements:
|
98
84
|
- - ">="
|
@@ -102,11 +88,11 @@ dependencies:
|
|
102
88
|
- 0
|
103
89
|
version: "0"
|
104
90
|
name: jeweler
|
105
|
-
version_requirements: *
|
91
|
+
version_requirements: *id005
|
106
92
|
prerelease: false
|
107
93
|
- !ruby/object:Gem::Dependency
|
108
94
|
type: :development
|
109
|
-
requirement: &
|
95
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
110
96
|
none: false
|
111
97
|
requirements:
|
112
98
|
- - ">="
|
@@ -116,7 +102,7 @@ dependencies:
|
|
116
102
|
- 0
|
117
103
|
version: "0"
|
118
104
|
name: rcov
|
119
|
-
version_requirements: *
|
105
|
+
version_requirements: *id006
|
120
106
|
prerelease: false
|
121
107
|
description: Purpose of this gem is to create neat, simple, technical graphs. This is alternative to most new libraries which create small, candy graphs using JavaScript.
|
122
108
|
email: bobikx@poczta.fm
|
@@ -128,9 +114,6 @@ extra_rdoc_files:
|
|
128
114
|
- LICENSE.txt
|
129
115
|
- README.md
|
130
116
|
files:
|
131
|
-
- .document
|
132
|
-
- .idea/dictionaries/olek.xml
|
133
|
-
- .rvmrc
|
134
117
|
- Gemfile
|
135
118
|
- Gemfile.lock
|
136
119
|
- LICENSE.txt
|
@@ -142,18 +125,11 @@ files:
|
|
142
125
|
- lib/technical_graph/graph_axis.rb
|
143
126
|
- lib/technical_graph/graph_data_processor.rb
|
144
127
|
- lib/technical_graph/graph_image_drawer.rb
|
145
|
-
- lib/technical_graph/refactoring_backup/lib/technical_graph.rb
|
146
|
-
- lib/technical_graph/refactoring_backup/lib/technical_graph/axis_layer.rb
|
147
|
-
- lib/technical_graph/refactoring_backup/lib/technical_graph/axis_layer_draw_module.rb
|
148
|
-
- lib/technical_graph/refactoring_backup/test/test_technical_graph.rb
|
149
|
-
- lib/technical_graph/refactoring_backup/test/test_technical_graph_axis.rb
|
150
|
-
- samples/1.png
|
151
|
-
- samples/home_io_batt_voltage.png
|
152
|
-
- technical_graph.gemspec
|
153
128
|
- test/helper.rb
|
154
129
|
- test/test_technical_axis_enlarge.rb
|
155
130
|
- test/test_technical_graph.rb
|
156
131
|
- test/test_technical_graph_axis.rb
|
132
|
+
- test/test_technical_multilayer.rb
|
157
133
|
- test/test_technical_simple_graph.rb
|
158
134
|
has_rdoc: true
|
159
135
|
homepage: http://github.com/akwiatkowski/technical_graph
|
data/.document
DELETED
data/.idea/dictionaries/olek.xml
DELETED
data/.rvmrc
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
rvm use 1.8.7@technical_graph --create
|
@@ -1,151 +0,0 @@
|
|
1
|
-
#encoding: utf-8
|
2
|
-
|
3
|
-
require 'technical_graph/axis_layer_draw_module'
|
4
|
-
|
5
|
-
# Decide min/max values, recalculate all points and draw axis
|
6
|
-
|
7
|
-
class AxisLayer
|
8
|
-
include AxisLayerDrawModule
|
9
|
-
|
10
|
-
def initialize(options = { })
|
11
|
-
@options = options
|
12
|
-
@options[:x_min] ||= (Time.now - 24 * 3600).to_f
|
13
|
-
@options[:x_max] ||= Time.now.to_f
|
14
|
-
@options[:y_min] ||= 0.0
|
15
|
-
@options[:y_max] ||= 1.0
|
16
|
-
# :default - coords are default
|
17
|
-
# :fixed or whatever else - min/max coords are fixed
|
18
|
-
@options[:xy_behaviour] ||= :default
|
19
|
-
|
20
|
-
# number of axis
|
21
|
-
@options[:y_axis_count] ||= 10
|
22
|
-
@options[:x_axis_count] ||= 10
|
23
|
-
# interval
|
24
|
-
@options[:y_axis_interval] ||= 1.0
|
25
|
-
@options[:x_axis_interval] ||= 1.0
|
26
|
-
# when false then axis are generated to meet 'count'
|
27
|
-
# when true then axis are generated every X from lowest
|
28
|
-
@options[:x_axis_fixed_interval] = true if @options[:x_axis_fixed_interval].nil?
|
29
|
-
@options[:y_axis_fixed_interval] = true if @options[:y_axis_fixed_interval].nil?
|
30
|
-
|
31
|
-
@zoom_x = 1.0
|
32
|
-
@zoom_y = 1.0
|
33
|
-
end
|
34
|
-
|
35
|
-
# Ranges are fixed
|
36
|
-
def fixed?
|
37
|
-
@options[:xy_behaviour] == :fixed
|
38
|
-
end
|
39
|
-
|
40
|
-
# Ranges without zoom
|
41
|
-
def raw_x_min
|
42
|
-
@options[:x_min]
|
43
|
-
end
|
44
|
-
|
45
|
-
def raw_x_max
|
46
|
-
@options[:x_max]
|
47
|
-
end
|
48
|
-
|
49
|
-
def raw_y_min
|
50
|
-
@options[:y_min]
|
51
|
-
end
|
52
|
-
|
53
|
-
def raw_y_max
|
54
|
-
@options[:y_max]
|
55
|
-
end
|
56
|
-
|
57
|
-
# Ranges with zoom
|
58
|
-
def x_min
|
59
|
-
calc_x_zoomed([self.raw_x_min]).first
|
60
|
-
end
|
61
|
-
|
62
|
-
def x_max
|
63
|
-
calc_x_zoomed([self.raw_x_max]).first
|
64
|
-
end
|
65
|
-
|
66
|
-
def y_min
|
67
|
-
calc_y_zoomed([self.raw_y_min]).first
|
68
|
-
end
|
69
|
-
|
70
|
-
def y_max
|
71
|
-
calc_y_zoomed([self.raw_y_max]).first
|
72
|
-
end
|
73
|
-
|
74
|
-
# Accessors
|
75
|
-
private
|
76
|
-
def raw_x_min=(x)
|
77
|
-
@options[:x_min] = x
|
78
|
-
end
|
79
|
-
|
80
|
-
def raw_x_max=(x)
|
81
|
-
@options[:x_max] = x
|
82
|
-
end
|
83
|
-
|
84
|
-
def raw_y_min=(y)
|
85
|
-
@options[:y_min] = y
|
86
|
-
end
|
87
|
-
|
88
|
-
def raw_y_max=(y)
|
89
|
-
@options[:y_max] = y
|
90
|
-
end
|
91
|
-
|
92
|
-
public
|
93
|
-
|
94
|
-
# Consider changing ranges
|
95
|
-
def process_data_layer(data_layer)
|
96
|
-
# ranges are set, can't change sir
|
97
|
-
return if fixed?
|
98
|
-
|
99
|
-
# updating ranges
|
100
|
-
self.raw_y_max = data_layer.y_max if not data_layer.y_max.nil? and data_layer.y_max > self.raw_y_max
|
101
|
-
self.raw_x_max = data_layer.x_max if not data_layer.x_max.nil? and data_layer.x_max > self.raw_x_max
|
102
|
-
|
103
|
-
self.raw_y_min = data_layer.y_min if not data_layer.y_min.nil? and data_layer.y_min < self.raw_y_min
|
104
|
-
self.raw_x_min = data_layer.x_min if not data_layer.x_min.nil? and data_layer.x_min < self.raw_x_min
|
105
|
-
end
|
106
|
-
|
107
|
-
# Change overall image zoom
|
108
|
-
def zoom=(z = 1.0)
|
109
|
-
self.x_zoom = z
|
110
|
-
self.y_zoom = z
|
111
|
-
end
|
112
|
-
|
113
|
-
# Change X axis zoom
|
114
|
-
def x_zoom=(z = 1.0)
|
115
|
-
@zoom_x = z
|
116
|
-
end
|
117
|
-
|
118
|
-
# Change X axis zoom
|
119
|
-
def y_zoom=(z = 1.0)
|
120
|
-
@zoom_y = z
|
121
|
-
end
|
122
|
-
|
123
|
-
attr_reader :zoom_x, :zoom_y
|
124
|
-
|
125
|
-
# Calculate zoomed X position for Array of X'es
|
126
|
-
def calc_x_zoomed(old_xes)
|
127
|
-
a = (raw_x_max.to_f + raw_x_min.to_f) / 2.0
|
128
|
-
new_xes = Array.new
|
129
|
-
|
130
|
-
old_xes.each do |x|
|
131
|
-
d = x - a
|
132
|
-
new_xes << (a + d * self.zoom_x)
|
133
|
-
end
|
134
|
-
|
135
|
-
return new_xes
|
136
|
-
end
|
137
|
-
|
138
|
-
# Calculate zoomed Y position for Array of Y'es
|
139
|
-
def calc_y_zoomed(old_yes)
|
140
|
-
a = (raw_y_max.to_f + raw_y_min.to_f) / 2.0
|
141
|
-
new_yes = Array.new
|
142
|
-
|
143
|
-
old_yes.each do |y|
|
144
|
-
d = y - a
|
145
|
-
new_yes << (a + d * self.zoom_y)
|
146
|
-
end
|
147
|
-
|
148
|
-
return new_yes
|
149
|
-
end
|
150
|
-
|
151
|
-
end
|
@@ -1,145 +0,0 @@
|
|
1
|
-
module AxisLayerDrawModule
|
2
|
-
def x_axis_fixed?
|
3
|
-
@options[:x_axis_fixed_interval] == true
|
4
|
-
end
|
5
|
-
|
6
|
-
# Value axis has fixed count
|
7
|
-
def y_axis_fixed?
|
8
|
-
@options[:y_axis_fixed_interval] == true
|
9
|
-
end
|
10
|
-
|
11
|
-
# Where to put axis values
|
12
|
-
def value_axis
|
13
|
-
return calc_axis(self.y_min, self.y_max, @options[:y_axis_interval], @options[:y_axis_count], y_axis_fixed?)
|
14
|
-
end
|
15
|
-
|
16
|
-
# Where to put axis values
|
17
|
-
def parameter_axis
|
18
|
-
return calc_axis(self.x_min, self.x_max, @options[:x_axis_interval], @options[:x_axis_count], x_axis_fixed?)
|
19
|
-
end
|
20
|
-
|
21
|
-
# Calculate axis using 2 methods
|
22
|
-
def calc_axis(from, to, interval, count, fixed_interval)
|
23
|
-
axis = Array.new
|
24
|
-
l = to - from
|
25
|
-
current = from
|
26
|
-
|
27
|
-
if fixed_interval
|
28
|
-
while current < to
|
29
|
-
axis << current
|
30
|
-
current += interval
|
31
|
-
end
|
32
|
-
return axis
|
33
|
-
|
34
|
-
else
|
35
|
-
(0...count).each do |i|
|
36
|
-
axis << from + (l.to_f * i.to_f) / count.to_f
|
37
|
-
end
|
38
|
-
return axis
|
39
|
-
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
|
44
|
-
def calc_bitmap_position(array)
|
45
|
-
# TODO move calculatio of lenght here
|
46
|
-
end
|
47
|
-
|
48
|
-
def calc_bitmap_x(_x)
|
49
|
-
l = self.x_max - self.x_min
|
50
|
-
offset = _x - self.x_min
|
51
|
-
return (offset.to_f * @image.width.to_f) / l.to_f
|
52
|
-
end
|
53
|
-
|
54
|
-
def calc_bitmap_y(_y)
|
55
|
-
l = self.y_max - self.y_min
|
56
|
-
offset = _y - self.y_min
|
57
|
-
return (offset.to_f * @image.width.to_f) / l.to_f
|
58
|
-
end
|
59
|
-
|
60
|
-
# Render axis on image
|
61
|
-
def render_on_image(image)
|
62
|
-
@image = image
|
63
|
-
|
64
|
-
render_values_axis
|
65
|
-
render_parameters_axis
|
66
|
-
end
|
67
|
-
|
68
|
-
def render_values_axis
|
69
|
-
plot_axis_y_line = Magick::Draw.new
|
70
|
-
plot_axis_y_text = Magick::Draw.new
|
71
|
-
|
72
|
-
plot_axis_y_line.fill_opacity(0)
|
73
|
-
plot_axis_y_line.stroke(@image.options[:axis_color])
|
74
|
-
plot_axis_y_line.stroke_opacity(1.0)
|
75
|
-
plot_axis_y_line.stroke_width(1.0)
|
76
|
-
plot_axis_y_line.stroke_linecap('square')
|
77
|
-
plot_axis_y_line.stroke_linejoin('miter')
|
78
|
-
|
79
|
-
plot_axis_y_text.font_family('helvetica')
|
80
|
-
plot_axis_y_text.font_style(Magick::NormalStyle)
|
81
|
-
plot_axis_y_text.text_align(Magick::LeftAlign)
|
82
|
-
plot_axis_y_text.text_undercolor(@image.options[:background_color])
|
83
|
-
|
84
|
-
value_axis.each do |y|
|
85
|
-
by = calc_bitmap_y(y)
|
86
|
-
plot_axis_y_line.line(
|
87
|
-
0, by.round,
|
88
|
-
@image.image.columns-1, by.round
|
89
|
-
)
|
90
|
-
|
91
|
-
plot_axis_y_text.text(
|
92
|
-
5,
|
93
|
-
by.round + 15,
|
94
|
-
"#{y}"
|
95
|
-
)
|
96
|
-
end
|
97
|
-
|
98
|
-
t = Time.now
|
99
|
-
plot_axis_y_line.draw(@image.image)
|
100
|
-
puts "#{Time.now - t} drawing lines"
|
101
|
-
plot_axis_y_text.draw(@image.image)
|
102
|
-
puts "#{Time.now - t} drawing text"
|
103
|
-
|
104
|
-
end
|
105
|
-
|
106
|
-
def render_parameters_axis
|
107
|
-
|
108
|
-
plot_axis_x_line = Magick::Draw.new
|
109
|
-
plot_axis_x_text = Magick::Draw.new
|
110
|
-
|
111
|
-
plot_axis_x_line.fill_opacity(0)
|
112
|
-
plot_axis_x_line.stroke(@image.options[:axis_color])
|
113
|
-
plot_axis_x_line.stroke_opacity(1.0)
|
114
|
-
plot_axis_x_line.stroke_width(1.0)
|
115
|
-
plot_axis_x_line.stroke_linecap('square')
|
116
|
-
plot_axis_x_line.stroke_linejoin('miter')
|
117
|
-
|
118
|
-
plot_axis_x_text.font_family('helvetica')
|
119
|
-
plot_axis_x_text.font_style(Magick::NormalStyle)
|
120
|
-
plot_axis_x_text.text_align(Magick::LeftAlign)
|
121
|
-
plot_axis_x_text.text_undercolor(@image.options[:background_color])
|
122
|
-
|
123
|
-
parameter_axis.each do |x|
|
124
|
-
bx = calc_bitmap_x(x)
|
125
|
-
plot_axis_x_line.line(
|
126
|
-
bx.round, 0,
|
127
|
-
bx.round, @image.image.rows-1
|
128
|
-
)
|
129
|
-
|
130
|
-
plot_axis_x_text.text(
|
131
|
-
bx.round + 15,
|
132
|
-
@image.image.rows - 15,
|
133
|
-
"#{x}"
|
134
|
-
)
|
135
|
-
end
|
136
|
-
|
137
|
-
t = Time.now
|
138
|
-
plot_axis_x_line.draw(@image.image)
|
139
|
-
puts "#{Time.now - t} drawing lines"
|
140
|
-
plot_axis_x_text.draw(@image.image)
|
141
|
-
puts "#{Time.now - t} drawing text"
|
142
|
-
|
143
|
-
end
|
144
|
-
|
145
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
#encoding: utf-8
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'technical_graph/data_processor'
|
5
|
-
#require 'technical_graph/graph_image'
|
6
|
-
#require 'technical_graph/data_layer'
|
7
|
-
#require 'technical_graph/axis_layer'
|
8
|
-
|
9
|
-
# Universal class for creating graphs/charts.
|
10
|
-
|
11
|
-
# options parameters:
|
12
|
-
# :width - width of image
|
13
|
-
# :height - height of image
|
14
|
-
# :x_min, :x_max, :y_min, :y_max - default or fixed ranges
|
15
|
-
# :xy_behaviour:
|
16
|
-
# * :default - use them as default ranges
|
17
|
-
# * :fixed - ranges will not be changed during addition of layers
|
18
|
-
|
19
|
-
class TechnicalGraph
|
20
|
-
|
21
|
-
def initialize(options = { })
|
22
|
-
@options = options
|
23
|
-
@data_processor = GraphDataProcessor.new(@options)
|
24
|
-
|
25
|
-
#@image = GraphImage.new(@options)
|
26
|
-
#@axis = AxisLayer.new(@options)
|
27
|
-
#@layers = []
|
28
|
-
end
|
29
|
-
attr_reader :options
|
30
|
-
#attr_reader :image
|
31
|
-
#attr_reader :layers
|
32
|
-
#attr_reader :axis
|
33
|
-
|
34
|
-
# Add new data layer to layer array
|
35
|
-
def add_layer(data = [], options = {})
|
36
|
-
@layers << DataLayer.new(data, options)
|
37
|
-
end
|
38
|
-
|
39
|
-
# Create graph
|
40
|
-
def render
|
41
|
-
@image.render_image
|
42
|
-
# recalculate ranges
|
43
|
-
@layers.each do |l|
|
44
|
-
@axis.process_data_layer(l)
|
45
|
-
end
|
46
|
-
# draw axis
|
47
|
-
@axis.render_on_image(@image)
|
48
|
-
# draw layers
|
49
|
-
@layers.each do |l|
|
50
|
-
# @xis used for calculation purpose
|
51
|
-
l.render_on_image(@image, @axis)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
@@ -1,104 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
class TestTechnicalGraph < Test::Unit::TestCase
|
4
|
-
context 'initial options' do
|
5
|
-
setup do
|
6
|
-
@technical_graph = TechnicalGraph.new
|
7
|
-
end
|
8
|
-
|
9
|
-
should "has options with default values" do
|
10
|
-
@technical_graph.options.class.should == Hash
|
11
|
-
@technical_graph.options[:width] > 0
|
12
|
-
@technical_graph.options[:height] > 0
|
13
|
-
end
|
14
|
-
|
15
|
-
should "has options with custom values" do
|
16
|
-
s = 10
|
17
|
-
tg = TechnicalGraph.new({ :height => s, :width => s })
|
18
|
-
@technical_graph.options[:width] == s
|
19
|
-
@technical_graph.options[:height] == s
|
20
|
-
|
21
|
-
@technical_graph.image.width == s
|
22
|
-
@technical_graph.image.height == s
|
23
|
-
end
|
24
|
-
|
25
|
-
should "has changeable options" do
|
26
|
-
s = 20
|
27
|
-
tg = TechnicalGraph.new
|
28
|
-
tg.image.width = s
|
29
|
-
tg.image.height = s
|
30
|
-
@technical_graph.options[:width] == s
|
31
|
-
@technical_graph.options[:height] == s
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
context 'basic layer operation and saving file' do
|
36
|
-
setup do
|
37
|
-
@tg = TechnicalGraph.new
|
38
|
-
@data_size = 100
|
39
|
-
|
40
|
-
# sample data
|
41
|
-
@data = Array.new
|
42
|
-
@second_data = Array.new
|
43
|
-
(0...@data_size).each do |i|
|
44
|
-
@data << { :x => Time.now.to_i - 3600 + i, :y => Math.sin(i.to_f / 10.0) }
|
45
|
-
@second_data << { :x => Time.now.to_i - 1800 + i*2, :y => Math.cos(i.to_f / 10.0) }
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
should 'has ability do add new layer' do
|
50
|
-
layers = @tg.layers.size
|
51
|
-
@tg.add_layer(@data)
|
52
|
-
@tg.layers.size.should == layers + 1
|
53
|
-
|
54
|
-
layer = @tg.layers.last
|
55
|
-
layer.data.size.should == @data_size
|
56
|
-
end
|
57
|
-
|
58
|
-
should 'has ability to manipulate layers, add more data' do
|
59
|
-
@tg.add_layer(@data)
|
60
|
-
layer = @tg.layers.last
|
61
|
-
layer.class.should == DataLayer
|
62
|
-
|
63
|
-
layer.data.size.should == @data_size
|
64
|
-
|
65
|
-
# adding second data
|
66
|
-
layer.append_data(@second_data)
|
67
|
-
layer.data.size.should == 2 * @data_size
|
68
|
-
|
69
|
-
# @tg.render
|
70
|
-
# @tg.image.save_to_file('test1.png')
|
71
|
-
end
|
72
|
-
|
73
|
-
should 'has ability to filter records with similar x\'es' do
|
74
|
-
@tg.add_layer
|
75
|
-
layer = @tg.layers.last
|
76
|
-
layer.data.size.should == 0
|
77
|
-
layer.append_data([{ :x => 0, :y => 1 }])
|
78
|
-
layer.data.size.should == 1
|
79
|
-
|
80
|
-
# uniq check
|
81
|
-
layer.append_data([{ :x => 0, :y => 1 }])
|
82
|
-
layer.append_data([{ :x => 0, :y => 1 }])
|
83
|
-
layer.data.size.should == 1
|
84
|
-
layer.append_data([{ :x => 2, :y => 1 }])
|
85
|
-
layer.data.size.should == 2
|
86
|
-
end
|
87
|
-
|
88
|
-
should 'has ability to filter bad records' do
|
89
|
-
@tg.add_layer
|
90
|
-
layer = @tg.layers.last
|
91
|
-
layer.data.size.should == 0
|
92
|
-
layer.append_data([{ :x => 0, :y => 1 }])
|
93
|
-
layer.data.size.should == 1
|
94
|
-
|
95
|
-
# uniq check
|
96
|
-
layer.append_data([{ :z => 0, :y => 1 }])
|
97
|
-
layer.append_data([{}])
|
98
|
-
layer.data.size.should == 1
|
99
|
-
end
|
100
|
-
|
101
|
-
end
|
102
|
-
|
103
|
-
|
104
|
-
end
|
@@ -1,306 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
class TestTechnicalGraphAxis < Test::Unit::TestCase
|
4
|
-
context 'ranges calculation' do
|
5
|
-
setup do
|
6
|
-
end
|
7
|
-
|
8
|
-
should 'provide defined ranges' do
|
9
|
-
x_min = 0.0
|
10
|
-
x_max = 10.0
|
11
|
-
y_min = -5.0
|
12
|
-
y_max = 5.0
|
13
|
-
|
14
|
-
@tg = TechnicalGraph.new(
|
15
|
-
{
|
16
|
-
:x_min => x_min,
|
17
|
-
:x_max => x_max,
|
18
|
-
:y_min => y_min,
|
19
|
-
:y_max => y_max,
|
20
|
-
:xy_behaviour => :fixed
|
21
|
-
}
|
22
|
-
)
|
23
|
-
@tg.render
|
24
|
-
|
25
|
-
@tg.axis.x_min.should == x_min
|
26
|
-
@tg.axis.x_max.should == x_max
|
27
|
-
@tg.axis.y_min.should == y_min
|
28
|
-
@tg.axis.y_max.should == y_max
|
29
|
-
end
|
30
|
-
|
31
|
-
should 'calculate ranges per layer' do
|
32
|
-
# adding simple layer
|
33
|
-
layer_data = [
|
34
|
-
{ :x => -1, :y => 3.0 },
|
35
|
-
{ :x => 3, :y => -8.0 },
|
36
|
-
{ :x => 0, :y => 3.0 },
|
37
|
-
{ :x => 10, :y => 10.0 }
|
38
|
-
]
|
39
|
-
dl = DataLayer.new(layer_data)
|
40
|
-
|
41
|
-
dl.x_min.should == -1
|
42
|
-
dl.x_max.should == 10
|
43
|
-
dl.y_min.should == -8.0
|
44
|
-
dl.y_max.should == 10.0
|
45
|
-
end
|
46
|
-
|
47
|
-
|
48
|
-
should 'provide ranges calculated using data layer, and multiple layers' do
|
49
|
-
x_min = 0.0
|
50
|
-
x_max = 1.0
|
51
|
-
y_min = -1.0
|
52
|
-
y_max = 1.0
|
53
|
-
|
54
|
-
@tg = TechnicalGraph.new(
|
55
|
-
{
|
56
|
-
:x_min => x_min,
|
57
|
-
:x_max => x_max,
|
58
|
-
:y_min => y_min,
|
59
|
-
:y_max => y_max,
|
60
|
-
:xy_behaviour => :default
|
61
|
-
}
|
62
|
-
)
|
63
|
-
|
64
|
-
# adding simple layer
|
65
|
-
layer_data = [
|
66
|
-
{ :x => -1, :y => 3.0 },
|
67
|
-
{ :x => 3, :y => -8.0 },
|
68
|
-
{ :x => 0, :y => 3.0 },
|
69
|
-
{ :x => 10, :y => 10.0 }
|
70
|
-
]
|
71
|
-
@tg.add_layer(layer_data)
|
72
|
-
# should be added
|
73
|
-
@tg.layers.last.data.size > 0
|
74
|
-
# checking ranger for layer
|
75
|
-
|
76
|
-
@tg.render
|
77
|
-
|
78
|
-
|
79
|
-
@tg.axis.x_min.should_not == x_min
|
80
|
-
@tg.axis.x_max.should_not == x_max
|
81
|
-
@tg.axis.y_min.should_not == y_min
|
82
|
-
@tg.axis.y_max.should_not == y_max
|
83
|
-
|
84
|
-
@tg.axis.x_min.should == -1
|
85
|
-
@tg.axis.x_max.should == 10
|
86
|
-
@tg.axis.y_min.should == -8.0
|
87
|
-
@tg.axis.y_max.should == 10.0
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
# adding another layer
|
92
|
-
|
93
|
-
# adding simple layer
|
94
|
-
layer_data = [
|
95
|
-
{ :x => -21, :y => -93.0 },
|
96
|
-
{ :x => -5, :y => 3.0 },
|
97
|
-
{ :x => 39, :y => -8.0 },
|
98
|
-
{ :x => 0, :y => 333.0 },
|
99
|
-
{ :x => 10, :y => 50.0 }
|
100
|
-
]
|
101
|
-
@tg.add_layer(layer_data)
|
102
|
-
# should be added
|
103
|
-
@tg.layers.last.data.size > 1
|
104
|
-
|
105
|
-
@tg.render
|
106
|
-
|
107
|
-
@tg.axis.x_min.should_not == x_min
|
108
|
-
@tg.axis.x_max.should_not == x_max
|
109
|
-
@tg.axis.y_min.should_not == y_min
|
110
|
-
@tg.axis.y_max.should_not == y_max
|
111
|
-
|
112
|
-
@tg.axis.x_min.should_not == -1.0
|
113
|
-
@tg.axis.x_max.should_not == 10.0
|
114
|
-
@tg.axis.y_min.should_not == -8.0
|
115
|
-
@tg.axis.y_max.should_not == 10.0
|
116
|
-
|
117
|
-
@tg.axis.x_min.should == -21.0
|
118
|
-
@tg.axis.x_max.should == 39.0
|
119
|
-
@tg.axis.y_min.should == -93.0
|
120
|
-
@tg.axis.y_max.should == 333.0
|
121
|
-
end
|
122
|
-
|
123
|
-
should 'provide ranges calculated with zoom' do
|
124
|
-
x_min = 0.0
|
125
|
-
x_max = 1.0
|
126
|
-
y_min = -1.0
|
127
|
-
y_max = 1.0
|
128
|
-
|
129
|
-
@tg = TechnicalGraph.new(
|
130
|
-
{
|
131
|
-
:x_min => x_min,
|
132
|
-
:x_max => x_max,
|
133
|
-
:y_min => y_min,
|
134
|
-
:y_max => y_max,
|
135
|
-
:xy_behaviour => :default
|
136
|
-
}
|
137
|
-
)
|
138
|
-
|
139
|
-
# adding simple layer
|
140
|
-
layer_data = [
|
141
|
-
{ :x => -5, :y => 5.0 },
|
142
|
-
{ :x => 2, :y => -5.0 },
|
143
|
-
{ :x => 0, :y => 5.0 },
|
144
|
-
{ :x => 5, :y => 5.0 }
|
145
|
-
]
|
146
|
-
@tg.add_layer(layer_data)
|
147
|
-
# should be added
|
148
|
-
@tg.layers.last.data.size > 0
|
149
|
-
# checking ranger for layer
|
150
|
-
|
151
|
-
@tg.render
|
152
|
-
|
153
|
-
|
154
|
-
@tg.axis.x_min.should_not == x_min
|
155
|
-
@tg.axis.x_max.should_not == x_max
|
156
|
-
@tg.axis.y_min.should_not == y_min
|
157
|
-
@tg.axis.y_max.should_not == y_max
|
158
|
-
|
159
|
-
@tg.axis.x_min.should == -5
|
160
|
-
@tg.axis.x_max.should == 5
|
161
|
-
@tg.axis.y_min.should == -5.0
|
162
|
-
@tg.axis.y_max.should == 5.0
|
163
|
-
|
164
|
-
@tg.axis.zoom = 2.0
|
165
|
-
|
166
|
-
@tg.axis.x_min.should == -10.0
|
167
|
-
@tg.axis.x_max.should == 10.0
|
168
|
-
@tg.axis.y_min.should == -10.0
|
169
|
-
@tg.axis.y_max.should == 10.0
|
170
|
-
|
171
|
-
@tg.axis.x_min.should_not == -5
|
172
|
-
@tg.axis.x_max.should_not == 5
|
173
|
-
@tg.axis.y_min.should_not == -5.0
|
174
|
-
@tg.axis.y_max.should_not == 5.0
|
175
|
-
|
176
|
-
@tg.axis.raw_x_min.should == -5
|
177
|
-
@tg.axis.raw_x_max.should == 5
|
178
|
-
@tg.axis.raw_y_min.should == -5.0
|
179
|
-
@tg.axis.raw_y_max.should == 5.0
|
180
|
-
end
|
181
|
-
|
182
|
-
|
183
|
-
should 'calculate axis with fixed interval' do
|
184
|
-
x_min = -5.0
|
185
|
-
x_max = 5.0
|
186
|
-
y_min = -5.0
|
187
|
-
y_max = 5.0
|
188
|
-
|
189
|
-
@tg = TechnicalGraph.new(
|
190
|
-
{
|
191
|
-
:x_min => x_min,
|
192
|
-
:x_max => x_max,
|
193
|
-
:y_min => y_min,
|
194
|
-
:y_max => y_max,
|
195
|
-
:xy_behaviour => :fixed,
|
196
|
-
|
197
|
-
:y_axis_count => 10,
|
198
|
-
:x_axis_count => 10,
|
199
|
-
:y_axis_interval => 1.0,
|
200
|
-
:x_axis_interval => 4.0,
|
201
|
-
:x_axis_fixed_interval => true,
|
202
|
-
:y_axis_fixed_interval => true
|
203
|
-
}
|
204
|
-
)
|
205
|
-
|
206
|
-
# adding simple layer
|
207
|
-
layer_data = [
|
208
|
-
{ :x => -1, :y => 2.0 },
|
209
|
-
{ :x => 1, :y => -2.0 },
|
210
|
-
{ :x => 0, :y => 2.0 },
|
211
|
-
{ :x => 1, :y => 2.0 }
|
212
|
-
]
|
213
|
-
@tg.add_layer(layer_data)
|
214
|
-
# should be added
|
215
|
-
@tg.layers.last.data.size > 0
|
216
|
-
# checking ranger for layer
|
217
|
-
|
218
|
-
@tg.render
|
219
|
-
|
220
|
-
@tg.axis.value_axis.should == [-5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0]
|
221
|
-
@tg.axis.parameter_axis.should == [-5.0, -1.0, 3.0]
|
222
|
-
end
|
223
|
-
|
224
|
-
|
225
|
-
should 'calculate axis with fixed count' do
|
226
|
-
x_min = -8.0
|
227
|
-
x_max = 8.0
|
228
|
-
y_min = -4.0
|
229
|
-
y_max = 4.0
|
230
|
-
|
231
|
-
@tg = TechnicalGraph.new(
|
232
|
-
{
|
233
|
-
:x_min => x_min,
|
234
|
-
:x_max => x_max,
|
235
|
-
:y_min => y_min,
|
236
|
-
:y_max => y_max,
|
237
|
-
:xy_behaviour => :fixed,
|
238
|
-
|
239
|
-
:x_axis_count => 8,
|
240
|
-
:y_axis_count => 4,
|
241
|
-
:x_axis_interval => 2.0,
|
242
|
-
:y_axis_interval => 1.0,
|
243
|
-
:x_axis_fixed_interval => false,
|
244
|
-
:y_axis_fixed_interval => false
|
245
|
-
}
|
246
|
-
)
|
247
|
-
|
248
|
-
# adding simple layer
|
249
|
-
layer_data = [
|
250
|
-
{ :x => -1, :y => 2.0 },
|
251
|
-
{ :x => 1, :y => -2.0 },
|
252
|
-
{ :x => 0, :y => 2.0 },
|
253
|
-
{ :x => 1, :y => 2.0 }
|
254
|
-
]
|
255
|
-
@tg.add_layer(layer_data)
|
256
|
-
# should be added
|
257
|
-
@tg.layers.last.data.size > 0
|
258
|
-
# checking ranger for layer
|
259
|
-
|
260
|
-
@tg.render
|
261
|
-
|
262
|
-
@tg.axis.parameter_axis.should == [-8.0, -6.0, -4.0, -2.0, 0.0, 2.0, 4.0, 6.0]
|
263
|
-
@tg.axis.value_axis.should == [-4.0, -2.0, 0.0, 2.0]
|
264
|
-
|
265
|
-
@tg.image.save_to_file('test1.png')
|
266
|
-
end
|
267
|
-
|
268
|
-
|
269
|
-
should 'draw simple graph' do
|
270
|
-
@tg = TechnicalGraph.new(
|
271
|
-
{
|
272
|
-
:x_axis_count => 10,
|
273
|
-
:y_axis_count => 10,
|
274
|
-
:x_axis_interval => 1.0,
|
275
|
-
:y_axis_interval => 1.0,
|
276
|
-
:x_axis_fixed_interval => false,
|
277
|
-
:y_axis_fixed_interval => false,
|
278
|
-
|
279
|
-
:x_min => -10.0,
|
280
|
-
:x_max => 10.0,
|
281
|
-
:y_min => -10.0,
|
282
|
-
:y_max => 10.0
|
283
|
-
}
|
284
|
-
)
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
# adding simple layer
|
289
|
-
layer_data = Array.new
|
290
|
-
(0..20).each do |i|
|
291
|
-
layer_data << {:x => Math.sin(i.to_f/10.0) * 10.0, :y => Math.cos(i.to_f/10.0) * 10.0 }
|
292
|
-
end
|
293
|
-
@tg.add_layer(layer_data)
|
294
|
-
# should be added
|
295
|
-
@tg.layers.last.data.size > 0
|
296
|
-
# checking ranger for layer
|
297
|
-
|
298
|
-
@tg.render
|
299
|
-
|
300
|
-
@tg.image.save_to_file('test2.png')
|
301
|
-
end
|
302
|
-
|
303
|
-
end
|
304
|
-
|
305
|
-
end
|
306
|
-
|
data/samples/1.png
DELETED
Binary file
|
Binary file
|
data/technical_graph.gemspec
DELETED
@@ -1,84 +0,0 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
-
# -*- encoding: utf-8 -*-
|
5
|
-
|
6
|
-
Gem::Specification.new do |s|
|
7
|
-
s.name = %q{technical_graph}
|
8
|
-
s.version = "0.1.1"
|
9
|
-
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors = ["Aleksander Kwiatkowski"]
|
12
|
-
s.date = %q{2011-10-09}
|
13
|
-
s.description = %q{Purpose of this gem is to create neat, simple, technical graphs. This is alternative to most new libraries which create small, candy graphs using JavaScript.}
|
14
|
-
s.email = %q{bobikx@poczta.fm}
|
15
|
-
s.extra_rdoc_files = [
|
16
|
-
"LICENSE.txt",
|
17
|
-
"README.md"
|
18
|
-
]
|
19
|
-
s.files = [
|
20
|
-
".document",
|
21
|
-
".idea/dictionaries/olek.xml",
|
22
|
-
".rvmrc",
|
23
|
-
"Gemfile",
|
24
|
-
"Gemfile.lock",
|
25
|
-
"LICENSE.txt",
|
26
|
-
"README.md",
|
27
|
-
"Rakefile",
|
28
|
-
"VERSION",
|
29
|
-
"lib/technical_graph.rb",
|
30
|
-
"lib/technical_graph/data_layer.rb",
|
31
|
-
"lib/technical_graph/graph_axis.rb",
|
32
|
-
"lib/technical_graph/graph_data_processor.rb",
|
33
|
-
"lib/technical_graph/graph_image_drawer.rb",
|
34
|
-
"lib/technical_graph/refactoring_backup/lib/technical_graph.rb",
|
35
|
-
"lib/technical_graph/refactoring_backup/lib/technical_graph/axis_layer.rb",
|
36
|
-
"lib/technical_graph/refactoring_backup/lib/technical_graph/axis_layer_draw_module.rb",
|
37
|
-
"lib/technical_graph/refactoring_backup/test/test_technical_graph.rb",
|
38
|
-
"lib/technical_graph/refactoring_backup/test/test_technical_graph_axis.rb",
|
39
|
-
"samples/1.png",
|
40
|
-
"samples/home_io_batt_voltage.png",
|
41
|
-
"technical_graph.gemspec",
|
42
|
-
"test/helper.rb",
|
43
|
-
"test/test_technical_axis_enlarge.rb",
|
44
|
-
"test/test_technical_graph.rb",
|
45
|
-
"test/test_technical_graph_axis.rb",
|
46
|
-
"test/test_technical_simple_graph.rb"
|
47
|
-
]
|
48
|
-
s.homepage = %q{http://github.com/akwiatkowski/technical_graph}
|
49
|
-
s.licenses = ["LGPLv3"]
|
50
|
-
s.require_paths = ["lib"]
|
51
|
-
s.rubygems_version = %q{1.6.2}
|
52
|
-
s.summary = %q{Create simple and neat graphs}
|
53
|
-
|
54
|
-
if s.respond_to? :specification_version then
|
55
|
-
s.specification_version = 3
|
56
|
-
|
57
|
-
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
58
|
-
s.add_runtime_dependency(%q<rmagick>, [">= 0"])
|
59
|
-
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
60
|
-
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
61
|
-
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
62
|
-
s.add_development_dependency(%q<rspec>, [">= 0"])
|
63
|
-
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
64
|
-
s.add_development_dependency(%q<rcov>, [">= 0"])
|
65
|
-
else
|
66
|
-
s.add_dependency(%q<rmagick>, [">= 0"])
|
67
|
-
s.add_dependency(%q<jeweler>, [">= 0"])
|
68
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
69
|
-
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
70
|
-
s.add_dependency(%q<rspec>, [">= 0"])
|
71
|
-
s.add_dependency(%q<jeweler>, [">= 0"])
|
72
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
73
|
-
end
|
74
|
-
else
|
75
|
-
s.add_dependency(%q<rmagick>, [">= 0"])
|
76
|
-
s.add_dependency(%q<jeweler>, [">= 0"])
|
77
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
78
|
-
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
79
|
-
s.add_dependency(%q<rspec>, [">= 0"])
|
80
|
-
s.add_dependency(%q<jeweler>, [">= 0"])
|
81
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|