博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ZedGraph源码学习(三)
阅读量:7220 次
发布时间:2019-06-29

本文共 7182 字,大约阅读时间需要 23 分钟。

我们先看下一段代码,这行代码是说在轴上对应的值转化成它对应的像素值。

public float Transform( double x )		{			// Must take into account Log, and Reverse Axes			double denom = ( _maxLinTemp - _minLinTemp );			double ratio;			if ( denom > 1e-100 )				ratio = ( Linearize( x ) - _minLinTemp ) / denom;			else				ratio = 0;			if ( _isReverse == ( _ownerAxis is XAxis || _ownerAxis is X2Axis ) )				return (float) ( _maxPix - ( _maxPix - _minPix ) * ratio );			else				return (float) ( _minPix + ( _maxPix - _minPix ) * ratio );		}

这段代码很好理解,我们假设这是X轴,轴没有反转,X轴上的坐标最小值minLinTemp,对应像素是minpix,坐标最大值是maxLinTemp,对应像素是maxpix,现有一点在x轴的坐标是xlin,那么它对应的像素是xpix,它们满足这样一个关系,(xlin-minLinTemp)/(maxLinTemp-minLinTemp)=(xpix-minpix)/(maxpix-minpix),根据这个关系我们能得到对应的xpix的关系。如果是Y轴,因为我们坐标系上的Y轴和在设备上的坐标系是反着来的,那么它们的关系要改着这样了,(xlin-minLinTemp)/(maxLinTemp-minLinTemp)=(maxpix-xpix)/(maxpix-minpix).

然后我们查看一下是如何绘制的,我们这里看线条的绘制过程。线条的元素LineItem里会封装一个Line的对象,这个对象主要是负责具体画什么样的线,如直线,基数样条等,我们看一下普通的基数样条的绘制代码。

public void DrawCurve( Graphics g, GraphPane pane,                                CurveItem curve, float scaleFactor )		{			Line source = this;			if ( curve.IsSelected )				source = Selection.Line;			// switch to int to optimize drawing speed (per Dale-a-b)			int	tmpX, tmpY,					lastX = int.MaxValue,					lastY = int.MaxValue;			double curX, curY, lowVal;			PointPair curPt, lastPt = new PointPair();			bool lastBad = true;			IPointList points = curve.Points;			ValueHandler valueHandler = new ValueHandler( pane, false );			Axis yAxis = curve.GetYAxis( pane );			Axis xAxis = curve.GetXAxis( pane );			bool xIsLog = xAxis._scale.IsLog;			bool yIsLog = yAxis._scale.IsLog;			// switch to int to optimize drawing speed (per Dale-a-b)			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;			using ( Pen pen = source.GetPen( pane, scaleFactor ) )			{				if ( points != null && !_color.IsEmpty && this.IsVisible )				{					//bool lastOut = false;					bool isOut;					bool isOptDraw = _isOptimizedDraw && points.Count > 1000;					// (Dale-a-b) we'll set an element to true when it has been drawn						bool[,] isPixelDrawn = null;										if ( isOptDraw )						isPixelDrawn = new bool[maxX + 1, maxY + 1]; 										// Loop over each point in the curve					for ( int i = 0; i < points.Count; i++ )					{						curPt = points[i];						if ( pane.LineType == LineType.Stack )						{							if ( !valueHandler.GetValues( curve, i, out curX, out lowVal, out curY ) )							{								curX = PointPair.Missing;								curY = PointPair.Missing;							}						}						else						{							curX = curPt.X;							curY = curPt.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 ) ||								( xIsLog && curX <= 0.0 ) ||								( yIsLog && curY <= 0.0 ) )						{							// If the point is invalid, then make a linebreak only if IsIgnoreMissing is false							// LastX and LastY are always the last valid point, so this works out							lastBad = lastBad || !pane.IsIgnoreMissing;							isOut = true;						}						else						{							// Transform the current point from user scale units to							// screen coordinates							tmpX = (int) xAxis.Scale.Transform( curve.IsOverrideOrdinal, i, curX );							tmpY = (int) yAxis.Scale.Transform( curve.IsOverrideOrdinal, i, curY );							// Maintain an array of "used" pixel locations to avoid duplicate drawing operations							// contributed by Dale-a-b							if ( isOptDraw && tmpX >= minX && tmpX <= maxX &&										tmpY >= minY && tmpY <= maxY ) // guard against the zoom-in case							{								if ( isPixelDrawn[tmpX, tmpY] )									continue;								isPixelDrawn[tmpX, tmpY] = true;							}							isOut = ( tmpX < minX && lastX < minX ) || ( tmpX > maxX && lastX > maxX ) ||								( tmpY < minY && lastY < minY ) || ( tmpY > maxY && lastY > maxY );							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 );									else if ( !isOut )									{										if ( !curve.IsSelected && this._gradientFill.IsGradientValueType )										{											using ( Pen tPen = GetPen( pane, scaleFactor, lastPt ) )											{												if ( this.StepType == StepType.NonStep )												{													g.DrawLine( tPen, lastX, lastY, tmpX, tmpY );												}												else if ( this.StepType == StepType.ForwardStep )												{													g.DrawLine( tPen, lastX, lastY, tmpX, lastY );													g.DrawLine( tPen, tmpX, lastY, tmpX, tmpY );												}												else if ( this.StepType == StepType.RearwardStep )												{													g.DrawLine( tPen, lastX, lastY, lastX, tmpY );													g.DrawLine( tPen, lastX, tmpY, tmpX, tmpY );												}												else if ( this.StepType == StepType.ForwardSegment )												{													g.DrawLine( tPen, lastX, lastY, tmpX, lastY );												}												else												{													g.DrawLine( tPen, lastX, tmpY, tmpX, tmpY );												}											}										}										else										{											if ( this.StepType == StepType.NonStep )											{												g.DrawLine( pen, lastX, lastY, tmpX, tmpY );											}											else if ( this.StepType == StepType.ForwardStep )											{												g.DrawLine( pen, lastX, lastY, tmpX, lastY );												g.DrawLine( pen, tmpX, lastY, tmpX, tmpY );											}											else if ( this.StepType == StepType.RearwardStep )											{												g.DrawLine( pen, lastX, lastY, lastX, tmpY );												g.DrawLine( pen, lastX, tmpY, tmpX, tmpY );											}											else if ( this.StepType == StepType.ForwardSegment )											{												g.DrawLine( pen, lastX, lastY, tmpX, lastY );											}											else if ( this.StepType == StepType.RearwardSegment )											{												g.DrawLine( pen, lastX, tmpY, tmpX, tmpY );											}										}									}								}								catch								{									InterpolatePoint( g, pane, curve, lastPt, scaleFactor, pen,												lastX, lastY, tmpX, tmpY );								}							}							lastPt = curPt;							lastX = tmpX;							lastY = tmpY;							lastBad = false;							//lastOut = isOut;						}					}				}			}		}

代码有些多,但是过程还是很清晰的,前面一部分代码都是来获取相关数据,然后遍历对应CurveItem里的IPointList数据,把每个Point数据(是我们看到的数据)对应当前CurveItem里的X轴与Y轴上的像素值(给机器来看的),这里用到的转换就是上面所说的那部分代码,根据我们选择StepType不同来绘制每二点决定的线。这样就绘制出了我们要的线条,别的元素具体上不同,但是都是这种逻辑。其实如果要多了解这一方面的逻辑,可以看下有关的知识。

PS:读源码有个地方要注意,不要只是跟着代码往下来,看一会不是分支过多就是跑题了,看的时候你要自己跟着想,如果是我来实现这一功能,应该怎么来实现,然后和看的代码比对。

转载地址:http://grqym.baihongyu.com/

你可能感兴趣的文章
“怪诞”的数学天才
查看>>
移动计算风起云涌:大数据处理大行其道
查看>>
Dapper入门使用,代替你的DbSQLhelper
查看>>
Struts+Spring+Hibernate/SSH整合开发详细二
查看>>
rsync部署
查看>>
angularJS file-up-load上传图片
查看>>
Win10 Yii2 advance版本点击init.bat闪退问题解决
查看>>
常用DOS命令
查看>>
Clone使用方法详解
查看>>
android jni 使用流程
查看>>
谁在使用我的网站——用户忠诚和价值分析
查看>>
Qt 5.6安装无法找到msvcr120.dll问题解决
查看>>
thinkphp的field方法的用法总结,或许还有你不知道的
查看>>
java String和Date转换
查看>>
我的友情链接
查看>>
你需要知道的文件robots.txt
查看>>
Feature: JSON Views
查看>>
Dubbo视频教程--基础篇--第03节--ZooKeeper注册中心安装详细步骤(单节点)
查看>>
php冒泡排序方法
查看>>
HBase中Scan类属性maxResultSize的说明
查看>>