technical_graph 0.2.0 → 0.3.0

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/README.md CHANGED
@@ -137,6 +137,10 @@ Layer options Hash
137
137
  * layer_options[:label] - label used in legend
138
138
  * layer_options[:color] - color of graph layer, ex.: 'red', 'green', '#FFFF00'
139
139
  * layer_options[:antialias] - use anti-aliasing for this, default false, override options[:layers_antialias]
140
+ * layer_options[:value_labels] - write values near 'dots', default true
141
+ * layer_options[:simple_smoother] - 'smooth' data, default false
142
+ * layer_options[:simple_smoother_level] - strength of smoothing, this is level of window used for processing, default 3
143
+ * layer_options[:simple_smoother_strategy] - strategy used for smoothing data, you can choose between :rectangular or :gauss, default :rectangular
140
144
 
141
145
 
142
146
  Contributing to technical-graph
data/Rakefile CHANGED
@@ -33,8 +33,8 @@ Jeweler::RubygemsDotOrgTasks.new
33
33
 
34
34
  desc "Remove all images created during tests"
35
35
  task :clean do
36
- `rm *.svg`
37
- `rm *.png`
36
+ `rm samples/tests/*.svg`
37
+ `rm samples/tests/*.png`
38
38
  end
39
39
 
40
40
  desc "Clean and release"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.3.0
@@ -49,6 +49,9 @@ class TechnicalGraph
49
49
  @axis.render_on_image(@image)
50
50
  # draw layers
51
51
  @layers.each do |l|
52
+ # external processing
53
+ l.process
54
+ # drawing
52
55
  @image_drawer.render_data_layer(l)
53
56
  end
54
57
  # draw legend
@@ -1,6 +1,7 @@
1
1
  #encoding: utf-8
2
2
 
3
3
  require 'technical_graph/graph_color_library'
4
+ require 'technical_graph/data_layer_processor'
4
5
 
5
6
  # Stores only data used for one layer
6
7
  # Instances of this class are used elsewhere
@@ -13,12 +14,27 @@ class DataLayer
13
14
 
14
15
  @data_params[:color] ||= GraphColorLibrary.instance.get_color
15
16
  @data_params[:label] ||= ''
17
+ # default true, write values near dots
18
+ @data_params[:value_labels] = false if options[:value_labels] == false
19
+
20
+ # smoothing parameters
21
+ # by default it is false
22
+ @data_params[:simple_smoother] = true if options[:simple_smoother] == true
23
+ @data_params[:simple_smoother_level] ||= 3
24
+ @data_params[:simple_smoother_strategy] ||= DataLayerProcessor::DEFAULT_STRATEGY
25
+ # was already done
26
+ @data_params[:processor_finished] = false
27
+
28
+ @processor = DataLayerProcessor.new(self)
16
29
 
17
30
  # set data and append initial data
18
31
  clear_data
19
32
  append_data(d)
20
33
  end
21
34
 
35
+ # can be used to approximation and other data processing
36
+ attr_reader :processor
37
+
22
38
  # Accessor for setting chart data for layer to draw
23
39
  def append_data(d)
24
40
  if d.kind_of? Array
@@ -33,6 +49,18 @@ class DataLayer
33
49
  # Array of {:x =>, :y =>}
34
50
  attr_reader :data
35
51
 
52
+ # Run external processor (smoothing, ...)
53
+ def process
54
+ if simple_smoother and not processor_finished?
55
+ @processor.strategy = simple_smoother_strategy
56
+ @processor.level = simple_smoother_level
57
+ @processor.generate_vector
58
+ @data = @processor.process
59
+
60
+ processor_finished!
61
+ end
62
+ end
63
+
36
64
  # Additional parameters
37
65
  attr_reader :data_params
38
66
 
@@ -49,6 +77,36 @@ class DataLayer
49
77
  return @data_params[:label]
50
78
  end
51
79
 
80
+ # Write values near dots
81
+ def value_labels
82
+ return @data_params[:value_labels]
83
+ end
84
+
85
+ # Turn on smoothing processor
86
+ def simple_smoother
87
+ return @data_params[:simple_smoother]
88
+ end
89
+
90
+ # Smoother level
91
+ def simple_smoother_level
92
+ return @data_params[:simple_smoother_level]
93
+ end
94
+
95
+ # Smoother strategy
96
+ def simple_smoother_strategy
97
+ return @data_params[:simple_smoother_strategy]
98
+ end
99
+
100
+ # Was already processed?
101
+ def processor_finished?
102
+ @data_params[:processor_finished]
103
+ end
104
+
105
+ # Mark as processed
106
+ def processor_finished!
107
+ @data_params[:processor_finished] = true
108
+ end
109
+
52
110
  # Clear data
