rubyvis 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
Binary file
data/History.txt CHANGED
@@ -1,3 +1,12 @@
1
+ === 0.3.1 / 2010-11-19
2
+
3
+ * Added Layout::Partition
4
+ * Added Rubyvis::Histogram
5
+ * Added sunburst and icicle example
6
+ * Added shortcuts methods for layouts
7
+ * Bug fix on Hierarchy
8
+ * Updated README and Histogram spec
9
+
1
10
  === 0.3.0 / 2010-11-17
2
11
  * Network and Hierarchy classes on module Layout implemented. Require testing
3
12
  * Rubyvis::Layout::Treemap fully operational
data/Manifest.txt CHANGED
@@ -20,6 +20,7 @@ examples/first_protovis_api.rb
20
20
  examples/first_rbp_api.rb
21
21
  examples/fixtures/tipsy.gif
22
22
  examples/grouped_charts.rb
23
+ examples/icicle.rb
23
24
  examples/image.rb
24
25
  examples/line.rb
25
26
  examples/line_and_step.rb
@@ -29,6 +30,7 @@ examples/pie_and_donut.rb
29
30
  examples/scatterplot.rb
30
31
  examples/second.rb
31
32
  examples/stacked_charts.rb
33
+ examples/sunburst.rb
32
34
  examples/third.rb
33
35
  examples/treemap/treemap.rb
34
36
  examples/treemap/treemap_data.rb
@@ -39,11 +41,13 @@ lib/rubyvis/dom.rb
39
41
  lib/rubyvis/format.rb
40
42
  lib/rubyvis/format/date.rb
41
43
  lib/rubyvis/format/number.rb
44
+ lib/rubyvis/histogram.rb
42
45
  lib/rubyvis/internals.rb
43
46
  lib/rubyvis/javascript_behaviour.rb
44
47
  lib/rubyvis/layout.rb
45
48
  lib/rubyvis/layout/hierarchy.rb
46
49
  lib/rubyvis/layout/network.rb
50
+ lib/rubyvis/layout/partition.rb
47
51
  lib/rubyvis/layout/stack.rb
48
52
  lib/rubyvis/layout/treemap.rb
49
53
  lib/rubyvis/mark.rb
@@ -82,6 +86,7 @@ spec/anchor_spec.rb
82
86
  spec/area_spec.rb
83
87
  spec/bar_spec.rb
84
88
  spec/dom_spec.rb
89
+ spec/histogram_spec.rb
85
90
  spec/internal_spec.rb
86
91
  spec/javascript_behaviour_spec.rb
87
92
  spec/label_spec.rb
