Search code examples
c#.netwinformsmschart

How to fill the area between two series in MS Chart


I am populating chart data under timer Tick event:

private void Timer_Tick(object sender, EventArgs e)
{ 
    Chart1.Series["Series2"].Points.AddY(17);
    Chart1.Series["Series3"].Points.AddY(10);
}

Which generates two series like this:

enter image description here

I'd like to fill the area between the series like this:

enter image description here

Here is the designer code for the chart:


chartArea1.BackColor = System.Drawing.Color.Black;
chartArea1.Name = "ChartArea1";
this.chart1.ChartAreas.Add(chartArea1);
legend1.Name = "Legend1";
this.chart1.Legends.Add(legend1);
this.chart1.Location = new System.Drawing.Point(72, 339);
this.chart1.Name = "chart1";
series1.ChartArea = "ChartArea1";
series1.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Spline;
series1.Color = System.Drawing.Color.Red;
series1.Legend = "Legend1";
series1.Name = "Series1";
series2.ChartArea = "ChartArea1";
series2.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Spline;
series2.Color = System.Drawing.Color.Aqua;
series2.Legend = "Legend1";
series2.Name = "Series2";
this.chart1.Series.Add(series1);
this.chart1.Series.Add(series2);

Solution

  • You can handle the Paint event of the chart and get the points of each series, then create a path based on those points and fill the path:

    enter image description here

    Axis.ValueToPixelPosition is the method which helps you to translate series point to paint surface point.

    Example - Filling the space between two series

    The following example, creates two series: Sin(α) and 2×Sin(α) and fills the area between the two charts with Pink color:

    private void Chart1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
        var points0 = chart1.Series[0].Points.Select(p =>
            new PointF(
                (float)chart1.ChartAreas[0].AxisX
                .ValueToPixelPosition(p.XValue),
                (float)chart1.ChartAreas[0].AxisY
                .ValueToPixelPosition(p.YValues[0]))).ToArray();
        var points1 = chart1.Series[1].Points.Select(p =>
            new PointF(
                (float)chart1.ChartAreas[0].AxisX
                .ValueToPixelPosition(p.XValue),
                (float)chart1.ChartAreas[0].AxisY
                .ValueToPixelPosition(p.YValues[0]))).ToArray();
        using (var path = new GraphicsPath())
        {
            path.StartFigure();
            path.AddCurve(points0);
            path.AddCurve(points1.Reverse().ToArray());
            path.CloseFigure();
            path.FillMode = FillMode.Alternate;
            using (var brush = new SolidBrush(Color.Pink))
                e.Graphics.FillPath(brush, path);
        }
    }
    
    private void Form1_Load(object sender, EventArgs e)
    {
        chart1.Series.Clear();
        chart1.ChartAreas.Clear();
    
        chart1.ChartAreas.Add("A1");
        chart1.ChartAreas[0].AxisX.Minimum = 0;
        chart1.ChartAreas[0].AxisX.Interval = 90;
    
        chart1.Series.Add("Sin(α)");
        chart1.Series[0].ChartType =
            System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Spline;
        chart1.Series[0].Color = Color.Blue;
        chart1.Series[0].BorderWidth = 3;
    
        chart1.Series.Add("2×Sin(α)");
        chart1.Series[1].ChartType =
            System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
        chart1.Series[1].Color = Color.Red;
        chart1.Series[1].BorderWidth = 3;
    
        for (int i = 0; i < 360; i++)
            chart1.Series[0].Points.AddXY(i, Math.Sin(i * Math.PI / 180));
        for (int i = 0; i < 360; i++)
            chart1.Series[1].Points.AddXY(i, 2 * Math.Sin(i * Math.PI / 180));
    
        chart1.Paint += Chart1_Paint;
    }