如何在程序中画更好看的折线


前言:



做的程序需要两种线,一种是贝塞尔曲线,一种是折线,贝塞尔线比较简单,这里主要说折现,折现的折点不能出现的过多,否则会出现上面的情况



 
一般这种折现会出现两种情况,我管着两种情况叫做凸点,和延伸点(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
博文全部为原创,谢绝一切转载
原文地址:https://www.cnblogs.com/gsralex/p/3538040.html