data/README.txt CHANGED
@@ -8,22 +8,20 @@ Ruby port of Protovis[http://vis.stanford.edu/protovis/], a great visualization
8
8
 
9
9
  == FEATURES/PROBLEMS:
10
10
 
11
- Implemented: All marks, except transient and transitions.
11
+ Implemented:
12
+ * Marks: All, except transient and transitions.
13
+ * Layout: Partition, Stack and Treemap.
12
14
 
13
- Basic protovis examples[http://vis.stanford.edu/protovis/ex/] works exactly like ruby ones with minor sintactic modifications:
14
- * Area Charts: Ok
15
- * Bar & Column Charts: Ok
16
- * Scatterplots: Ok
17
- * Pie & Donut: Interaction with mouse not implemented
18
- * Line & Step Charts: Ok
19
- * Stacked Charts: Ok
20
- * Grouped Charts: Ok.
15
+ Using protovis examples[http://vis.stanford.edu/protovis/ex/] as reference
21
16
 
22
- Complex examples requires more works:
23
-
24
- * antibiotics: Ok
25
- * barley: Ok
26
- * crimea: line and grouped line ok.
17
+ * Conventional: All working
18
+ * Custom:
19
+ * Backer's Barley
20
+ * Burtin's Antibiotics
21
+ * Hierarchies:
22
+ * Sunbursts
23
+ * Icicles
24
+ * Treemaps
27
25
 
28
26
 
29
27
  I try to maintain, when posible, complete compatibility with Javascript API, including camel case naming of functions. Johnson [http://github.com/jbarnette/johnson] - the lovely Javascript wrapper inside Ruby embrace - is our friend to test implementation of basic object.
@@ -34,16 +32,23 @@ User could use +pv+ freely, cause is defined as a global method which call Rubyv
34
32
 
35
33
  * pv.js
36
34
  * pv-internals.js
37
- * color/Color.js (incomplete)
35
+ * color/Color.js
38
36
  * color/Colors.js
39
37
  * data/Arrays.js
38
+ * data/Histogram.js
40
39
  * data/Numbers.js
41
- * data/Scale.js
42
40
  * data/LinearScale.js
43
41
  * data/LogScale.js (incomplete)
44
42
  * data/Nest.js
45
43
  * data/QuantitativeScale.js
46
44
  * data/OrdinalScale.js
45
+ * data/Scale.js
46
+ * layout/Hierarchy.js
47
+ * layout/Layout.js
48
+ * layout/Hierarchy.js
49
+ * layout/Network.js
50
+ * layout/Partition.js
51
+ * layout/Stack.js
47
52
  * mark/Anchor.js
48
53
  * mark/Area.js
49
54
  * mark/Bar.js
@@ -60,6 +65,7 @@ User could use +pv+ freely, cause is defined as a global method which call Rubyv
60
65
  * scene/SvgPanel.js
61
66
  * scene/SvgRule.js
62
67
  * scene/SvgScene.js
68
+ * scene/SvgWedge.js
63
69
  * text/Format.js (incomplete)
64
70
  * text/NumberFormat.js (incomplete)
65
71
 
@@ -81,7 +81,7 @@ vis.add(pv.Rule)
81
81
 
82
82
  # A legend showing the year. */
83
83
  vis.add(pv.Dot)
84
- .extend(dot)
84
+ .mark_extend(dot)
85
85
  .data([{:year=>1931}, {:year=>1932}])
86
86
  .left(lambda {|d| 260 + self.index * 40})
87
87
  .top(-8)
@@ -0,0 +1,48 @@
1
+ # = Icicle
2
+ # An icicle is simply a sunburst transformed from polar to cartesian coordinates. Here we show the various files on Rubyvis package; the color of each cell corresponds to the package, while the area encodes the size of the source code in bytes
3
+ # Uses Protovis API
4
+ $:.unshift(File.dirname(__FILE__)+"/../lib")
5
+ require 'rubyvis'
6
+
7
+ def get_files(path)
8
+ h={}
9
+ Dir.glob("#{path}/*").each {|e|
10
+ next if File.expand_path(e)=~/pkg|web|vendor|doc|~/
11
+ pa=File.expand_path(e)
12
+ if File.stat(pa).directory?
13
+ h[File.basename(pa)]=get_files(pa)
14
+ else
15
+ h[File.basename(pa)]=File.stat(pa).size
16
+ end
17
+ }
18
+ h
19
+ end
20
+
21
+ files=get_files(File.dirname(__FILE__)+"/../")
22
+
23
+ colors=Rubyvis::Colors.category19
24
+ vis = Rubyvis::Panel.new.
25
+ width(600).
26
+ height(500).
27
+ bottom(30)
28
+
29
+ layout = vis.add(Rubyvis::Layout::Partition::Fill).
30
+ nodes(Rubyvis.dom(files).root("rubyvis").nodes)
31
+ layout.order("descending")
32
+ layout.orient("top")
33
+ layout.size(lambda {|d| d.node_value})
34
+
35
+ layout.node.add(pv.Bar).
36
+ fill_style( lambda {|d|
37
+ colors.scale(d.parent_node ? d.parent_node.node_name : '')}
38
+ ).
39
+ stroke_style("rgba(255,255,255,.5)").
40
+ line_width(1).
41
+ antialias(false)
42
+
43
+ layout.node_label.add(pv.Label)
44
+ .text_angle(-Math::PI / 2.0)
45
+ .visible(lambda {|d| d.dx >6 })
46
+ vis.render()
47
+
48
+ puts vis.to_svg
@@ -0,0 +1,50 @@
1
+ # = Sunbursts
2
+ # A sunburst is an adjacency diagram: a space-filling variant of the node-link diagram. Rather than drawing a link between parent and child in the hierarchy, nodes are drawn as solid areas (either wedges or bars), and their placement relative to adjacent nodes reveals their position in the hierarchy. Because the nodes are now space-filling, we can use an angle encoding for the size of software files. This reveals an additional dimension that would be difficult to show in a node-link diagram.
3
+ # Uses RBP Api
4
+
5
+ $:.unshift(File.dirname(__FILE__)+"/../lib")
6
+ require 'rubyvis'
7
+
8
+ def get_files(path)
9
+ h={}
10
+ Dir.glob("#{path}/*").each {|e|
11
+ next if File.expand_path(e)=~/pkg|web|vendor|doc|~/
12
+ pa=File.expand_path(e)
13
+ if File.stat(pa).directory?
14
+ h[File.basename(pa)]=get_files(pa)
15
+ else
16
+ h[File.basename(pa)]=File.stat(pa).size
17
+ end
18
+ }
19
+ h
20
+ end
21
+
22
+ files=get_files(File.dirname(__FILE__)+"/../")
23
+ colors=Rubyvis::Colors.category19()
24
+
25
+ vis = Rubyvis::Panel.new do
26
+ width 900
27
+ height 900
28
+ bottom -80
29
+ layout_partition_fill do
30
+ nodes Rubyvis.dom(files).root("rubyvis").nodes
31
+ size {|d| d.node_value}
32
+ order "descending"
33
+ orient "radial"
34
+
35
+ node.wedge do
36
+ fill_style {|d| colors.scale(d.parent_node)}
37
+ stroke_style("#fff")
38
+ line_width(0.5)
39
+ end
40
+
41
+ node_label.label do
42
+ visible {|d| d.angle * d.outer_radius >= 6}
43
+ end
44
+
45
+ end
46
+ end
47
+ vis.render
48
+
49
+
50
+ puts vis.to_svg
@@ -4,7 +4,7 @@
4
4
  $:.unshift(File.dirname(__FILE__)+"/../../lib")
5
5
  require 'rubyvis'
6
6
  load(File.dirname(__FILE__)+"/treemap_data.rb")
7
- color = pv.Colors.category19()
7
+ color = pv.Colors.category19
8
8
  nodes = pv.dom($flare).root("flare").nodes
9
9
 
10
10
 
data/lib/rubyvis.rb CHANGED
@@ -13,6 +13,8 @@ require 'rubyvis/javascript_behaviour'
13
13
  require 'rubyvis/format'
14
14
  require 'rubyvis/mark'
15
15
  require 'rubyvis/scale'
16
+ require 'rubyvis/histogram'
17
+
16
18
  require 'rubyvis/color/color'
17
19
  require 'rubyvis/color/colors'
18
20
 
@@ -21,12 +23,13 @@ require 'rubyvis/dom'
21
23
 
22
24
  require 'rubyvis/scene/svg_scene'
23
25
  require 'rubyvis/transform'
26
+ require 'rubyvis/mark/shorcut_methods'
24
27
 
25
28
 
26
29
  module Rubyvis
27
30
  @document=nil
28
31
  # Rubyvis version
29
- VERSION = '0.3.0'
32
+ VERSION = '0.3.1'
30
33
  # Protovis API on which current Rubyvis is based
31
34
  PROTOVIS_API_VERSION='3.3'
32
35
  # You actually can do it! http://snipplr.com/view/2137/uses-for-infinity-in-ruby/
data/lib/rubyvis/dom.rb CHANGED
@@ -100,7 +100,19 @@ module Rubyvis
100
100
  attr_accessor :y
101
101
  attr_accessor :size
102
102
 
103
+ attr_accessor :min_breadth
104
+ attr_accessor :max_breadth
105
+ attr_accessor :breadth
106
+ attr_accessor :min_depth
107
+ attr_accessor :max_depth
103
108
 
109
+ attr_accessor :mid_angle
110
+ attr_accessor :angle
111
+ attr_accessor :start_angle
112
+ attr_accessor :outer_radius
113
+ attr_accessor :inner_radius
114
+
115
+
104
116
  # Constructs a DOM node for the specified value. Instances of this class are
105
117
  # not typically created directly; instead they are generated from a JavaScript
106
118
  # map using the {@link pv.Dom} operator.
@@ -0,0 +1,44 @@
1
+ module Rubyvis
2
+ def self.histogram(data,f=nil)
3
+ Rubyvis::Histogram.new(data,f)
4
+ end
5
+ class Histogram
6
+ module Bin
7
+ attr_accessor :x, :dx, :y
8
+ end
9
+ attr_accessor :frequency
10
+ attr_reader :data
11
+ attr_reader :f
12
+ def initialize(data,f=nil)
13
+ @data=data
14
+ @f=f
15
+ @frequency=true
16
+ end
17
+ def bins(ticks=nil)
18
+ x=Rubyvis.map(data,f)
19
+ bins=[]
20
+ ticks||=Rubyvis::Scale.linear(x).ticks()
21
+ # Initialize the bins
22
+ (ticks.size-1).times {|i|
23
+ bin=bins[i]=[]
24
+ bin.extend Bin
25
+ bin.x=ticks[i]
26
+ bin.dx=ticks[i+1]-ticks[i]
27
+ bin.y=0
28
+ }
29
+ x.size.times {|i|
30
+ j=Rubyvis.search_index(ticks, x[i])-1
31
+ bin=bins[ [0,[bins.size-1,j].min].max]
32
+ bin.y+=1
33
+ bin.push(data[i])
34
+ }
35
+ if !@frequency
36
+ bins.each {|b|
37
+ b.y=b.y/x.size.to_f
38
+ }
39
+ end
40
+ bins
41
+ end
42
+
43
+ end
44
+ end
@@ -4,13 +4,13 @@ module Rubyvis
4
4
  end
5
5
  class Layout < Rubyvis::Panel
6
6
  @properties=Panel.properties.dup
7
- def build_properties(s,properties)
7
+ def build_properties(s,properties)
8
8
  layout_build_properties(s,properties)
9
9
  end
10
10
  def layout_build_properties(s,properties)
11
- mark_build_properties(s,properties)
11
+ mark_build_properties(s, properties)
12
12
  end
13
- def layout_build_implied(s)
13
+ def layout_build_implied(s)
14
14
  panel_build_implied(s)
15
15
  end
16
16
  def self.attr_accessor_dsl(*attr)
@@ -35,5 +35,5 @@ require 'rubyvis/layout/stack'
35
35
  require 'rubyvis/layout/network'
36
36
  require 'rubyvis/layout/hierarchy'
37
37
  require 'rubyvis/layout/treemap'
38
-
38
+ require 'rubyvis/layout/partition'
39
39
 
@@ -56,191 +56,188 @@ module Rubyvis
56
56
  :link_value=>1
57
57
  })}
58
58
  end
59
- def node_link
60
- NodeLink.new(self)
61
- end
62
- def fill
63
- Fill.new(self)
64
- end
59
+ #def node_link
60
+ # NodeLink.new(self)
61
+ #end
62
+ #def fill
63
+ # Fill.new(self)
64
+ #end
65
65
  end
66
66
 
67
- class NodeLink
68
- attr_accessor :ir, :_or, :orient, :w, :h
69
- def initialize(obj)
70
- @obj=obj
71
- end
72
- def build_implied(s)
67
+ module NodeLink
68
+ attr_accessor :_ir, :_or, :_orient, :_w, :_h
69
+ def node_link_build_implied(s)
73
70
  nodes = s.nodes
74
- orient= s.orient
75
- orient=~/^(top|bottom)$/
71
+ @_orient= s.orient
72
+ @_orient=~/^(top|bottom)$/
76
73
 
77
- horizontal = $1
78
- w = s.width
79
- h = s.height
74
+ horizontal = !$1.nil?
75
+ @_w = s.width
76
+ @_h = s.height
80
77
  # /* Compute default inner and outer radius. */
81
- if (orient == "radial")
82
- ir = s.inner_radius
83
- _or = s.outer_radius
84
- ir||=0
85
- _or||=[w,h].min / 2.0
78
+ if (@_orient == "radial")
79
+ @_ir = s.inner_radius
80
+ @_or = s.outer_radius
81
+ @_ir||=0
82
+ @_or||=[@_w,@_h].min / 2.0
86
83
  end
87
- nodes.length.times {|i|
88
- n = nodes[i]
89
- n.mid_angle = (orient == "radial") ? mid_angle(n) : (horizontal ? Math::PI / 2.0 : 0)
90
- n.x = x(n)
91
- n.y = y(n)
84
+ nodes.each_with_index{|n,i|
85
+ n.mid_angle = (@_orient == "radial") ? mid_angle(n) : (horizontal ? Math::PI / 2.0 : 0)
86
+ n.x = node_link_x(n)
87
+ n.y = node_link_y(n)
92
88
  n.mid_angle+=Math::PI if (n.first_child)
93
- }
89
+ }
90
+ false
94
91
  end
95
92
  def radius(n)
96
- n.parent_node ? (n.depth * (_or-ir)+ir) : 0
93
+ n.parent_node ? (n.depth * (@_or-@_ir)+@_ir) : 0
97
94
  end
98
- def min_angle(n)
95
+ def mid_angle(n)
99
96
  n.parent_node ? ((n.breadth - 0.25) * 2 * Math::PI ) : 0
100
97
  end
101
- def x(n)
102
- case orient
98
+ def node_link_x(n)
99
+ case @_orient
103
100
  when "left"
104
- n.depth*w
101
+ n.depth*@_w
105
102
  when "right"
106
- w-n.depth*w
103
+ @_w-n.depth*@_w
107
104
  when "top"
108
- n.breadth*w
105
+ n.breadth*@_w
109
106
  when "bottom"
110
- w-n.breath*w
107
+ @_w-n.breath*@_w
111
108
  when "radial"
112
- w/2.0+radius(n)*Math.cos(n.mid_angle)
109
+ @_w/2.0+radius(n)*Math.cos(n.mid_angle)
113
110
  end
114
111
  end
115
- def y(n)
116
- case orient
112
+ def node_link_y(n)
113
+ case @_orient
117
114
  when "left"
118
- n.breadth*h
115
+ n.breadth*@_h
119
116
  when "right"
120
- h-n.depth*h
117
+ @_h-n.depth*@_h
121
118
  when "top"
122
- n.depth*h
119
+ n.depth*@_h
123
120
  when "bottom"
124
- h-n.breath*h
121
+ @_h-n.breath*@_h
125
122
  when "radial"
126
- h / 2.0 + radius(n) * Math.sin(n.mid_angle)
123
+ @_h / 2.0 + radius(n) * Math.sin(n.mid_angle)
127
124
  end # end case
128
125
  end # end method
129
126
  end # end class
130
127
 
131
- class Fill
132
- attr_accessor :ir, :_or, :orient, :w, :h
133
- def initialize(obj)
134
- @obj=obj
135
- end
136
- def constructor
137
- self.node.
138
- stroke_style("#fff").
139
- fill_style("#ccc").
140
- width(lambda {|n| n.dx}).
141
- height(lambda {|n| n.dy}).
142
- inner_radius(lambda {|n| n.inner_radius}).
143
- outer_radius(lambda {|n| n.outer_radius}).
144
- start_angle(lambda {|n| n.start_angle}).
145
- angle(lambda {return n.angle})
146
- self.node_label.
147
- text_align("center").
148
- left(lambda {|n| n.x+ (n.dx / 2.0) })
149
- top(lambda {|n| n.y+(n.dy / 0.2)})
150
- # delete this.link
128
+ module Fill
129
+ attr_accessor :ir, :_or, :_orient, :_w, :_h
130
+ def fill_constructor
131
+ @node.stroke_style("#fff").
132
+ fill_style("#ccc").
133
+ width(lambda {|n| n.dx}).
134
+ height(lambda {|n| n.dy}).
135
+ inner_radius(lambda {|n| n.inner_radius}).
136
+ outer_radius(lambda {|n| n.outer_radius}).
137
+ start_angle(lambda {|n| n.start_angle}).
138
+ angle(lambda {|n| n.angle})
139
+
140
+ @node_label.
141
+ text_align("center").
142
+ left(lambda {|n| n.x+ (n.dx / 2.0) }).
143
+ top(lambda {|n| n.y+(n.dy / 2.0)})
144
+ @link=nil
145
+
151
146
  end
152
- def build_implied(s)
147
+
148
+ def fill_build_implied(s)
153
149
  nodes = s.nodes
154
- orient= s.orient
155
- orient=~/^(top|bottom)$/
156
- horizontal = $1
157
- w = s.width
158
- h = s.height
159
- depth = -nodes[0].min_depth
160
- if (orient == "radial")
161
- ir = s.inner_radius
162
- _or = s.outer_radius
163
- ir||=0
164
- depth = depth * 2 if ir!=0
165
- _or||=[w,h].min / 2.0
150
+ @_orient= s.orient
151
+ @_orient=~/^(top|bottom)$/
152
+ horizontal = !$1.nil?
153
+ @_w = s.width
154
+ @_h = s.height
155
+ @_depth = -nodes[0].min_depth
156
+ if (@_orient == "radial")
157
+ @_ir = s.inner_radius
158
+ @_or = s.outer_radius
159
+ @_ir||=0
160
+ @_depth = @_depth * 2 if @_ir!=0
161
+ @_or||=[@_w,@_h].min / 2.0
166
162
  end
167
163
  nodes.each_with_index {|n,i|
168
- n.x = x(n)
169
- n.y = y(n)
170
- if (orient == "radial")
164
+ n.x = fill_x(n)
165
+ n.y = fill_y(n)
166
+ if (@_orient == "radial")
171
167
  n.inner_radius = inner_radius(n);
172
168
  n.outer_radius = outer_radius(n);
173
169
  n.start_angle = start_angle(n);
174
170
  n.angle = angle(n);
175
- n.mid_Angle = n.start_angle + n.angle / 2.0;
171
+ n.mid_angle = n.start_angle + n.angle / 2.0
176
172
  else
177
- n.mid_angle = horizontal ? -Math::PI / 2.0 : 0;
173
+ n.mid_angle = horizontal ? -Math::PI / 2.0 : 0
178
174
  end
179
175
  n.dx = dx(n)
180
176
  n.dy = dy(n)
181
177
  }
178
+ false
182
179
  end
183
180
 
184
- def scale(d, depth)
181
+ def fill_scale(d, depth)
185
182
  (d+depth) / (1.0+depth)
186
183
  end
187
- def x(n)
188
- case orient
184
+ def fill_x(n)
185
+ case @_orient
189
186
  when "left"
190
- scale(n.min_depth,depth)*w
187
+ fill_scale(n.min_depth,@_depth)*@_w
191
188
  when "right"
192
- (1-scale(n.max_depth,depth))*w
189
+ (1-fill_scale(n.max_depth,@_depth))*@_w
193
190
  when "top"
194
- n.min_breadth*w
191
+ n.min_breadth*@_w
195
192
  when "bottom"
196
- (1-n.max_breath)*w
193
+ (1-n.max_breath)*@_w
197
194
  when "radial"
198
- w / 2.0
195
+ @_w / 2.0
199
196
  end
200
197
  end
201
- def y(n)
202
- case orient
198
+ def fill_y(n)
199
+ case @_orient
203
200
  when "left"
204
- n.min_breadth*h
201
+ n.min_breadth*@_h
205
202
  when "right"
206
- (1-n.max_breadth)*h
203
+ (1-n.max_breadth)*@_h
207
204
  when "top"
208
- scale(n.min_depth, depth) * h
205
+ fill_scale(n.min_depth, @_depth) * @_h
209
206
  when "bottom"
210
- (1-scale(n.max_depth, depth)) * h
207
+ (1-fill_scale(n.max_depth, @_depth)) * @_h
211
208
  when "radial"
212
- h / 2.0
209
+ @_h / 2.0
213
210
  end # end case
214
211
  end # end method
215
212
  def dx(n)
216
- if orient=='left' or orient=='right'
217
- (n.max_depth - n.min_depth) / (1.0 + depth) * w;
218
- elsif orient=='top' or orient=='bottom'
219
- (n.max_breadth - n.min_breadth) * w
220
- elsif orient=='radial'
213
+ if @_orient=='left' or @_orient=='right'
214
+ (n.max_depth - n.min_depth) / (1.0 + @_depth) * @_w
215
+ elsif @_orient=='top' or @_orient=='bottom'
216
+ (n.max_breadth - n.min_breadth) * @_w
217
+ elsif @_orient=='radial'
221
218
  n.parent_node ? (n.inner_radius + n.outer_radius) * Math.cos(n.mid_angle) : 0
222
219
  end
223
220
  end
224
221
  def dy(n)
225
- if orient=='left' or orient=='right'
226
- (n.max_breadth - n.min_breadth) * h;
227
- elsif orient=='top' or orient=='bottom'
228
- (n.max_depth - n.min_depth) / (1.0 + depth) * h;
222
+ if @_orient=='left' or @_orient=='right'
223
+ (n.max_breadth - n.min_breadth) * @_h
224
+ elsif @_orient=='top' or @_orient=='bottom'
225
+ (n.max_depth - n.min_depth) / (1.0 + @_depth) * @_h
229
226
  elsif orient=='radial'
230
227
  n.parent_node ? (n.inner_radius + n.outer_radius) * Math.sin(n.mid_angle) : 0
231
228
  end
232
229
  end
233
230
  def inner_radius(n)
234
- [0, scale(n.min_depth, depth/2.0)].max * (_or - _ir) + ir
231
+ [0, fill_scale(n.min_depth, @_depth/2.0)].max * (@_or - @_ir) + @_ir
235
232
  end
236
233
  def outer_radius(n)
237
- scale(n.max_depth, depth / 2.0) * (_or - ir) + ir
234
+ fill_scale(n.max_depth, @_depth / 2.0) * (@_or - @_ir) + @_ir
238
235
  end
239
236
  def start_angle(n)
240
237
  (n.parent_node ? n.min_breadth - 0.25 : 0) * 2 * Math::PI
241
238
  end
242
239
  def angle(n)
243
- (n.parent_node ? n.max_breadt - n.min_breadth : 1 ) * 2 * Math::PI
240
+ (n.parent_node ? n.max_breadth - n.min_breadth : 1 ) * 2 * Math::PI
244
241
  end
245
242
  end
246
243
  end
@@ -136,7 +136,8 @@ module Rubyvis
136
136
  # but it was replaced to not conflict with Mark.label()
137
137
  def _node_label
138
138
  that=self
139
- nl=Mark.new.mark_extend(@node).
139
+ nl=Mark.new().
140
+ mark_extend(@node).
140
141
  text_margin(7).
141
142
  text_baseline("middle").
142
143
  text(lambda {|n| n.node_name ? n.node_name : n.node_value }).
@@ -198,7 +199,7 @@ module Rubyvis
198
199
  end
199
200
  end
200
201
 
201
- def build_implied(s)
202
+ def build_implied(s)
202
203
  network_build_implied(s)
203
204
  end
204
205
  def network_build_implied(s)
@@ -0,0 +1,227 @@
1
+ module Rubyvis
2
+ class Layout
3
+ # Alias for Rubyvis::Layout::Partition
4
+ def self.Partition
5
+ Rubyvis::Layout::Partition
6
+ end
7
+ # Implemeents a hierarchical layout using the partition (or sunburst,
8
+ # icicle) algorithm. This layout provides both node-link and space-filling
9
+ # implementations of partition diagrams. In many ways it is similar to
10
+ # {@link pv.Layout.Cluster}, except that leaf nodes are positioned based on
11
+ # their distance from the root.
12
+ #
13
+ # <p>The partition layout support dynamic sizing for leaf nodes, if a
14
+ # {@link #size} psuedo-property is specified. The default size function returns
15
+ # 1, causing all leaf nodes to be sized equally, and all internal nodes to be
16
+ # sized by the number of leaf nodes they have as descendants.
17
+ #
18
+ # <p>The size function can be used in conjunction with the order property,
19
+ # which allows the nodes to the sorted by the computed size. Note: for sorting
20
+ # based on other data attributes, simply use the default <tt>null</tt> for the
21
+ # order property, and sort the nodes beforehand using the {@link pv.Dom}
22
+ # operator.
23
+ #
24
+ # <p>For more details on how to use this layout, see
25
+ # {@link pv.Layout.Hierarchy}.
26
+ #
27
+ # @see pv.Layout.Partition.Fill
28
+ # @extends pv.Layout.Hierarchy
29
+
30
+ class Partition < Hierarchy
31
+ include NodeLink
32
+ @properties=Hierarchy.properties.dup
33
+ # Constructs a new, empty partition layout. Layouts are not typically
34
+ # constructed directly; instead, they are added to an existing panel via
35
+ # {@link pv.Mark#add}.
36
+ #
37
+ def initialize
38
+ super
39
+ end
40
+
41
+ ##
42
+ # :attr: order
43
+ # The sibling node order. The default order is <tt>null</tt>, which means to
44
+ # use the sibling order specified by the nodes property as-is. A value of
45
+ # "ascending" will sort siblings in ascending order of size, while "descending"
46
+ # will do the reverse. For sorting based on data attributes other than size,
47
+ # use the default <tt>null</tt> for the order property, and sort the nodes
48
+ # beforehand using the {@link pv.Dom} operator.
49
+ #
50
+ # @see pv.Dom.Node#sort
51
+ # @type string
52
+
53
+ ##
54
+ # :attr: orient
55
+ # The orientation. The default orientation is "top", which means that the root
56
+ # node is placed on the top edge, leaf nodes appear at the bottom, and internal
57
+ # nodes are in-between. The following orientations are supported:<ul>
58
+ #
59
+ # <li>left - left-to-right.
60
+ # <li>right - right-to-left.
61
+ # <li>top - top-to-bottom.
62
+ # <li>bottom - bottom-to-top.
63
+ # <li>radial - radially, with the root at the center.</ul>
64
+ #
65
+ # @type string
66
+
67
+ ##
68
+ # :attr: inner_radius
69
+ #
70
+ # The inner radius; defaults to 0. This property applies only to radial
71
+ # orientations, and can be used to compress the layout radially. Note that for
72
+ # the node-link implementation, the root node is always at the center,
73
+ # regardless of the value of this property; this property only affects internal
74
+ # and leaf nodes. For the space-filling implementation, a non-zero value of
75
+ # this property will result in the root node represented as a ring rather than
76
+ # a circle.
77
+ #
78
+ # @type number
79
+
80
+ ##
81
+ # :attr: outer_radius
82
+ #
83
+ # The outer radius; defaults to fill the containing panel, based on the height
84
+ # and width of the layout. If the layout has no height and width specified, it
85
+ # will extend to fill the enclosing panel.
86
+ #
87
+ # @type number
88
+
89
+ attr_accessor_dsl :order, :orient , :inner_radius, :outer_radius
90
+
91
+ # Default properties for partition layouts. The default orientation is "top".
92
+ def self.defaults
93
+ Rubyvis::Layout::Partition.new.mark_extend(Rubyvis::Layout::Hierarchy.defaults).
94
+ orient("top")
95
+ end
96
+ def _size(f)
97
+ if @_size.nil?
98
+ 1
99
+ else
100
+ @_size.call(f)
101
+ end
102
+ end
103
+ # Specifies the sizing function. By default, a sizing function is disabled and
104
+ # all nodes are given constant size. The sizing function is invoked for each
105
+ # leaf node in the tree (passed to the constructor).
106
+ #
107
+ # <p>For example, if the tree data structure represents a file system, with
108
+ # files as leaf nodes, and each file has a <tt>bytes</tt> attribute, you can
109
+ # specify a size function as:
110
+ #
111
+ # <pre> .size(function(d) d.bytes)</pre>
112
+ #
113
+ # As with other properties, a size function may specify additional arguments to
114
+ # access the data associated with the layout and any enclosing panels.
115
+ #
116
+ # @param {function} f the new sizing function.
117
+ # @returns {pv.Layout.Partition} this.
118
+
119
+ def size(f=nil,&block)
120
+ f=block if f.nil?
121
+ raise "You should pass a proc" if f.nil?
122
+ @_size=f
123
+ self
124
+ end
125
+ def build_implied(s)
126
+ partition_build_implied(s)
127
+ end
128
+ def partition_build_implied(s)
129
+
130
+ return false if hierarchy_build_implied(s)
131
+ that = self
132
+ root = s.nodes[0]
133
+
134
+ stack = Rubyvis::Mark.stack
135
+ max_depth = 0
136
+
137
+ # Recursively compute the tree depth and node size. #/
138
+ stack.unshift(nil)
139
+ root.visit_after {|n,i|
140
+ max_depth=i if i>max_depth
141
+ if n.first_child
142
+ n.size = Rubyvis.sum(n.child_nodes, lambda {|v| v.size})
143
+ else
144
+ stack[0]=n
145
+ n.size=that._size(stack[0])
146
+ end
147
+ }
148
+
149
+ stack.shift
150
+ # # Order #/
151
+ case s.order
152
+ when 'ascending'
153
+ root.sort(lambda {|a,b| a.size<=>b.size})
154
+ when 'descending'
155
+ root.sort(lambda {|a,b| b.size<=>a.size})
156
+ end
157
+ # Compute the unit breadth and depth of each node. #/
158
+ ds = 1 / max_depth.to_f
159
+ root.min_breadth = 0;
160
+ root.breadth = 0.5
161
+ root.max_breadth = 1
162
+ root.visit_before {|n,i|
163
+ b = n.min_breadth
164
+ ss = n.max_breadth - b
165
+ c = n.first_child
166
+ while(c) do
167
+ c.min_breadth=b
168
+ b+=(c.size/n.size.to_f)*ss
169
+
170
+ c.max_breadth=b
171
+ c.breadth=(b+c.min_breadth) / 2.0
172
+ c=c.next_sibling
173
+
174
+ end
175
+ }
176
+ root.visit_after {|n,i|
177
+ n.min_depth=(i-1)*ds
178
+ n.max_depth=n.depth=i*ds
179
+ }
180
+
181
+ node_link_build_implied(s)
182
+ false
183
+ end
184
+
185
+ # A variant of partition layout that is space-filling. The meaning of
186
+ # the exported mark prototypes changes slightly in the space-filling
187
+ # implementation:<ul>
188
+ #
189
+ # <li><tt>node</tt> - for rendering nodes; typically a {@link pv.Bar} for
190
+ # non-radial orientations, and a {@link pv.Wedge} for radial orientations.
191
+ #
192
+ # <p><li><tt>link</tt> - unsupported; undefined. Links are encoded implicitly
193
+ # in the arrangement of the space-filling nodes.
194
+ #
195
+ # <p><li><tt>label</tt> - for rendering node labels; typically a
196
+ # {@link pv.Label}.
197
+ #
198
+ # </ul>For more details on how to use this layout, see
199
+ # {@link pv.Layout.Partition}.
200
+ #
201
+ # @extends pv.Layout.Partition
202
+
203
+
204
+ class Fill < Partition
205
+ include Hierarchy::Fill
206
+ @properties=Partition.properties.dup
207
+
208
+ # Constructs a new, empty space-filling partition layout. Layouts are not
209
+ # typically constructed directly; instead, they are added to an existing panel
210
+ # via {@link pv.Mark#add}.
211
+ def initialize
212
+ super
213
+ fill_constructor
214
+ end
215
+ def build_implied(s)
216
+ return nil if partition_build_implied(s)
217
+ fill_build_implied(s)
218
+ end
219
+
220
+ def self.defaults
221
+ Rubyvis::Layout::Partition::Fill.new.mark_extend(Rubyvis::Layout::Partition.defaults)
222
+ end
223
+
224
+ end
225
+ end
226
+ end
227
+ end
@@ -37,6 +37,7 @@ module Rubyvis
37
37
  def initialize
38
38
  super
39
39
  @size=lambda {|d| d.node_value.to_f}
40
+
40
41
  @node.stroke_style("#fff").
41
42
  fill_style("rgba(31, 119, 180, .25)").
42
43
  width(lambda {|n| n.dx}).
@@ -48,7 +49,6 @@ module Rubyvis
48
49
  top(lambda {|n| n.y + (n.dy / 2.0) }).
49
50
  text_align("center").
50
51
  text_angle(lambda {|n| n.dx > n.dy ? 0 : -Math::PI / 2.0 })
51
-
52
52
  end
53
53
 
54
54
  def leaf
data/lib/rubyvis/mark.rb CHANGED
@@ -979,7 +979,6 @@ module Rubyvis
979
979
  def build
980
980
  scene=self.scene
981
981
  stack=Mark.stack
982
-
983
982
  if(!scene)
984
983
  self.scene=SceneElement.new
985
984
  scene=self.scene
@@ -1046,7 +1045,7 @@ module Rubyvis
1046
1045
  end
1047
1046
 
1048
1047
  def mark_build_properties(ss, props) # :nodoc:
1049
- #p props
1048
+ #p "#{type}:"+props.map {|prop| prop.name}.join(",")
1050
1049
  props.each do |prop|
1051
1050
  v=prop.value
1052
1051
 
@@ -1057,6 +1056,7 @@ module Rubyvis
1057
1056
  ss.send((prop.name.to_s+"=").to_sym, v)
1058
1057
  end
1059
1058
  end
1059
+
1060
1060
  # @todo implement
1061
1061
  def event(type,handler) # :nodoc:
1062
1062
  #@_handlers[type]=handler
@@ -1075,5 +1075,4 @@ require 'rubyvis/mark/rule'
1075
1075
  require 'rubyvis/mark/label'
1076
1076
  require 'rubyvis/mark/dot'
1077
1077
  require 'rubyvis/mark/wedge'
1078
- require 'rubyvis/mark/shorcut_methods'
1079
1078
 
@@ -4,7 +4,7 @@ class Rubyvis::Mark
4
4
  ##
5
5
 
6
6
  # Create
7
- def self.mark_method(name,mark) #:nodoc:
7
+ def self.mark_method(name, mark) #:nodoc:
8
8
  define_method(name) do |*args,&block|
9
9
  opts=args[0]
10
10
  opts||=Hash.new
@@ -126,7 +126,7 @@ class Rubyvis::Mark
126
126
  # Paramenter references new mark
127
127
  #
128
128
  # See Mark for examples of use
129
- #
129
+
130
130
  mark_method :rule, Rubyvis::Rule
131
131
  ##
132
132
  # :method: wedge(opts,&block)
@@ -141,6 +141,62 @@ class Rubyvis::Mark
141
141
  #
142
142
  # See Mark for examples of use
143
143
 
144
- #
145
- mark_method :wedge, Rubyvis::Rule
144
+ mark_method :wedge, Rubyvis::Wedge
145
+ ##
146
+ # :method: layout_stack(opts,&block)
147
+ #
148
+ # Adds a Layout::Stack to current mark.
149
+ #
150
+ # If a block is provided, the context will be defined differently if
151
+ # parameter is provided
152
+ # * Without parameter: block executed inside context of new mark
153
+ # * With paramenter: block executed inside context of current mark.
154
+ # Paramenter references new mark
155
+ #
156
+ # See Mark for examples of use
157
+ mark_method :layout_stack, Rubyvis::Layout::Stack
158
+
159
+ ##
160
+ # :method: layout_partition(opts,&block)
161
+ #
162
+ # Adds a Layout::Partition to current mark.
163
+ #
164
+ # If a block is provided, the context will be defined differently if
165
+ # parameter is provided
166
+ # * Without parameter: block executed inside context of new mark
167
+ # * With paramenter: block executed inside context of current mark.
168
+ # Paramenter references new mark
169
+ #
170
+ # See Mark for examples of use
171
+ mark_method :layout_partition, Rubyvis::Layout::Partition
172
+
173
+ ##
174
+ # :method: layout_partition_fill(opts,&block)
175
+ #
176
+ # Adds a Layout::Partition::Fill to current mark.
177
+ #
178
+ # If a block is provided, the context will be defined differently if
179
+ # parameter is provided
180
+ # * Without parameter: block executed inside context of new mark
181
+ # * With paramenter: block executed inside context of current mark.
182
+ # Paramenter references new mark
183
+ #
184
+ # See Mark for examples of use
185
+ mark_method :layout_partition_fill, Rubyvis::Layout::Partition::Fill
186
+
187
+ ##
188
+ # :method: layout_treemap(opts,&block)
189
+ #
190
+ # Adds a Layout::Treemap to current mark.
191
+ #
192
+ # If a block is provided, the context will be defined differently if
193
+ # parameter is provided
194
+ # * Without parameter: block executed inside context of new mark
195
+ # * With paramenter: block executed inside context of current mark.
196
+ # Paramenter references new mark
197
+ #
198
+ # See Mark for examples of use
199
+ mark_method :layout_treemap, Rubyvis::Layout::Treemap
200
+
201
+
146
202
  end
@@ -110,13 +110,18 @@ module Rubyvis
110
110
 
111
111
  end
112
112
 
113
-
114
- def upright(angle)
113
+ def self.upright(angle)
115
114
  angle=angle % (2*Math::PI)
116
115
  angle=(angle<0) ? (2*Math::PI+angle) : angle
117
- (angle < Math::PI/2.0) or (angle>=3*Math::PI / 2.0)
116
+ (angle < Math::PI/2.0) or (angle>=3*Math::PI / 2.0)
118
117
 
119
118
  end
119
+ def upright(angle)
120
+ angle=angle % (2*Math::PI)
121
+ angle=(angle<0) ? (2*Math::PI+angle) : angle
122
+ (angle < Math::PI/2.0) or (angle>=3*Math::PI / 2.0)
123
+ end
124
+
120
125
  def build_implied(s)
121
126
 
122
127
  if s.angle.nil?
@@ -0,0 +1,28 @@
1
+ require File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb")
2
+ describe Rubyvis::Histogram do
3
+ describe "bins" do
4
+ before do
5
+ data = Rubyvis.range(0, 10, 0.1).map {|x|
6
+ Math.sin(x)
7
+ }
8
+ @hist=Rubyvis::Histogram.new(data)
9
+ @bins=@hist.bins
10
+ end
11
+ it "size should be correct" do
12
+ @bins.size.should eq 8
13
+ end
14
+ it "bin.x should be correct" do
15
+ @bins.map {|b| b.x}.should eq [-0.8, -0.6, -0.4, -0.2, 0, 0.2,0.4, 0.6]
16
+ end
17
+ it "bin.dx should be correct" do
18
+ @bins.map {|b| b.dx}.should eq [0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2]
19
+ end
20
+ it "bin.y should be correct" do
21
+ @bins.map {|b| b.y}.should eq [19,5,6,7,8,8,11,36]
22
+ end
23
+ it "bin.y should be correct using frequency=false" do
24
+ @hist.frequency=false
25
+ @hist.bins.map {|b| b.y}.should eq [0.19,0.05,0.06,0.07,0.08,0.08,0.11,0.36]
26
+ end
27
+ end
28
+ end
data/web/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
1
  # -*- ruby -*-
2
2
  require 'rake'
3
-
3
+ require 'fileutils'
4
4
  directory "examples"
5
5
 
6
6
  def get_base(f)
@@ -17,6 +17,19 @@ task :build_site do
17
17
  ruby "build_site.rb"
18
18
  end
19
19
 
20
+
21
+ task :clean do
22
+ Dir.glob(File.dirname(__FILE__)+"/examples/*.svg").each do |t|
23
+ FileUtils.rm t
24
+ end
25
+ Dir.glob(File.dirname(__FILE__)+"/examples/*.html").each do |t|
26
+ FileUtils.rm t
27
+ end
28
+ Dir.glob(File.dirname(__FILE__)+"/examples/*.png").each do |t|
29
+ FileUtils.rm t
30
+ end
31
+
32
+ end
20
33
  task :default=>["examples", "index.html", "../lib/rubyvis.rb"]+EXAMPLES_BASE.map {|v| "examples/#{v}.html"}
21
34
 
22
35
  file "index.html"=>["index.haml", :build_site]+EXAMPLES_BASE.map {|v| "examples/#{v}.png"}
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubyvis
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 0
10
- version: 0.3.0
9
+ - 1
10
+ version: 0.3.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Claudio Bustos
@@ -36,7 +36,7 @@ cert_chain:
36
36
  rpP0jjs0
37
37
  -----END CERTIFICATE-----
38
38
 
39
- date: 2010-11-17 00:00:00 -03:00
39
+ date: 2010-11-19 00:00:00 -03:00
40
40
  default_executable:
41
41
  dependencies:
42
42
  - !ruby/object:Gem::Dependency
@@ -162,6 +162,7 @@ files:
162
162
  - examples/first_rbp_api.rb
163
163
  - examples/fixtures/tipsy.gif
164
164
  - examples/grouped_charts.rb
165
+ - examples/icicle.rb
165
166
  - examples/image.rb
166
167
  - examples/line.rb
167
168
  - examples/line_and_step.rb
@@ -171,6 +172,7 @@ files:
171
172
  - examples/scatterplot.rb
172
173
  - examples/second.rb
173
174
  - examples/stacked_charts.rb
175
+ - examples/sunburst.rb
174
176
  - examples/third.rb
175
177
  - examples/treemap/treemap.rb
176
178
  - examples/treemap/treemap_data.rb
@@ -181,11 +183,13 @@ files:
181
183
  - lib/rubyvis/format.rb
182
184
  - lib/rubyvis/format/date.rb
183
185
  - lib/rubyvis/format/number.rb
186
+ - lib/rubyvis/histogram.rb
184
187
  - lib/rubyvis/internals.rb
185
188
  - lib/rubyvis/javascript_behaviour.rb
186
189
  - lib/rubyvis/layout.rb
187
190
  - lib/rubyvis/layout/hierarchy.rb
188
191
  - lib/rubyvis/layout/network.rb
192
+ - lib/rubyvis/layout/partition.rb
189
193
  - lib/rubyvis/layout/stack.rb
190
194
  - lib/rubyvis/layout/treemap.rb
191
195
  - lib/rubyvis/mark.rb
@@ -224,6 +228,7 @@ files:
224
228
  - spec/area_spec.rb
225
229
  - spec/bar_spec.rb
226
230
  - spec/dom_spec.rb
231
+ - spec/histogram_spec.rb
227
232
  - spec/internal_spec.rb
228
233
  - spec/javascript_behaviour_spec.rb
229
234
  - spec/label_spec.rb
metadata.gz.sig CHANGED
Binary file