4

C# の MSChart を使用して、線に破線のスタイルで折れ線グラフをレンダリングしようとしています。スタイルの設定に問題はありませんが、大量のデータがあります。これにより、すべての線分を描画するときに「ダッシュ」シーケンスを再開するように見えるため、破線のレンダリングが正しく行われなくなります。そのため、実線と同じように見える線が得られます。データ ポイントの密度が減少するように右にズームインすると、破線のスタイルが表示されます。

これは、どのズームレベルでもダッシュを維持するために本当に必要なので、私にとっては良くありません. これがどのように可能になるかについて、誰かアイデアはありますか? このようにレンダリングを台無しにするのは奇妙に思えます...

何かご意見は?

4

1 に答える 1

7

まあ、これは私が予想していたよりもちょっとしたファフになりました。この問題は、MSChart が個別の DrawLine 呼び出しとして各 2 点間に線を描画するために発生します。すべてが 1 回の DrawLines 呼び出しで描画された場合、問題は存在しません。

そのため、描画を処理する方法を考え出しました。

まず PrePaint で、すべての「BorderWidth」を 0 に設定する前に保存します。これは、MSChart が線を描画しないことを意味します。

最後に PostPaint で、必要なダッシュ スタイルを使用して線を描画します。これにより、完全なレンダリングが得られます。

私のコードが機能しないエッジケースがいくつかあると確信していますが、これはそれを行う方法の良いアイデアを与えるはずです:

    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 );
        }
    }

それが誰かの痛みを救うことを本当に願っています!

于 2012-08-29T12:08:20.567 に答える