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.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.travis.yml +13 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +37 -0
- data/History.txt +6 -0
- data/LICENSE.txt +23 -0
- data/{README.txt → README.md} +15 -12
- data/Rakefile +4 -11
- data/lib/rubyvis.rb +1 -1
- data/lib/rubyvis/scale/quantitative.rb +14 -18
- data/lib/rubyvis/scene/svg_label.rb +1 -1
- data/rubyvis.gemspec +21 -0
- data/spec/anchor_spec.rb +2 -1
- data/spec/line_spec.rb +2 -2
- data/spec/scale_linear_datetime_spec.rb +23 -8
- data/spec/spec_helper.rb +2 -1
- metadata +31 -214
- data/.gemtest +0 -0
- data/vendor/protovis/protovis-r3.3.js +0 -287
- data/vendor/protovis/src/behavior/Behavior.js +0 -32
- data/vendor/protovis/src/behavior/Drag.js +0 -112
- data/vendor/protovis/src/behavior/Pan.js +0 -110
- data/vendor/protovis/src/behavior/Point.js +0 -157
- data/vendor/protovis/src/behavior/Resize.js +0 -104
- data/vendor/protovis/src/behavior/Select.js +0 -100
- data/vendor/protovis/src/behavior/Zoom.js +0 -85
- data/vendor/protovis/src/color/Color.js +0 -598
- data/vendor/protovis/src/color/Colors.js +0 -135
- data/vendor/protovis/src/color/Ramp.js +0 -17
- data/vendor/protovis/src/data/Arrays.js +0 -277
- data/vendor/protovis/src/data/Dom.js +0 -380
- data/vendor/protovis/src/data/Flatten.js +0 -146
- data/vendor/protovis/src/data/Histogram.js +0 -120
- data/vendor/protovis/src/data/LinearScale.js +0 -54
- data/vendor/protovis/src/data/LogScale.js +0 -142
- data/vendor/protovis/src/data/Nest.js +0 -257
- data/vendor/protovis/src/data/Numbers.js +0 -313
- data/vendor/protovis/src/data/Objects.js +0 -78
- data/vendor/protovis/src/data/OrdinalScale.js +0 -267
- data/vendor/protovis/src/data/QuantileScale.js +0 -180
- data/vendor/protovis/src/data/QuantitativeScale.js +0 -440
- data/vendor/protovis/src/data/RootScale.js +0 -55
- data/vendor/protovis/src/data/Scale.js +0 -86
- data/vendor/protovis/src/data/Transform.js +0 -109
- data/vendor/protovis/src/data/Tree.js +0 -124
- data/vendor/protovis/src/data/Vector.js +0 -118
- data/vendor/protovis/src/geo/Geo.js +0 -5
- data/vendor/protovis/src/geo/GeoScale.js +0 -307
- data/vendor/protovis/src/geo/LatLng.js +0 -23
- data/vendor/protovis/src/geo/Projection.js +0 -43
- data/vendor/protovis/src/geo/Projections.js +0 -117
- data/vendor/protovis/src/lang/Array.js +0 -112
- data/vendor/protovis/src/lang/init.js +0 -26
- data/vendor/protovis/src/layout/Arc.js +0 -178
- data/vendor/protovis/src/layout/Bullet.js +0 -164
- data/vendor/protovis/src/layout/Cluster.js +0 -205
- data/vendor/protovis/src/layout/Force.js +0 -309
- data/vendor/protovis/src/layout/Grid.js +0 -119
- data/vendor/protovis/src/layout/Hierarchy.js +0 -249
- data/vendor/protovis/src/layout/Horizon.js +0 -159
- data/vendor/protovis/src/layout/Indent.js +0 -83
- data/vendor/protovis/src/layout/Layout.js +0 -56
- data/vendor/protovis/src/layout/Matrix.js +0 -177
- data/vendor/protovis/src/layout/Network.js +0 -302
- data/vendor/protovis/src/layout/Pack.js +0 -323
- data/vendor/protovis/src/layout/Partition.js +0 -203
- data/vendor/protovis/src/layout/Rollup.js +0 -203
- data/vendor/protovis/src/layout/Stack.js +0 -391
- data/vendor/protovis/src/layout/Tree.js +0 -282
- data/vendor/protovis/src/layout/Treemap.js +0 -347
- data/vendor/protovis/src/mark/Anchor.js +0 -81
- data/vendor/protovis/src/mark/Area.js +0 -268
- data/vendor/protovis/src/mark/Bar.js +0 -93
- data/vendor/protovis/src/mark/Dot.js +0 -212
- data/vendor/protovis/src/mark/Ease.js +0 -150
- data/vendor/protovis/src/mark/Image.js +0 -154
- data/vendor/protovis/src/mark/Label.js +0 -155
- data/vendor/protovis/src/mark/Line.js +0 -195
- data/vendor/protovis/src/mark/Mark.js +0 -1237
- data/vendor/protovis/src/mark/Panel.js +0 -273
- data/vendor/protovis/src/mark/Rule.js +0 -143
- data/vendor/protovis/src/mark/Transient.js +0 -7
- data/vendor/protovis/src/mark/Transition.js +0 -195
- data/vendor/protovis/src/mark/Wedge.js +0 -244
- data/vendor/protovis/src/physics/BoundConstraint.js +0 -75
- data/vendor/protovis/src/physics/ChargeForce.js +0 -184
- data/vendor/protovis/src/physics/CollisionConstraint.js +0 -113
- data/vendor/protovis/src/physics/Constraint.js +0 -26
- data/vendor/protovis/src/physics/DragForce.js +0 -49
- data/vendor/protovis/src/physics/Force.js +0 -25
- data/vendor/protovis/src/physics/Particle.js +0 -81
- data/vendor/protovis/src/physics/PositionConstraint.js +0 -72
- data/vendor/protovis/src/physics/Quadtree.js +0 -195
- data/vendor/protovis/src/physics/Simulation.js +0 -159
- data/vendor/protovis/src/physics/SpringForce.js +0 -141
- data/vendor/protovis/src/pv-internals.js +0 -154
- data/vendor/protovis/src/pv.js +0 -95
- data/vendor/protovis/src/scene/SvgArea.js +0 -172
- data/vendor/protovis/src/scene/SvgBar.js +0 -28
- data/vendor/protovis/src/scene/SvgCurve.js +0 -354
- data/vendor/protovis/src/scene/SvgDot.js +0 -81
- data/vendor/protovis/src/scene/SvgImage.js +0 -45
- data/vendor/protovis/src/scene/SvgLabel.js +0 -46
- data/vendor/protovis/src/scene/SvgLine.js +0 -159
- data/vendor/protovis/src/scene/SvgPanel.js +0 -126
- data/vendor/protovis/src/scene/SvgRule.js +0 -26
- data/vendor/protovis/src/scene/SvgScene.js +0 -185
- data/vendor/protovis/src/scene/SvgWedge.js +0 -66
- data/vendor/protovis/src/text/DateFormat.js +0 -262
- data/vendor/protovis/src/text/Format.js +0 -78
- data/vendor/protovis/src/text/NumberFormat.js +0 -227
- 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ünger
|
|
10
|
-
* & 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 & 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
|
-
};
|