这篇文章主要有如下3个简单的算法,本人将它们结合起来练习练习手感。
(1)不重复随机颜色数组算法
(2)坐标换行算法
(3)改进后的箭头算法
先看下用这3个算法实现的效果图(自动绘制会从1个一直绘制到174个圆,然后再从1个绘起........看起来就像动态的哦!!),如下(图一):
(图二)
哥只是实现功能而已,至于其他页面布局什么的,哥不太会,各位不要见怪,界面实在是简单得不能太简单了,^_^。以下内容将以上述3个算法来讲解。
(一)不重复随机颜色数组算法
这个是在eaglet写的那篇文章中想到了,效率挺高的。哥改动下,也拿来用用,eaglet兄弟不要见怪,代码如下。
1 public class RandomColorHelper 2 { 3 ///
7 ///
15-36行为改进的代码。
1:先通过反射获取KnownColor的所有枚举字符串(typeof(KnownColor).GetEnumNames();) 2:通过Enum.TryParse
3:通过Color.FromKnownColor(color);来获取对应的Color对象,并且传递到数组中。 39-47为数组移位操作,将随机到的Color(位置为Index)对象与数组中位置为end的Color对象互换。
调用这个方法,最多能获取174个颜色,哈哈,其他的改进留给你们吧(如果需要改进的话)。
(二)改进后的箭头算法
1 public static void DrawArrow(Graphics graphics, PointF startPoint, 2 PointF endPoint, float length=15, float realtiveValue=3, float radius=6) 3 { 4 if (graphics == null) 5 { 6 return; 7 } 8 9 float startX = startPoint.X; 10 float startY = startPoint.Y; 11 float endX = endPoint.X; 12 float endY = endPoint.Y; 13 14 //计算2点之间的距离 15 double distance = Math.Abs(Math.Sqrt( 16 (startX - endX) * (startX - endX) + 17 (startY - endY) * (startY - endY))); 18 19 if (distance == 0) 20 { 21 return; 22 } 23 24 //计算起始点至终点距离为radius的坐标点 25 startX = (float)(radius / distance * (endX - startX)) + startX; 26 startY = (float)(radius / distance * (endY - startY)) + startY; 27 28 //计算终点至起始点距离为radius的坐标点 29 endX = (float)(radius / distance * (startX - endX)) + endX; 30 endY = (float)(radius / distance * (startY - endY)) + endY; 31 32 //计算箭头顶点外的2个角的坐标点 33 double xa = endX + length * ((startX - endX) 34 + (startY - endY) / realtiveValue) / distance; 35 double ya = endY + length * ((startY - endY) 36 - (startX - endX) / realtiveValue) / distance; 37 double xb = endX + length * ((startX - endX) 38 - (startY - endY) / realtiveValue) / distance; 39 double yb = endY + length * ((startY - endY) 40 + (startX - endX) / realtiveValue) / distance; 41 42 //绘制箭头图形 43 PointF[] polygonPoints ={ 44 new PointF(endX , endY), 45 new PointF( (float)xa , (float)ya), 46 new PointF( (float)xb , (float)yb)}; 47 48 graphics.DrawLine(new Pen(new SolidBrush(Color.Red), 2), 49 startX, startY, endX, endY); 50 51 graphics.DrawPolygon(Pens.Red, polygonPoints); 52 graphics.FillPolygon(new SolidBrush(Color.Red), polygonPoints); 53 }
以下为本人用系统自带的绘图工具绘制的,不堪入目,汗,还真不是搞图片的料子,仅仅是能够让读者更加清晰明了的知道怎么计算的坐标。
先通过数学的方法获取直线与起始圆周、结束圆周的切割点,分别将切割点设置为相应的起始点和结束点。
//计算起始点至终点距离为radius的坐标点 25 startX = (float)(radius / distance * (endX - startX)) + startX; 26 startY = (float)(radius / distance * (endY - startY)) + startY; 27 28 //计算终点至起始点距离为radius的坐标点 29 endX = (float)(radius / distance * (startX - endX)) + endX; 30 endY = (float)(radius / distance * (startY - endY)) + endY;
然后通过graphics.DrawLine(new Pen(new SolidBrush(Color.Red), 2), startX, startY, endX, endY);绘制重新设置后的起始点到结束点的直线。
可能,你会想:为什么不直接用原始的起始点和结束点直接绘制直线?这就会牵涉到直线覆盖圆的某些部分的现象,并且箭头的终点是指在圆周的中心点,而不是直线与圆周的切割点,如下所示:
因此,将起始点和终点重新设置为直线与圆周的相应的交点,这样,绘制的直线不会覆盖到圆周上,并且箭头也固定在直线与圆周相交的点上。如下为正常显示的图:
箭头算法这里就不再讲了,因为已经讲了一次..........
(三)坐标换行算法
这个是本人在近期项目中的测试路线算法的第二种需求中的算法,后来这种需求被推到、不用了,汗,哥写算法写得累啊。开始花了点时间想了出来,后来突然想要记起这个算法时,却怎么也想不起来了。不过,幸好哥保存了一个项目副本,哈哈,哥可是有预感啊,谢天谢地!.......
以下的为改进版的换行坐标算法(当前行的绘制点的个数等于指定的perRowPointNumber时候,自动换行绘制,绘制方向改变):
1 public class LocationCalculator 2 { 3 ///
7 /// 起始点
8 /// 水平间隔
9 /// 垂直间隔
10 /// 每行点的个数
11 ///
26-49为循环设置点的坐标,注释比较清晰,这里就不再讲解。
总结
这里主要是将3个算法整合到一起进行运用,以一种图形的效果更加清晰的展现相应算法的结果。首先,对箭头算法灵活的运用,并且考虑圆周的半径来重新计算起始点和结束点,避免不必要的bug。其次,是不重复随机颜色数组的算法实现以及运用。再次,是对坐标换行算法的实现和运用。本文中难免会有bug,肯定有本人考虑不周全的地方,希望读者见谅。如有什么疑问,请留言............
源代码下载:算法整合的图形显示源代码
最新评论