简体   繁体   English

具有虚线样式和大量数据点的MSChart折线图

[英]MSChart line graph with dashed style and large amount of data points

I'm trying to render a line graph using MSChart from C# with a dashed style to the line. 我正在尝试使用MSChart从C#以虚线样式绘制折线图。 I have no problems setting the style but I have a large amount of data. 设置样式没有问题,但是我有大量数据。 This causes the dashed rendering to go wrong as it seems to re-start the "dash" sequence as it draws every line segment. 这会导致虚线渲染出错,因为在绘制每个线段时似乎重新开始了“虚线”序列。 As such I get a line that looks identical to the solid line. 这样,我得到的线看起来与实线相同。 If i zoom right in such that my data point density reduces then the dashed style becomes visible. 如果我放大以使数据点密度降低,则虚线样式将变为可见。

This is no good for me as I really need it to keep the dashing at any zoom level. 这对我没有好处,因为我真的需要它来使虚线保持在任何缩放级别。 Has anyone any ideas as to how this might be possible? 有没有人对如何做到这一点有任何想法? It seems strange that it messes up rendering like this to me ... 对我来说像这样弄乱了渲染似乎很奇怪...

Any thoughts? 有什么想法吗?

Well this turned into a tad more of a faff than I was expecting. 好吧,这比我预期的要麻烦得多。 The problem arises due to the fact that MSChart draws the line between each 2 points as a seperate DrawLine call. 由于MSChart作为单独的DrawLine调用在每2个点之间绘制一条线,因此出现了问题。 If the whole things was drawn with one DrawLines call the problem would not exist. 如果使用一条DrawLines调用绘制了整个对象,则该问题将不存在。

As such I have come up with a method to handle drawing it. 因此,我想出了一种方法来绘制它。

Firstly in the PrePaint I store all the "BorderWidth"s before setting them to 0. This means that MSChart does not draw my lines. 首先,在PrePaint中,我将所有“ BorderWidth”设置为0之前先进行存储。这意味着MSChart不会绘制线条。

Finally in the PostPaint I draw the lines using the dash style I want. 最后,在PostPaint中,使用所需的破折号样式绘制线条。 This gives Perfect rendering. 这提供了完美的渲染。

