rubyvis 0.6.0 → 0.6.1

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 (113) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.travis.yml +13 -0
  4. data/Gemfile +8 -0
  5. data/Gemfile.lock +37 -0
  6. data/History.txt +6 -0
  7. data/LICENSE.txt +23 -0
  8. data/{README.txt → README.md} +15 -12
  9. data/Rakefile +4 -11
  10. data/lib/rubyvis.rb +1 -1
  11. data/lib/rubyvis/scale/quantitative.rb +14 -18
  12. data/lib/rubyvis/scene/svg_label.rb +1 -1
  13. data/rubyvis.gemspec +21 -0
  14. data/spec/anchor_spec.rb +2 -1
  15. data/spec/line_spec.rb +2 -2
  16. data/spec/scale_linear_datetime_spec.rb +23 -8
  17. data/spec/spec_helper.rb +2 -1
  18. metadata +31 -214
  19. data/.gemtest +0 -0
  20. data/vendor/protovis/protovis-r3.3.js +0 -287
  21. data/vendor/protovis/src/behavior/Behavior.js +0 -32
  22. data/vendor/protovis/src/behavior/Drag.js +0 -112
  23. data/vendor/protovis/src/behavior/Pan.js +0 -110
  24. data/vendor/protovis/src/behavior/Point.js +0 -157
  25. data/vendor/protovis/src/behavior/Resize.js +0 -104
  26. data/vendor/protovis/src/behavior/Select.js +0 -100
  27. data/vendor/protovis/src/behavior/Zoom.js +0 -85
  28. data/vendor/protovis/src/color/Color.js +0 -598
  29. data/vendor/protovis/src/color/Colors.js +0 -135
  30. data/vendor/protovis/src/color/Ramp.js +0 -17
  31. data/vendor/protovis/src/data/Arrays.js +0 -277
  32. data/vendor/protovis/src/data/Dom.js +0 -380
  33. data/vendor/protovis/src/data/Flatten.js +0 -146
  34. data/vendor/protovis/src/data/Histogram.js +0 -120
  35. data/vendor/protovis/src/data/LinearScale.js +0 -54
  36. data/vendor/protovis/src/data/LogScale.js +0 -142
  37. data/vendor/protovis/src/data/Nest.js +0 -257
  38. data/vendor/protovis/src/data/Numbers.js +0 -313
  39. data/vendor/protovis/src/data/Objects.js +0 -78
  40. data/vendor/protovis/src/data/OrdinalScale.js +0 -267
  41. data/vendor/protovis/src/data/QuantileScale.js +0 -180
  42. data/vendor/protovis/src/data/QuantitativeScale.js +0 -440
  43. data/vendor/protovis/src/data/RootScale.js +0 -55
  44. data/vendor/protovis/src/data/Scale.js +0 -86
  45. data/vendor/protovis/src/data/Transform.js +0 -109
  46. data/vendor/protovis/src/data/Tree.js +0 -124
  47. data/vendor/protovis/src/data/Vector.js +0 -118
  48. data/vendor/protovis/src/geo/Geo.js +0 -5
  49. data/vendor/protovis/src/geo/GeoScale.js +0 -307
  50. data/vendor/protovis/src/geo/LatLng.js +0 -23
  51. data/vendor/protovis/src/geo/Projection.js +0 -43
  52. data/vendor/protovis/src/geo/Projections.js +0 -117
  53. data/vendor/protovis/src/lang/Array.js +0 -112
  54. data/vendor/protovis/src/lang/init.js +0 -26
  55. data/vendor/protovis/src/layout/Arc.js +0 -178
  56. data/vendor/protovis/src/layout/Bullet.js +0 -164
  57. data/vendor/protovis/src/layout/Cluster.js +0 -205
  58. data/vendor/protovis/src/layout/Force.js +0 -309
  59. data/vendor/protovis/src/layout/Grid.js +0 -119
  60. data/vendor/protovis/src/layout/Hierarchy.js +0 -249
  61. data/vendor/protovis/src/layout/Horizon.js +0 -159
  62. data/vendor/protovis/src/layout/Indent.js +0 -83
  63. data/vendor/protovis/src/layout/Layout.js +0 -56
  64. data/vendor/protovis/src/layout/Matrix.js +0 -177
  65. data/vendor/protovis/src/layout/Network.js +0 -302
  66. data/vendor/protovis/src/layout/Pack.js +0 -323
  67. data/vendor/protovis/src/layout/Partition.js +0 -203
  68. data/vendor/protovis/src/layout/Rollup.js +0 -203
  69. data/vendor/protovis/src/layout/Stack.js +0 -391
  70. data/vendor/protovis/src/layout/Tree.js +0 -282
  71. data/vendor/protovis/src/layout/Treemap.js +0 -347
  72. data/vendor/protovis/src/mark/Anchor.js +0 -81
  73. data/vendor/protovis/src/mark/Area.js +0 -268
  74. data/vendor/protovis/src/mark/Bar.js +0 -93
  75. data/vendor/protovis/src/mark/Dot.js +0 -212
  76. data/vendor/protovis/src/mark/Ease.js +0 -150
  77. data/vendor/protovis/src/mark/Image.js +0 -154
  78. data/vendor/protovis/src/mark/Label.js +0 -155
  79. data/vendor/protovis/src/mark/Line.js +0 -195
  80. data/vendor/protovis/src/mark/Mark.js +0 -1237
  81. data/vendor/protovis/src/mark/Panel.js +0 -273
  82. data/vendor/protovis/src/mark/Rule.js +0 -143
  83. data/vendor/protovis/src/mark/Transient.js +0 -7
  84. data/vendor/protovis/src/mark/Transition.js +0 -195
  85. data/vendor/protovis/src/mark/Wedge.js +0 -244
  86. data/vendor/protovis/src/physics/BoundConstraint.js +0 -75
  87. data/vendor/protovis/src/physics/ChargeForce.js +0 -184
  88. data/vendor/protovis/src/physics/CollisionConstraint.js +0 -113
  89. data/vendor/protovis/src/physics/Constraint.js +0 -26
  90. data/vendor/protovis/src/physics/DragForce.js +0 -49
  91. data/vendor/protovis/src/physics/Force.js +0 -25
  92. data/vendor/protovis/src/physics/Particle.js +0 -81
  93. data/vendor/protovis/src/physics/PositionConstraint.js +0 -72
  94. data/vendor/protovis/src/physics/Quadtree.js +0 -195
  95. data/vendor/protovis/src/physics/Simulation.js +0 -159
  96. data/vendor/protovis/src/physics/SpringForce.js +0 -141
  97. data/vendor/protovis/src/pv-internals.js +0 -154
  98. data/vendor/protovis/src/pv.js +0 -95
  99. data/vendor/protovis/src/scene/SvgArea.js +0 -172
  100. data/vendor/protovis/src/scene/SvgBar.js +0 -28
  101. data/vendor/protovis/src/scene/SvgCurve.js +0 -354
  102. data/vendor/protovis/src/scene/SvgDot.js +0 -81
  103. data/vendor/protovis/src/scene/SvgImage.js +0 -45
  104. data/vendor/protovis/src/scene/SvgLabel.js +0 -46
  105. data/vendor/protovis/src/scene/SvgLine.js +0 -159
  106. data/vendor/protovis/src/scene/SvgPanel.js +0 -126
  107. data/vendor/protovis/src/scene/SvgRule.js +0 -26
  108. data/vendor/protovis/src/scene/SvgScene.js +0 -185
  109. data/vendor/protovis/src/scene/SvgWedge.js +0 -66
  110. data/vendor/protovis/src/text/DateFormat.js +0 -262
  111. data/vendor/protovis/src/text/Format.js +0 -78
  112. data/vendor/protovis/src/text/NumberFormat.js +0 -227
  113. data/vendor/protovis/src/text/TimeFormat.js +0 -115