53
111
  def clear_data
54
112
  @data = Array.new
@@ -0,0 +1,212 @@
1
+ #encoding: utf-8
2
+
3
+ # Approximate data layer
4
+
5
+ class DataLayerProcessor
6
+ STRATEGIES = {
7
+ :rectangular => 'generate_vector_rectangular',
8
+ :gauss => 'generate_vector_gauss'
9
+ }
10
+ DEFAULT_STRATEGY = :rectangular
11
+
12
+ MIN_LEVEL = 1
13
+ MAX_LEVEL = 200
14
+
15
+ # use 'x' axis for processing also
16
+ PROCESS_WITH_PARAMETER_DISTANCE = false
17
+
18
+ # default Gauss coefficient
19
+ DEFAULT_GAUSS_COEFF = 0.2
20
+
21
+ def initialize(data_layer)
22
+ @data_layer = data_layer
23
+ @strategy = DEFAULT_STRATEGY
24
+ @level = MIN_LEVEL
25
+ @vector = Array.new
26
+ @gauss_coeff = DEFAULT_GAUSS_COEFF
27
+ end
28
+
29
+ attr_reader :vector
30
+ attr_accessor :gauss_coeff
31
+
32
+ # Level of approximation
33
+ def level=(l)
34
+ @level = l.to_i if l.to_i >= MIN_LEVEL and l.to_i < MAX_LEVEL
35
+ end
36
+
37
+ attr_reader :level
38
+
39
+ # Choose other strategy from STRATEGIES
40
+ def strategy=(s)
41
+ method = STRATEGIES[s]
42
+ @strategy = s unless method.nil?
43
+ end
44
+
45
+ attr_reader :strategy
46
+
47
+
48
+ # This vector will be used to process values (Y'es)
49
+ # Use proper strategy
50
+ def generate_vector
51
+ method = STRATEGIES[@strategy]
52
+ if method.nil?
53
+ method = STRATEGIES[DEFAULT_STRATEGY]
54
+ end
55
+ return self.send(method)
56
+ end
57
+
58
+ # Process values
59
+ def process
60
+ t = Time.now
61
+ old_data = @data_layer.data
62
+ new_data = Array.new
63
+
64
+ (0...old_data.size).each do |i|
65
+ new_data << {
66
+ :x => old_data[i][:x],
67
+ :y => process_part(old_data, i)
68
+ }
69
+ end
70
+
71
+ puts "Smoothing completed, level #{level}, data size #{old_data.size}, time #{Time.now - t}"
72
+
73
+ return new_data
74
+ end
75
+
76
+ # Process part (size depends on level)
77
+ def process_part(old_data, position)
78
+ # neutral data, used where position is near edge to calculate new value
79
+ neutral_data = {
80
+ :x => old_data[position][:x],
81
+ :y => old_data[position][:y]
82
+ }
83
+ part_array = Array.new(level, neutral_data)
84
+
85
+ # add data from old_data to part_array
86
+ offset = (level/2.0).floor
87
+ # copying data
88
+ (0...level).each do |l|
89
+ copy_pos = position + l - offset
90
+ # if copy_pos is inside data
91
+ if copy_pos >= 0 and old_data.size > copy_pos
92
+ part_array[l] = old_data[copy_pos]
93
+ end
94
+ end
95
+ # here we should have part_array and vector
96
+ # and now do some magic :]
97
+
98
+ if PROCESS_WITH_PARAMETER_DISTANCE == false
99
+ y_sum = 0.0
100
+ (0...level).each do |l|
101
+ y_sum += part_array[l][:y] * vector[l]
102
+ end
103
+ return y_sum
104
+ else
105
+ # TODO bugs!, issues with NaN
106
+ # waged average using inverted distance
107
+ _sum = 0.0
108
+ _wages = 0.0
109
+ _x_position = old_data[position][:x]
110
+
111
+ (0...level).each do |l|
112
+ _x_distance = (part_array[l][:x] - _x_position).abs
113
+ _wage = (1.0 / _x_distance)
114
+
115
+ unless _wage.nan?
116
+ _wages += _wage
117
+ _sum += (part_array[l][:y] * vector[l]) / _x_distance
118
+ end
119
+ end
120
+ y = _sum.to_f / _wages.to_f
121
+ puts y
122
+ return y
123
+ end
124
+
125
+ end
126
+
127
+
128
+ # This vector will be used to process values (Y'es), linear algorithm
129
+ def generate_vector_rectangular
130
+ @vector = Array.new
131
+ # calculated
132
+ (1..level).each do |i|
133
+ @vector << 1.0 / level.to_f
134
+ end
135
+ return @vector
136
+ end
137
+
138
+ # This vector will be used to process values (Y'es), linear algorithm
139
+ def generate_vector_gauss
140
+ # http://www.techotopia.com/index.php/Ruby_Math_Functions_and_Methods#Ruby_Math_Constants
141
+ # http://pl.wikipedia.org/wiki/Okno_czasowe
142
+
143
+ # calculation
144
+ count = (level.to_f / 2.0).floor + 1
145
+
146
+ v = Array.new
147
+ # calculated
148
+ (1..count).each do |i|
149
+ v << Math::E ** ((-0.5) * (i*gauss_coeff) ** 2)
150
+ end
151
+
152
+ @vector = make_mirror(v, level)
153
+
154
+ normalize_vector
155
+
156
+ return @vector
157
+ end
158
+
159
+ # Multiply vector to have sum eq. 1.0
160
+ def normalize_vector
161
+ s = 0.0
162
+ @vector.each do |v|
163
+ s += v
164
+ end
165
+
166
+ new_vector = Array.new
167
+
168
+ @vector.each do |v|
169
+ new_vector << v / s
170
+ end
171
+
172
+ @vector = new_vector
173
+
174
+ return @vector
175
+ end
176
+
177
+ # Make mirror array
178
+ # size = 7 => [ i[3], i[2], i[1], i[0], i[1], i[2], i[3] ]
179
+ # size = 8 => [ i[3], i[2], i[1], i[0], i[0], i[1], i[2], i[3] ]
180
+ def make_mirror(input, size)
181
+ a = Array.new(size, 0.1)
182
+ if size.even?
183
+ # two 'first' in central
184
+ c_left = size/2 - 1
185
+ c_right = size/2
186
+
187
+ a[c_left] = input[0]
188
+ a[c_right] = input[0]
189
+ else
190
+ # there is one 'first'
191
+ c_left = (size/2.0).floor
192
+ c_right = (size/2.0).floor
193
+
194
+ a[c_left] = input[0]
195
+ # a[c_right] = input[0]
196
+ end
197
+
198
+ # the rest
199
+ i = 0
200
+ while c_left > 0
201
+ i += 1
202
+ c_left -= 1
203
+ c_right += 1
204
+
205
+ a[c_left] = input[i]
206
+ a[c_right] = input[i]
207
+ end
208
+
209
+ return a
210
+ end
211
+
212
+ end
@@ -215,14 +215,16 @@ class GraphImageDrawer
215
215
  end
