UNPKG

2.21 kBMarkdownView Raw
1Here's what it looks like:
2
3![screen recording](smooth-plotter-p1-recording.gif)
4
5This uses cubic splines (aka bezier curves) to smooth out the lines
6between points. To draw a bezier curve between two points, you must also
7specify two control points which specify how it bends:
8
9![bezier_curve](smooth-plotter-p2-bezier.png)
10
11The problem is to determine those control points.
12
13When you connect a bunch of bezier curves, each original point in the
14series has both a left control point and a right control point. To avoid
15forming a kink in the chart, the left control point, the series point
16and the right control point all need to fall on a line.
17
18The algorithm I wound up using follows the HighCharts implementation of
19this. Here's how it works...
20
21The setup is that you have a point whose left & right controls you're
22trying to determine. You also know the previous and next point:
23
24![setup](smooth-plotter-p3-setup.png)
25
26Start by placing the control points α of the way along each line
27segment. This is the only parameter we'll need to control the amount of
28smoothing:
29
30![controls on line](smooth-plotter-p4-on-line.png)
31
32But now we've broken the rule that the original point has to be on the
33line between the control points! To fix that, we shift the control
34points up by ∆y, which can be determined with some simple algebra:
35
36![controls shifted](smooth-plotter-p5-shifted.png)
37
38But this introduces a new problem: the right control point is above the
39data points, and so it will create an impression of a false maximum to
40the right of the data point. To fix this, we cap the y-value of the
41control points:
42
43![controls capped](smooth-plotter-p6-capped.png)
44
45But now we've re-broken that rule about being on a line. So we have to
46do the mirror-image adjustment to the left control point:
47
48![controls capped and adjusted](smooth-plotter-p7-adjusted.png)
49
50and now we have our control points!
51
52Hopefully the algorithm makes good sense now. I implemented this as a
53separate plotter in `/extras` for now, but it might make more sense to
54move this into core dygraphs. That would make it easier to have the
55smooth plots play nicely with other options like
56`connectSeparatedPoints`, `strokePattern` and `drawPoints`.