如何在程序中画更好看的折线
前言:
做的程序需要两种线,一种是贝塞尔曲线,一种是折线,贝塞尔线比较简单,这里主要说折现,折现的折点不能出现的过多,否则会出现上面的情况
一般这种折现会出现两种情况,我管着两种情况叫做凸点,和延伸点(ps:纯粹乱起),如上图所示,左上角的是“凸点”,右下角是“节省点”,折点过多主要是因为这两种原因造成的,我们可以对这两种折点进行优化,达到去除折点的作用,下面是一些代码片段
<summary > 合 并凸点 节 省 点 </ summary> private void Combine() { 允许控制点超过4 if ( ControlPoints.Count <= 4 ) return; List<ControlPoint> removeControlPointList = new List<ControlPoint>(); ControlPoint lastControlPoint = ControlPoints.LastOrDefault(); Point2Direct = GetDirect( lastControlPoint.Point, Point2 ); List<int> leftList = new List<int>(); List<int> rightList = new List<int>(); List<int> upList = new List<int>(); List<int> downList = new List<int>(); int i = 0; foreach ( ControlPoint controlPoint in this.ControlPoints ) { if ( i == 0 ) { }else if ( i == ControlPoints.Count - 1 ) { }else { switch ( controlPoint.BrokeLinePointDirect ) { case BrokeLinePointDirect.Left: { leftList.Add( i ); break; } case BrokeLinePointDirect.Right: { rightList.Add( i ); break; } case BrokeLinePointDirect.Up: { upList.Add( i ); break; } case BrokeLinePointDirect.Down: { downList.Add( i ); break; } } } i++; } #region 注释 #region 凸点 /* 找到有效凸点 */ if ( leftList.Count > 0 && rightList.Count > 0 ) { foreach ( int leftItem in leftList ) { foreach ( int rightItem in rightList ) { /*有效凸点 */ if ( Math.Abs( leftItem - rightItem ) == 2 ) { ControlPoint previousLeft = ControlPoints[leftItem - 1]; ControlPoint left = ControlPoints[leftItem]; ControlPoint previousRight = ControlPoints[rightItem - 1]; ControlPoint right = ControlPoints[rightItem]; /* 非对称凸点 */ if ( previousLeft.Point.Y != right.Point.Y ) { if ( leftItem < rightItem ) { ControlPoint addControlPoint = new ControlPoint(); addControlPoint.Point = new Point( right.Point.X, previousLeft.Point.Y ); addControlPoint.BrokeLinePointDirect = GetDirect( addControlPoint.Point, right.Point ); this.ControlPoints.Insert( rightItem - 1, addControlPoint ); removeControlPointList.Add( left ); removeControlPointList.Add( previousRight ); removeControlPointList.Add( right ); }else { ControlPoint addControlPoint = new ControlPoint(); addControlPoint.Point = new Point( left.Point.X, previousRight.Point.Y ); addControlPoint.BrokeLinePointDirect = GetDirect( addControlPoint.Point, left.Point ); this.ControlPoints.Insert( leftItem - 1, addControlPoint ); removeControlPointList.Add( previousLeft ); removeControlPointList.Add( left ); removeControlPointList.Add( right ); } } /* 对称凸点 */ else{ removeControlPointList.Add( ControlPoints[leftItem - 1] ); removeControlPointList.Add( ControlPoints[leftItem] ); removeControlPointList.Add( ControlPoints[rightItem - 1] ); removeControlPointList.Add( ControlPoints[rightItem] ); } } } } } if ( upList.Count > 0 && downList.Count > 0 ) { foreach ( int upItem in upList ) { foreach ( int downItem in downList ) { /*有效凸点 */ if ( Math.Abs( upItem - downItem ) == 2 ) { ControlPoint previousUp = ControlPoints[upItem - 1]; ControlPoint up = ControlPoints[upItem]; ControlPoint previousDown = ControlPoints[downItem - 1]; ControlPoint down = ControlPoints[downItem]; /* 非对称凸点 */ if ( previousUp.Point.X != down.Point.X ) { if ( upItem < downItem ) { ControlPoint addControlPoint = new ControlPoint(); addControlPoint.Point = new Point( down.Point.X, previousUp.Point.Y ); addControlPoint.BrokeLinePointDirect = GetDirect( addControlPoint.Point, down.Point ); this.ControlPoints.Insert( downItem - 1, addControlPoint ); removeControlPointList.Add( previousUp ); removeControlPointList.Add( up ); removeControlPointList.Add( previousDown ); }else { ControlPoint addControlPoint = new ControlPoint(); addControlPoint.Point = new Point( up.Point.X, previousDown.Point.Y ); addControlPoint.BrokeLinePointDirect = GetDirect( addControlPoint.Point, up.Point ); this.ControlPoints.Insert( upItem - 1, addControlPoint ); removeControlPointList.Add( previousUp ); removeControlPointList.Add( previousDown ); removeControlPointList.Add( down ); } } /* 对称凸点 */ else{ removeControlPointList.Add( ControlPoints[upItem - 1] ); removeControlPointList.Add( ControlPoints[upItem] ); removeControlPointList.Add( ControlPoints[downItem - 1] ); removeControlPointList.Add( ControlPoints[downItem] ); } } } } } foreach ( ControlPoint controlPoint in removeControlPointList ) { this.ControlPoints.Remove( controlPoint ); } #endregion #region 效节省点 /* 找到有效省节点 */ List<ControlPoint> removeControlList = new List<ControlPoint>(); for ( int j = 0; j < leftList.Count; j++ ) { for ( int k = 0; k < leftList.Count; k++ ) { if ( leftList[k] - leftList[j] == 2 ) { ControlPoint jPreviousControlPoint = ControlPoints[leftList[j] - 1]; ControlPoint jControlPoint = ControlPoints[leftList[j]]; ControlPoint kPreviousControlPoint = ControlPoints[leftList[k] - 1]; ControlPoint kControlPoint = ControlPoints[leftList[k]]; ControlPoint addControlPoint = new ControlPoint(); addControlPoint.Point = new Point( kControlPoint.Point.X, jControlPoint.Point.Y ); addControlPoint.BrokeLinePointDirect = GetDirect( jPreviousControlPoint.Point, addControlPoint.Point ); this.ControlPoints.Insert( leftList[k - 1], addControlPoint ); removeControlList.Add( jControlPoint ); removeControlList.Add( kPreviousControlPoint ); removeControlList.Add( kControlPoint ); /* 找到节省点 */ } } } for ( int j = 0; j < rightList.Count; j++ ) { for ( int k = 0; k < rightList.Count; k++ ) { if ( rightList[k] - rightList[j] == 2 ) { ControlPoint jPreviousControlPoint = ControlPoints[rightList[j] - 1]; ControlPoint jControlPoint = ControlPoints[rightList[j]]; ControlPoint kPreviousControlPoint = ControlPoints[rightList[k] - 1]; ControlPoint kControlPoint = ControlPoints[rightList[k]]; ControlPoint addControlPoint = new ControlPoint(); addControlPoint.Point = new Point( kControlPoint.Point.X, jControlPoint.Point.Y ); addControlPoint.BrokeLinePointDirect = GetDirect( jPreviousControlPoint.Point, addControlPoint.Point ); this.ControlPoints.Insert( rightList[k - 1], addControlPoint ); removeControlList.Add( jControlPoint ); removeControlList.Add( kPreviousControlPoint ); removeControlList.Add( kControlPoint ); /* 找到节省点 */ } } } foreach ( ControlPoint controlPoint in removeControlList ) { this.ControlPoints.Remove( controlPoint ); } #endregion #endregion }
经过一番调整,效果如下
永远不会有超过4个的折点(我们判断是4个),去掉折点标注,效果不错,注意上面的方法,比如给每个折点加入一个enum,描述为现在折点的方向,才能进行优化。比如“凸点”的确认方式,就是先上 隔1个 再下 或者 先下 隔1个 再上 或者 先左 隔一个 再右 或者先右 隔一个 再左 ;节省点的确认方式,就是 先左 隔一个 还是左 或者 先右 隔一个 还是右 即可 上下不用判断 或者 判断上下也可以,不判断左右
ps:可惜最后和要做的效果不符,所以推翻重做,发博文是因为博文太少了,来充数,呵呵,见笑
后续:悲催周五做了一天的工作算是白做了,周六在家加班又改制了一个好的使用体验的,程序员就是悲催啊
2012年7月28日 于郑州 天气:晴 晚上在家加班中。。。
博客搬家从blog.163.com/gsralex 搬家到 www.cnblogs.com/gsralex
博文全部为原创,谢绝一切转载
博文全部为原创,谢绝一切转载