216
216
 
217
217
  # labels
218
- coords.each do |c|
219
- string_label = "#{truncate_string % c[:dy]}"
220
- layer_text.text(
221
- c[:ax] + 5, c[:ay],
222
- string_label
223
- )
218
+ if l.value_labels
219
+ coords.each do |c|
220
+ string_label = "#{truncate_string % c[:dy]}"
221
+ layer_text.text(
222
+ c[:ax] + 5, c[:ay],
223
+ string_label
224
+ )
225
+ end
226
+ layer_text.draw(@image)
224
227
  end
225
- layer_text.draw(@image)
226
228
 
227
229
  # lines and circles
228
230
  coords.each do |c|
@@ -244,8 +246,8 @@ class GraphImageDrawer
244
246
 
245
247
  # used for auto positioning of legend
246
248
  if legend_auto_position
247
- @drawn_points << {:x => c[:ax], :y => c[:ay]}
248
- @drawn_points << {:x => c[:bx], :y => c[:by]}
249
+ @drawn_points << { :x => c[:ax], :y => c[:ay] }
250
+ @drawn_points << { :x => c[:bx], :y => c[:by] }
249
251
  end
250
252
  end
251
253
  layer_line.draw(@image)
@@ -264,14 +266,14 @@ class GraphImageDrawer
264
266
 
265
267
  # check 8 places:
266
268
  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
