rubyvis 0.6.0 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- 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,113 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Constructs a new collision constraint. The default search radius is 10, and
|
3
|
-
* the default repeat count is 1. A radius function must be specified to compute
|
4
|
-
* the radius of particles.
|
5
|
-
*
|
6
|
-
* @class Constraints circles to avoid overlap. Each particle is treated as a
|
7
|
-
* circle, with the radius of the particle computed using a specified function.
|
8
|
-
* For example, if the particle has an <tt>r</tt> attribute storing the radius,
|
9
|
-
* the radius <tt>function(d) d.r</tt> specifies a collision constraint using
|
10
|
-
* this radius. The radius function is passed each {@link pv.Particle} as the
|
11
|
-
* first argument.
|
12
|
-
*
|
13
|
-
* <p>To accelerate collision detection, this implementation uses a quadtree and
|
14
|
-
* a search radius. The search radius is computed as the maximum radius of all
|
15
|
-
* particles in the simulation.
|
16
|
-
*
|
17
|
-
* @see pv.Constraint
|
18
|
-
* @param {function} radius the radius function.
|
19
|
-
*/
|
20
|
-
pv.Constraint.collision = function(radius) {
|
21
|
-
var n = 1, // number of times to repeat the constraint
|
22
|
-
r1,
|
23
|
-
px1,
|
24
|
-
py1,
|
25
|
-
px2,
|
26
|
-
py2,
|
27
|
-
constraint = {};
|
28
|
-
|
29
|
-
if (!arguments.length) r1 = 10; // default search radius
|
30
|
-
|
31
|
-
/**
|
32
|
-
* Sets or gets the repeat count. If the repeat count is greater than 1, the
|
33
|
-
* constraint will be applied repeatedly; this is a form of the Gauss-Seidel
|
34
|
-
* method for constraints relaxation. Repeating the collision constraint makes
|
35
|
-
* the constraint have more of an effect when there is a potential for many
|
36
|
-
* co-occurring collisions.
|
37
|
-
*
|
38
|
-
* @function
|
39
|
-
* @name pv.Constraint.collision.prototype.repeat
|
40
|
-
* @param {number} x the number of times to repeat this constraint.
|
41
|
-
* @returns {pv.Constraint.collision} this.
|
42
|
-
*/
|
43
|
-
constraint.repeat = function(x) {
|
44
|
-
if (arguments.length) {
|
45
|
-
n = Number(x);
|
46
|
-
return constraint;
|
47
|
-
}
|
48
|
-
return n;
|
49
|
-
};
|
50
|
-
|
51
|
-
/** @private */
|
52
|
-
function constrain(n, p, x1, y1, x2, y2) {
|
53
|
-
if (!n.leaf) {
|
54
|
-
var sx = (x1 + x2) * .5,
|
55
|
-
sy = (y1 + y2) * .5,
|
56
|
-
top = sy > py1,
|
57
|
-
bottom = sy < py2,
|
58
|
-
left = sx > px1,
|
59
|
-
right = sx < px2;
|
60
|
-
if (top) {
|
61
|
-
if (n.c1 && left) constrain(n.c1, p, x1, y1, sx, sy);
|
62
|
-
if (n.c2 && right) constrain(n.c2, p, sx, y1, x2, sy);
|
63
|
-
}
|
64
|
-
if (bottom) {
|
65
|
-
if (n.c3 && left) constrain(n.c3, p, x1, sy, sx, y2);
|
66
|
-
if (n.c4 && right) constrain(n.c4, p, sx, sy, x2, y2);
|
67
|
-
}
|
68
|
-
}
|
69
|
-
if (n.p && (n.p != p)) {
|
70
|
-
var dx = p.x - n.p.x,
|
71
|
-
dy = p.y - n.p.y,
|
72
|
-
l = Math.sqrt(dx * dx + dy * dy),
|
73
|
-
d = r1 + radius(n.p);
|
74
|
-
if (l < d) {
|
75
|
-
var k = (l - d) / l * .5;
|
76
|
-
dx *= k;
|
77
|
-
dy *= k;
|
78
|
-
p.x -= dx;
|
79
|
-
p.y -= dy;
|
80
|
-
n.p.x += dx;
|
81
|
-
n.p.y += dy;
|
82
|
-
}
|
83
|
-
}
|
84
|
-
}
|
85
|
-
|
86
|
-
/**
|
87
|
-
* Applies this constraint to the specified particles.
|
88
|
-
*
|
89
|
-
* @function
|
90
|
-
* @name pv.Constraint.collision.prototype.apply
|
91
|
-
* @param {pv.Particle} particles particles to which to apply this constraint.
|
92
|
-
* @param {pv.Quadtree} q a quadtree for spatial acceleration.
|
93
|
-
*/
|
94
|
-
constraint.apply = function(particles, q) {
|
95
|
-
var p, r, max = -Infinity;
|
96
|
-
for (p = particles; p; p = p.next) {
|
97
|
-
r = radius(p);
|
98
|
-
if (r > max) max = r;
|
99
|
-
}
|
100
|
-
for (var i = 0; i < n; i++) {
|
101
|
-
for (p = particles; p; p = p.next) {
|
102
|
-
r = (r1 = radius(p)) + max;
|
103
|
-
px1 = p.x - r;
|
104
|
-
px2 = p.x + r;
|
105
|
-
py1 = p.y - r;
|
106
|
-
py2 = p.y + r;
|
107
|
-
constrain(q.root, p, q.xMin, q.yMin, q.xMax, q.yMax);
|
108
|
-
}
|
109
|
-
}
|
110
|
-
};
|
111
|
-
|
112
|
-
return constraint;
|
113
|
-
};
|
@@ -1,26 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Abstract; see an implementing class.
|
3
|
-
*
|
4
|
-
* @class Represents a constraint that acts on particles. Note that this
|
5
|
-
* interface does not specify how to bind a constraint to specific particles; in
|
6
|
-
* general, constraints are applied globally to all particles. However, some
|
7
|
-
* constraints may be applied to specific particles or between particles, such
|
8
|
-
* as position constraints, through additional specialization.
|
9
|
-
*
|
10
|
-
* @see pv.Simulation
|
11
|
-
* @see pv.Particle
|
12
|
-
* @see pv.Constraint.bound
|
13
|
-
* @see pv.Constraint.collision
|
14
|
-
* @see pv.Constraint.position
|
15
|
-
*/
|
16
|
-
pv.Constraint = {};
|
17
|
-
|
18
|
-
/**
|
19
|
-
* Applies this constraint to the specified particles.
|
20
|
-
*
|
21
|
-
* @function
|
22
|
-
* @name pv.Constraint.prototype.apply
|
23
|
-
* @param {pv.Particle} particles particles to which to apply this constraint.
|
24
|
-
* @param {pv.Quadtree} q a quadtree for spatial acceleration.
|
25
|
-
* @returns {pv.Constraint} this.
|
26
|
-
*/
|
@@ -1,49 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Constructs a new drag force with the specified constant.
|
3
|
-
*
|
4
|
-
* @class Implements a drag force, simulating friction. The drag force is
|
5
|
-
* applied in the opposite direction of the particle's velocity. Since Position
|
6
|
-
* Verlet integration does not track velocities explicitly, the error term with
|
7
|
-
* this estimate of velocity is fairly high, so the drag force may be
|
8
|
-
* inaccurate.
|
9
|
-
*
|
10
|
-
* @extends pv.Force
|
11
|
-
* @param {number} k the drag constant.
|
12
|
-
* @see #constant
|
13
|
-
*/
|
14
|
-
pv.Force.drag = function(k) {
|
15
|
-
var force = {};
|
16
|
-
|
17
|
-
if (!arguments.length) k = .1; // default drag constant
|
18
|
-
|
19
|
-
/**
|
20
|
-
* Sets or gets the drag constant, in the range [0,1]. The default drag
|
21
|
-
* constant is 0.1. The drag forces scales linearly with the particle's
|
22
|
-
* velocity based on the given drag constant.
|
23
|
-
*
|
24
|
-
* @function
|
25
|
-
* @name pv.Force.drag.prototype.constant
|
26
|
-
* @param {number} x the new drag constant.
|
27
|
-
* @returns {pv.Force.drag} this, or the current drag constant.
|
28
|
-
*/
|
29
|
-
force.constant = function(x) {
|
30
|
-
if (arguments.length) { k = x; return force; }
|
31
|
-
return k;
|
32
|
-
};
|
33
|
-
|
34
|
-
/**
|
35
|
-
* Applies this force to the specified particles.
|
36
|
-
*
|
37
|
-
* @function
|
38
|
-
* @name pv.Force.drag.prototype.apply
|
39
|
-
* @param {pv.Particle} particles particles to which to apply this force.
|
40
|
-
*/
|
41
|
-
force.apply = function(particles) {
|
42
|
-
if (k) for (var p = particles; p; p = p.next) {
|
43
|
-
p.fx -= k * p.vx;
|
44
|
-
p.fy -= k * p.vy;
|
45
|
-
}
|
46
|
-
};
|
47
|
-
|
48
|
-
return force;
|
49
|
-
};
|
@@ -1,25 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Abstract; see an implementing class.
|
3
|
-
*
|
4
|
-
* @class Represents a force that acts on particles. Note that this interface
|
5
|
-
* does not specify how to bind a force to specific particles; in general,
|
6
|
-
* forces are applied globally to all particles. However, some forces may be
|
7
|
-
* applied to specific particles or between particles, such as spring forces,
|
8
|
-
* through additional specialization.
|
9
|
-
*
|
10
|
-
* @see pv.Simulation
|
11
|
-
* @see pv.Particle
|
12
|
-
* @see pv.Force.charge
|
13
|
-
* @see pv.Force.drag
|
14
|
-
* @see pv.Force.spring
|
15
|
-
*/
|
16
|
-
pv.Force = {};
|
17
|
-
|
18
|
-
/**
|
19
|
-
* Applies this force to the specified particles.
|
20
|
-
*
|
21
|
-
* @function
|
22
|
-
* @name pv.Force.prototype.apply
|
23
|
-
* @param {pv.Particle} particles particles to which to apply this force.
|
24
|
-
* @param {pv.Quadtree} q a quadtree for spatial acceleration.
|
25
|
-
*/
|
@@ -1,81 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Abstract; not implemented. There is no explicit constructor; this class
|
3
|
-
* merely serves to document the attributes that are used on particles in
|
4
|
-
* physics simulations.
|
5
|
-
*
|
6
|
-
* @class A weighted particle that can participate in a force simulation.
|
7
|
-
*
|
8
|
-
* @name pv.Particle
|
9
|
-
*/
|
10
|
-
|
11
|
-
/**
|
12
|
-
* The next particle in the simulation. Particles form a singly-linked list.
|
13
|
-
*
|
14
|
-
* @field
|
15
|
-
* @type pv.Particle
|
16
|
-
* @name pv.Particle.prototype.next
|
17
|
-
*/
|
18
|
-
|
19
|
-
/**
|
20
|
-
* The <i>x</i>-position of the particle.
|
21
|
-
*
|
22
|
-
* @field
|
23
|
-
* @type number
|
24
|
-
* @name pv.Particle.prototype.x
|
25
|
-
*/
|
26
|
-
|
27
|
-
/**
|
28
|
-
* The <i>y</i>-position of the particle.
|
29
|
-
*
|
30
|
-
* @field
|
31
|
-
* @type number
|
32
|
-
* @name pv.Particle.prototype.y
|
33
|
-
*/
|
34
|
-
|
35
|
-
/**
|
36
|
-
* The <i>x</i>-velocity of the particle.
|
37
|
-
*
|
38
|
-
* @field
|
39
|
-
* @type number
|
40
|
-
* @name pv.Particle.prototype.vx
|
41
|
-
*/
|
42
|
-
|
43
|
-
/**
|
44
|
-
* The <i>y</i>-velocity of the particle.
|
45
|
-
*
|
46
|
-
* @field
|
47
|
-
* @type number
|
48
|
-
* @name pv.Particle.prototype.vy
|
49
|
-
*/
|
50
|
-
|
51
|
-
/**
|
52
|
-
* The <i>x</i>-position of the particle at -dt.
|
53
|
-
*
|
54
|
-
* @field
|
55
|
-
* @type number
|
56
|
-
* @name pv.Particle.prototype.px
|
57
|
-
*/
|
58
|
-
|
59
|
-
/**
|
60
|
-
* The <i>y</i>-position of the particle at -dt.
|
61
|
-
*
|
62
|
-
* @field
|
63
|
-
* @type number
|
64
|
-
* @name pv.Particle.prototype.py
|
65
|
-
*/
|
66
|
-
|
67
|
-
/**
|
68
|
-
* The <i>x</i>-force on the particle.
|
69
|
-
*
|
70
|
-
* @field
|
71
|
-
* @type number
|
72
|
-
* @name pv.Particle.prototype.fx
|
73
|
-
*/
|
74
|
-
|
75
|
-
/**
|
76
|
-
* The <i>y</i>-force on the particle.
|
77
|
-
*
|
78
|
-
* @field
|
79
|
-
* @type number
|
80
|
-
* @name pv.Particle.prototype.fy
|
81
|
-
*/
|
@@ -1,72 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Constructs a default position constraint using the <tt>fix</tt> attribute.
|
3
|
-
* An optional position function can be specified to determine how the fixed
|
4
|
-
* position per-particle is determined.
|
5
|
-
*
|
6
|
-
* @class Constraints particles to a fixed position. The fixed position per
|
7
|
-
* particle is determined using a given position function, which defaults to
|
8
|
-
* <tt>function(d) d.fix</tt>.
|
9
|
-
*
|
10
|
-
* <p>If the position function returns null, then no position constraint is
|
11
|
-
* applied to the given particle. Otherwise, the particle's position is set to
|
12
|
-
* the returned position, as expressed by a {@link pv.Vector}. (Note: the
|
13
|
-
* position does not need to be an instance of <tt>pv.Vector</tt>, but simply an
|
14
|
-
* object with <tt>x</tt> and <tt>y</tt> attributes.)
|
15
|
-
*
|
16
|
-
* <p>This constraint also supports a configurable alpha parameter, which
|
17
|
-
* defaults to 1. If the alpha parameter is in the range [0,1], then rather than
|
18
|
-
* setting the particle's new position directly to the position returned by the
|
19
|
-
* supplied position function, the particle's position is interpolated towards
|
20
|
-
* the fixed position. This results is a smooth (exponential) drift towards the
|
21
|
-
* fixed position, which can increase the stability of the physics simulation.
|
22
|
-
* In addition, the alpha parameter can be decayed over time, relaxing the
|
23
|
-
* position constraint, which helps to stabilize on an optimal solution.
|
24
|
-
*
|
25
|
-
* @param {function} [f] the position function.
|
26
|
-
*/
|
27
|
-
pv.Constraint.position = function(f) {
|
28
|
-
var a = 1, // default alpha
|
29
|
-
constraint = {};
|
30
|
-
|
31
|
-
if (!arguments.length) /** @ignore */ f = function(p) { return p.fix; };
|
32
|
-
|
33
|
-
/**
|
34
|
-
* Sets or gets the alpha parameter for position interpolation. If the alpha
|
35
|
-
* parameter is in the range [0,1], then rather than setting the particle's
|
36
|
-
* new position directly to the position returned by the supplied position
|
37
|
-
* function, the particle's position is interpolated towards the fixed
|
38
|
-
* position.
|
39
|
-
*
|
40
|
-
* @function
|
41
|
-
* @name pv.Constraint.position.prototype.alpha
|
42
|
-
* @param {number} x the new alpha parameter, in the range [0,1].
|
43
|
-
* @returns {pv.Constraint.position} this.
|
44
|
-
*/
|
45
|
-
constraint.alpha = function(x) {
|
46
|
-
if (arguments.length) {
|
47
|
-
a = Number(x);
|
48
|
-
return constraint;
|
49
|
-
}
|
50
|
-
return a;
|
51
|
-
};
|
52
|
-
|
53
|
-
/**
|
54
|
-
* Applies this constraint to the specified particles.
|
55
|
-
*
|
56
|
-
* @function
|
57
|
-
* @name pv.Constraint.position.prototype.apply
|
58
|
-
* @param {pv.Particle} particles particles to which to apply this constraint.
|
59
|
-
*/
|
60
|
-
constraint.apply = function(particles) {
|
61
|
-
for (var p = particles; p; p = p.next) {
|
62
|
-
var v = f(p);
|
63
|
-
if (v) {
|
64
|
-
p.x += (v.x - p.x) * a;
|
65
|
-
p.y += (v.y - p.y) * a;
|
66
|
-
p.fx = p.fy = p.vx = p.vy = 0;
|
67
|
-
}
|
68
|
-
}
|
69
|
-
};
|
70
|
-
|
71
|
-
return constraint;
|
72
|
-
};
|
@@ -1,195 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Constructs a new quadtree for the specified array of particles.
|
3
|
-
*
|
4
|
-
* @class Represents a quadtree: a two-dimensional recursive spatial
|
5
|
-
* subdivision. This particular implementation uses square partitions, dividing
|
6
|
-
* each square into four equally-sized squares. Each particle exists in a unique
|
7
|
-
* node; if multiple particles are in the same position, some particles may be
|
8
|
-
* stored on internal nodes rather than leaf nodes.
|
9
|
-
*
|
10
|
-
* <p>This quadtree can be used to accelerate various spatial operations, such
|
11
|
-
* as the Barnes-Hut approximation for computing n-body forces, or collision
|
12
|
-
* detection.
|
13
|
-
*
|
14
|
-
* @see pv.Force.charge
|
15
|
-
* @see pv.Constraint.collision
|
16
|
-
* @param {pv.Particle} particles the linked list of particles.
|
17
|
-
*/
|
18
|
-
pv.Quadtree = function(particles) {
|
19
|
-
var p;
|
20
|
-
|
21
|
-
/* Compute bounds. */
|
22
|
-
var x1 = Number.POSITIVE_INFINITY, y1 = x1,
|
23
|
-
x2 = Number.NEGATIVE_INFINITY, y2 = x2;
|
24
|
-
for (p = particles; p; p = p.next) {
|
25
|
-
if (p.x < x1) x1 = p.x;
|
26
|
-
if (p.y < y1) y1 = p.y;
|
27
|
-
if (p.x > x2) x2 = p.x;
|
28
|
-
if (p.y > y2) y2 = p.y;
|
29
|
-
}
|
30
|
-
|
31
|
-
/* Squarify the bounds. */
|
32
|
-
var dx = x2 - x1, dy = y2 - y1;
|
33
|
-
if (dx > dy) y2 = y1 + dx;
|
34
|
-
else x2 = x1 + dy;
|
35
|
-
this.xMin = x1;
|
36
|
-
this.yMin = y1;
|
37
|
-
this.xMax = x2;
|
38
|
-
this.yMax = y2;
|
39
|
-
|
40
|
-
/**
|
41
|
-
* @ignore Recursively inserts the specified particle <i>p</i> at the node
|
42
|
-
* <i>n</i> or one of its descendants. The bounds are defined by [<i>x1</i>,
|
43
|
-
* <i>x2</i>] and [<i>y1</i>, <i>y2</i>].
|
44
|
-
*/
|
45
|
-
function insert(n, p, x1, y1, x2, y2) {
|
46
|
-
if (isNaN(p.x) || isNaN(p.y)) return; // ignore invalid particles
|
47
|
-
if (n.leaf) {
|
48
|
-
if (n.p) {
|
49
|
-
/*
|
50
|
-
* If the particle at this leaf node is at the same position as the new
|
51
|
-
* particle we are adding, we leave the particle associated with the
|
52
|
-
* internal node while adding the new particle to a child node. This
|
53
|
-
* avoids infinite recursion.
|
54
|
-
*/
|
55
|
-
if ((Math.abs(n.p.x - p.x) + Math.abs(n.p.y - p.y)) < .01) {
|
56
|
-
insertChild(n, p, x1, y1, x2, y2);
|
57
|
-
} else {
|
58
|
-
var v = n.p;
|
59
|
-
n.p = null;
|
60
|
-
insertChild(n, v, x1, y1, x2, y2);
|
61
|
-
insertChild(n, p, x1, y1, x2, y2);
|
62
|
-
}
|
63
|
-
} else {
|
64
|
-
n.p = p;
|
65
|
-
}
|
66
|
-
} else {
|
67
|
-
insertChild(n, p, x1, y1, x2, y2);
|
68
|
-
}
|
69
|
-
}
|
70
|
-
|
71
|
-
/**
|
72
|
-
* @ignore Recursively inserts the specified particle <i>p</i> into a
|
73
|
-
* descendant of node <i>n</i>. The bounds are defined by [<i>x1</i>,
|
74
|
-
* <i>x2</i>] and [<i>y1</i>, <i>y2</i>].
|
75
|
-
*/
|
76
|
-
function insertChild(n, p, x1, y1, x2, y2) {
|
77
|
-
/* Compute the split point, and the quadrant in which to insert p. */
|
78
|
-
var sx = (x1 + x2) * .5,
|
79
|
-
sy = (y1 + y2) * .5,
|
80
|
-
right = p.x >= sx,
|
81
|
-
bottom = p.y >= sy;
|
82
|
-
|
83
|
-
/* Recursively insert into the child node. */
|
84
|
-
n.leaf = false;
|
85
|
-
switch ((bottom << 1) + right) {
|
86
|
-
case 0: n = n.c1 || (n.c1 = new pv.Quadtree.Node()); break;
|
87
|
-
case 1: n = n.c2 || (n.c2 = new pv.Quadtree.Node()); break;
|
88
|
-
case 2: n = n.c3 || (n.c3 = new pv.Quadtree.Node()); break;
|
89
|
-
case 3: n = n.c4 || (n.c4 = new pv.Quadtree.Node()); break;
|
90
|
-
}
|
91
|
-
|
92
|
-
/* Update the bounds as we recurse. */
|
93
|
-
if (right) x1 = sx; else x2 = sx;
|
94
|
-
if (bottom) y1 = sy; else y2 = sy;
|
95
|
-
insert(n, p, x1, y1, x2, y2);
|
96
|
-
}
|
97
|
-
|
98
|
-
/* Insert all particles. */
|
99
|
-
this.root = new pv.Quadtree.Node();
|
100
|
-
for (p = particles; p; p = p.next) insert(this.root, p, x1, y1, x2, y2);
|
101
|
-
};
|
102
|
-
|
103
|
-
/**
|
104
|
-
* The root node of the quadtree.
|
105
|
-
*
|
106
|
-
* @type pv.Quadtree.Node
|
107
|
-
* @name pv.Quadtree.prototype.root
|
108
|
-
*/
|
109
|
-
|
110
|
-
/**
|
111
|
-
* The minimum x-coordinate value of all contained particles.
|
112
|
-
*
|
113
|
-
* @type number
|
114
|
-
* @name pv.Quadtree.prototype.xMin
|
115
|
-
*/
|
116
|
-
|
117
|
-
/**
|
118
|
-
* The maximum x-coordinate value of all contained particles.
|
119
|
-
*
|
120
|
-
* @type number
|
121
|
-
* @name pv.Quadtree.prototype.xMax
|
122
|
-
*/
|
123
|
-
|
124
|
-
/**
|
125
|
-
* The minimum y-coordinate value of all contained particles.
|
126
|
-
*
|
127
|
-
* @type number
|
128
|
-
* @name pv.Quadtree.prototype.yMin
|
129
|
-
*/
|
130
|
-
|
131
|
-
/**
|
132
|
-
* The maximum y-coordinate value of all contained particles.
|
133
|
-
*
|
134
|
-
* @type number
|
135
|
-
* @name pv.Quadtree.prototype.yMax
|
136
|
-
*/
|
137
|
-
|
138
|
-
/**
|
139
|
-
* Constructs a new node.
|
140
|
-
*
|
141
|
-
* @class A node in a quadtree.
|
142
|
-
*
|
143
|
-
* @see pv.Quadtree
|
144
|
-
*/
|
145
|
-
pv.Quadtree.Node = function() {
|
146
|
-
/*
|
147
|
-
* Prepopulating all attributes significantly increases performance! Also,
|
148
|
-
* letting the language interpreter manage garbage collection was moderately
|
149
|
-
* faster than creating a cache pool.
|
150
|
-
*/
|
151
|
-
this.leaf = true;
|
152
|
-
this.c1 = null;
|
153
|
-
this.c2 = null;
|
154
|
-
this.c3 = null;
|
155
|
-
this.c4 = null;
|
156
|
-
this.p = null;
|
157
|
-
};
|
158
|
-
|
159
|
-
/**
|
160
|
-
* True if this node is a leaf node; i.e., it has no children. Note that both
|
161
|
-
* leaf nodes and non-leaf (internal) nodes may have associated particles. If
|
162
|
-
* this is a non-leaf node, then at least one of {@link #c1}, {@link #c2},
|
163
|
-
* {@link #c3} or {@link #c4} is guaranteed to be non-null.
|
164
|
-
*
|
165
|
-
* @type boolean
|
166
|
-
* @name pv.Quadtree.Node.prototype.leaf
|
167
|
-
*/
|
168
|
-
|
169
|
-
/**
|
170
|
-
* The particle associated with this node, if any.
|
171
|
-
*
|
172
|
-
* @type pv.Particle
|
173
|
-
* @name pv.Quadtree.Node.prototype.p
|
174
|
-
*/
|
175
|
-
|
176
|
-
/**
|
177
|
-
* The child node for the second quadrant, if any.
|
178
|
-
*
|
179
|
-
* @type pv.Quadtree.Node
|
180
|
-
* @name pv.Quadtree.Node.prototype.c2
|
181
|
-
*/
|
182
|
-
|
183
|
-
/**
|
184
|
-
* The child node for the third quadrant, if any.
|
185
|
-
*
|
186
|
-
* @type pv.Quadtree.Node
|
187
|
-
* @name pv.Quadtree.Node.prototype.c3
|
188
|
-
*/
|
189
|
-
|
190
|
-
/**
|
191
|
-
* The child node for the fourth quadrant, if any.
|
192
|
-
*
|
193
|
-
* @type pv.Quadtree.Node
|
194
|
-
* @name pv.Quadtree.Node.prototype.c4
|
195
|
-
*/
|