@@ -1,282 +0,0 @@
1
- /**
2
- * Constructs a new, empty tree layout. Layouts are not typically constructed
3
- * directly; instead, they are added to an existing panel via
4
- * {@link pv.Mark#add}.
5
- *
6
- * @class Implements a node-link tree diagram using the Reingold-Tilford "tidy"
7
- * tree layout algorithm. The specific algorithm used by this layout is based on
8
- * <a href="http://citeseer.ist.psu.edu/buchheim02improving.html">"Improving
9
- * Walker's Algorithm to Run in Linear Time"</A> by C. Buchheim, M. J&uuml;nger
10
- * &amp; S. Leipert, Graph Drawing 2002. This layout supports both cartesian and
11
- * radial orientations orientations for node-link diagrams.
12
- *
13
- * <p>The tree layout supports a "group" property, which if true causes siblings
14
- * to be positioned closer together than unrelated nodes at the same depth. The
15
- * layout can be configured using the <tt>depth</tt> and <tt>breadth</tt>
16
- * properties, which control the increments in pixel space between nodes in both
17
- * dimensions, similar to the indent layout.
18
- *
19
- * <p>For more details on how to use this layout, see
20
- * {@link pv.Layout.Hierarchy}.
21
- *
22
- * @extends pv.Layout.Hierarchy
23
- */
24
- pv.Layout.Tree = function() {
25
- pv.Layout.Hierarchy.call(this);
26
- };
27
-
28
- pv.Layout.Tree.prototype = pv.extend(pv.Layout.Hierarchy)
29
- .property("group", Number)
30
- .property("breadth", Number)
31
- .property("depth", Number)
32
- .property("orient", String);
33
-
34
- /**
35
- * Default properties for tree layouts. The default orientation is "top", the
36
- * default group parameter is 1, and the default breadth and depth offsets are
37
- * 15 and 60 respectively.
38
- *
39
- * @type pv.Layout.Tree
40
- */
41
- pv.Layout.Tree.prototype.defaults = new pv.Layout.Tree()
42
- .extend(pv.Layout.Hierarchy.prototype.defaults)
43
- .group(1)
44
- .breadth(15)
45
- .depth(60)
46
- .orient("top");
47
-
48
- /** @private */
49
- pv.Layout.Tree.prototype.buildImplied = function(s) {
50
- if (pv.Layout.Hierarchy.prototype.buildImplied.call(this, s)) return;
51
-
52
- var nodes = s.nodes,
53
- orient = s.orient,
54
- depth = s.depth,
55
- breadth = s.breadth,
56
- group = s.group,
57
- w = s.width,
58
- h = s.height;
59
-
60
- /** @private */
61
- function firstWalk(v) {
62
- var l, r, a;
63
- if (!v.firstChild) {
64
- if (l = v.previousSibling) {
65
- v.prelim = l.prelim + distance(v.depth, true);
66
- }
67
- } else {
68
- l = v.firstChild;
69
- r = v.lastChild;
70
- a = l; // default ancestor
71
- for (var c = l; c; c = c.nextSibling) {
72
- firstWalk(c);
73
- a = apportion(c, a);
74
- }
75
- executeShifts(v);
76
- var midpoint = .5 * (l.prelim + r.prelim);
77
- if (l = v.previousSibling) {
78
- v.prelim = l.prelim + distance(v.depth, true);
79
- v.mod = v.prelim - midpoint;
80
- } else {
81
- v.prelim = midpoint;
82
- }
83
- }
84
- }
85
-
86
- /** @private */
87
- function secondWalk(v, m, depth) {
88
- v.breadth = v.prelim + m;
89
- m += v.mod;
90
- for (var c = v.firstChild; c; c = c.nextSibling) {
91
- secondWalk(c, m, depth);
92
- }
93
- }
94
-
95
- /** @private */
96
- function apportion(v, a) {
97
- var w = v.previousSibling;
98
- if (w) {
99
- var vip = v,
100
- vop = v,
101
- vim = w,
102
- vom = v.parentNode.firstChild,
103
- sip = vip.mod,
104
- sop = vop.mod,
105
- sim = vim.mod,
106
- som = vom.mod,
107
- nr = nextRight(vim),
108
- nl = nextLeft(vip);
109
- while (nr && nl) {
110
- vim = nr;
111
- vip = nl;
112
- vom = nextLeft(vom);
113
- vop = nextRight(vop);
114
- vop.ancestor = v;
115
- var shift = (vim.prelim + sim) - (vip.prelim + sip) + distance(vim.depth, false);
116
- if (shift > 0) {
117
- moveSubtree(ancestor(vim, v, a), v, shift);
118
- sip += shift;
119
- sop += shift;
120
- }
121
- sim += vim.mod;
122
- sip += vip.mod;
123
- som += vom.mod;
124
- sop += vop.mod;
125
- nr = nextRight(vim);
126
- nl = nextLeft(vip);
127
- }
128
- if (nr && !nextRight(vop)) {
129
- vop.thread = nr;
130
- vop.mod += sim - sop;
131
- }
132
- if (nl && !nextLeft(vom)) {
133
- vom.thread = nl;
134
- vom.mod += sip - som;
135
- a = v;
136
- }
137
- }
138
- return a;
139
- }
140
-
141
- /** @private */
142
- function nextLeft(v) {
143
- return v.firstChild || v.thread;
144
- }
145
-
146
- /** @private */
147
- function nextRight(v) {
148
- return v.lastChild || v.thread;
149
- }
150
-
151
- /** @private */
152
- function moveSubtree(wm, wp, shift) {
153
- var subtrees = wp.number - wm.number;
154
- wp.change -= shift / subtrees;
155
- wp.shift += shift;
156
- wm.change += shift / subtrees;
157
- wp.prelim += shift;
158
- wp.mod += shift;
159
- }
160
-
161
- /** @private */
162
- function executeShifts(v) {
163
- var shift = 0, change = 0;
164
- for (var c = v.lastChild; c; c = c.previousSibling) {
165
- c.prelim += shift;
166
- c.mod += shift;
167
- change += c.change;
168
- shift += c.shift + change;
169
- }
170
- }
171
-
172
- /** @private */
173
- function ancestor(vim, v, a) {
174
- return (vim.ancestor.parentNode == v.parentNode) ? vim.ancestor : a;
175
- }
176
-
177
- /** @private */
178
- function distance(depth, siblings) {
179
- return (siblings ? 1 : (group + 1)) / ((orient == "radial") ? depth : 1);
180
- }
181
-
182
- /* Initialize temporary layout variables. TODO: store separately. */
183
- var root = nodes[0];
184
- root.visitAfter(function(v, i) {
185
- v.ancestor = v;
186
- v.prelim = 0;
187
- v.mod = 0;
188
- v.change = 0;
189
- v.shift = 0;
190
- v.number = v.previousSibling ? (v.previousSibling.number + 1) : 0;
191
- v.depth = i;
192
- });
193
-
194
- /* Compute the layout using Buchheim et al.'s algorithm. */
195
- firstWalk(root);
196
- secondWalk(root, -root.prelim, 0);
197
-
198
- /** @private Returns the angle of the given node. */
199
- function midAngle(n) {
200
- return (orient == "radial") ? n.breadth / depth : 0;
201
- }
202
-
203
- /** @private */
204
- function x(n) {
205
- switch (orient) {
206
- case "left": return n.depth;
207
- case "right": return w - n.depth;
208
- case "top":
209
- case "bottom": return n.breadth + w / 2;
210
- case "radial": return w / 2 + n.depth * Math.cos(midAngle(n));
211
- }
212
- }
213
-
214
- /** @private */
215
- function y(n) {
216
- switch (orient) {
217
- case "left":
218
- case "right": return n.breadth + h / 2;
219
- case "top": return n.depth;
220
- case "bottom": return h - n.depth;
221
- case "radial": return h / 2 + n.depth * Math.sin(midAngle(n));
222
- }
223
- }
224
-
225
- /* Clear temporary layout variables; transform depth and breadth. */
226
- root.visitAfter(function(v) {
227
- v.breadth *= breadth;
228
- v.depth *= depth;
229
- v.midAngle = midAngle(v);
230
- v.x = x(v);
231
- v.y = y(v);
232
- if (v.firstChild) v.midAngle += Math.PI;
233
- delete v.breadth;
234
- delete v.depth;
235
- delete v.ancestor;
236
- delete v.prelim;
237
- delete v.mod;
238
- delete v.change;
239
- delete v.shift;
240
- delete v.number;
241
- delete v.thread;
242
- });
243
- };
244
-
245
- /**
246
- * The offset between siblings nodes; defaults to 15.
247
- *
248
- * @type number
249
- * @name pv.Layout.Tree.prototype.breadth
250
- */
251
-
252
- /**
253
- * The offset between parent and child nodes; defaults to 60.
254
- *
255
- * @type number
256
- * @name pv.Layout.Tree.prototype.depth
257
- */
258
-
259
- /**
260
- * The orientation. The default orientation is "top", which means that the root
261
- * node is placed on the top edge, leaf nodes appear at the bottom, and internal
262
- * nodes are in-between. The following orientations are supported:<ul>
263
- *
264
- * <li>left - left-to-right.
265
- * <li>right - right-to-left.
266
- * <li>top - top-to-bottom.
267
- * <li>bottom - bottom-to-top.
268
- * <li>radial - radially, with the root at the center.</ul>
269
- *
270
- * @type string
271
- * @name pv.Layout.Tree.prototype.orient
272
- */
273
-
274
- /**
275
- * The sibling grouping, i.e., whether differentiating space is placed between
276
- * sibling groups. The default is 1 (or true), causing sibling leaves to be
277
- * separated by one breadth offset. Setting this to false (or 0) causes
278
- * non-siblings to be adjacent.
279
- *
280
- * @type number
281
- * @name pv.Layout.Tree.prototype.group
282
- */
@@ -1,347 +0,0 @@
1
- /**
2
- * Constructs a new, empty treemap layout. Layouts are not typically
3
- * constructed directly; instead, they are added to an existing panel via
4
- * {@link pv.Mark#add}.
5
- *
6
- * @class Implements a space-filling rectangular layout, with the hierarchy
7
- * represented via containment. Treemaps represent nodes as boxes, with child
8
- * nodes placed within parent boxes. The size of each box is proportional to the
9
- * size of the node in the tree. This particular algorithm is taken from Bruls,
10
- * D.M., C. Huizing, and J.J. van Wijk, <a
11
- * href="http://www.win.tue.nl/~vanwijk/stm.pdf">"Squarified Treemaps"</a> in
12
- * <i>Data Visualization 2000, Proceedings of the Joint Eurographics and IEEE
13
- * TCVG Sumposium on Visualization</i>, 2000, pp. 33-42.
14
- *
15
- * <p>The meaning of the exported mark prototypes changes slightly in the
16
- * space-filling implementation:<ul>
17
- *
18
- * <li><tt>node</tt> - for rendering nodes; typically a {@link pv.Bar}. The node
19
- * data is populated with <tt>dx</tt> and <tt>dy</tt> attributes, in addition to
20
- * the standard <tt>x</tt> and <tt>y</tt> position attributes.
21
- *
22
- * <p><li><tt>leaf</tt> - for rendering leaf nodes only, with no fill or stroke
23
- * style by default; typically a {@link pv.Panel} or another layout!
24
- *
25
- * <p><li><tt>link</tt> - unsupported; undefined. Links are encoded implicitly
26
- * in the arrangement of the space-filling nodes.
27
- *
28
- * <p><li><tt>label</tt> - for rendering node labels; typically a
29
- * {@link pv.Label}.
30
- *
31
- * </ul>For more details on how to use this layout, see
32
- * {@link pv.Layout.Hierarchy}.
33
- *
34
- * @extends pv.Layout.Hierarchy
35
- */
36
- pv.Layout.Treemap = function() {
37
- pv.Layout.Hierarchy.call(this);
38
-
39
- this.node
40
- .strokeStyle("#fff")
41
- .fillStyle("rgba(31, 119, 180, .25)")
42
- .width(function(n) { return n.dx; })
43
- .height(function(n) { return n.dy; });
44
-
45
- this.label
46
- .visible(function(n) { return !n.firstChild; })
47
- .left(function(n) { return n.x + (n.dx / 2); })
48
- .top(function(n) { return n.y + (n.dy / 2); })
49
- .textAlign("center")
50
- .textAngle(function(n) { return n.dx > n.dy ? 0 : -Math.PI / 2; });
51
-
52
- (this.leaf = new pv.Mark()
53
- .extend(this.node)
54
- .fillStyle(null)
55
- .strokeStyle(null)
56
- .visible(function(n) { return !n.firstChild; })).parent = this;
57
-
58
- /* Hide unsupported link. */
59
- delete this.link;
60
- };
61
-
62
- pv.Layout.Treemap.prototype = pv.extend(pv.Layout.Hierarchy)
63
- .property("round", Boolean)
64
- .property("paddingLeft", Number)
65
- .property("paddingRight", Number)
66
- .property("paddingTop", Number)
67
- .property("paddingBottom", Number)
68
- .property("mode", String)
69
- .property("order", String);
70
-
71
- /**
72
- * Default propertiess for treemap layouts. The default mode is "squarify" and
73
- * the default order is "ascending".
74
- *
75
- * @type pv.Layout.Treemap
76
- */
77
- pv.Layout.Treemap.prototype.defaults = new pv.Layout.Treemap()
78
- .extend(pv.Layout.Hierarchy.prototype.defaults)
79
- .mode("squarify") // squarify, slice-and-dice, slice, dice
80
- .order("ascending"); // ascending, descending, reverse, null
81
-
82
- /**
83
- * Whether node sizes should be rounded to integer values. This has a similar
84
- * effect to setting <tt>antialias(false)</tt> for node values, but allows the
85
- * treemap algorithm to accumulate error related to pixel rounding.
86
- *
87
- * @type boolean
88
- * @name pv.Layout.Treemap.prototype.round
89
- */
90
-
91
- /**
92
- * The left inset between parent add child in pixels. Defaults to 0.
93
- *
94
- * @type number
95
- * @name pv.Layout.Treemap.prototype.paddingLeft
96
- * @see #padding
97
- */
98
-
99
- /**
100
- * The right inset between parent add child in pixels. Defaults to 0.
101
- *
102
- * @type number
103
- * @name pv.Layout.Treemap.prototype.paddingRight
104
- * @see #padding
105
- */
106
-
107
- /**
108
- * The top inset between parent and child in pixels. Defaults to 0.
109
- *
110
- * @type number
111
- * @name pv.Layout.Treemap.prototype.paddingTop
112
- * @see #padding
113
- */
114
-
115
- /**
116
- * The bottom inset between parent and child in pixels. Defaults to 0.
117
- *
118
- * @type number
119
- * @name pv.Layout.Treemap.prototype.paddingBottom
120
- * @see #padding
121
- */
122
-
123
- /**
124
- * The treemap algorithm. The default value is "squarify". The "slice-and-dice"
125
- * algorithm may also be used, which alternates between horizontal and vertical
126
- * slices for different depths. In addition, the "slice" and "dice" algorithms
127
- * may be specified explicitly to control whether horizontal or vertical slices
128
- * are used, which may be useful for nested treemap layouts.
129
- *
130
- * @type string
131
- * @name pv.Layout.Treemap.prototype.mode
132
- * @see <a
133
- * href="ftp://ftp.cs.umd.edu/pub/hcil/Reports-Abstracts-Bibliography/2001-06html/2001-06.pdf"
134
- * >"Ordered Treemap Layouts"</a> by B. Shneiderman &amp; M. Wattenberg, IEEE
135
- * InfoVis 2001.
136
- */
137
-
138
- /**
139
- * The sibling node order. A <tt>null</tt> value means to use the sibling order
140
- * specified by the nodes property as-is; "reverse" will reverse the given
141
- * order. The default value "ascending" will sort siblings in ascending order of
142
- * size, while "descending" will do the reverse. For sorting based on data
143
- * attributes other than size, use the default <tt>null</tt> for the order
144
- * property, and sort the nodes beforehand using the {@link pv.Dom} operator.
145
- *
146
- * @type string
147
- * @name pv.Layout.Treemap.prototype.order
148
- */
149
-
150
- /**
151
- * Alias for setting the left, right, top and bottom padding properties
152
- * simultaneously.
153
- *
154
- * @see #paddingLeft
155
- * @see #paddingRight
156
- * @see #paddingTop
157
- * @see #paddingBottom
158
- * @returns {pv.Layout.Treemap} this.
159
- */
160
- pv.Layout.Treemap.prototype.padding = function(n) {
161
- return this.paddingLeft(n).paddingRight(n).paddingTop(n).paddingBottom(n);
162
- };
163
-
164
- /** @private The default size function. */
165
- pv.Layout.Treemap.prototype.$size = function(d) {
166
- return Number(d.nodeValue);
167
- };
168
-
169
- /**
170
- * Specifies the sizing function. By default, the size function uses the
171
- * <tt>nodeValue</tt> attribute of nodes as a numeric value: <tt>function(d)
172
- * Number(d.nodeValue)</tt>.
173
- *
174
- * <p>The sizing function is invoked for each leaf node in the tree, per the
175
- * <tt>nodes</tt> property. For example, if the tree data structure represents a
176
- * file system, with files as leaf nodes, and each file has a <tt>bytes</tt>
177
- * attribute, you can specify a size function as:
178
- *
179
- * <pre> .size(function(d) d.bytes)</pre>
180
- *
181
- * @param {function} f the new sizing function.
182
- * @returns {pv.Layout.Treemap} this.
183
- */
184
- pv.Layout.Treemap.prototype.size = function(f) {
185
- this.$size = pv.functor(f);
186
- return this;
187
- };
188
-
189
- /** @private */
190
- pv.Layout.Treemap.prototype.buildImplied = function(s) {
191
- if (pv.Layout.Hierarchy.prototype.buildImplied.call(this, s)) return;
192
-
193
- var that = this,
194
- nodes = s.nodes,
195
- root = nodes[0],
196
- stack = pv.Mark.stack,
197
- left = s.paddingLeft,
198
- right = s.paddingRight,
199
- top = s.paddingTop,
200
- bottom = s.paddingBottom,
201
- /** @ignore */ size = function(n) { return n.size; },
202
- round = s.round ? Math.round : Number,
203
- mode = s.mode;
204
-
205
- /** @private */
206
- function slice(row, sum, horizontal, x, y, w, h) {
207
- for (var i = 0, d = 0; i < row.length; i++) {
208
- var n = row[i];
209
- if (horizontal) {
210
- n.x = x + d;
211
- n.y = y;
212
- d += n.dx = round(w * n.size / sum);
213
- n.dy = h;
214
- } else {
215
- n.x = x;
216
- n.y = y + d;
217
- n.dx = w;
218
- d += n.dy = round(h * n.size / sum);
219
- }
220
- }
221
- if (n) { // correct on-axis rounding error
222
- if (horizontal) {
223
- n.dx += w - d;
224
- } else {
225
- n.dy += h - d;
226
- }
227
- }
228
- }
229
-
230
- /** @private */
231
- function ratio(row, l) {
232
- var rmax = -Infinity, rmin = Infinity, s = 0;
233
- for (var i = 0; i < row.length; i++) {
234
- var r = row[i].size;
235
- if (r < rmin) rmin = r;
236
- if (r > rmax) rmax = r;
237
- s += r;
238
- }
239
- s = s * s;
240
- l = l * l;
241
- return Math.max(l * rmax / s, s / (l * rmin));
242
- }
243
-
244
- /** @private */
245
- function layout(n, i) {
246
- var x = n.x + left,
247
- y = n.y + top,
248
- w = n.dx - left - right,
249
- h = n.dy - top - bottom;
250
-
251
- /* Assume squarify by default. */
252
- if (mode != "squarify") {
253
- slice(n.childNodes, n.size,
254
- mode == "slice" ? true
255
- : mode == "dice" ? false
256
- : i & 1, x, y, w, h);
257
- return;
258
- }
259
-
260
- var row = [],
261
- mink = Infinity,
262
- l = Math.min(w, h),
263
- k = w * h / n.size;
264
-
265
- /* Abort if the size is nonpositive. */
266
- if (n.size <= 0) return;
267
-
268
- /* Scale the sizes to fill the current subregion. */
269
- n.visitBefore(function(n) { n.size *= k; });
270
-
271
- /** @private Position the specified nodes along one dimension. */
272
- function position(row) {
273
- var horizontal = w == l,
274
- sum = pv.sum(row, size),
275
- r = l ? round(sum / l) : 0;
276
- slice(row, sum, horizontal, x, y, horizontal ? w : r, horizontal ? r : h);
277
- if (horizontal) {
278
- y += r;
279
- h -= r;
280
- } else {
281
- x += r;
282
- w -= r;
283
- }
284
- l = Math.min(w, h);
285
- return horizontal;
286
- }
287
-
288
- var children = n.childNodes.slice(); // copy
289
- while (children.length) {
290
- var child = children[children.length - 1];
291
- if (!child.size) {
292
- children.pop();
293
- continue;
294
- }
295
- row.push(child);
296
-
297
- var k = ratio(row, l);
298
- if (k <= mink) {
299
- children.pop();
300
- mink = k;
301
- } else {
302
- row.pop();
303
- position(row);
304
- row.length = 0;
305
- mink = Infinity;
306
- }
307
- }
308
-
309
- /* correct off-axis rounding error */
310
- if (position(row)) for (var i = 0; i < row.length; i++) {
311
- row[i].dy += h;
312
- } else for (var i = 0; i < row.length; i++) {
313
- row[i].dx += w;
314
- }
315
- }
316
-
317
- /* Recursively compute the node depth and size. */
318
- stack.unshift(null);
319
- root.visitAfter(function(n, i) {
320
- n.depth = i;
321
- n.x = n.y = n.dx = n.dy = 0;
322
- n.size = n.firstChild
323
- ? pv.sum(n.childNodes, function(n) { return n.size; })
324
- : that.$size.apply(that, (stack[0] = n, stack));
325
- });
326
- stack.shift();
327
-
328
- /* Sort. */
329
- switch (s.order) {
330
- case "ascending": {
331
- root.sort(function(a, b) { return a.size - b.size; });
332
- break;
333
- }
334
- case "descending": {
335
- root.sort(function(a, b) { return b.size - a.size; });
336
- break;
337
- }
338
- case "reverse": root.reverse(); break;
339
- }
340
-
341
- /* Recursively compute the layout. */
342
- root.x = 0;
343
- root.y = 0;
344
- root.dx = s.width;
345
- root.dy = s.height;
346
- root.visitBefore(layout);
347
- };