多点旋转计算磁吸角度算法探究

5 篇文章 0 订阅

  多点触控操作对象时,对象自由旋转。但是如果想要正向摆放,光靠两个手指,非常困难,除去精度问题,手指抖动再所难免,所以有必要为旋转添加一个磁吸特性。

这里写图片描述
  所谓磁吸就是当旋转到0度、90度、180度、270度附近时,对象角度被吸入,当继续操作超过一定度数,操作才能继续。QT QGraphicsItem有roation和setRotation,使用的都是度数值。当要做磁吸效果时,不能当真调用setRotation,需做一层截留。

  带入一个假设数据:欲设置角度90.1度,截留此值,判定认为需要磁吸,直接设置角度为90度。当多点操作需要获取当前角度值时,要将截留值90.1返回,否则影响旋转计算阻碍正常操作。

  问题的关键最终总结为:输入一个角度值,识别是否4个特定角度,是的话将对象角度设置为接近的此四个角度。输入值可能大于360也可能小于0。目前采用算法如下:

void CXXXXXXXItem::setRotationR(qreal degree)
{
  fsRotation = degree;
  qreal showDegree = this->parentItem()->rotation() + degree;
  showDegree -= qFloor(showDegree/360)*360; //在0~360之间
  int x = qFloor(showDegree/90);
  int y = qFloor(showDegree/45);
  if(qAbs(showDegree-x*90-45) > 40)
  {
    if(y%2)x++;
    degree = x*90 - this->parentItem()->rotation();
  }
  this->setRotation(degree);
}

注1:qFloor(x)函数是取小于x的最大整数,负数同样奏效。C中也有同名floor函数。
注2:qAbs(x)函数取绝对值,可用#define ABS(x) ((x)>0?(x):-(x))
  算法首先记录设置的角度到成员变量fsRotation,获取用户眼中看到的角度showDegree(因为父对象可能旋转过),通过-=qFloor(showDegree/360)*360将showDegree转换为等效的0~360之间,此时再通过qFloor(showDegree/90)和qFloor(showDegree/45)将角度按两种区间分区记录算得x,y。将有八种组合:(0,0)(0,1) (1,2)(1,3) (2,4)(2,5) (3,6)(3,7)而showDegree-x*90则会得到0~90之间的值,若值与0或90接近,则可磁吸。将值-45取绝对值判断是否大于40的方法可以免去if.else的使用而将磁吸控制在正负5度之间。设0度、90度、180度、270度分别为0、1、2、3角度位,则角度位*90度即是磁吸到的目标角度。观察可知(0,0)(1,2)(2,4)(3,6)的角度位等于x,(0,1)(1,3)(2,5)(3,7)的角度位等于x+1。所以总结规律有y/2不等于x的角度位=x+1.但x、y都是整型不便于除法,换用y%2有余则区数=x+1的办法。

  如有更好更省的算法,欢迎交流!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值