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,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
- };