rubyvis 0.3.3 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data.tar.gz.sig +0 -0
  2. data/History.txt +8 -0
  3. data/Manifest.txt +45 -36
  4. data/examples/{first_rbp_api.rb → 1_basic/1a_bar_rbp_api.rb} +1 -1
  5. data/examples/{first_protovis_api.rb → 1_basic/1b_bar_pv_api.rb} +1 -1
  6. data/examples/{second.rb → 1_basic/2_bar_and_rule.rb} +2 -2
  7. data/examples/{third.rb → 1_basic/3_grouped_bars.rb} +1 -1
  8. data/examples/{area_interpolation.rb → 1_basic/area_interpolation.rb} +1 -1
  9. data/examples/{dot.rb → 1_basic/dot.rb} +1 -1
  10. data/examples/{fixtures → 1_basic/fixtures}/tipsy.gif +0 -0
  11. data/examples/1_basic/grid.rb +29 -0
  12. data/examples/{image.rb → 1_basic/image.rb} +1 -1
  13. data/examples/{line.rb → 1_basic/line.rb} +1 -1
  14. data/examples/{line_interpolation.rb → 1_basic/line_interpolation.rb} +1 -1
  15. data/examples/2_medium/censo_agropecuario/censo_agropecuario_chile_data.rb +53 -0
  16. data/examples/2_medium/censo_agropecuario/census_treemap.rb +63 -0
  17. data/examples/2_medium/censo_agropecuario/create_data.rb +10 -0
  18. data/examples/2_medium/censo_agropecuario/resultset.csv +51 -0
  19. data/examples/{nested_grid.rb → 2_medium/nested_grid.rb} +3 -4
  20. data/examples/{area.rb → 3_pv_conventional/area.rb} +1 -1
  21. data/examples/{bar_column_chart.rb → 3_pv_conventional/bar_column_chart.rb} +1 -1
  22. data/examples/{grouped_charts.rb → 3_pv_conventional/grouped_charts.rb} +1 -1
  23. data/examples/{line_and_step.rb → 3_pv_conventional/line_and_step.rb} +1 -1
  24. data/examples/{pie_and_donut.rb → 3_pv_conventional/pie_and_donut.rb} +1 -1
  25. data/examples/{scatterplot.rb → 3_pv_conventional/scatterplot.rb} +1 -1
  26. data/examples/{stacked_charts.rb → 3_pv_conventional/stacked_charts.rb} +1 -3
  27. data/examples/{antibiotics → 4_pv_custom/antibiotics}/antibiotics_data.rb +0 -0
  28. data/examples/{antibiotics → 4_pv_custom/antibiotics}/antibiotics_scatter.rb +1 -1
  29. data/examples/{antibiotics → 4_pv_custom/antibiotics}/antibiotics_wedge.rb +1 -1
  30. data/examples/{barley → 4_pv_custom/barley}/barley.rb +5 -1
  31. data/examples/{barley → 4_pv_custom/barley}/barley_data.rb +0 -0
  32. data/examples/{cars → 4_pv_custom/cars}/cars.rb +1 -1
  33. data/examples/{cars → 4_pv_custom/cars}/cars_data.rb +0 -0
  34. data/examples/{crimea → 4_pv_custom/crimea}/crimea_data.rb +0 -0
  35. data/examples/{crimea → 4_pv_custom/crimea}/crimea_grouped_bar.rb +1 -1
  36. data/examples/{crimea → 4_pv_custom/crimea}/crimea_line.rb +1 -1
  37. data/examples/{bubble_charts.rb → 5_pv_hierarchies/bubble_charts.rb} +3 -2
  38. data/examples/5_pv_hierarchies/bubble_charts_matrix.rb +64 -0
  39. data/examples/{circle_packing.rb → 5_pv_hierarchies/circle_packing.rb} +4 -4
  40. data/examples/{dendogram.rb → 5_pv_hierarchies/dendogram.rb} +2 -2
  41. data/examples/{icicle.rb → 5_pv_hierarchies/icicle.rb} +2 -2
  42. data/examples/{indent.rb → 5_pv_hierarchies/indent.rb} +2 -2
  43. data/examples/5_pv_hierarchies/node_link_tree.rb +52 -0
  44. data/examples/{sunburst.rb → 5_pv_hierarchies/sunburst.rb} +2 -2
  45. data/examples/5_pv_hierarchies/treemap.rb +48 -0
  46. data/lib/rubyvis.rb +1 -1
  47. data/lib/rubyvis/dom.rb +16 -1
  48. data/lib/rubyvis/internals.rb +2 -2
  49. data/lib/rubyvis/layout.rb +2 -0
  50. data/lib/rubyvis/layout/grid.rb +105 -0
  51. data/lib/rubyvis/layout/pack.rb +53 -54
  52. data/lib/rubyvis/layout/stack.rb +26 -24
  53. data/lib/rubyvis/layout/tree.rb +267 -0
  54. data/lib/rubyvis/layout/treemap.rb +1 -0
  55. data/lib/rubyvis/mark.rb +10 -8
  56. data/lib/rubyvis/mark/area.rb +6 -6
  57. data/lib/rubyvis/mark/dot.rb +1 -1
  58. data/lib/rubyvis/mark/shorcut_methods.rb +29 -2
  59. data/lib/rubyvis/nest.rb +48 -2
  60. data/lib/rubyvis/scale/ordinal.rb +6 -6
  61. data/lib/rubyvis/scale/quantitative.rb +13 -7
  62. data/lib/rubyvis/scene/svg_area.rb +20 -14
  63. data/lib/rubyvis/scene/svg_bar.rb +1 -1
  64. data/lib/rubyvis/scene/svg_scene.rb +0 -1
  65. data/lib/rubyvis/sceneelement.rb +1 -1
  66. data/spec/area_spec.rb +12 -0
  67. data/spec/dom_spec.rb +15 -8
  68. data/spec/layout_stack_spec.rb +70 -0
  69. data/spec/nest_spec.rb +8 -2
  70. data/spec/scale_linear_spec.rb +7 -1
  71. data/spec/scale_ordinal_spec.rb +4 -0
  72. data/spec/spec_helper.rb +1 -1
  73. data/web/build_site.rb +6 -2
  74. data/web/index.haml +2 -2
  75. metadata +61 -68
  76. metadata.gz.sig +0 -0
  77. data/examples/treemap/treemap.rb +0 -29
  78. data/examples/treemap/treemap_data.rb +0 -285
@@ -0,0 +1,267 @@
1
+ module Rubyvis
2
+ class Layout
3
+ # Alias for Rubyvis::Layout::Tree
4
+ def self.Tree
5
+ Rubyvis::Layout::Tree
6
+ end
7
+ # Implements a node-link tree diagram using the Reingold-Tilford "tidy"
8
+ # tree layout algorithm. The specific algorithm used by this layout is based on
9
+ # <a href="http://citeseer.ist.psu.edu/buchheim02improving.html">"Improving
10
+ # Walker's Algorithm to Run in Linear Time"</A> by C. Buchheim, M. J&uuml;nger
11
+ # &amp; S. Leipert, Graph Drawing 2002. This layout supports both cartesian and
12
+ # radial orientations orientations for node-link diagrams.
13
+ #
14
+ # <p>The tree layout supports a "group" property, which if true causes siblings
15
+ # to be positioned closer together than unrelated nodes at the same depth. The
16
+ # layout can be configured using the <tt>depth</tt> and <tt>breadth</tt>
17
+ # properties, which control the increments in pixel space between nodes in both
18
+ # dimensions, similar to the indent layout.
19
+ #
20
+ # <p>For more details on how to use this layout, see
21
+ # {@link pv.Layout.Hierarchy}
22
+ class Tree < Hierarchy
23
+ @properties=Hierarchy.properties.dup
24
+ def initialize
25
+ super
26
+ end
27
+
28
+ ##
29
+ # :attr: breadth
30
+ # The offset between siblings nodes; defaults to 15.
31
+
32
+ ##
33
+ # :attr: depth
34
+ # The offset between parent and child nodes; defaults to 60.
35
+ #
36
+
37
+ ##
38
+ # :attr: orient
39
+ # The orientation. The default orientation is "top", which means that the root
40
+ # node is placed on the top edge, leaf nodes appear at the bottom, and internal
41
+ # nodes are in-between. The following orientations are supported:<ul>
42
+ #
43
+ # <li>left - left-to-right.
44
+ # <li>right - right-to-left.
45
+ # <li>top - top-to-bottom.
46
+ # <li>bottom - bottom-to-top.
47
+ # <li>radial - radially, with the root at the center.</ul>
48
+ #
49
+
50
+ ##
51
+ # :group:
52
+ # The sibling grouping, i.e., whether differentiating space is placed between
53
+ # sibling groups. The default is 1 (or true), causing sibling leaves to be
54
+ # separated by one breadth offset. Setting this to false (or 0) causes
55
+ # non-siblings to be adjacent.
56
+
57
+ attr_accessor_dsl :group, :breadth, :depth, :orient
58
+
59
+ # Default properties for tree layouts. The default orientation is "top",
60
+ # the default group parameter is 1, and the default breadth and depth
61
+ # offsets are 15 and 60 respectively.
62
+ def self.defaults
63
+ Rubyvis::Layout::Tree.new.mark_extend(Rubyvis::Layout::Hierarchy.defaults).
64
+ group(1).
65
+ breadth(15).
66
+ depth(60).
67
+ orient("top")
68
+ end
69
+
70
+ def first_walk(v)
71
+ l,r,a=nil,nil,nil
72
+ if (!v.first_child)
73
+ l= v.previous_sibling
74
+ v.prelim = l.prelim + distance(v.depth, true) if l
75
+ else
76
+ l = v.first_child
77
+ r = v.last_child
78
+ a = l # default ancestor
79
+ v.each_child {|c|
80
+ first_walk(c)
81
+ a = apportion(c, a)
82
+ }
83
+ execute_shifts(v)
84
+ midpoint = 0.5 * (l.prelim + r.prelim)
85
+ l = v.previous_sibling
86
+ if l
87
+ v.prelim = l.prelim + distance(v.depth, true)
88
+ v.mod = v.prelim - midpoint
89
+ else
90
+ v.prelim = midpoint
91
+ end
92
+ end
93
+ end
94
+ def second_walk(v,m,depth)
95
+ v.breadth = v.prelim + m
96
+ m += v.mod
97
+ v.each_child {|c|
98
+ second_walk(c, m, depth)
99
+ }
100
+ end
101
+ def apportion(v,a)
102
+ w = v.previous_sibling
103
+ if w
104
+ vip = v
105
+ vop = v
106
+ vim = w
107
+ vom = v.parent_node.first_child
108
+ sip = vip.mod
109
+ sop = vop.mod
110
+ sim = vim.mod
111
+ som = vom.mod
112
+ nr = next_right(vim)
113
+ nl = next_left(vip)
114
+ while (nr and nl) do
115
+ vim = nr
116
+ vip = nl
117
+ vom = next_left(vom)
118
+ vop = next_right(vop)
119
+ vop.ancestor = v
120
+ shift = (vim.prelim + sim) - (vip.prelim + sip) + distance(vim.depth, false)
121
+ if (shift > 0)
122
+ move_subtree(ancestor(vim, v, a), v, shift)
123
+ sip += shift
124
+ sop += shift
125
+ end
126
+ sim += vim.mod
127
+ sip += vip.mod
128
+ som += vom.mod
129
+ sop += vop.mod
130
+ nr = next_right(vim)
131
+ nl = next_left(vip)
132
+ end
133
+
134
+ if (nr and !next_right(vop))
135
+ vop.thread = nr
136
+ vop.mod += sim - sop
137
+ end
138
+ if (nl and !next_left(vom))
139
+ vom.thread = nl
140
+ vom.mod += sip - som
141
+ a = v
142
+ end
143
+ end
144
+ a
145
+ end
146
+
147
+ def next_left(v)
148
+ v.first_child ? v.first_child : v.thread
149
+ end
150
+ def next_right(v)
151
+ v.last_child ? v.last_child : v.thread
152
+ end
153
+
154
+ def move_subtree(wm, wp, shift)
155
+ subtrees = wp.number - wm.number
156
+ wp.change -= shift / subtrees.to_f
157
+ wp.shift += shift
158
+ wm.change += shift / subtrees.to_f
159
+ wp.prelim += shift
160
+ wp.mod += shift
161
+ end
162
+
163
+ def execute_shifts(v)
164
+ shift = 0
165
+ change = 0
166
+ c=v.last_child
167
+ while c
168
+ c.prelim += shift
169
+ c.mod += shift
170
+ change += c.change
171
+ shift += c.shift + change
172
+ c = c.previous_sibling
173
+ end
174
+ end
175
+ def ancestor(vim, v, a)
176
+ (vim.ancestor.parent_node == v.parent_node) ? vim.ancestor : a
177
+ end
178
+
179
+ def distance(depth, siblings)
180
+ (siblings ? 1 : (@_group + 1)).to_f / ((@_orient == "radial") ? depth : 1)
181
+ end
182
+
183
+
184
+ def mid_angle(n)
185
+ (@_orient == "radial") ? n.breadth.to_f / depth : 0;
186
+ end
187
+
188
+ #/** @private */
189
+ def x(n)
190
+ case @_orient
191
+ when "left"
192
+ n.depth;
193
+ when "right"
194
+ @_w - n.depth;
195
+ when "top"
196
+ n.breadth + @_w / 2.0
197
+ when "bottom"
198
+ n.breadth + @_w / 2.0
199
+ when "radial"
200
+ @_w / 2.0 + n.depth * Math.cos(mid_angle(n))
201
+ end
202
+ end
203
+
204
+ #/** @private */
205
+ def y(n)
206
+ case @_orient
207
+ when "left"
208
+ n.breadth + @_h / 2.0
209
+ when "right"
210
+ n.breadth + @_h / 2.0
211
+ when "top"
212
+ n.depth;
213
+ when "bottom"
214
+ @_h - n.depth
215
+ when "radial"
216
+ @_h / 2.0 + n.depth * Math.sin(mid_angle(n))
217
+ end
218
+ end
219
+
220
+
221
+
222
+ def build_implied(s)
223
+ return nil if hierarchy_build_implied(s)
224
+ @_nodes = s.nodes
225
+ @_orient = s.orient
226
+ @_depth = s.depth
227
+ @_breadth = s.breadth
228
+ @_group = s.group
229
+ @_w = s.width
230
+ @_h = s.height
231
+ root=@_nodes[0]
232
+ root.visit_after {|v,i|
233
+ v.ancestor = v
234
+ v.prelim = 0
235
+ v.mod = 0
236
+ v.change = 0
237
+ v.shift = 0
238
+ v.number = v.previous_sibling ? (v.previous_sibling.number + 1) : 0
239
+ v.depth = i
240
+ }
241
+ #/* Compute the layout using Buchheim et al.'s algorithm. */
242
+ first_walk(root)
243
+ second_walk(root, -root.prelim, 0)
244
+
245
+ root.visit_after {|v,i|
246
+ v.breadth *= breadth
247
+ v.depth *= depth
248
+ v.mid_angle = mid_angle(v)
249
+ v.x = x(v)
250
+ v.y = y(v)
251
+ v.mid_angle += Math::PI if (v.first_child)
252
+ v.breadth=nil
253
+ v.depth=nil
254
+ v.ancestor=nil
255
+ v.prelim=nil
256
+ v.mod=nil
257
+ v.change=nil
258
+ v.shift=nil
259
+ v.number=nil
260
+ v.thread=nil
261
+ }
262
+
263
+
264
+ end
265
+ end
266
+ end
267
+ end
@@ -174,6 +174,7 @@ module Rubyvis
174
174
 
175
175
  def size(f)
176
176
  @size=Rubyvis.functor(f)
177
+ self
177
178
  end
178
179
 
179
180
 
@@ -699,7 +699,11 @@ module Rubyvis
699
699
  width=self.parent ? self.parent.width() : (w+(l.nil? ? 0 : l)+(r.nil? ? 0 : r))
700
700
  #puts (self.parent)? "parent width: #{self.parent.width}" : "no parent" if $DEBUG
701
701
  #p prop.sort if $DEBUG
702
- puts "build implied #{type}: l:#{l},r:#{r},t:#{t},b:#{b}, w:#{prop[:width]} #{w},h: #{prop[:height]} #{h}, width:#{width}" if $DEBUG
702
+
703
+ height=self.parent ? self.parent.height(): (h+(t.nil? ? 0 : t )+(b.nil? ? 0 : b))
704
+
705
+ puts "build implied #{type}: l:#{l},r:#{r},t:#{t},b:#{b}, w:#{prop[:width]} #{w},h: #{prop[:height]} #{h}, width:#{width}, height:#{height}" if $DEBUG
706
+
703
707
  if w.nil?
704
708
  r||=0
705
709
  l||=0
@@ -715,7 +719,7 @@ module Rubyvis
715
719
  l=width-w-r
716
720
  end
