【C++】转盘旋转算法

今天应公司要求,实现一个转盘旋转算法,
 
         网上找了很多资料,再根据实际效果构造出了一个算法,其实原理很简单,下面我就来做一下总结:希望对遇到此类问题的朋友有所帮助或启发。
 
 
首先:转盘旋转分几个阶段:加速,减速,停止到指定位置。
 
       当然旋转当然与角度与弧度有关,弧度在这里我就不介绍了,当然是用旋转角度来转换的,公式为:角度/180 * PI
 
       一开始我对于加速过程与减速过程想了很多办法,结果没一种接近现实效果的。但是做这么多实验当然也不是徒劳的,从这些办法中我最终选择了正切函数曲线图(tan),
 
我将这个旋转过程分为两部分:加速,减速,我以原点坐标来表示加速到减速这个过度点,见下草图
 
 
从图中可以得出:
 
      当 Δx为常量时: Δy从-∞到0    减少, Δy从0到+∞    增加。(哈哈,正是我想要的结果,并且不是线性增加的,更接近真实性)
 
故:我决定以y代表时间,x代表角度。
 
//-------------------------------------------------------------------------------------------------------------
 
下面我开始编程实现:
 
定义变量:
 
doublem_dCurAngle;//当前的旋转角度
 
doublem_dTime;//距离旋转开始的时间
 
doublem_dCurveMid;//过度点时间(及前一段加速总时间)
 
c++中及得到算法函数(反正切函数):
 
            m_dCurAngle = atan((m_dTime - m_dCurveMid));
 
对,到此,雏形已经明了,现在就需要解决三个问题了:
 
       1、对于时间控制(我们淡然不是想y轴所对应的时间间隔相对于现实时间是一一对应的,说白了就是我们希望y轴的时间区块是可缩放的)
 
2、对于旋转到指定的点的问题还未解决的(随机出来的终点角度当然要是可控的)
 
         3、从上一次旋转结果开始运动,
 
下面我来解决这几个问题:
 
       对于第一个问题,非常简单,我们可以给时间设置一个时间参数(当然其实术语应该叫:曲线参数)
 
               我是将所有时间除以一个参数(如下定义):
 
    double m_dCurveParam;     //曲线参数(这里我设置为150)
 
    以上旋转就变成了:  m_dCurAngle = atan((m_dwRotateTime - m_dCurveMid) / m_dCurveParam);
 
对于第二个问题,解决办法很多:我这里说一个我自己实现的办法。
 
doublem_dRotateAngle;//旋转总角度(绝对角度)
 
 
doublem_dwRotateTime;//转盘旋转总时
 
doublem_dCurveScale;                                               //曲线量表
 
doublem_dCurveOffset;                                             //加速旋转总角度
 
我的解决办法依然是给设置个参数:
 
                     我们可以从上图中得到两段中共旋转角度:
 
                                 m_dCurveOffset = atan(- m_dCurveMid / m_dCurveParam);//前半段旋转角度负值
 
                             故能得到:
 
                                  m_dCurveScale=m_dRotateAngle / (atan((m_dwRotateTime - m_dCurveMid) / m_dCurveParam) - m_dCurveOffset);
 
                                其中:atan((m_dwRotateTime - m_dCurveMid) / m_dCurveParam) 表示后半段减速所旋转角度
 
故得出最后旋转算法:
 
                           m_dCurAngle = m_dCurveScale * ( atan((m_dTime - m_dCurveMid) / m_dCurveParam) - m_dCurveOffset);
 
这样:当旋转总时间结束后,就旋转到当前要旋转的点了,
 
 
 
下面做逻辑:
 
          if (m_dTime <= m_dwRotateTime)//旋转没结束
 
{
 
m_dCurAngle = m_dCurveScale * (atan((m_dTime - m_dCurveMid) / m_dCurveParam) - m_dCurveOffset);
 
}
 
      else{
 
            //结束处理
 
              }
 
到此:第二个问题也被解决了:
 
下面来解决第三个问题:
 
       相信第二个问题解决了后,这个问题就简单到爆了。
 
              这个问题只需要改变两个地方:
 
1、改变旋转总角度(m_dRotateAngle)
 
             如果你    m_dRotateAngle = 360.0 * Random(6)+ m_dRotateOffsetNow;  (m_dRotateOffsetNow表示此次相对于原点偏移)
 
          那么你需要改成:m_dRotateAngle = 360.0 * Random(6)+ (m_dRotateOffsetNow-m_dRotateOffsetPve);(m_dRotateOffsetPve表示上次相对于原点偏移)
 
2、改变当前的旋转角度(m_dRotateAngle)
 
             之前是这样  m_dRotateAngle = m_dRotateAngle;
 
           那么你要改成这样:m_dRotateAngle = m_dRotateAngle + m_dRotateOffsetPve;(m_dRotateOffsetPve表示上次相对于原点偏移)
 
到此:全部旋转都解决(当然,此旋转为顺时针旋转,逆时针同理)
 
你不妨试试效果。
 
你可以调整前半段时间m_dCurveMid,跟曲线参数m_dCurveParam来实现自定义效果!
 
Good luck!!!

posted @ 2013-10-04 10:57  来自你520的末班车  阅读(1232)  评论(0编辑  收藏  举报