需求:
不采用QGraphicsView本身的平移和旋转是因为所有的item是自定义封装的,存在交互上的数据变化,如果采用Qt自带的转换会导致交互数据出现错乱
实现思想:
放弃了坐标系的概念,采用虚拟坐标系代替–坐标系不存在,但是体现在所有item的数据上;
所有的数据都是原始坐标系,只是记录相对坐标系的值。
实现步骤:
当前坐标系的点----》需要被转换的坐标系的点----》原始坐标系的点
简单点就是:在相对坐标系(100,100)中,点(10,10)(注:该点是实际相对坐标系的点的位置) ---->在原始坐标系中的点的坐标为(110,110)---->相对坐标系(200,200)中的点(210,210)。最后的结果是原始坐标值的数值,但是我记录了相对坐标系的值。如果想知道该点在原始坐标系中的值,可以通过记录的相对坐标值进行转换
代码注释不多。主要是实现该功能的思想。
#define Pi 3.1415926
const qreal deg2rad = qreal(0.0174532925199) // pi/180
struct CoorDinate_Stru{
qreal x = 0;
qreal y = 0;
qreal angle = 0; //坐标系角度
qreal scale; //暂时不考虑
}
QPointF conver_coordinate(CoorDinate_Stru stru_pre,CoorDinate_Stru stru,QPointF pointF)
{
double pre_x = stru_pre.x;
double pre_y = stru_pre.y;
double pre_angle = stru_pre.angle;
double x = stru.x;
double y = stru.y;
double angle = stru.angle;
//平移 先计算出点在新的坐标系中的坐标。pointF是之前坐标系(stru_pre)中的点,需要转换为新的坐标系(stru)中的点
pointF = QPointF(pointF.x()+(x - pre_x),pointF.y+(y-pre_y)); //此时坐标为转换后的新坐标的点 在 原始坐标系中的位置---未旋转的情况下
//此处偷个懒,采用了Qt的源码的部分代码
/*
//Qt的源码计算 , 求一个角度的sin值和cos值 qmatrix.cpp中的rotate()函数
qreal sina = 0;
qreal cosa = 0;
if (a == 90. || a == -270.)
sina = 1.;
else if (a == 270. || a == -90.)
sina = -1.;
else if (a == 180.)
cosa = -1.;
else{
qreal b = deg2rad*a; // convert to radians
sina = qSin(b); // fast and convenient
cosa = qCos(b);
}
*/
double a = angle - pre_angle; //获取此坐标系相对原始坐标系的角度
double len = hypot(pointF.x()-x,pointF.y()-y);
if(len == 0)
return pointF;
double b = acos((double)(pointF.x())-x)/len);
if(pointF.y()-y < 0)
b = 2*Pi - b;
b = b / deg2rad;
a = a + b;
qreal sina = 0;
qreal cosa = 0;
if (a == 90. || a == -270.)
sina = 1.;
else if (a == 270. || a == -90.)
sina = -1.;
else if (a == 180.)
cosa = -1.;
else{
qreal c = deg2rad*a; // convert to radians
sina = qSin(c); // fast and convenient
cosa = qCos(c);
}
qreal dx = len * cosa;
qreal dy = len * sina;
QPointF p = QPointF(dx + x;dy + y);
return p;
}