ZedGraph大数据显示问题

ZedGraph在NET.开发软件,感觉用起来还行,就一直在用。

一次开发汽车测量数据(MDF)的解析工具时,发现5.1.5版本在显示数据超过几千点后,图形缩放明显变慢,完全满足不了开发需要。

经过下载源代码,进行分析。

发现问题主要出现在绘制中,ZedGraph每次刷新都会讲所有点进行重绘,这就存在个问题,屏幕能够显示的分辨率有限的,重复绘制大大降低了显示效率。主要更改如下,具体算法还可以优化:


一、线段的绘制

修改 Lline.CS 中

        public void DrawCurve(Graphics g, GraphPane pane,
                                CurveItem curve, float scaleFactor)

……

            using (Pen pen = source.GetPen(pane, scaleFactor))
            {
                // 数据过滤缓冲区
                PointPairList filteList = new PointPairList();
                PointPairList filtePoint = new PointPairList();
                int filteCount = 0;  // 过滤缓冲最后一个值
                int filteXLast = int.MaxValue;
                double filtePower = 0;
……

                            if (!lastBad)
                                try
                                {


                                    // GDI+ plots the data wrong and/or throws an exception for
                                    // outrageous coordinates, so we do a sanity check here
                                    if (lastX > 5000000 || lastX < -5000000 ||
                                            lastY > 5000000 || lastY < -5000000 ||
                                            tmpX > 5000000 || tmpX < -5000000 ||
                                            tmpY > 5000000 || tmpY < -5000000)
                                    {
//                                         InterpolatePoint(g, pane, curve, lastPt, scaleFactor, pen,
//                                                         lastX, lastY, tmpX, tmpY);
                                        
                                        filteCount = 0;
                                        filteXLast = int.MaxValue;
                                        filtePower = 0;
                                    }
                                    else if (!isOut)
                                    {
                                        if (filteXLast != tmpX)
                                        {
                                            if (filteCount == 0)
                                            {
                                                filtePower = tmpY;
                                                filteCount = 1;
                                                filteList.Add(tmpX, filtePower / filteCount);
                                            }
                                            else
                                            {
                                                filteList.Add(filteXLast, filtePower / filteCount);
                                            }

                                            filtePoint.Add(curPt);
                                            filteCount = 0;
                                            filteXLast = tmpX;
                                            filtePower = 0;
                                        }
                                        else
                                        {
                                            filtePower += tmpY;
                                            filteCount++;
                                        }
                                    }
                                catch
                                {
//                                     InterpolatePoint(g, pane, curve, lastPt, scaleFactor, pen,
//                                                 lastX, lastY, tmpX, tmpY);
                                }
                            }

                            lastBad = false;
                            //lastOut = isOut;
                        }
                    }
                }

                lastX = (int)(filteList[0].X);
                lastY = (int)(filteList[0].Y);
                lastPt = filtePoint[0];

                for (int i = 0; i < filteList.Count; i++)
                {
                    tmpX = (int)(filteList[i].X);
                    tmpY = (int)(filteList[i].Y);
                    curPt = filtePoint[i];

                    if (!curve.IsSelected && this._gradientFill.IsGradientValueType)
                    {



二、点的绘制(同理)

在 Symbol.CS的 

		public void Draw( Graphics g, GraphPane pane, LineItem curve, float scaleFactor,
			bool isSelected )
		{
			Symbol source = this;
			if ( isSelected )
				source = Selection.Symbol;

			int tmpX, tmpY;

			int minX = (int)pane.Chart.Rect.Left;
			int maxX = (int)pane.Chart.Rect.Right;
			int minY = (int)pane.Chart.Rect.Top;
			int maxY = (int)pane.Chart.Rect.Bottom;

			// (Dale-a-b) we'll set an element to true when it has been drawn	
			bool[,] isPixelDrawn = new bool[maxX + 1, maxY + 1];

			double curX, curY, lowVal;
			IPointList points = curve.Points;
            
			if ( points != null && ( _border.IsVisible || _fill.IsVisible ) )
			{
				SmoothingMode sModeSave = g.SmoothingMode;
				if ( _isAntiAlias )
					g.SmoothingMode = SmoothingMode.HighQuality;

				// For the sake of speed, go ahead and create a solid brush and a pen
				// If it's a gradient fill, it will be created on the fly for each symbol
				//SolidBrush	brush = new SolidBrush( this.fill.Color );

				using ( Pen pen = source._border.GetPen( pane, scaleFactor ) )
				using ( GraphicsPath path = MakePath( g, scaleFactor ) )
				{
					RectangleF rect = path.GetBounds();

					using ( Brush brush = source.Fill.MakeBrush( rect ) )
					{
                        // 数据过滤
                        int filteCount = 0;  // 过滤缓冲最后一个值
                        int filteXLast = int.MaxValue;
                        double filtePower = 0;

						ValueHandler valueHandler = new ValueHandler( pane, false );
						Scale xScale = curve.GetXAxis( pane ).Scale;
						Scale yScale = curve.GetYAxis( pane ).Scale;

						bool xIsLog = xScale.IsLog;
						bool yIsLog = yScale.IsLog;
						bool xIsOrdinal = xScale.IsAnyOrdinal;

						double xMin = xScale.Min;
						double xMax = xScale.Max;

						// Loop over each defined point	
                        int start = (int)xScale.Min;
                        start = start < 0 ? 0 : start;
                        int end = (int)xScale.Max;

                        int Nnum = (end - start) / (maxX - minX);
                        Nnum = Nnum > 0 ? Nnum : 1;
                        
                        ///Test
                        start = 0; end = points.Count; Nnum = 1;

                        for (int i = start; i < end && i < points.Count; i += Nnum)
						//for ( int i = 0; i < points.Count; i++ )
						{
							// Get the user scale values for the current point
							// use the valueHandler only for stacked types
							if ( pane.LineType == LineType.Stack )
							{
								valueHandler.GetValues( curve, i, out curX, out lowVal, out curY );
							}
							// otherwise, just access the values directly.  Avoiding the valueHandler for
							// non-stacked types is an optimization to minimize overhead in case there are
							// a large number of points.
							else
							{
								curX = points[i].X;
								if ( curve is StickItem )
									curY = points[i].Z;
								else
									curY = points[i].Y;
							}

							// Any value set to double max is invalid and should be skipped
							// This is used for calculated values that are out of range, divide
							//   by zero, etc.
							// Also, any value <= zero on a log scale is invalid

							if ( curX != PointPair.Missing &&
									curY != PointPair.Missing &&
									!System.Double.IsNaN( curX ) &&
									!System.Double.IsNaN( curY ) &&
									!System.Double.IsInfinity( curX ) &&
									!System.Double.IsInfinity( curY ) &&
									( curX > 0 || !xIsLog ) &&
									( !yIsLog || curY > 0.0 ) &&
									( xIsOrdinal || ( curX >= xMin && curX <= xMax ) ) )
							{
								// Transform the user scale values to pixel locations
								tmpX = (int) xScale.Transform( curve.IsOverrideOrdinal, i, curX );
								tmpY = (int) yScale.Transform( curve.IsOverrideOrdinal, i, curY );

								// Maintain an array of "used" pixel locations to avoid duplicate drawing operations
								if ( tmpX >= minX && tmpX <= maxX && tmpY >= minY && tmpY <= maxY ) // guard against the zoom-in case
								{
									if ( isPixelDrawn[tmpX, tmpY] )
										continue;
									isPixelDrawn[tmpX, tmpY] = true;
								}

                                if (filteXLast != tmpX)
                                {
                                    if (filteCount == 0)
                                    {

                                    }
                                    else
                                    {
                                        tmpY = (int)(filtePower / filteCount);
                                    }

                                    filteCount = 0;
                                    filteXLast = tmpX;
                                    filtePower = 0;
                                }
                                else
                                {
                                    filtePower += tmpY;
                                    filteCount++;
                                }  
                                
								// If the fill type for this symbol is a Gradient by value type,
								// the make a brush corresponding to the appropriate current value
								if ( _fill.IsGradientValueType || _border._gradientFill.IsGradientValueType )
								{
									using ( Brush tBrush = _fill.MakeBrush( rect, points[i] ) )
									using ( Pen tPen = _border.GetPen( pane, scaleFactor, points[i] ) )
										this.DrawSymbol( g, tmpX, tmpY, path, tPen, tBrush );
								}
								else
								{
									// Otherwise, the brush is already defined
									// Draw the symbol at the specified pixel location
									this.DrawSymbol( g, tmpX, tmpY, path, pen, brush );
								}
							}
						}
					}
				}

				g.SmoothingMode = sModeSave;
			}
		}



  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值