717
721
 
718
- height=self.parent ? self.parent.height(): (h+(t.nil? ? 0 : t )+(b.nil? ? 0 : b))
722
+
719
723
 
720
724
  if h.nil?
721
725
  t||=0
@@ -739,11 +743,9 @@ module Rubyvis
739
743
  s.top=t
740
744
  s.bottom=b
741
745
 
742
- puts "Post->left: #{l},right:#{r},top:#{t},bottom:#{b}, width:#{w}, height:#{h}" if $DEBUG
743
-
744
- s.width=w if prop[:width]
745
- #puts "width:#{s.width}" if $DEBUG
746
- s.height=h if prop[:height]
746
+ puts "Post->left: #{l},right:#{r},top:#{t},bottom:#{b}, width:#{w}, height:#{h}\n\n" if $DEBUG
747
+ s.width = w if prop[:width]
748
+ s.height = h if prop[:height]
747
749
  s.text_style=Rubyvis::Color.transparent if prop[:text_style] and !s.text_style
748
750
  s.fill_style=Rubyvis::Color.transparent if prop[:fill_style] and !s.fill_style
749
751
  s.stroke_style=Rubyvis::Color.transparent if prop[:stroke_style] and !s.stroke_style
@@ -874,7 +876,7 @@ module Rubyvis
874
876
  @types[2].push(@seen[name])
875
877
  end
876
878
  }
877
- end while(mark=mark.proto)
879
+ end while(mark = mark.proto)
878
880
  @binds=OpenStruct.new({:properties=>@seen, :data=>@_data, :required=>@_required, :optional=>@types[1]+@types[2]+@types[3]
879
881
  })
880
882
  end
@@ -55,9 +55,9 @@ module Rubyvis
55
55
  # p binds.fixed
56
56
  #/* Evaluate all properties on the first instance. */
57
57
  else
58
- binds.required = binds._required;
59
- binds.optional = binds._optional;
60
- binds.fixed = nil;
58
+ binds.required = binds._required
59
+ binds.optional = binds._optional
60
+ binds.fixed = nil
61
61
  end
62
62
  # pp binds
63
63
  mark_build_instance(s)
@@ -66,7 +66,7 @@ module Rubyvis
66
66
 
67
67
 
68
68
  def area_bind
69
- mark_bind()
69
+ mark_bind
70
70
  binds = self.binds
71
71
 
72
72
  required = binds.required
@@ -80,8 +80,8 @@ module Rubyvis
80
80
  }
81
81
  optional.delete_if {|v| v.name=='segmented'}
82
82
  # Cache the original arrays so they can be restored on build. */
83
- @binds._required = required;
84
- @binds._optional = optional;
83
+ @binds._required = required
84
+ @binds._optional = optional
85
85
  end
86
86
 
87
87
 
@@ -21,7 +21,7 @@ module Rubyvis
21
21
  # :attr: shape_size
22
22
  # The size of the shape, in square pixels. Square pixels are used such that the
23
23
  # area of the shape is linearly proportional to the value of the
24
- # <tt>shapeSize</tt> property, facilitating representative encodings. This is
24
+ # <tt>shape_size</tt> property, facilitating representative encodings. This is
25
25
  # an alternative to using shape_radius
26
26
  #
27
27
 
@@ -1,9 +1,9 @@
1
1
  class Rubyvis::Mark
2
2
  ##
3
- # :section: Ruby API
3
+ # :section: RBP Api
4
4
  ##
5
5
 
6
- # Create
6
+ # Create a new Mark method shorcut.
7
7
  def self.mark_method(name, mark) #:nodoc:
8
8
  define_method(name) do |*args,&block|
9
9
  opts=args[0]
@@ -240,5 +240,32 @@ class Rubyvis::Mark
240
240
  # See Mark for examples of use
241
241
  mark_method :layout_pack, Rubyvis::Layout::Pack
