Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Smooth plotter using bezier curves #469

Merged
merged 2 commits into from
Nov 16, 2014
Merged

Smooth plotter using bezier curves #469

merged 2 commits into from
Nov 16, 2014

Conversation

danvk
Copy link
Owner

@danvk danvk commented Nov 15, 2014

Fixes #370, one of our more popular issues.

Here's what it looks like:
screen recording 2014-11-15 at 04 08 pm

This uses cubic splines (aka bezier curves) to smooth out the lines between points. To draw a bezier curve between two points, you must also specify two control points which specify how it bends:

300px-bezier_curve svg

The problem is to determine those control points.

When you connect a bunch of bezier curves, each original point in the series has both a left control point and a right control point. To avoid forming a kink in the chart, the left control point, the series point and the right control point all need to fall on a line.

The algorithm I wound up using follows the HighCharts implementation of this. Here's how it works...

The setup is that you have a point whose left & right controls you're trying to determine. You also know the previous and next point:
setup

Start by placing the control points α of the way along each line segment. This is the only parameter we'll need to control the amount of smoothing:
controls on line

But now we've broken the rule that the original point has to be on the line between the control points! To fix that, we shift the control points up by ∆y, which can be determined with some simple algebra:
controls shifted

But this introduces a new problem: the right control point is above the data points, and so it will create an impression of a false maximum to the right of the data point. To fix this, we cap the y-value of the control points:
controls capped

But now we've re-broken that rule about being on a line. So we have to do the mirror-image adjustment to the left control point:
controls capped and adjusted

and now we have our control points!

Hopefully the algorithm makes good sense now. I implemented this as a separate plotter in /extras for now, but it might make more sense to move this into core dygraphs. That would make it easier to have the smooth plots play nicely with other options like connectSeparatedPoints, strokePattern and drawPoints.

@kberg
Copy link
Collaborator

kberg commented Nov 16, 2014

It's tough for me to follow, but seems fine, particularly as it's an isolated plotter.

danvk added a commit that referenced this pull request Nov 16, 2014
Smooth plotter using bezier curves
@danvk danvk merged commit eec4fd0 into master Nov 16, 2014
@Stafie
Copy link

Stafie commented Mar 30, 2015

@danvk Is there a way to have the drawPoints enabled when using the smooth-plotter?

Thank you!

@danvk
Copy link
Owner Author

danvk commented Mar 30, 2015

Unfortunately, no. Feel free to file an issue (or, better, a pull request!).

One nice solution would be to pull the drawPoints behavior out into its own plotter. That way it would work with any sort of display.

@bhyatm
Copy link

bhyatm commented Aug 14, 2015

Hi,

The fillGraph option does not seem to be supported when using the smooth plotter -
Is this supported and if so how do I implement ??

Thanks

@shufanhao
Copy link

very good.Thanks for dygraph.

@RedShift1
Copy link

Would also like to see fillGraph working with the smooth plotter

@protyagov
Copy link

The filllGraph appears working when I specify plotter function per series like so:

                // plotter: smoothPlotter,
                series: {
                    "V": {
                        color: "#5997FA",
                    },
                    "H": {
                        plotter: smoothPlotter,
                        color: "orange",
                    }
                },
                fillGraph: true,

screen shot 2018-06-12 at 4 24 21 pm

@olivier-monaco
Copy link

@protyagov fillGraph does not work. Zoom in on your graph and you will see line of the fill, no curves.

I tried to adapt the smoothPlotter to create smoothFillPlotter. See #937

@armsp
Copy link

armsp commented Oct 11, 2019

@danvk I needed some help with understanding the Bezier plot.

I understood how you are finding the control points of a given data point. But what I am not able to figure out is -
The general literature on cubic Bezier curves talks about control points for 2 data points unlike yours. So after you calculate the control point for a single data point, how exactly do you then draw the curves from the previous data point to the next data point and how do you use the control point for drawing the curve ?
Please do let me know how you did it.

@mirabilos mirabilos deleted the re-smooth-plotter branch January 13, 2023 20:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add a "smooth line" plotter
9 participants