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
data/vendor/protovis/src/pv.js
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The top-level Protovis namespace. All public methods and fields should be
|
|
3
|
-
* registered on this object. Note that core Protovis source is surrounded by an
|
|
4
|
-
* anonymous function, so any other declared globals will not be visible outside
|
|
5
|
-
* of core methods. This also allows multiple versions of Protovis to coexist,
|
|
6
|
-
* since each version will see their own <tt>pv</tt> namespace.
|
|
7
|
-
*
|
|
8
|
-
* @namespace The top-level Protovis namespace, <tt>pv</tt>.
|
|
9
|
-
*/
|
|
10
|
-
var pv = {};
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Protovis major and minor version numbers.
|
|
14
|
-
*
|
|
15
|
-
* @namespace Protovis major and minor version numbers.
|
|
16
|
-
*/
|
|
17
|
-
pv.version = {
|
|
18
|
-
/**
|
|
19
|
-
* The major version number.
|
|
20
|
-
*
|
|
21
|
-
* @type number
|
|
22
|
-
* @constant
|
|
23
|
-
*/
|
|
24
|
-
major: 3,
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* The minor version number.
|
|
28
|
-
*
|
|
29
|
-
* @type number
|
|
30
|
-
* @constant
|
|
31
|
-
*/
|
|
32
|
-
minor: 3
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Returns the passed-in argument, <tt>x</tt>; the identity function. This method
|
|
37
|
-
* is provided for convenience since it is used as the default behavior for a
|
|
38
|
-
* number of property functions.
|
|
39
|
-
*
|
|
40
|
-
* @param x a value.
|
|
41
|
-
* @returns the value <tt>x</tt>.
|
|
42
|
-
*/
|
|
43
|
-
pv.identity = function(x) { return x; };
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Returns <tt>this.index</tt>. This method is provided for convenience for use
|
|
47
|
-
* with scales. For example, to color bars by their index, say:
|
|
48
|
-
*
|
|
49
|
-
* <pre>.fillStyle(pv.Colors.category10().by(pv.index))</pre>
|
|
50
|
-
*
|
|
51
|
-
* This method is equivalent to <tt>function() this.index</tt>, but more
|
|
52
|
-
* succinct. Note that the <tt>index</tt> property is also supported for
|
|
53
|
-
* accessor functions with {@link pv.max}, {@link pv.min} and other array
|
|
54
|
-
* utility methods.
|
|
55
|
-
*
|
|
56
|
-
* @see pv.Scale
|
|
57
|
-
* @see pv.Mark#index
|
|
58
|
-
*/
|
|
59
|
-
pv.index = function() { return this.index; };
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Returns <tt>this.childIndex</tt>. This method is provided for convenience for
|
|
63
|
-
* use with scales. For example, to color bars by their child index, say:
|
|
64
|
-
*
|
|
65
|
-
* <pre>.fillStyle(pv.Colors.category10().by(pv.child))</pre>
|
|
66
|
-
*
|
|
67
|
-
* This method is equivalent to <tt>function() this.childIndex</tt>, but more
|
|
68
|
-
* succinct.
|
|
69
|
-
*
|
|
70
|
-
* @see pv.Scale
|
|
71
|
-
* @see pv.Mark#childIndex
|
|
72
|
-
*/
|
|
73
|
-
pv.child = function() { return this.childIndex; };
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Returns <tt>this.parent.index</tt>. This method is provided for convenience
|
|
77
|
-
* for use with scales. This method is provided for convenience for use with
|
|
78
|
-
* scales. For example, to color bars by their parent index, say:
|
|
79
|
-
*
|
|
80
|
-
* <pre>.fillStyle(pv.Colors.category10().by(pv.parent))</pre>
|
|
81
|
-
*
|
|
82
|
-
* Tthis method is equivalent to <tt>function() this.parent.index</tt>, but more
|
|
83
|
-
* succinct.
|
|
84
|
-
*
|
|
85
|
-
* @see pv.Scale
|
|
86
|
-
* @see pv.Mark#index
|
|
87
|
-
*/
|
|
88
|
-
pv.parent = function() { return this.parent.index; };
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Stores the current event. This field is only set within event handlers.
|
|
92
|
-
*
|
|
93
|
-
* @type Event
|
|
94
|
-
* @name pv.event
|
|
95
|
-
*/
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
pv.SvgScene.area = function(scenes) {
|
|
2
|
-
var e = scenes.$g.firstChild;
|
|
3
|
-
if (!scenes.length) return e;
|
|
4
|
-
var s = scenes[0];
|
|
5
|
-
|
|
6
|
-
/* segmented */
|
|
7
|
-
if (s.segmented) return this.areaSegment(scenes);
|
|
8
|
-
|
|
9
|
-
/* visible */
|
|
10
|
-
if (!s.visible) return e;
|
|
11
|
-
var fill = s.fillStyle, stroke = s.strokeStyle;
|
|
12
|
-
if (!fill.opacity && !stroke.opacity) return e;
|
|
13
|
-
|
|
14
|
-
/** @private Computes the straight path for the range [i, j]. */
|
|
15
|
-
function path(i, j) {
|
|
16
|
-
var p1 = [], p2 = [];
|
|
17
|
-
for (var k = j; i <= k; i++, j--) {
|
|
18
|
-
var si = scenes[i],
|
|
19
|
-
sj = scenes[j],
|
|
20
|
-
pi = si.left + "," + si.top,
|
|
21
|
-
pj = (sj.left + sj.width) + "," + (sj.top + sj.height);
|
|
22
|
-
|
|
23
|
-
/* interpolate */
|
|
24
|
-
if (i < k) {
|
|
25
|
-
var sk = scenes[i + 1], sl = scenes[j - 1];
|
|
26
|
-
switch (s.interpolate) {
|
|
27
|
-
case "step-before": {
|
|
28
|
-
pi += "V" + sk.top;
|
|
29
|
-
pj += "H" + (sl.left + sl.width);
|
|
30
|
-
break;
|
|
31
|
-
}
|
|
32
|
-
case "step-after": {
|
|
33
|
-
pi += "H" + sk.left;
|
|
34
|
-
pj += "V" + (sl.top + sl.height);
|
|
35
|
-
break;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
p1.push(pi);
|
|
41
|
-
p2.push(pj);
|
|
42
|
-
}
|
|
43
|
-
return p1.concat(p2).join("L");
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** @private Computes the curved path for the range [i, j]. */
|
|
47
|
-
function pathCurve(i, j) {
|
|
48
|
-
var pointsT = [], pointsB = [], pathT, pathB;
|
|
49
|
-
|
|
50
|
-
for (var k = j; i <= k; i++, j--) {
|
|
51
|
-
var sj = scenes[j];
|
|
52
|
-
pointsT.push(scenes[i]);
|
|
53
|
-
pointsB.push({left: sj.left + sj.width, top: sj.top + sj.height});
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (s.interpolate == "basis") {
|
|
57
|
-
pathT = pv.SvgScene.curveBasis(pointsT);
|
|
58
|
-
pathB = pv.SvgScene.curveBasis(pointsB);
|
|
59
|
-
} else if (s.interpolate == "cardinal") {
|
|
60
|
-
pathT = pv.SvgScene.curveCardinal(pointsT, s.tension);
|
|
61
|
-
pathB = pv.SvgScene.curveCardinal(pointsB, s.tension);
|
|
62
|
-
} else { // monotone
|
|
63
|
-
pathT = pv.SvgScene.curveMonotone(pointsT);
|
|
64
|
-
pathB = pv.SvgScene.curveMonotone(pointsB);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return pointsT[0].left + "," + pointsT[0].top + pathT
|
|
68
|
-
+ "L" + pointsB[0].left + "," + pointsB[0].top + pathB;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/* points */
|
|
72
|
-
var d = [], si, sj;
|
|
73
|
-
for (var i = 0; i < scenes.length; i++) {
|
|
74
|
-
si = scenes[i]; if (!si.width && !si.height) continue;
|
|
75
|
-
for (var j = i + 1; j < scenes.length; j++) {
|
|
76
|
-
sj = scenes[j]; if (!sj.width && !sj.height) break;
|
|
77
|
-
}
|
|
78
|
-
if (i && (s.interpolate != "step-after")) i--;
|
|
79
|
-
if ((j < scenes.length) && (s.interpolate != "step-before")) j++;
|
|
80
|
-
d.push(((j - i > 2
|
|
81
|
-
&& (s.interpolate == "basis"
|
|
82
|
-
|| s.interpolate == "cardinal"
|
|
83
|
-
|| s.interpolate == "monotone"))
|
|
84
|
-
? pathCurve : path)(i, j - 1));
|
|
85
|
-
i = j - 1;
|
|
86
|
-
}
|
|
87
|
-
if (!d.length) return e;
|
|
88
|
-
|
|
89
|
-
e = this.expect(e, "path", {
|
|
90
|
-
"shape-rendering": s.antialias ? null : "crispEdges",
|
|
91
|
-
"pointer-events": s.events,
|
|
92
|
-
"cursor": s.cursor,
|
|
93
|
-
"d": "M" + d.join("ZM") + "Z",
|
|
94
|
-
"fill": fill.color,
|
|
95
|
-
"fill-opacity": fill.opacity || null,
|
|
96
|
-
"stroke": stroke.color,
|
|
97
|
-
"stroke-opacity": stroke.opacity || null,
|
|
98
|
-
"stroke-width": stroke.opacity ? s.lineWidth / this.scale : null
|
|
99
|
-
});
|
|
100
|
-
return this.append(e, scenes, 0);
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
pv.SvgScene.areaSegment = function(scenes) {
|
|
104
|
-
var e = scenes.$g.firstChild, s = scenes[0], pathsT, pathsB;
|
|
105
|
-
if (s.interpolate == "basis"
|
|
106
|
-
|| s.interpolate == "cardinal"
|
|
107
|
-
|| s.interpolate == "monotone") {
|
|
108
|
-
var pointsT = [], pointsB = [];
|
|
109
|
-
|
|
110
|
-
for (var i = 0, n = scenes.length; i < n; i++) {
|
|
111
|
-
var sj = scenes[n - i - 1];
|
|
112
|
-
pointsT.push(scenes[i]);
|
|
113
|
-
pointsB.push({left: sj.left + sj.width, top: sj.top + sj.height});
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if (s.interpolate == "basis") {
|
|
117
|
-
pathsT = this.curveBasisSegments(pointsT);
|
|
118
|
-
pathsB = this.curveBasisSegments(pointsB);
|
|
119
|
-
} else if (s.interpolate == "cardinal") {
|
|
120
|
-
pathsT = this.curveCardinalSegments(pointsT, s.tension);
|
|
121
|
-
pathsB = this.curveCardinalSegments(pointsB, s.tension);
|
|
122
|
-
} else { // monotone
|
|
123
|
-
pathsT = this.curveMonotoneSegments(pointsT);
|
|
124
|
-
pathsB = this.curveMonotoneSegments(pointsB);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
for (var i = 0, n = scenes.length - 1; i < n; i++) {
|
|
129
|
-
var s1 = scenes[i], s2 = scenes[i + 1];
|
|
130
|
-
|
|
131
|
-
/* visible */
|
|
132
|
-
if (!s1.visible || !s2.visible) continue;
|
|
133
|
-
var fill = s1.fillStyle, stroke = s1.strokeStyle;
|
|
134
|
-
if (!fill.opacity && !stroke.opacity) continue;
|
|
135
|
-
|
|
136
|
-
var d;
|
|
137
|
-
if (pathsT) {
|
|
138
|
-
var pathT = pathsT[i],
|
|
139
|
-
pathB = "L" + pathsB[n - i - 1].substr(1);
|
|
140
|
-
|
|
141
|
-
d = pathT + pathB + "Z";
|
|
142
|
-
} else {
|
|
143
|
-
/* interpolate */
|
|
144
|
-
var si = s1, sj = s2;
|
|
145
|
-
switch (s1.interpolate) {
|
|
146
|
-
case "step-before": si = s2; break;
|
|
147
|
-
case "step-after": sj = s1; break;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/* path */
|
|
151
|
-
d = "M" + s1.left + "," + si.top
|
|
152
|
-
+ "L" + s2.left + "," + sj.top
|
|
153
|
-
+ "L" + (s2.left + s2.width) + "," + (sj.top + sj.height)
|
|
154
|
-
+ "L" + (s1.left + s1.width) + "," + (si.top + si.height)
|
|
155
|
-
+ "Z";
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
e = this.expect(e, "path", {
|
|
159
|
-
"shape-rendering": s1.antialias ? null : "crispEdges",
|
|
160
|
-
"pointer-events": s1.events,
|
|
161
|
-
"cursor": s1.cursor,
|
|
162
|
-
"d": d,
|
|
163
|
-
"fill": fill.color,
|
|
164
|
-
"fill-opacity": fill.opacity || null,
|
|
165
|
-
"stroke": stroke.color,
|
|
166
|
-
"stroke-opacity": stroke.opacity || null,
|
|
167
|
-
"stroke-width": stroke.opacity ? s1.lineWidth / this.scale : null
|
|
168
|
-
});
|
|
169
|
-
e = this.append(e, scenes, i);
|
|
170
|
-
}
|
|
171
|
-
return e;
|
|
172
|
-
};
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
pv.SvgScene.bar = function(scenes) {
|
|
2
|
-
var e = scenes.$g.firstChild;
|
|
3
|
-
for (var i = 0; i < scenes.length; i++) {
|
|
4
|
-
var s = scenes[i];
|
|
5
|
-
|
|
6
|
-
/* visible */
|
|
7
|
-
if (!s.visible) continue;
|
|
8
|
-
var fill = s.fillStyle, stroke = s.strokeStyle;
|
|
9
|
-
if (!fill.opacity && !stroke.opacity) continue;
|
|
10
|
-
|
|
11
|
-
e = this.expect(e, "rect", {
|
|
12
|
-
"shape-rendering": s.antialias ? null : "crispEdges",
|
|
13
|
-
"pointer-events": s.events,
|
|
14
|
-
"cursor": s.cursor,
|
|
15
|
-
"x": s.left,
|
|
16
|
-
"y": s.top,
|
|
17
|
-
"width": Math.max(1E-10, s.width),
|
|
18
|
-
"height": Math.max(1E-10, s.height),
|
|
19
|
-
"fill": fill.color,
|
|
20
|
-
"fill-opacity": fill.opacity || null,
|
|
21
|
-
"stroke": stroke.color,
|
|
22
|
-
"stroke-opacity": stroke.opacity || null,
|
|
23
|
-
"stroke-width": stroke.opacity ? s.lineWidth / this.scale : null
|
|
24
|
-
});
|
|
25
|
-
e = this.append(e, scenes, i);
|
|
26
|
-
}
|
|
27
|
-
return e;
|
|
28
|
-
};
|
|
@@ -1,354 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @private Converts the specified b-spline curve segment to a bezier curve
|
|
3
|
-
* compatible with SVG "C".
|
|
4
|
-
*
|
|
5
|
-
* @param p0 the first control point.
|
|
6
|
-
* @param p1 the second control point.
|
|
7
|
-
* @param p2 the third control point.
|
|
8
|
-
* @param p3 the fourth control point.
|
|
9
|
-
*/
|
|
10
|
-
pv.SvgScene.pathBasis = (function() {
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Matrix to transform basis (b-spline) control points to bezier control
|
|
14
|
-
* points. Derived from FvD 11.2.8.
|
|
15
|
-
*/
|
|
16
|
-
var basis = [
|
|
17
|
-
[ 1/6, 2/3, 1/6, 0 ],
|
|
18
|
-
[ 0, 2/3, 1/3, 0 ],
|
|
19
|
-
[ 0, 1/3, 2/3, 0 ],
|
|
20
|
-
[ 0, 1/6, 2/3, 1/6 ]
|
|
21
|
-
];
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Returns the point that is the weighted sum of the specified control points,
|
|
25
|
-
* using the specified weights. This method requires that there are four
|
|
26
|
-
* weights and four control points.
|
|
27
|
-
*/
|
|
28
|
-
function weight(w, p0, p1, p2, p3) {
|
|
29
|
-
return {
|
|
30
|
-
x: w[0] * p0.left + w[1] * p1.left + w[2] * p2.left + w[3] * p3.left,
|
|
31
|
-
y: w[0] * p0.top + w[1] * p1.top + w[2] * p2.top + w[3] * p3.top
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
var convert = function(p0, p1, p2, p3) {
|
|
36
|
-
var b1 = weight(basis[1], p0, p1, p2, p3),
|
|
37
|
-
b2 = weight(basis[2], p0, p1, p2, p3),
|
|
38
|
-
b3 = weight(basis[3], p0, p1, p2, p3);
|
|
39
|
-
return "C" + b1.x + "," + b1.y
|
|
40
|
-
+ "," + b2.x + "," + b2.y
|
|
41
|
-
+ "," + b3.x + "," + b3.y;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
convert.segment = function(p0, p1, p2, p3) {
|
|
45
|
-
var b0 = weight(basis[0], p0, p1, p2, p3),
|
|
46
|
-
b1 = weight(basis[1], p0, p1, p2, p3),
|
|
47
|
-
b2 = weight(basis[2], p0, p1, p2, p3),
|
|
48
|
-
b3 = weight(basis[3], p0, p1, p2, p3);
|
|
49
|
-
return "M" + b0.x + "," + b0.y
|
|
50
|
-
+ "C" + b1.x + "," + b1.y
|
|
51
|
-
+ "," + b2.x + "," + b2.y
|
|
52
|
-
+ "," + b3.x + "," + b3.y;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
return convert;
|
|
56
|
-
})();
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* @private Interpolates the given points using the basis spline interpolation.
|
|
60
|
-
* Returns an SVG path without the leading M instruction to allow path
|
|
61
|
-
* appending.
|
|
62
|
-
*
|
|
63
|
-
* @param points the array of points.
|
|
64
|
-
*/
|
|
65
|
-
pv.SvgScene.curveBasis = function(points) {
|
|
66
|
-
if (points.length <= 2) return "";
|
|
67
|
-
var path = "",
|
|
68
|
-
p0 = points[0],
|
|
69
|
-
p1 = p0,
|
|
70
|
-
p2 = p0,
|
|
71
|
-
p3 = points[1];
|
|
72
|
-
path += this.pathBasis(p0, p1, p2, p3);
|
|
73
|
-
for (var i = 2; i < points.length; i++) {
|
|
74
|
-
p0 = p1;
|
|
75
|
-
p1 = p2;
|
|
76
|
-
p2 = p3;
|
|
77
|
-
p3 = points[i];
|
|
78
|
-
path += this.pathBasis(p0, p1, p2, p3);
|
|
79
|
-
}
|
|
80
|
-
/* Cycle through to get the last point. */
|
|
81
|
-
path += this.pathBasis(p1, p2, p3, p3);
|
|
82
|
-
path += this.pathBasis(p2, p3, p3, p3);
|
|
83
|
-
return path;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* @private Interpolates the given points using the basis spline interpolation.
|
|
88
|
-
* If points.length == tangents.length then a regular Hermite interpolation is
|
|
89
|
-
* performed, if points.length == tangents.length + 2 then the first and last
|
|
90
|
-
* segments are filled in with cubic bazier segments. Returns an array of path
|
|
91
|
-
* strings.
|
|
92
|
-
*
|
|
93
|
-
* @param points the array of points.
|
|
94
|
-
*/
|
|
95
|
-
pv.SvgScene.curveBasisSegments = function(points) {
|
|
96
|
-
if (points.length <= 2) return "";
|
|
97
|
-
var paths = [],
|
|
98
|
-
p0 = points[0],
|
|
99
|
-
p1 = p0,
|
|
100
|
-
p2 = p0,
|
|
101
|
-
p3 = points[1],
|
|
102
|
-
firstPath = this.pathBasis.segment(p0, p1, p2, p3);
|
|
103
|
-
|
|
104
|
-
p0 = p1;
|
|
105
|
-
p1 = p2;
|
|
106
|
-
p2 = p3;
|
|
107
|
-
p3 = points[2];
|
|
108
|
-
paths.push(firstPath + this.pathBasis(p0, p1, p2, p3)); // merge first & second path
|
|
109
|
-
for (var i = 3; i < points.length; i++) {
|
|
110
|
-
p0 = p1;
|
|
111
|
-
p1 = p2;
|
|
112
|
-
p2 = p3;
|
|
113
|
-
p3 = points[i];
|
|
114
|
-
paths.push(this.pathBasis.segment(p0, p1, p2, p3));
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// merge last & second-to-last path
|
|
118
|
-
paths.push(this.pathBasis.segment(p1, p2, p3, p3) + this.pathBasis(p2, p3, p3, p3));
|
|
119
|
-
return paths;
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* @private Interpolates the given points with respective tangents using the cubic
|
|
124
|
-
* Hermite spline interpolation. If points.length == tangents.length then a regular
|
|
125
|
-
* Hermite interpolation is performed, if points.length == tangents.length + 2 then
|
|
126
|
-
* the first and last segments are filled in with cubic bazier segments.
|
|
127
|
-
* Returns an SVG path without the leading M instruction to allow path appending.
|
|
128
|
-
*
|
|
129
|
-
* @param points the array of points.
|
|
130
|
-
* @param tangents the array of tangent vectors.
|
|
131
|
-
*/
|
|
132
|
-
pv.SvgScene.curveHermite = function(points, tangents) {
|
|
133
|
-
if (tangents.length < 1
|
|
134
|
-
|| (points.length != tangents.length
|
|
135
|
-
&& points.length != tangents.length + 2)) return "";
|
|
136
|
-
var quad = points.length != tangents.length,
|
|
137
|
-
path = "",
|
|
138
|
-
p0 = points[0],
|
|
139
|
-
p = points[1],
|
|
140
|
-
t0 = tangents[0],
|
|
141
|
-
t = t0,
|
|
142
|
-
pi = 1;
|
|
143
|
-
|
|
144
|
-
if (quad) {
|
|
145
|
-
path += "Q" + (p.left - t0.x * 2 / 3) + "," + (p.top - t0.y * 2 / 3)
|
|
146
|
-
+ "," + p.left + "," + p.top;
|
|
147
|
-
p0 = points[1];
|
|
148
|
-
pi = 2;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (tangents.length > 1) {
|
|
152
|
-
t = tangents[1];
|
|
153
|
-
p = points[pi];
|
|
154
|
-
pi++;
|
|
155
|
-
path += "C" + (p0.left + t0.x) + "," + (p0.top + t0.y)
|
|
156
|
-
+ "," + (p.left - t.x) + "," + (p.top - t.y)
|
|
157
|
-
+ "," + p.left + "," + p.top;
|
|
158
|
-
for (var i = 2; i < tangents.length; i++, pi++) {
|
|
159
|
-
p = points[pi];
|
|
160
|
-
t = tangents[i];
|
|
161
|
-
path += "S" + (p.left - t.x) + "," + (p.top - t.y)
|
|
162
|
-
+ "," + p.left + "," + p.top;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
if (quad) {
|
|
167
|
-
var lp = points[pi];
|
|
168
|
-
path += "Q" + (p.left + t.x * 2 / 3) + "," + (p.top + t.y * 2 / 3) + ","
|
|
169
|
-
+ lp.left + "," + lp.top;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return path;
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* @private Interpolates the given points with respective tangents using the
|
|
177
|
-
* cubic Hermite spline interpolation. Returns an array of path strings.
|
|
178
|
-
*
|
|
179
|
-
* @param points the array of points.
|
|
180
|
-
* @param tangents the array of tangent vectors.
|
|
181
|
-
*/
|
|
182
|
-
pv.SvgScene.curveHermiteSegments = function(points, tangents) {
|
|
183
|
-
if (tangents.length < 1
|
|
184
|
-
|| (points.length != tangents.length
|
|
185
|
-
&& points.length != tangents.length + 2)) return [];
|
|
186
|
-
var quad = points.length != tangents.length,
|
|
187
|
-
paths = [],
|
|
188
|
-
p0 = points[0],
|
|
189
|
-
p = p0,
|
|
190
|
-
t0 = tangents[0],
|
|
191
|
-
t = t0,
|
|
192
|
-
pi = 1;
|
|
193
|
-
|
|
194
|
-
if (quad) {
|
|
195
|
-
p = points[1];
|
|
196
|
-
paths.push("M" + p0.left + "," + p0.top
|
|
197
|
-
+ "Q" + (p.left - t.x * 2 / 3) + "," + (p.top - t.y * 2 / 3)
|
|
198
|
-
+ "," + p.left + "," + p.top);
|
|
199
|
-
pi = 2;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
for (var i = 1; i < tangents.length; i++, pi++) {
|
|
203
|
-
p0 = p;
|
|
204
|
-
t0 = t;
|
|
205
|
-
p = points[pi];
|
|
206
|
-
t = tangents[i];
|
|
207
|
-
paths.push("M" + p0.left + "," + p0.top
|
|
208
|
-
+ "C" + (p0.left + t0.x) + "," + (p0.top + t0.y)
|
|
209
|
-
+ "," + (p.left - t.x) + "," + (p.top - t.y)
|
|
210
|
-
+ "," + p.left + "," + p.top);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
if (quad) {
|
|
214
|
-
var lp = points[pi];
|
|
215
|
-
paths.push("M" + p.left + "," + p.top
|
|
216
|
-
+ "Q" + (p.left + t.x * 2 / 3) + "," + (p.top + t.y * 2 / 3) + ","
|
|
217
|
-
+ lp.left + "," + lp.top);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
return paths;
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* @private Computes the tangents for the given points needed for cardinal
|
|
225
|
-
* spline interpolation. Returns an array of tangent vectors. Note: that for n
|
|
226
|
-
* points only the n-2 well defined tangents are returned.
|
|
227
|
-
*
|
|
228
|
-
* @param points the array of points.
|
|
229
|
-
* @param tension the tension of hte cardinal spline.
|
|
230
|
-
*/
|
|
231
|
-
pv.SvgScene.cardinalTangents = function(points, tension) {
|
|
232
|
-
var tangents = [],
|
|
233
|
-
a = (1 - tension) / 2,
|
|
234
|
-
p0 = points[0],
|
|
235
|
-
p1 = points[1],
|
|
236
|
-
p2 = points[2];
|
|
237
|
-
|
|
238
|
-
for (var i = 3; i < points.length; i++) {
|
|
239
|
-
tangents.push({x: a * (p2.left - p0.left), y: a * (p2.top - p0.top)});
|
|
240
|
-
p0 = p1;
|
|
241
|
-
p1 = p2;
|
|
242
|
-
p2 = points[i];
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
tangents.push({x: a * (p2.left - p0.left), y: a * (p2.top - p0.top)});
|
|
246
|
-
return tangents;
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* @private Interpolates the given points using cardinal spline interpolation.
|
|
251
|
-
* Returns an SVG path without the leading M instruction to allow path
|
|
252
|
-
* appending.
|
|
253
|
-
*
|
|
254
|
-
* @param points the array of points.
|
|
255
|
-
* @param tension the tension of hte cardinal spline.
|
|
256
|
-
*/
|
|
257
|
-
pv.SvgScene.curveCardinal = function(points, tension) {
|
|
258
|
-
if (points.length <= 2) return "";
|
|
259
|
-
return this.curveHermite(points, this.cardinalTangents(points, tension));
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* @private Interpolates the given points using cardinal spline interpolation.
|
|
264
|
-
* Returns an array of path strings.
|
|
265
|
-
*
|
|
266
|
-
* @param points the array of points.
|
|
267
|
-
* @param tension the tension of hte cardinal spline.
|
|
268
|
-
*/
|
|
269
|
-
pv.SvgScene.curveCardinalSegments = function(points, tension) {
|
|
270
|
-
if (points.length <= 2) return "";
|
|
271
|
-
return this.curveHermiteSegments(points, this.cardinalTangents(points, tension));
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* @private Interpolates the given points using Fritsch-Carlson Monotone cubic
|
|
276
|
-
* Hermite interpolation. Returns an array of tangent vectors.
|
|
277
|
-
*
|
|
278
|
-
* @param points the array of points.
|
|
279
|
-
*/
|
|
280
|
-
pv.SvgScene.monotoneTangents = function(points) {
|
|
281
|
-
var tangents = [],
|
|
282
|
-
d = [],
|
|
283
|
-
m = [],
|
|
284
|
-
dx = [],
|
|
285
|
-
k = 0;
|
|
286
|
-
|
|
287
|
-
/* Compute the slopes of the secant lines between successive points. */
|
|
288
|
-
for (k = 0; k < points.length-1; k++) {
|
|
289
|
-
d[k] = (points[k+1].top - points[k].top)/(points[k+1].left - points[k].left);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/* Initialize the tangents at every point as the average of the secants. */
|
|
293
|
-
m[0] = d[0];
|
|
294
|
-
dx[0] = points[1].left - points[0].left;
|
|
295
|
-
for (k = 1; k < points.length - 1; k++) {
|
|
296
|
-
m[k] = (d[k-1]+d[k])/2;
|
|
297
|
-
dx[k] = (points[k+1].left - points[k-1].left)/2;
|
|
298
|
-
}
|
|
299
|
-
m[k] = d[k-1];
|
|
300
|
-
dx[k] = (points[k].left - points[k-1].left);
|
|
301
|
-
|
|
302
|
-
/* Step 3. Very important, step 3. Yep. Wouldn't miss it. */
|
|
303
|
-
for (k = 0; k < points.length - 1; k++) {
|
|
304
|
-
if (d[k] == 0) {
|
|
305
|
-
m[ k ] = 0;
|
|
306
|
-
m[k+1] = 0;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
/* Step 4 + 5. Out of 5 or more steps. */
|
|
311
|
-
for (k = 0; k < points.length - 1; k++) {
|
|
312
|
-
if ((Math.abs(m[k]) < 1e-5) || (Math.abs(m[k+1]) < 1e-5)) continue;
|
|
313
|
-
var ak = m[k] / d[k],
|
|
314
|
-
bk = m[k + 1] / d[k],
|
|
315
|
-
s = ak * ak + bk * bk; // monotone constant (?)
|
|
316
|
-
if (s > 9) {
|
|
317
|
-
var tk = 3 / Math.sqrt(s);
|
|
318
|
-
m[k] = tk * ak * d[k];
|
|
319
|
-
m[k + 1] = tk * bk * d[k];
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
var len;
|
|
324
|
-
for (var i = 0; i < points.length; i++) {
|
|
325
|
-
len = 1 + m[i] * m[i]; // pv.vector(1, m[i]).norm().times(dx[i]/3)
|
|
326
|
-
tangents.push({x: dx[i] / 3 / len, y: m[i] * dx[i] / 3 / len});
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
return tangents;
|
|
330
|
-
};
|
|
331
|
-
|
|
332
|
-
/**
|
|
333
|
-
* @private Interpolates the given points using Fritsch-Carlson Monotone cubic
|
|
334
|
-
* Hermite interpolation. Returns an SVG path without the leading M instruction
|
|
335
|
-
* to allow path appending.
|
|
336
|
-
*
|
|
337
|
-
* @param points the array of points.
|
|
338
|
-
*/
|
|
339
|
-
pv.SvgScene.curveMonotone = function(points) {
|
|
340
|
-
if (points.length <= 2) return "";
|
|
341
|
-
return this.curveHermite(points, this.monotoneTangents(points));
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* @private Interpolates the given points using Fritsch-Carlson Monotone cubic
|
|
346
|
-
* Hermite interpolation.
|
|
347
|
-
* Returns an array of path strings.
|
|
348
|
-
*
|
|
349
|
-
* @param points the array of points.
|
|
350
|
-
*/
|
|
351
|
-
pv.SvgScene.curveMonotoneSegments = function(points) {
|
|
352
|
-
if (points.length <= 2) return "";
|
|
353
|
-
return this.curveHermiteSegments(points, this.monotoneTangents(points));
|
|
354
|
-
};
|