rubyvis 0.6.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
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,244 +0,0 @@
1
- /**
2
- * Constructs a new wedge with default properties. Wedges are not typically
3
- * constructed directly, but by adding to a panel or an existing mark via
4
- * {@link pv.Mark#add}.
5
- *
6
- * @class Represents a wedge, or pie slice. Specified in terms of start and end
7
- * angle, inner and outer radius, wedges can be used to construct donut charts
8
- * and polar bar charts as well. If the {@link #angle} property is used, the end
9
- * angle is implied by adding this value to start angle. By default, the start
10
- * angle is the previously-generated wedge's end angle. This design allows
11
- * explicit control over the wedge placement if desired, while offering
12
- * convenient defaults for the construction of radial graphs.
13
- *
14
- * <p>The center point of the circle is positioned using the standard box model.
15
- * The wedge can be stroked and filled, similar to {@link pv.Bar}.
16
- *
17
- * <p>See also the <a href="../../api/Wedge.html">Wedge guide</a>.
18
- *
19
- * @extends pv.Mark
20
- */
21
- pv.Wedge = function() {
22
- pv.Mark.call(this);
23
- };
24
-
25
- pv.Wedge.prototype = pv.extend(pv.Mark)
26
- .property("startAngle", Number)
27
- .property("endAngle", Number)
28
- .property("angle", Number)
29
- .property("innerRadius", Number)
30
- .property("outerRadius", Number)
31
- .property("lineWidth", Number)
32
- .property("strokeStyle", pv.color)
33
- .property("fillStyle", pv.color);
34
-
35
- pv.Wedge.prototype.type = "wedge";
36
-
37
- /**
38
- * The start angle of the wedge, in radians. The start angle is measured
39
- * clockwise from the 3 o'clock position. The default value of this property is
40
- * the end angle of the previous instance (the {@link Mark#sibling}), or -PI / 2
41
- * for the first wedge; for pie and donut charts, typically only the
42
- * {@link #angle} property needs to be specified.
43
- *
44
- * @type number
45
- * @name pv.Wedge.prototype.startAngle
46
- */
47
-
48
- /**
49
- * The end angle of the wedge, in radians. If not specified, the end angle is
50
- * implied as the start angle plus the {@link #angle}.
51
- *
52
- * @type number
53
- * @name pv.Wedge.prototype.endAngle
54
- */
55
-
56
- /**
57
- * The angular span of the wedge, in radians. This property is used if end angle
58
- * is not specified.
59
- *
60
- * @type number
61
- * @name pv.Wedge.prototype.angle
62
- */
63
-
64
- /**
65
- * The inner radius of the wedge, in pixels. The default value of this property
66
- * is zero; a positive value will produce a donut slice rather than a pie slice.
67
- * The inner radius can vary per-wedge.
68
- *
69
- * @type number
70
- * @name pv.Wedge.prototype.innerRadius
71
- */
72
-
73
- /**
74
- * The outer radius of the wedge, in pixels. This property is required. For
75
- * pies, only this radius is required; for donuts, the inner radius must be
76
- * specified as well. The outer radius can vary per-wedge.
77
- *
78
- * @type number
79
- * @name pv.Wedge.prototype.outerRadius
80
- */
81
-
82
- /**
83
- * The width of stroked lines, in pixels; used in conjunction with
84
- * <tt>strokeStyle</tt> to stroke the wedge's border.
85
- *
86
- * @type number
87
- * @name pv.Wedge.prototype.lineWidth
88
- */
89
-
90
- /**
91
- * The style of stroked lines; used in conjunction with <tt>lineWidth</tt> to
92
- * stroke the wedge's border. The default value of this property is null,
93
- * meaning wedges are not stroked by default.
94
- *
95
- * @type string
96
- * @name pv.Wedge.prototype.strokeStyle
97
- * @see pv.color
98
- */
99
-
100
- /**
101
- * The wedge fill style; if non-null, the interior of the wedge is filled with
102
- * the specified color. The default value of this property is a categorical
103
- * color.
104
- *
105
- * @type string
106
- * @name pv.Wedge.prototype.fillStyle
107
- * @see pv.color
108
- */
109
-
110
- /**
111
- * Default properties for wedges. By default, there is no stroke and the fill
112
- * style is a categorical color.
113
- *
114
- * @type pv.Wedge
115
- */
116
- pv.Wedge.prototype.defaults = new pv.Wedge()
117
- .extend(pv.Mark.prototype.defaults)
118
- .startAngle(function() {
119
- var s = this.sibling();
120
- return s ? s.endAngle : -Math.PI / 2;
121
- })
122
- .innerRadius(0)
123
- .lineWidth(1.5)
124
- .strokeStyle(null)
125
- .fillStyle(pv.Colors.category20().by(pv.index));
126
-
127
- /**
128
- * Returns the mid-radius of the wedge, which is defined as half-way between the
129
- * inner and outer radii.
130
- *
131
- * @see #innerRadius
132
- * @see #outerRadius
133
- * @returns {number} the mid-radius, in pixels.
134
- */
135
- pv.Wedge.prototype.midRadius = function() {
136
- return (this.innerRadius() + this.outerRadius()) / 2;
137
- };
138
-
139
- /**
140
- * Returns the mid-angle of the wedge, which is defined as half-way between the
141
- * start and end angles.
142
- *
143
- * @see #startAngle
144
- * @see #endAngle
145
- * @returns {number} the mid-angle, in radians.
146
- */
147
- pv.Wedge.prototype.midAngle = function() {
148
- return (this.startAngle() + this.endAngle()) / 2;
149
- };
150
-
151
- /**
152
- * Constructs a new wedge anchor with default properties. Wedges support five
153
- * different anchors:<ul>
154
- *
155
- * <li>outer
156
- * <li>inner
157
- * <li>center
158
- * <li>start
159
- * <li>end
160
- *
161
- * </ul>In addition to positioning properties (left, right, top bottom), the
162
- * anchors support text rendering properties (text-align, text-baseline,
163
- * textAngle). Text is rendered to appear inside the wedge.
164
- *
165
- * @param {string} name the anchor name; either a string or a property function.
166
- * @returns {pv.Anchor}
167
- */
168
- pv.Wedge.prototype.anchor = function(name) {
169
- function partial(s) { return s.innerRadius || s.angle < 2 * Math.PI; }
170
- function midRadius(s) { return (s.innerRadius + s.outerRadius) / 2; }
171
- function midAngle(s) { return (s.startAngle + s.endAngle) / 2; }
172
- return pv.Mark.prototype.anchor.call(this, name)
173
- .left(function() {
174
- var s = this.scene.target[this.index];
175
- if (partial(s)) switch (this.name()) {
176
- case "outer": return s.left + s.outerRadius * Math.cos(midAngle(s));
177
- case "inner": return s.left + s.innerRadius * Math.cos(midAngle(s));
178
- case "start": return s.left + midRadius(s) * Math.cos(s.startAngle);
179
- case "center": return s.left + midRadius(s) * Math.cos(midAngle(s));
180
- case "end": return s.left + midRadius(s) * Math.cos(s.endAngle);
181
- }
182
- return s.left;
183
- })
184
- .top(function() {
185
- var s = this.scene.target[this.index];
186
- if (partial(s)) switch (this.name()) {
187
- case "outer": return s.top + s.outerRadius * Math.sin(midAngle(s));
188
- case "inner": return s.top + s.innerRadius * Math.sin(midAngle(s));
189
- case "start": return s.top + midRadius(s) * Math.sin(s.startAngle);
190
- case "center": return s.top + midRadius(s) * Math.sin(midAngle(s));
191
- case "end": return s.top + midRadius(s) * Math.sin(s.endAngle);
192
- }
193
- return s.top;
194
- })
195
- .textAlign(function() {
196
- var s = this.scene.target[this.index];
197
- if (partial(s)) switch (this.name()) {
198
- case "outer": return pv.Wedge.upright(midAngle(s)) ? "right" : "left";
199
- case "inner": return pv.Wedge.upright(midAngle(s)) ? "left" : "right";
200
- }
201
- return "center";
202
- })
203
- .textBaseline(function() {
204
- var s = this.scene.target[this.index];
205
- if (partial(s)) switch (this.name()) {
206
- case "start": return pv.Wedge.upright(s.startAngle) ? "top" : "bottom";
207
- case "end": return pv.Wedge.upright(s.endAngle) ? "bottom" : "top";
208
- }
209
- return "middle";
210
- })
211
- .textAngle(function() {
212
- var s = this.scene.target[this.index], a = 0;
213
- if (partial(s)) switch (this.name()) {
214
- case "center":
215
- case "inner":
216
- case "outer": a = midAngle(s); break;
217
- case "start": a = s.startAngle; break;
218
- case "end": a = s.endAngle; break;
219
- }
220
- return pv.Wedge.upright(a) ? a : (a + Math.PI);
221
- });
222
- };
223
-
224
- /**
225
- * Returns true if the specified angle is considered "upright", as in, text
226
- * rendered at that angle would appear upright. If the angle is not upright,
227
- * text is rotated 180 degrees to be upright, and the text alignment properties
228
- * are correspondingly changed.
229
- *
230
- * @param {number} angle an angle, in radius.
231
- * @returns {boolean} true if the specified angle is upright.
232
- */
233
- pv.Wedge.upright = function(angle) {
234
- angle = angle % (2 * Math.PI);
235
- angle = (angle < 0) ? (2 * Math.PI + angle) : angle;
236
- return (angle < Math.PI / 2) || (angle >= 3 * Math.PI / 2);
237
- };
238
-
239
- /** @private Sets angle based on endAngle or vice versa. */
240
- pv.Wedge.prototype.buildImplied = function(s) {
241
- if (s.angle == null) s.angle = s.endAngle - s.startAngle;
242
- else if (s.endAngle == null) s.endAngle = s.startAngle + s.angle;
243
- pv.Mark.prototype.buildImplied.call(this, s);
244
- };
@@ -1,75 +0,0 @@
1
- /**
2
- * Constructs a new bound constraint. Before the constraint can be used, the
3
- * {@link #x} and {@link #y} methods must be call to specify the bounds.
4
- *
5
- * @class Constrains particles to within fixed rectangular bounds. For example,
6
- * this constraint can be used to constrain particles in a physics simulation
7
- * within the bounds of an enclosing panel.
8
- *
9
- * <p>Note that the current implementation treats particles as points, with no
10
- * area. If the particles are rendered as dots, be sure to include some
11
- * additional padding to inset the bounds such that the edges of the dots do not
12
- * get clipped by the panel bounds. If the particles have different radii, this
13
- * constraint would need to be extended using a radius function, similar to
14
- * {@link pv.Constraint.collision}.
15
- *
16
- * @see pv.Layout.Force
17
- * @extends pv.Constraint
18
- */
19
- pv.Constraint.bound = function() {
20
- var constraint = {},
21
- x,
22
- y;
23
-
24
- /**
25
- * Sets or gets the bounds on the x-coordinate.
26
- *
27
- * @function
28
- * @name pv.Constraint.bound.prototype.x
29
- * @param {number} min the minimum allowed x-coordinate.
30
- * @param {number} max the maximum allowed x-coordinate.
31
- * @returns {pv.Constraint.bound} this.
32
- */
33
- constraint.x = function(min, max) {
34
- if (arguments.length) {
35
- x = {min: Math.min(min, max), max: Math.max(min, max)};
36
- return this;
37
- }
38
- return x;
39
- };
40
-
41
- /**
42
- * Sets or gets the bounds on the y-coordinate.
43
- *
44
- * @function
45
- * @name pv.Constraint.bound.prototype.y
46
- * @param {number} min the minimum allowed y-coordinate.
47
- * @param {number} max the maximum allowed y-coordinate.
48
- * @returns {pv.Constraint.bound} this.
49
- */
50
- constraint.y = function(min, max) {
51
- if (arguments.length) {
52
- y = {min: Math.min(min, max), max: Math.max(min, max)};
53
- return this;
54
- }
55
- return y;
56
- };
57
-
58
- /**
59
- * Applies this constraint to the specified particles.
60
- *
61
- * @function
62
- * @name pv.Constraint.bound.prototype.apply
63
- * @param {pv.Particle} particles particles to which to apply this constraint.
64
- */
65
- constraint.apply = function(particles) {
66
- if (x) for (var p = particles; p; p = p.next) {
67
- p.x = p.x < x.min ? x.min : (p.x > x.max ? x.max : p.x);
68
- }
69
- if (y) for (var p = particles; p; p = p.next) {
70
- p.y = p.y < y.min ? y.min : (p.y > y.max ? y.max : p.y);
71
- }
72
- };
73
-
74
- return constraint;
75
- };
@@ -1,184 +0,0 @@
1
- /**
2
- * Constructs a new charge force, with an optional charge constant. The charge
3
- * constant can be negative for repulsion (e.g., particles with electrical
4
- * charge of equal sign), or positive for attraction (e.g., massive particles
5
- * with mutual gravity). The default charge constant is -40.
6
- *
7
- * @class An n-body force, as defined by Coulomb's law or Newton's law of
8
- * gravitation, inversely proportional to the square of the distance between
9
- * particles. Note that the force is independent of the <i>mass</i> of the
10
- * associated particles, and that the particles do not have charges of varying
11
- * magnitude; instead, the attraction or repulsion of all particles is globally
12
- * specified as the charge {@link #constant}.
13
- *
14
- * <p>This particular implementation uses the Barnes-Hut algorithm. For details,
15
- * see <a
16
- * href="http://www.nature.com/nature/journal/v324/n6096/abs/324446a0.html">"A
17
- * hierarchical O(N log N) force-calculation algorithm"</a>, J. Barnes &amp;
18
- * P. Hut, <i>Nature</i> 1986.
19
- *
20
- * @name pv.Force.charge
21
- * @param {number} [k] the charge constant.
22
- */
23
- pv.Force.charge = function(k) {
24
- var min = 2, // minimum distance at which to observe forces
25
- min1 = 1 / min,
26
- max = 500, // maximum distance at which to observe forces
27
- max1 = 1 / max,
28
- theta = .9, // Barnes-Hut theta approximation constant
29
- force = {};
30
-
31
- if (!arguments.length) k = -40; // default charge constant (repulsion)
32
-
33
- /**
34
- * Sets or gets the charge constant. If an argument is specified, it is the
35
- * new charge constant. The charge constant can be negative for repulsion
36
- * (e.g., particles with electrical charge of equal sign), or positive for
37
- * attraction (e.g., massive particles with mutual gravity). The default
38
- * charge constant is -40.
39
- *
40
- * @function
41
- * @name pv.Force.charge.prototype.constant
42
- * @param {number} x the charge constant.
43
- * @returns {pv.Force.charge} this.
44
- */
45
- force.constant = function(x) {
46
- if (arguments.length) {
47
- k = Number(x);
48
- return force;
49
- }
50
- return k;
51
- };
52
-
53
- /**
54
- * Sets or gets the domain; specifies the minimum and maximum domain within
55
- * which charge forces are applied. A minimum distance threshold avoids
56
- * applying forces that are two strong (due to granularity of the simulation's
57
- * numeric integration). A maximum distance threshold improves performance by
58
- * skipping force calculations for particles that are far apart.
59
- *
60
- * <p>The default domain is [2, 500].
61
- *
62
- * @function
63
- * @name pv.Force.charge.prototype.domain
64
- * @param {number} a
65
- * @param {number} b
66
- * @returns {pv.Force.charge} this.
67
- */
68
- force.domain = function(a, b) {
69
- if (arguments.length) {
70
- min = Number(a);
71
- min1 = 1 / min;
72
- max = Number(b);
73
- max1 = 1 / max;
74
- return force;
75
- }
76
- return [min, max];
77
- };
78
-
79
- /**
80
- * Sets or gets the Barnes-Hut approximation factor. The Barnes-Hut
81
- * approximation criterion is the ratio of the size of the quadtree node to
82
- * the distance from the point to the node's center of mass is beneath some
83
- * threshold.
84
- *
85
- * @function
86
- * @name pv.Force.charge.prototype.theta
87
- * @param {number} x the new Barnes-Hut approximation factor.
88
- * @returns {pv.Force.charge} this.
89
- */
90
- force.theta = function(x) {
91
- if (arguments.length) {
92
- theta = Number(x);
93
- return force;
94
- }
95
- return theta;
96
- };
97
-
98
- /**
99
- * @ignore Recursively computes the center of charge for each node in the
100
- * quadtree. This is equivalent to the center of mass, assuming that all
101
- * particles have unit weight.
102
- */
103
- function accumulate(n) {
104
- var cx = 0, cy = 0;
105
- n.cn = 0;
106
- function accumulateChild(c) {
107
- accumulate(c);
108
- n.cn += c.cn;
109
- cx += c.cn * c.cx;
110
- cy += c.cn * c.cy;
111
- }
112
- if (!n.leaf) {
113
- if (n.c1) accumulateChild(n.c1);
114
- if (n.c2) accumulateChild(n.c2);
115
- if (n.c3) accumulateChild(n.c3);
116
- if (n.c4) accumulateChild(n.c4);
117
- }
118
- if (n.p) {
119
- n.cn += k;
120
- cx += k * n.p.x;
121
- cy += k * n.p.y;
122
- }
123
- n.cx = cx / n.cn;
124
- n.cy = cy / n.cn;
125
- }
126
-
127
- /**
128
- * @ignore Recursively computes forces on the given particle using the given
129
- * quadtree node. The Barnes-Hut approximation criterion is the ratio of the
130
- * size of the quadtree node to the distance from the point to the node's
131
- * center of mass is beneath some threshold.
132
- */
133
- function forces(n, p, x1, y1, x2, y2) {
134
- var dx = n.cx - p.x,
135
- dy = n.cy - p.y,
136
- dn = 1 / Math.sqrt(dx * dx + dy * dy);
137
-
138
- /* Barnes-Hut criterion. */
139
- if ((n.leaf && (n.p != p)) || ((x2 - x1) * dn < theta)) {
140
- if (dn < max1) return;
141
- if (dn > min1) dn = min1;
142
- var kc = n.cn * dn * dn * dn,
143
- fx = dx * kc,
144
- fy = dy * kc;
145
- p.fx += fx;
146
- p.fy += fy;
147
- } else if (!n.leaf) {
148
- var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5;
149
- if (n.c1) forces(n.c1, p, x1, y1, sx, sy);
150
- if (n.c2) forces(n.c2, p, sx, y1, x2, sy);
151
- if (n.c3) forces(n.c3, p, x1, sy, sx, y2);
152
- if (n.c4) forces(n.c4, p, sx, sy, x2, y2);
153
- if (dn < max1) return;
154
- if (dn > min1) dn = min1;
155
- if (n.p && (n.p != p)) {
156
- var kc = k * dn * dn * dn,
157
- fx = dx * kc,
158
- fy = dy * kc;
159
- p.fx += fx;
160
- p.fy += fy;
161
- }
162
- }
163
- }
164
-
165
- /**
166
- * Applies this force to the specified particles. The force is applied between
167
- * all pairs of particles within the domain, using the specified quadtree to
168
- * accelerate n-body force calculation using the Barnes-Hut approximation
169
- * criterion.
170
- *
171
- * @function
172
- * @name pv.Force.charge.prototype.apply
173
- * @param {pv.Particle} particles particles to which to apply this force.
174
- * @param {pv.Quadtree} q a quadtree for spatial acceleration.
175
- */
176
- force.apply = function(particles, q) {
177
- accumulate(q.root);
178
- for (var p = particles; p; p = p.next) {
179
- forces(q.root, p, q.xMin, q.yMin, q.xMax, q.yMax);
180
- }
181
- };
182
-
183
- return force;
184
- };