I'm sure there are some edge cases for which my code won't work but this should give you a good idea of how to do it: 我确定在某些极端情况下我的代码将无法正常工作,但这应该使您对如何做到这一点有个好主意:

    private List< int > mBorderWidths   = null;
    private void LineChartPrePaint( object sender, System.Windows.Forms.DataVisualization.Charting.ChartPaintEventArgs e )
    {
        if ( e.ChartElement.GetType() == typeof( System.Windows.Forms.DataVisualization.Charting.ChartArea ) )
        {
            System.Windows.Forms.DataVisualization.Charting.Chart           c   = (System.Windows.Forms.DataVisualization.Charting.Chart)e.Chart;
            System.Windows.Forms.DataVisualization.Charting.ChartArea       ca  = (System.Windows.Forms.DataVisualization.Charting.ChartArea)e.ChartElement;

            mBorderWidths   = new List<int>();
            foreach( System.Windows.Forms.DataVisualization.Charting.Series s in c.Series )
            {
                mBorderWidths.Add( s.BorderWidth );
                s.BorderWidth   = 0;
                s.ShadowOffset  = 0;
            }

            RectangleF rectF    = ca.Position.ToRectangleF();
            rectF               = e.ChartGraphics.GetAbsoluteRectangle( rectF );

            e.ChartGraphics.Graphics.FillRectangle( new SolidBrush( ca.BackColor ), rectF );
        }
        if ( e.ChartElement.GetType() == typeof( System.Windows.Forms.DataVisualization.Charting.Chart ) )
        {
            RectangleF rectF    = e.Position.ToRectangleF();
            rectF               = e.ChartGraphics.GetAbsoluteRectangle( rectF );

            e.ChartGraphics.Graphics.FillRectangle( new SolidBrush( e.Chart.BackColor ), rectF );
        }
    }

    System.Drawing.Drawing2D.DashStyle ChartToDrawingDashStyle( System.Windows.Forms.DataVisualization.Charting.ChartDashStyle cds )
    {
        switch( cds )
        {
            case System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.NotSet:
            case System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Solid:
                return System.Drawing.Drawing2D.DashStyle.Solid;
            case System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Dash:
                return System.Drawing.Drawing2D.DashStyle.Dash;
            case System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.DashDot:
                return System.Drawing.Drawing2D.DashStyle.DashDot;
            case System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.DashDotDot:
                return System.Drawing.Drawing2D.DashStyle.DashDotDot;
            case System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Dot:
                return System.Drawing.Drawing2D.DashStyle.Dot;
        }
        return System.Drawing.Drawing2D.DashStyle.Solid;
    }

    private void LineChartPostPaint( object sender, System.Windows.Forms.DataVisualization.Charting.ChartPaintEventArgs e )
    {
        if ( e.ChartElement.GetType() == typeof( System.Windows.Forms.DataVisualization.Charting.ChartArea ) )
        {
            System.Windows.Forms.DataVisualization.Charting.Chart       c   = (System.Windows.Forms.DataVisualization.Charting.Chart)e.Chart;
            System.Windows.Forms.DataVisualization.Charting.ChartArea   ca  = (System.Windows.Forms.DataVisualization.Charting.ChartArea)e.ChartElement;

            RectangleF clipRect = e.ChartGraphics.GetAbsoluteRectangle( e.Position.ToRectangleF() );
            RectangleF oldClip  = e.ChartGraphics.Graphics.ClipBounds;
            e.ChartGraphics.Graphics.SetClip( clipRect );

            int seriesIdx   = 0;
            foreach( System.Windows.Forms.DataVisualization.Charting.Series s in c.Series )
            {
                PointF  ptFLast         = new PointF( 0.0f, 0.0f );
                List< PointF > points   = new List<PointF>();
                foreach( System.Windows.Forms.DataVisualization.Charting.DataPoint dp in s.Points )
                {
                    double dx   = (double)dp.XValue;
                    double dy   = (double)dp.YValues[0];

                    // Log the value if its axis is logarithmic.
                    if ( ca.AxisX.IsLogarithmic )
                    {
                        dx  = Math.Log10( dx );
                    }
                    if ( ca.AxisY.IsLogarithmic )
                    {
                        dy  = Math.Log10( dy );
                    }

                    dx  = e.ChartGraphics.GetPositionFromAxis( ca.Name, System.Windows.Forms.DataVisualization.Charting.AxisName.X, dx );
                    dy  = e.ChartGraphics.GetPositionFromAxis( ca.Name, System.Windows.Forms.DataVisualization.Charting.AxisName.Y, dy );

                    PointF  ptFThis         = e.ChartGraphics.GetAbsolutePoint( new PointF( (float)dx, (float)dy ) );
                    points.Add( ptFThis );
                }


                if ( points.Count > 0 )
                {
                    Pen pen = new Pen( Color.FromArgb( 255, s.Color ) );
                    pen.Width       = mBorderWidths[seriesIdx];
                    pen.DashStyle   = ChartToDrawingDashStyle( s.BorderDashStyle );
                    //pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom;
                    //pen.DashPattern   = new float[]{ 4.0f, 4.0f, 1.0f, 3.0f, 2.0f, 3.0f };
                    pen.DashCap     = System.Drawing.Drawing2D.DashCap.Round;

                    e.ChartGraphics.Graphics.SmoothingMode  = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                    e.ChartGraphics.Graphics.DrawLines( pen, points.ToArray() );

                }
                s.BorderWidth   = mBorderWidths[seriesIdx];
            }

            e.ChartGraphics.Graphics.SetClip( oldClip );
        }
    }

I truly hope that saves someone some pain! 我真的希望这可以减轻别人的痛苦!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM