rubyvis 0.3.3 → 0.3.4

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.
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