269
+ { :x => legend_margin, :y => 0 + legend_margin }, # top-left
270
+ { :x => width/2, :y => 0 + legend_margin }, # top-center
271
+ { :x => width - legend_margin - legend_width, :y => 0 + legend_margin }, # top-right
272
+ { :x => legend_margin, :y => height/2 }, # middle-left
273
+ { :x => width - legend_margin - legend_width, :y => height/2 }, # middle-right
274
+ { :x => legend_margin, :y => height - legend_margin - legend_height }, # bottom-left
275
+ { :x => width/2, :y => height - legend_margin - legend_height }, # bottom-center
276
+ { :x => width - legend_margin - legend_width, :y => height - legend_margin - legend_height }, # bottom-right
275
277
  ]
276
278
 
277
279
  # calculate nearest distance of all drawn points
@@ -279,7 +281,7 @@ class GraphImageDrawer
279
281
  p[:distance] = (width ** 2 + height ** 2) ** 0.5 # max distance, diagonal of graph
280
282
  @drawn_points.each do |dp|
281
283
  # 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
284
+ two_points_distance = ((p[:x] - dp[:x]) ** 2 + (p[:y] - dp[:y]) ** 2) ** 0.5
283
285
  # modify only if distance is closer
284
286
  if p[:distance] > two_points_distance
285
287
  p[:distance] = two_points_distance
@@ -288,7 +290,7 @@ class GraphImageDrawer
288
290
  end
289
291
 
290
292
  # chose position with hihest distance
291
- positions.sort!{|a,b| a[:distance] <=> b[:distance]}
293
+ positions.sort! { |a, b| a[:distance] <=> b[:distance] }
292
294
  best_position = positions.last
293
295
  options[:legend_x] = best_position[:x]
294
296
  options[:legend_y] = best_position[:y]
@@ -318,7 +320,7 @@ class GraphImageDrawer
318
320
 
319
321
  layers.each do |l|
320
322
  legend_text.fill(l.color)
321
-
323
+
322
324
  string_label = l.label
