Chart C# add Data Point in cubic bezier curve

750 views Asked by At

I have written a method to create a Bezier curve for rendering in a Chart control. I have a collection of data points which I retrieve from another method. I would like to form the Bezier curve on my chart to produce something similar to a spline, but instead I am receiving a blank chart. The code to produce the curve is:

public static double XChart(double t, double x0, double x1, double x2, doubl x3)
{
    return (double)(
        x0 * Math.Pow((1 - t), 3) +
        x1 * 3 * t * Math.Pow((1 - t), 2) +
        x2 * 3 * Math.Pow(t, 2) * (1 - t) +
        x3 * Math.Pow(t, 3)
    );
}

I then add the curve to the chart with the code below:

chart1.Series["Series1"].Points.AddXY(XChart(0.1, a, c, b, d), YChart(0.1, l, f, i, g));

Where a, b, c, d, l, f, i, g are the values I get from a list of data points.

List<DataPoint> dataPoints0 = new List<DataPoint>();
var a = dataPoints0[0].XValue;
var b = dataPoints0[1].XValue;
var c = dataPoints0[2].XValue;
var d = dataPoints0[3].XValue;
var l = dataPoints0[0].YValues[0];
var i = dataPoints0[1].YValues[0];
var f = dataPoints0[2].YValues[0];
var g = dataPoints0[3].YValues[0];

Now, suppose that:

a= 4 , l= 0
b= 3 , i= 3
c= 4 , f= 5
d= 3 , g= 6

I should get the curve like this:
enter image description here

However, what I get on my chart is this:
enter image description here

I'm not sure why this is happening, any help is appreciated.

1

There are 1 answers

1
Hazel へいぜる On BEST ANSWER

It appears as though you're only adding a single point to your chart; to fix this, you'll need to add each point from your curve that you are concerned with:

for (float t = 0.0f; t < 1.0f; t += 0.01f)
    chart1.Series["Series1"].Points.AddXY(XChart(t, a, b, c, d), YChart(t, l, f, i, g));

The example above iterates from a start time of 0 and adds 100 points to your chart using 0.00f - 1.00f.


The Bezier curve function you've implemented gives you a specific point in your curve based on time. You can always write a helper method to give you all points by adding an argument for the number of points that should be returned:

public static double XChart(double t, double x0, double x1, double x2, double x3) {
    return (double)(
        x0 * Math.Pow((1 - t), 3) +
        x1 * 3 * t * Math.Pow((1 - t), 2) +
        x2 * 3 * Math.Pow(t, 2) * (1 - t) +
        x3 * Math.Pow(t, 3));
}
public static double[] XChart(double x0, double x1, double x2, double x3, int totalPoints) {
    List<double> points = new List<double>();
    for (float t = 0.0f; t < 1.0f; t += (1 / (float)totalPoints))
        points.Add(XChart(t, x0, x1, x2, x3));

    return points.ToArray();
}

You can then utilize this helper method to build your chart as below:

double[] xPoints = XChart(a, b, c, d, 100);
double[] yPoints = YChart(l, f, i, g, 100);
if (xPoints.Length != yPoints.Length)
    throw new InvalidOperationException("The number of points between axes must match.");

for (int i = 0; i < xPoints.Length; i++)
    chart1.Series["Series1"].Points.AddXY(xPoints[i], yPoints[i]);

I would take a look at the Wikipedia page regarding the construction of Bezier curves. I would start with the Quadratic curve, and then after understanding how it works I would progress to your representation of high-order curves.

For quadratic Bézier curves one can construct intermediate points Q0 and Q1 such that as t varies from 0 to 1:

  • Point Q0(t) varies from P0 to P1 and describes a linear Bézier curve.

  • Point Q1(t) varies from P1 to P2 and describes a linear Bézier curve.

  • Point B(t) is interpolated linearly between Q0(t) to Q1(t) and describes a quadratic Bézier curve.