sankey 0.0.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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Jan Stępień
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,11 @@
1
+ = Sankey
2
+
3
+ A small tool which generates Sankey diagrams.
4
+
5
+ = Dependencies
6
+
7
+ * {rmagick}[http://rmagick.rubyforge.org/]
8
+
9
+ = Usage
10
+
11
+ See +examples/coffee.rb+.
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+ require 'rake'
3
+
4
+ desc "Run rdoc"
5
+ task :rdoc do
6
+ print `rdoc -a -S -N -w 2 -U -o doc/rdoc README.rdoc lib`
7
+ end
8
+
9
+ begin
10
+ require 'jeweler'
11
+ Jeweler::Tasks.new do |gemspec|
12
+ gemspec.name = 'sankey'
13
+ gemspec.summary = 'Sankey diagrams generator'
14
+ gemspec.description = 'A small tool which generates Sankey diagrams.'
15
+ gemspec.email = 'jstepien@users.sourceforge.net'
16
+ gemspec.homepage = "http://github.com/jstepien/sankey"
17
+ gemspec.authors = ['Jan Stępień']
18
+ gemspec.files.exclude '.gitignore'
19
+ gemspec.add_dependency 'rmagick'
20
+ end
21
+ rescue LoadError
22
+ puts "Jeweler not available. Install it with: gem install jeweler"
23
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/ruby -I../lib
2
+ require 'sankey'
3
+ require 'renderers/rvg'
4
+
5
+ g = Sankey::Generator.new
6
+ beans = Sankey::Reagent.new 100
7
+ ground_coffee = Sankey::Reagent.new 100
8
+ water = Sankey::Reagent.new 200
9
+ beverage = Sankey::Reagent.new 280
10
+ crema = Sankey::Reagent.new 20
11
+ espresso_machine = Sankey::Process.new
12
+ grinder = Sankey::Process.new
13
+ beans.drain = grinder
14
+ water.drain = espresso_machine
15
+ ground_coffee.drain = espresso_machine
16
+ ground_coffee.source = grinder
17
+ beverage.source = espresso_machine
18
+ crema.source = espresso_machine
19
+ g.processes.push espresso_machine
20
+ g.processes.push grinder
21
+ g.go!
22
+ p = Sankey::Renderers::RVG.new g.data, "espresso.png"
23
+ p.render
@@ -0,0 +1,233 @@
1
+ require 'processvertex'
2
+ require 'point'
3
+ require 'imagedata'
4
+
5
+ module Sankey
6
+ class Generator
7
+ attr_reader :processes, :data
8
+
9
+ ProcessWidth = 40
10
+ ProcessLayerStep = 100
11
+ ProcessSideStep = 50
12
+ Margin = 5
13
+ InputReagentsStep = 20
14
+ OutputReagentsStep = 20
15
+
16
+ def initialize
17
+ @processes = []
18
+ end
19
+
20
+ def go!
21
+ @processes_vertices = {}
22
+ @drawn_reagents = []
23
+ @vertices = []
24
+ @input_reagent_offset = Margin
25
+ @below_next_process_offset = {}
26
+ @process_input_offset = {}
27
+ @process_output_left_offset = {}
28
+ @process_output_right_offset = {}
29
+ get_max_distances_to_processes
30
+ to_be_drawn = []
31
+ input_reagents.each { |r| to_be_drawn.push r }
32
+ until to_be_drawn.empty? do
33
+ STDERR.puts "to draw"
34
+ to_be_drawn.each { |r| STDERR.puts " " + r.to_s + " " + r.name }
35
+ not_drawn = []
36
+ to_be_drawn.each { |r| not_drawn += recursively_draw r }
37
+ to_be_drawn = not_drawn.uniq
38
+ end
39
+ make_coordinates_positive
40
+ w, h = get_size
41
+ @data = ImageData.new @vertices, w, h
42
+ end
43
+
44
+ private
45
+
46
+ # Moves all vertices so that there are no negative coordinates.
47
+ def make_coordinates_positive
48
+ min_y = @vertices[0].points[0].y
49
+ min_x = @vertices[0].points[0].x
50
+ @vertices.each do |v|
51
+ v.points.each do |p|
52
+ min_y = [min_y, p.y].min
53
+ min_x = [min_x, p.x].min
54
+ end
55
+ end
56
+ min_x -= Margin
57
+ STDERR.puts "Vector: #{-min_x} -#{-min_y}."
58
+ vector = [-min_x, -min_y]
59
+ @vertices.each do |v|
60
+ v.points.map! do |p|
61
+ p + vector
62
+ end
63
+ end
64
+ end
65
+
66
+ def get_max_distances_to_processes(reagent = nil, level = 0)
67
+ if reagent.nil?
68
+ @max_distances_to_processes = {}
69
+ input_reagents.each { |r| get_max_distances_to_processes r }
70
+ elsif !reagent.drain.nil?
71
+ new_level = level + 1
72
+ if @max_distances_to_processes[reagent.drain].nil? or
73
+ @max_distances_to_processes[reagent.drain] < new_level
74
+ @max_distances_to_processes[reagent.drain] = new_level
75
+ end
76
+ reagent.drain.output.each do |r|
77
+ get_max_distances_to_processes r, new_level
78
+ end
79
+ end
80
+ end
81
+
82
+ def draw_process(process)
83
+ layer = @max_distances_to_processes[process] - 1
84
+ height = process.total_reagents_mass
85
+ corner = Point.new (layer+1)*(ProcessLayerStep+ProcessWidth) + Margin,
86
+ Margin
87
+ v = ProcessVertex.new corner, corner + [0, height],
88
+ corner + [ProcessWidth, height], corner + [ProcessWidth, 0]
89
+ @vertices.push v
90
+ @processes_vertices[process] = v
91
+ # Initialize @below_next_process_offset
92
+ process.input.each do |r|
93
+ unless r.source.nil?
94
+ @below_next_process_offset[r.source] = Margin + height
95
+ break
96
+ end
97
+ end
98
+ end
99
+
100
+ def recursively_draw(reagent)
101
+ return [] if @drawn_reagents.include? reagent
102
+ STDERR.puts " drawing " + reagent.name if reagent.name != ""
103
+ if reagent.drain.nil?
104
+ if reagent.source.is_first_in_output_queue reagent
105
+ draw_output_reagent reagent
106
+ reagent.source.remove_from_output_queue reagent
107
+ else
108
+ STDERR.puts " later"
109
+ return [reagent]
110
+ end
111
+ elsif reagent.source.nil?
112
+ if reagent.drain.is_first_in_input_queue reagent
113
+ draw_input_reagent reagent
114
+ reagent.drain.remove_from_input_queue reagent
115
+ else
116
+ STDERR.puts " later"
117
+ return [reagent]
118
+ end
119
+ else
120
+ if reagent.drain.is_first_in_input_queue(reagent) and
121
+ reagent.source.is_first_in_output_queue(reagent)
122
+ draw_middle_reagent reagent
123
+ reagent.source.remove_from_output_queue reagent
124
+ reagent.drain.remove_from_input_queue reagent
125
+ else
126
+ #STDERR.puts reagent.drain.is_first_in_input_queue(reagent)
127
+ #STDERR.puts reagent.source.is_first_in_output_queue(reagent)
128
+ STDERR.puts " later"
129
+ return [reagent]
130
+ end
131
+ end
132
+ @drawn_reagents.push reagent
133
+ to_draw_later = []
134
+ unless reagent.drain.nil?
135
+ reagent.drain.output.each { |r| to_draw_later += recursively_draw r }
136
+ end
137
+ to_draw_later
138
+ end
139
+
140
+ def draw_middle_reagent(reagent)
141
+ left_height = reagent.source.total_reagents_mass *
142
+ reagent.source.fraction(reagent)
143
+ right_height = reagent.drain.total_reagents_mass *
144
+ reagent.drain.fraction(reagent)
145
+ [reagent.source, reagent.drain].each do |p|
146
+ draw_process p unless @processes_vertices.include? p
147
+ end
148
+ @process_input_offset[reagent.drain] ||= 0
149
+ @process_output_left_offset[reagent.source] ||= 0
150
+ left_corner = @processes_vertices[reagent.source].output_edge[:top] +
151
+ [0, @process_output_left_offset[reagent.source]]
152
+ right_corner = @processes_vertices[reagent.drain].input_edge[:top] +
153
+ [0, @process_input_offset[reagent.drain]]
154
+ v = Vertex.new
155
+ v.points.push left_corner
156
+ v.points.push left_corner + [0, left_height]
157
+ v.points.push right_corner + [0, right_height]
158
+ v.points.push right_corner
159
+ @vertices.push v
160
+ @process_input_offset[reagent.drain] += right_height
161
+ @process_output_left_offset[reagent.source] += left_height
162
+ end
163
+
164
+ def draw_input_reagent(reagent)
165
+ draw_process reagent.drain unless @processes_vertices.include? reagent.drain
166
+ height = reagent.drain.total_reagents_mass * reagent.drain.fraction(reagent)
167
+ @process_input_offset[reagent.drain] ||= 0
168
+ v = Vertex.new
169
+ if @process_input_offset[reagent.drain] == 0 and reagent.joins_later
170
+ left_corner = @processes_vertices[reagent.drain].input_edge[:top] +
171
+ [-ProcessSideStep, -height]
172
+ else
173
+ left_corner = Point.new Margin, @input_reagent_offset
174
+ end
175
+ v.points.push left_corner
176
+ v.points.push left_corner + [5, height / 2]
177
+ v.points.push left_corner + [0, height]
178
+ v.points.push @processes_vertices[reagent.drain].input_edge[:top] +
179
+ [0, @process_input_offset[reagent.drain] + height]
180
+ v.points.push @processes_vertices[reagent.drain].input_edge[:top] +
181
+ [0, @process_input_offset[reagent.drain]]
182
+ @vertices.push v
183
+ @input_reagent_offset += height + InputReagentsStep
184
+ @process_input_offset[reagent.drain] += height
185
+ end
186
+
187
+ def draw_output_reagent(reagent)
188
+ height = reagent.source.total_reagents_mass *
189
+ reagent.source.fraction(reagent)
190
+ @process_output_left_offset[reagent.source] ||= 0
191
+ @process_output_right_offset[reagent.source] ||= 0
192
+ right_offset = @process_output_right_offset[reagent.source] +
193
+ (@below_next_process_offset[reagent.source] ||= 0)
194
+ left_corner = @processes_vertices[reagent.source].output_edge[:top] +
195
+ [0, @process_output_left_offset[reagent.source]]
196
+ v = Vertex.new
197
+ v.points.push left_corner
198
+ v.points.push left_corner + [0, height]
199
+ v.points.push left_corner +
200
+ [ProcessLayerStep, right_offset + height]
201
+ v.points.push left_corner +
202
+ [ProcessLayerStep + 5, right_offset + height / 2]
203
+ v.points.push left_corner +
204
+ [ProcessLayerStep, right_offset]
205
+ @vertices.push v
206
+ @process_output_left_offset[reagent.source] += height
207
+ @process_output_right_offset[reagent.source] += height + InputReagentsStep
208
+ end
209
+
210
+ def input_reagents
211
+ return @input_reagents if defined? @input_reagents
212
+ @input_reagents = []
213
+ @processes.each do |process|
214
+ process.input.each do |reagent|
215
+ @input_reagents.push reagent if reagent.source.nil?
216
+ end
217
+ end
218
+ @input_reagents.uniq!
219
+ @input_reagents
220
+ end
221
+
222
+ def get_size
223
+ w = h = 0
224
+ @vertices.each do |vertex|
225
+ vertex.points.each do |point|
226
+ w = point.x + Margin if point.x + Margin > w
227
+ h = point.y + Margin if point.y + Margin > h
228
+ end
229
+ end
230
+ return w, h
231
+ end
232
+ end
233
+ end
@@ -0,0 +1,11 @@
1
+ module Sankey
2
+ class ImageData
3
+ attr_reader :vertices, :width, :height
4
+
5
+ def initialize(vertices, width, height)
6
+ @vertices = vertices
7
+ @width = width
8
+ @height = height
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,20 @@
1
+ module Sankey
2
+ class Point
3
+ attr_reader :x, :y
4
+
5
+ def initialize(x, y)
6
+ @x = x
7
+ @y = y
8
+ end
9
+
10
+ def +(val)
11
+ if val.is_a? Array and 2 == val.count
12
+ x = val[0]
13
+ y = val[1]
14
+ else
15
+ throw "Invalid argument"
16
+ end
17
+ Point.new @x + x, @y + y
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,83 @@
1
+ module Sankey
2
+ class Process
3
+ attr_reader :input, :output
4
+
5
+ def initialize
6
+ @input = []
7
+ @output = []
8
+ @input_reagents_queue = {}
9
+ @output_reagents_queue = {}
10
+ end
11
+
12
+ def fraction(reagent)
13
+ side = nil
14
+ [@output, @input].each { |io| side = io if io.include? reagent }
15
+ throw "Reagent isn't present in this process" if side.nil?
16
+ sum = 0
17
+ side.each { |r| sum += r.size }
18
+ reagent.size * 1.0 / sum
19
+ end
20
+
21
+ def total_reagents_mass
22
+ check_conservation_of_mass
23
+ end
24
+
25
+ def add_output(reagent, order = nil)
26
+ @output.push reagent
27
+ @output_reagents_queue[order] = reagent unless order.nil?
28
+ end
29
+
30
+ def add_input(reagent, order = nil)
31
+ @input.push reagent
32
+ @input_reagents_queue[order] = reagent unless order.nil?
33
+ end
34
+
35
+ def remove_from_input_queue(reagent)
36
+ key_to_be_removed = nil
37
+ @input_reagents_queue.each do |key, val|
38
+ key_to_be_removed = key if val == reagent
39
+ end
40
+ @input_reagents_queue.delete key_to_be_removed
41
+ end
42
+
43
+ def remove_from_output_queue(reagent)
44
+ key_to_be_removed = nil
45
+ @output_reagents_queue.each do |key, val|
46
+ key_to_be_removed = key if val == reagent
47
+ end
48
+ @output_reagents_queue.delete key_to_be_removed
49
+ end
50
+
51
+ def is_first_in_input_queue(reagent)
52
+ min_key = nil
53
+ return true unless @input_reagents_queue.values.include? reagent
54
+ @input_reagents_queue.each do |key, val|
55
+ #STDERR.puts "#{key} -> #{val.name}"
56
+ min_key ||= key
57
+ min_key = [min_key, key].min
58
+ end
59
+ @input_reagents_queue[min_key] == reagent
60
+ end
61
+
62
+ def is_first_in_output_queue(reagent)
63
+ min_key = nil
64
+ return true unless @output_reagents_queue.values.include? reagent
65
+ @output_reagents_queue.each do |key, val|
66
+ min_key ||= key
67
+ min_key = [min_key, key].min
68
+ end
69
+ @output_reagents_queue[min_key] == reagent
70
+ end
71
+
72
+ private
73
+
74
+ def check_conservation_of_mass
75
+ input_sum = output_sum = 0
76
+ @input.each { |r| input_sum += r.size }
77
+ @output.each { |r| output_sum += r.size }
78
+ throw 'Conservation of mass constraint failed: ' +
79
+ "#{input_sum} != #{output_sum}" if input_sum != output_sum
80
+ input_sum
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,18 @@
1
+ require 'vertex'
2
+
3
+ module Sankey
4
+ class ProcessVertex < Vertex
5
+ def initialize(a, b, c, d)
6
+ super()
7
+ [a, b, c, d].each { |x| @points.push x }
8
+ end
9
+
10
+ def input_edge
11
+ {:bottom => @points[1], :top => @points[0]}
12
+ end
13
+
14
+ def output_edge
15
+ {:bottom => @points[2], :top => @points[3]}
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,40 @@
1
+ module Sankey
2
+ class Reagent
3
+ attr_reader :size, :source, :drain, :name
4
+
5
+ def initialize(size, name = '')
6
+ @size = size
7
+ @name = name
8
+ end
9
+
10
+ def source=(process)
11
+ process.add_output self
12
+ @source = process
13
+ end
14
+
15
+ def drain=(process)
16
+ process.add_input self
17
+ @drain = process
18
+ end
19
+
20
+ def add_drain(process, order = nil)
21
+ process.add_input self, order
22
+ @drain = process
23
+ end
24
+
25
+ def add_source(process, order = nil)
26
+ process.add_output self, order
27
+ @source= process
28
+ end
29
+
30
+ def joins_later
31
+ drain.input.each do |r|
32
+ next if r == self
33
+ if r.source != nil
34
+ return true
35
+ end
36
+ end
37
+ false
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,7 @@
1
+ module Sankey::Renderers
2
+ module Renderer
3
+ def render
4
+ throw 'Not implemented'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,65 @@
1
+ require 'renderers/renderer'
2
+ require 'rvg/rvg'
3
+ require 'imagedata'
4
+
5
+ module Sankey::Renderers
6
+ class RVG
7
+ include Renderer
8
+ include Sankey
9
+
10
+ def initialize(data, filename = nil, args = {})
11
+ throw "data isn't ImageData" unless data.is_a? ImageData
12
+ @grid = args[:grid] || false
13
+ @vertices = data.vertices
14
+ @filename = filename
15
+ @width = args[:width] || data.width
16
+ @height = args[:height] || data.height
17
+ @width_ratio = 1.0 * @width / data.width
18
+ @height_ratio = 1.0 * @height / data.height
19
+ end
20
+
21
+ def render
22
+ canvas = Magick::ImageList.new
23
+ canvas.new_image(@width, @height)
24
+ draw_grid canvas if @grid
25
+ @vertices.each { |v| draw_vertex canvas, v }
26
+ if @filename.nil?
27
+ return canvas.to_blob { self.format = 'PNG' }
28
+ else
29
+ canvas.write @filename
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def draw_grid(canvas)
36
+ grid = Magick::Draw.new
37
+ grid.stroke = 'lightgray'
38
+ grid.stroke_width = 1
39
+ 0.upto @width/@grid/@width_ratio do |x|
40
+ grid.line @width_ratio*(x*@grid+@grid-1), 0,
41
+ (x*@grid+@grid-1)*@width_ratio, @height
42
+ end
43
+ 0.upto @height/@grid/@height_ratio do |x|
44
+ grid.line 0, (x*@grid+@grid-1)*@height_ratio, @width,
45
+ (x*@grid+@grid-1)*@height_ratio
46
+ end
47
+ grid.draw canvas
48
+ end
49
+
50
+ def draw_vertex(canvas, v)
51
+ vertex = Magick::Draw.new
52
+ vertex.stroke = 'black'
53
+ vertex.stroke_width = 1
54
+ first_x = prev_x = v.points.first.x * @width_ratio
55
+ first_y = prev_y = v.points.first.y * @height_ratio
56
+ v.points.each do |p|
57
+ vertex.line prev_x, prev_y, p.x * @width_ratio, p.y * @height_ratio
58
+ prev_x = p.x * @width_ratio
59
+ prev_y = p.y * @height_ratio
60
+ end
61
+ vertex.line prev_x, prev_y, first_x, first_y
62
+ vertex.draw canvas
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,3 @@
1
+ require 'process'
2
+ require 'reagent'
3
+ require 'generator'
@@ -0,0 +1,9 @@
1
+ module Sankey
2
+ class Vertex
3
+ attr_reader :points
4
+
5
+ def initialize
6
+ @points = []
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,59 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{sankey}
8
+ s.version = "0.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Jan Stępień"]
12
+ s.date = %q{2010-02-18}
13
+ s.description = %q{A small tool which generates Sankey diagrams.}
14
+ s.email = %q{jstepien@users.sourceforge.net}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ "LICENSE",
21
+ "README.rdoc",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "examples/coffee.rb",
25
+ "lib/generator.rb",
26
+ "lib/imagedata.rb",
27
+ "lib/point.rb",
28
+ "lib/process.rb",
29
+ "lib/processvertex.rb",
30
+ "lib/reagent.rb",
31
+ "lib/renderers/renderer.rb",
32
+ "lib/renderers/rvg.rb",
33
+ "lib/sankey.rb",
34
+ "lib/vertex.rb",
35
+ "sankey.gemspec"
36
+ ]
37
+ s.homepage = %q{http://github.com/jstepien/sankey}
38
+ s.rdoc_options = ["--charset=UTF-8"]
39
+ s.require_paths = ["lib"]
40
+ s.rubygems_version = %q{1.3.5}
41
+ s.summary = %q{Sankey diagrams generator}
42
+ s.test_files = [
43
+ "examples/coffee.rb"
44
+ ]
45
+
46
+ if s.respond_to? :specification_version then
47
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
48
+ s.specification_version = 3
49
+
50
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
51
+ s.add_runtime_dependency(%q<rmagick>, [">= 0"])
52
+ else
53
+ s.add_dependency(%q<rmagick>, [">= 0"])
54
+ end
55
+ else
56
+ s.add_dependency(%q<rmagick>, [">= 0"])
57
+ end
58
+ end
59
+
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sankey
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - "Jan St\xC4\x99pie\xC5\x84"
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-18 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rmagick
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: A small tool which generates Sankey diagrams.
26
+ email: jstepien@users.sourceforge.net
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README.rdoc
34
+ files:
35
+ - LICENSE
36
+ - README.rdoc
37
+ - Rakefile
38
+ - VERSION
39
+ - examples/coffee.rb
40
+ - lib/generator.rb
41
+ - lib/imagedata.rb
42
+ - lib/point.rb
43
+ - lib/process.rb
44
+ - lib/processvertex.rb
45
+ - lib/reagent.rb
46
+ - lib/renderers/renderer.rb
47
+ - lib/renderers/rvg.rb
48
+ - lib/sankey.rb
49
+ - lib/vertex.rb
50
+ - sankey.gemspec
51
+ has_rdoc: true
52
+ homepage: http://github.com/jstepien/sankey
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options:
57
+ - --charset=UTF-8
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "0"
71
+ version:
72
+ requirements: []
73
+
74
+ rubyforge_project:
75
+ rubygems_version: 1.3.5
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: Sankey diagrams generator
79
+ test_files:
80
+ - examples/coffee.rb