242
242
 
243
+ ##
244
+ # :method: layout_grid(opts,&block)
245
+ #
246
+ # Adds a Layout::Grid to current mark.
247
+ #
248
+ # If a block is provided, the context will be defined differently if
249
+ # parameter is provided
250
+ # * Without parameter: block executed inside context of new mark
251
+ # * With paramenter: block executed inside context of current mark.
252
+ # Paramenter references new mark
253
+ #
254
+ # See Mark for examples of use
255
+ mark_method :layout_grid, Rubyvis::Layout::Grid
256
+
257
+ ##
258
+ # :method: tree_grid(opts,&block)
259
+ #
260
+ # Adds a Layout::Tree to current mark.
261
+ #
262
+ # If a block is provided, the context will be defined differently if
263
+ # parameter is provided
264
+ # * Without parameter: block executed inside context of new mark
265
+ # * With paramenter: block executed inside context of current mark.
266
+ # Paramenter references new mark
267
+ #
268
+ # See Mark for examples of use
269
+ mark_method :layout_tree, Rubyvis::Layout::Tree
243
270
 
244
271
  end
@@ -90,6 +90,22 @@ module Rubyvis
90
90
  @order = order.nil? ? Rubyvis.natural_order : order
91
91
  return self
92
92
  end
93
+
94
+ # Returns a hierarchical map of values. Each key adds one level to the
95
+ # hierarchy. With only a single key, the returned map will have a key for each
96
+ # distinct value of the key function; the correspond value with be an array of
97
+ # elements with that key value. If a second key is added, this will be a nested
98
+ # map. For example:
99
+ #
100
+ # <pre>Rubyvis.nest(yields)
101
+ # .key(function(d) d.variety)
102
+ # .key(function(d) d.site)
103
+ # .map()</pre>
104
+ #
105
+ # returns a map <tt>m</tt> such that <tt>m[variety][site]</tt> is an array, a subset of
106
+ # <tt>yields</tt>, with each element having the given variety and site.
107
+ #
108
+ # @returns a hierarchical map of values
93
109
  def map
94
110
  #i=0
95
111
  map={}
@@ -116,6 +132,19 @@ module Rubyvis
116
132
  end
117
133
  map
118
134
  end
135
+
136
+ # Returns a hierarchical nested array. This method is similar to
137
+ # {@link pv.entries}, but works recursively on the entire hierarchy. Rather
138
+ # than returning a map like {@link #map}, this method returns a nested
139
+ # array. Each element of the array has a <tt>key</tt> and <tt>values</tt>
140
+ # field. For leaf nodes, the <tt>values</tt> array will be a subset of the
141
+ # underlying elements array; for non-leaf nodes, the <tt>values</tt> array will
142
+ # contain more key-values pairs.
143
+ #
144
+ # <p>For an example usage, see the {@link Nest} constructor.
145
+ #
146
+ # @returns a hierarchical nested array.
147
+
119
148
  def entries()
120
149
  entries_sort(entries_entries(map),0)
121
150
  end
@@ -145,13 +174,30 @@ module Rubyvis
145
174
  if value.is_a? Array
146
175
  map[key]=f.call(value)
147
176
  else
148
- rollup_rollup(value)
177
+ rollup_rollup(value,f)
149
178
  end
150
179
  }
151
180
  return map;
152
181
  end
182
+
183
+ # Returns a rollup map. The behavior of this method is the same as
184
+ # {@link #map}, except that the leaf values are replaced with the return value
185
+ # of the specified rollup function <tt>f</tt>. For example,
186
+ #
187
+ # <pre>pv.nest(yields)
188
+ # .key(function(d) d.site)
189
+ # .rollup(function(v) pv.median(v, function(d) d.yield))</pre>
190
+ #
191
+ # first groups yield data by site, and then returns a map from site to median
192
+ # yield for the given site.
193
+ #
194
+ # @see #map
195
+ # @param {function} f a rollup function.
196
+ # @returns a hierarchical map, with the leaf values computed by <tt>f</tt>.
197
+
198
+
153
199
  def rollup(f)
154
- rollup_rollup(self.map,f)
200
+ rollup_rollup(self.map, f)
155
201
  end
156
202
  end
157
203
  end