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