323
325
  legend_text.text(
324
326
  x, y,
@@ -82,7 +82,7 @@ class TestTechnicalAutocolor < Test::Unit::TestCase
82
82
 
83
83
  @tg.render
84
84
 
85
- @tg.image_drawer.save_to_file('test_autocolor.png')
85
+ @tg.image_drawer.save_to_file('samples/tests/test_autocolor.png')
86
86
  @tg.image_drawer.to_png.class.should == String
87
87
 
88
88
  end
@@ -58,8 +58,8 @@ class TestTechnicalAxisEnlarge < Test::Unit::TestCase
58
58
 
59
59
  @tg.render
60
60
 
61
- @tg.image_drawer.save_to_file('test_axis_enlarge.png')
62
- @tg.image_drawer.save_to_file('test_axis_enlarge.svg')
61
+ @tg.image_drawer.save_to_file('samples/tests/test_axis_enlarge.png')
62
+ @tg.image_drawer.save_to_file('samples/tests/test_axis_enlarge.svg')
63
63
  @tg.image_drawer.to_png.class.should == String
64
64
 
65
65
  end
@@ -67,7 +67,7 @@ class TestTechnicalGraph < Test::Unit::TestCase
67
67
  layer.data.size.should == 2 * @data_size
68
68
 
69
69
  # @tg.render
70
- # @tg.image.save_to_file('test1.png')
70
+ # @tg.image.save_to_file('samples/tests/test1.png')
71
71
  end
72
72
 
73
73
  should 'has ability to filter records with similar x\'es' do
@@ -262,7 +262,7 @@ class TestTechnicalGraphAxis < Test::Unit::TestCase
262
262
  @tg.axis.parameter_axis.should == [-8.0, -6.0, -4.0, -2.0, 0.0, 2.0, 4.0, 6.0]
263
263
  @tg.axis.value_axis.should == [-4.0, -2.0, 0.0, 2.0]
264
264
 
265
- @tg.image_drawer.save_to_file('test1.png')
265
+ @tg.image_drawer.save_to_file('samples/tests/test1.png')
266
266
  end
267
267
 
268
268
 
@@ -297,7 +297,7 @@ class TestTechnicalGraphAxis < Test::Unit::TestCase
297
297
 
298
298
  @tg.render
299
299
 
300
- @tg.image_drawer.save_to_file('test2.png')
300
+ @tg.image_drawer.save_to_file('samples/tests/test2.png')
301
301
  end
302
302
 
303
303
  end
@@ -86,7 +86,7 @@ class TestTechnicalMultilayer < Test::Unit::TestCase
86
86
 
87
87
  @tg.render
88
88
 
89
- @tg.image_drawer.save_to_file('test_multilayer.png')
89
+ @tg.image_drawer.save_to_file('samples/tests/test_multilayer.png')
90
90
  @tg.image_drawer.to_png.class.should == String
91
91
 
92
92
  end
@@ -54,7 +54,7 @@ class TestTechnicalSimpleGraph < Test::Unit::TestCase
54
54
 
55
55
  @tg.render
56
56
 
57
- @tg.image_drawer.save_to_file('test_simple.png')
57
+ @tg.image_drawer.save_to_file('samples/tests/test_simple.png')
58
58
  @tg.image_drawer.to_png.class.should == String
59
59
 
60
60
  end
@@ -0,0 +1,214 @@
1
+ require 'helper'
2
+
3
+ class TestTechnicalSmoother < Test::Unit::TestCase
4
+ context 'calculations' do
5
+ setup do
6
+ max = 500
7
+
8
+ # adding simple layer
9
+ @layer_params = {
10
+ :antialias => true,
11
+ :label => 'first',
12
+ :value_labels => false,
13
+ :simple_smother => 4
14
+ }
15
+ @layer_data = Array.new
16
+ (0..max).each do |i|
17
+ x = -10.0 + (20.0 * i.to_f / max.to_f)
18
+ y = 10.0 * Math.cos(i.to_f * (0.5 * 3.14 / max.to_f))
19
+
20
+ y += rand
21
+ x += rand / max.to_f
22
+
23
+ @layer_data << { :x => x, :y => y }
24
+ end
25
+
26
+
27
+ @data_layer = DataLayer.new(@layer_data, @layer_params)
28
+ @processor = @data_layer.processor
29
+ end
30
+
31
+ should 'do some basic tests' do
32
+ @processor.should.kind_of? DataLayerProcessor
33
+ end
34
+
35
+ should 'calculated vector has proper size and sum eq. 1.0' do
36
+ @processor.generate_vector.should.kind_of? Array
37
+ @processor.generate_vector.size.should == @processor.level
38
+
39
+ DataLayerProcessor::STRATEGIES.keys.each do |s|
40
+ @processor.strategy = s
41
+ @processor.strategy.should == s
42
+
43
+ (1...10).each do |i|
44
+ @processor.level = i
45
+ @processor.level.should == i
46
+
47
+ @processor.generate_vector.size.should == @processor.level
48
+
49
+ s = 0.0
50
+ @processor.generate_vector.each do |t|
51
+ s += t
52
+ end
53
+ s.should be_within(0.01).of(1.0)
54
+
55
+ # puts @processor.vector.inspect
56
+ end
57
+ end
58
+
59
+ end
60
+
61
+ should 'processed data has the same size that old one' do
62
+ DataLayerProcessor::STRATEGIES.keys.each do |s|
63
+ @processor.strategy = s
64
+ @processor.strategy.should == s
65
+ (1...9).each do |i|
66
+ @processor.level = i
67
+ @processor.level.should == i
68
+
69
+ @processor.generate_vector.size.should == @processor.level
70
+
71
+ new_data = @processor.process
72
+ new_data.size.should == @data_layer.data.size
73
+
74
+ # add as new layer
75
+ #@data_layer = DataLayer.new(@layer_data, @layer_params)
76
+ # @tg.add_layer(new_data, @layer_params)
77
+ end
78
+ end
79
+ end
80
+
81
+ should 'create simple graph with unprocessed and processed layer (gauss)' do
82
+ tg = TechnicalGraph.new(
83
+ {
84
+ :width => 2000,
85
+ :height => 1500,
86
+ }
87
+ )
88
+ max = 1000
89
+
90
+ # adding simple layer
91
+ layer_params = {
92
+ :antialias => true,
93
+ :color => 'red',
94
+ :label => 'raw',
95
+ :value_labels => false,
96
+ # :simple_smother => 8
97
+ }
98
+ layer_data = Array.new
99
+ (0..max).each do |i|
100
+ x = -10.0 + (20.0 * i.to_f / max.to_f)
101
+ y = 10.0 * Math.cos(i.to_f * (0.5 * 3.14 / max.to_f))
102
+
103
+ y += rand
104
+ x += rand / max.to_f
105
+
106
+ layer_data << { :x => x, :y => y }
107
+ end
108
+
109
+ # non processed
110
+ tg.add_layer(layer_data, layer_params)
111
+
112
+ # process and add
113
+ approx = layer_data_b = tg.layers[0].processor
114
+ approx.strategy = :gauss
115
+ approx.level = 9
116
+ approx.generate_vector
117
+
118
+ layer_data_b = approx.process
119
+ layer_params_b = {
120
+ :antialias => false,
121
+ :color => 'blue',
122
+ :label => 'processed',
123
+ :value_labels => false,
124
+ # :simple_smother => 9
125
+ }
126
+ tg.add_layer(layer_data_b, layer_params_b)
127
+
128
+ tg.render
129
+ tg.image_drawer.save_to_file('samples/tests/test_simple_gauss.png')
130
+ end
131
+
132
+ should 'create simple graph using only layer params' do
133
+ tg = TechnicalGraph.new(
134
+ {
135
+ :width => 5000,
136
+ :height => 3000,
137
+
138
+ :legend => true,
139
+ :legend_auto => true,
140
+ :legend_width => 90,
141
+ :legend_margin => 60,
142
+ :legend_x => 50,
143
+ :legend_y => 50,
144
+ }
145
+ )
146
+ max = 2000
147
+
148
+ layer_data = Array.new
149
+ (0..max).each do |i|
150
+ x = -10.0 + (20.0 * i.to_f / max.to_f)
151
+ y = 10.0 * Math.cos(i.to_f * (2.0 * 3.14 / max.to_f))
152
+
153
+ y += rand * 4.0
154
+ x += rand / max.to_f
155
+
156
+ layer_data << { :x => x, :y => y }
157
+ end
158
+
159
+ # adding simple layer
160
+ layer_params = {
161
+ :antialias => false,
162
+ :color => 'red',
163
+ :label => 'raw',
164
+ :value_labels => false,
165
+ :simple_smoother => true,
166
+ :simple_smoother_level => 1,
167
+ :simple_smoother_strategy => :gauss
168
+ }
169
+ #tg.add_layer(layer_data.clone, layer_params)
170
+ #layer_params_b = layer_params.merge({
171
+ # :color => 'blue',
172
+ # :label => 'processed - level 3',
173
+ # :simple_smoother_level => 3,
174
+ # :simple_smoother => true
175
+ #})
176
+ #tg.add_layer(layer_data.clone, layer_params)
177
+ layer_params_c = layer_params.clone.merge({
178
+ :color => 'green',
179
+ :label => 'processed - level 100',
180
+ :simple_smoother_level => 100,
181
+ :simple_smoother => true
182
+ })
183
+ #tg.add_layer(layer_data.clone, layer_params)
184
+ #layer_params_d = layer_params.clone.merge({
185
+ # :color => 'brown',
186
+ # :label => 'processed - level 50',
187
+ # :simple_smoother_level => 50,
188
+ # :simple_smoother => true
189
+ #})
190
+ tg.add_layer(layer_data.clone, layer_params)
191
+ #tg.add_layer(layer_data.clone, layer_params_b)
192
+ tg.add_layer(layer_data.clone, layer_params_c)
193
+ #tg.add_layer(layer_data.clone, layer_params_d)
194
+
195
+
196
+ layer_params_e = layer_params.clone.merge({
197
+ :color => 'blue',
198
+ :label => 'processed (rectangular) - level 100',
199
+ :simple_smoother_level => 100,
200
+ :simple_smoother => true,
201
+ :simple_smoother_strategy => :rectangular
202
+ })
203
+ tg.add_layer(layer_data.clone, layer_params_e)
204
+
205
+
206
+ tg.render
207
+ tg.image_drawer.save_to_file('samples/tests/test_smoothing_multiple.png')
208
+ end
209
+
210
+
211
+ end
212
+
213
+
214
+ 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: 23
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 2
8
+ - 3
9
9
  - 0
10
- version: 0.2.0
10
+ version: 0.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Aleksander Kwiatkowski
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-10-09 00:00:00 +02:00
18
+ date: 2011-10-12 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -122,6 +122,7 @@ files:
122
122
  - VERSION
123
123
  - lib/technical_graph.rb
124
124
  - lib/technical_graph/data_layer.rb
125
+ - lib/technical_graph/data_layer_processor.rb
125
126
  - lib/technical_graph/graph_axis.rb
126
127
  - lib/technical_graph/graph_color_library.rb
127
128
  - lib/technical_graph/graph_data_processor.rb
@@ -133,6 +134,7 @@ files:
133
134
  - test/test_technical_graph_axis.rb
134
135
  - test/test_technical_multilayer.rb
135
136
  - test/test_technical_simple_graph.rb
137
+ - test/test_technical_smoother.rb
136
138
  has_rdoc: true
137
139
  homepage: http://github.com/akwiatkowski/technical_graph
138
140
  licenses: