如上图所示,绘制矩形之后,可以按住中间缩放、然后按住右侧中间进行旋转,按住右下角进行缩放,按住下方中间进行斜切矩形。
整体都是仿照visionpro里面的矩形卡尺制作的。
至于拖动、缩放、旋转功能可详见我的博客:https://blog.csdn.net/weixin_43935474/article/details/107033591
这里主要讲一下切变,和切变之后的缩放功能。
注:我的切变暂时只支持宽度方向切变!
首先,切变主要使用qt里面的
QTransform &QTransform::shear(qreal sh, qreal sv)
Shears the coordinate system by sh horizontally and sv vertically, and returns a reference to the matrix.
QTransform::shear的参数关系为:
假设矩形正中央为坐标原点(0,0),矩形边上某一点坐标在切变之前为(x1,y1),切变之后为(x2,y2),则x2=x1+sh*y1
用法如下:
1 QTransform trans;
2 trans.translate(m_RECT.center().x(),m_RECT.center().y());//QRectF m_RECT为切变前的矩形
3 trans.shear(m_fShearX,0);
4 trans.translate(-m_RECT.center().x(),-m_RECT.center().y());
5 m_RECTShear = trans.map(m_RECTShear);//m_RECT斜切之后成了多边形QPolygonF m_RECTShear
拖动和缩放时候需要用下面这张图来解释:
因为要考虑到旋转之后依然支持切变,拖动鼠标进行切变时,切变参数sh的计算是根据鼠标在矩形横向的偏移量来计算的:
假设点pCross3和pCross5的距离dis1,点pc到pCross3的距离为h1(因为制作横向切变,所以h1=矩形高度的一半),则
sh = dis1/h1;
然后在paint()函数里面就可以根据sh这个参数来绘制切变后的矩形。
切变之后的的缩放需要保持原有的切变参数以及旋转角度,所以拖动鼠标进行缩放时,矩形的宽高的偏移量是根据如下方式计算得到的:
假设pos到直线pc pCross1的距离为h2,点pc到pCross1的距离为w2,则缩放后的新矩形参数为:
QRectF newRECT = QRectF(pc.x()-w2,pc.y()-h2,w2*2,h2*2);
核心代码如下:
头文件:
1 #ifndef MYGRAPHICCALIPERITEM_H
2 #define MYGRAPHICCALIPERITEM_H
3 #include <QObject>
4 #include <QWidget>
5 #include <QMouseEvent>
6 #include <QGraphicsScene>
7 #include <QGraphicsRectItem>
8 #include <QGraphicsSceneMouseEvent>
9 #include <QRect>
10 #include <QPainter>
11 #include <QPolygon>
12 #include <QList>
13 #include <QTransform>
14 #include <QMap>
15 enum CALIPER_STATE_FLAG{
16 CALI_DEFAULT=0,
17 CALI_RECT_TL,//标记当前为用户按下矩形的左上角
18 CALI_RECT_TR,//标记当前为用户按下矩形的右上角
19 CALI_RECT_BL,//左下角
20 CALI_RECT_BR,//右下角
21 CALI_RECT_SHEAR,//标记当前为用户按下矩形的下边中点的切变矩形
22 CALI_RECT_MOVE,//标记当前为鼠标拖动矩形移动状态
23 CALI_RECT_ROTATE,//标记当前为旋转状态
24 CALIMOV_POLYGON_POINT//移动多边形的某个点
25 };
26 enum CALIPER_SHAPE_TYPE{
27 CALIPER_RECT,//矩形
28 CALIPER_LINE,
29 CALIPER_CIRCLE,
30 CALIPER_ELLIPSE
31 };
32
33 class mygraphicCaliperitem:public QObject,public QGraphicsItem
34 {
35 Q_OBJECT
36 public:
37 CALIPER_SHAPE_TYPE m_ShapeType;
38 mygraphicCaliperitem(QGraphicsItem *parent = nullptr);
39 ~mygraphicCaliperitem();
40 //mygraphicCaliperitem(QRectF m_OriginRect = QRectF(0,0,100,100));
41 QRectF boundingRect() const;
42 QPainterPath shape() const;
43 QPainterPath getCollideShape();
44 QPainterPath getCollideShapeTopLeftAsOriginPoint();
45 void setRectSize(QRectF mrect,bool bResetRotateCenter = true);
46 void setShearRectSize(QRectF mrect);
47 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
48 void mousePressEvent(QGraphicsSceneMouseEvent *event);
49 void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
50 void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
51 int type() const;
52 void SetRotate(qreal RotateAngle);
53 void SetSideCursorByRotateAngle(qreal RotateAngle);
54 //计算两点距离
55 double CalDis(const double x1, const double y1,const double x2, const double y2);
56 //计算点(ptx,pty)到线段(x1y1,x2y2)的距离
57 double CalDis(const double ptx, const double pty,const double x1, const double y1,const double x2, const double y2);
58 double CalDisPoint2longLine(const double ptx, const double pty,const double x1, const double y1,const double x2, const double y2);
59 //计算斜切后分别经过中心点和鼠标所在点的两平行线的2个焦点
60 bool get2CrossPt(QPointF p0, QPointF p1, QPointF p2, QPointF pc, QPointF pos, QPointF &pCross1, QPointF &pCross2);
61 QPointF pCross1,pCross2,pCross3,pCross5;
62 QPointF getRotatePoint(QPointF ptCenter, QPointF ptIn, qreal angle);//获取旋转后的点
63 QList<QPointF> getRotatePoints(QPointF ptCenter,QList<QPointF> ptIns,qreal angle);//获取多个旋转后的点
64 QPolygonF getRotatePolygonFromRect(QPointF ptCenter,QRectF rectIn,qreal angle);//将矩形旋转之后返回多边形
65 QPolygonF getRotatePolygonFromPolygon(QPointF ptCenter,QPolygonF polyIn,qreal angle);//将多边形旋转之后返回多边形
66 QRectF getBoundedRectToSceen();
67 QPolygonF getCrtPolygonToScreen();
68 QPointF getSmallRotateRectCenter(QPointF ptA,QPointF ptB);//获取旋转时候矩形正上方的旋转标记矩形
69 QRectF getSmallRotateRect(QPointF ptA,QPointF ptB);
70 qreal m_RotateAngle;
71 QPointF m_RotateCenter;
72 bool m_bKeepShadowLength;//保持投影长度不变
73 private:
74 //CALIPER_RECT矩形卡尺使用
75 QRectF m_RECT;
76 QRectF m_newShearRECT;
77 QPolygonF m_RECTShear;//矩形斜切后
78 QPolygonF m_RECT_Pol;//矩形旋转后
79 QPolygonF m_RECT_TL_Pol;//左上角顶点旋转后
80 QRectF m_RECT_TL;//左上角顶点
81 QPolygonF m_RECT_TR_Pol;//右上角顶点旋转后
82 QRectF m_RECT_TR;//右上角顶点
83 QPolygonF m_RECT_BL_Pol;//左下角顶点旋转后
84 QRectF m_RECT_BL;//左下角顶点
85 QPolygonF m_RECT_BR_Pol;//右下角顶点旋转后
86 QRectF m_RECT_BR;//右下角顶点
87 QPolygonF m_RECT_Inside_Pol;//内部区域旋转后
88 QPolygonF m_RECT_InsideShear;//内部区域斜切后
89 QRectF m_RECT_Inside;//内部区域
90 QPolygonF m_RECT_Scan_Dir_Pol;//扫描方向标记旋转后
91 QRectF m_RECT_Scan_Dir;//扫描方向标记
92 QPolygonF m_RECT_Shadow_Dir_Pol;//投影方向标记旋转后
93 QRectF m_RECT_Shadow_Dir;//投影方向标记
94 qreal m_fShadowLength;//投影长度
95 QPolygonF m_RECT_Rotate_Pol;//旋转的标记的矩形旋转后形成的多边形
96 QRectF m_RECT_Rotate;//旋转的标记的矩形
97 QPolygonF m_RECT_Shear_Pol;//切变矩形标记旋转后
98 QRectF m_RECT_Shear;//切变矩形标记
99 qreal m_fShearX;//切变矩形x方向参数
100
101 //
102 QPointF m_startPos;
103 CALIPER_STATE_FLAG m_StateFlag;
104 QMenu *pMenu;//弹出菜单
105 QPolygonF m_oldPolygon;
106 QMap<qreal,int> m_MapDis2Line;//记录鼠标右击时的坐标离m_oldPolygon中每一条线段的距离
107 qreal m_MinDis;//记录鼠标右击时,离m_oldPolygon最近一条线段的距离;
108 int m_nPolygonMovePointIndex;//移动多边形顶点的索引
109 int m_nPolyRemoveIndex;
110
111 bool m_bResize;
112 protected:
113 private slots:
114 void onMenuEvent();//弹出菜单点击后响应函数
115 };
116
117 #endif // MYGRAPHICCALIPERITEM_H
源文件:
1 #include "myGraphicCaliperItem.h"
2 #include <QtMath>
3 #include <QDebug>
4 #include <QMenu>
5
6 #pragma execution_character_set("utf-8")//让能够正常显示中文字符串
7
8 mygraphicCaliperitem::mygraphicCaliperitem(QGraphicsItem *parent):
9 m_ShapeType(CALIPER_RECT),
10 m_bResize(false),
11 m_RECT(-100,-200,200,400),
12 m_RotateAngle(0),
13 m_bKeepShadowLength(false),
14 m_fShearX(0),
15 m_StateFlag(CALI_DEFAULT)
16 {
17 //setParent(parent);
18 m_newShearRECT.setWidth(0);
19 setRectSize(m_RECT);
20 //setToolTip("Click and drag me!"); //提示
21 setCursor(Qt::ArrowCursor); //改变光标形状,手的形状
22 setFlag(QGraphicsItem::ItemIsMovable);
23 //SetRotate(0);
24 //setFlag(QGraphicsItem::ItemIsSelectable);//
25 setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable);
26 // //创建菜单对象
27 // pMenu = new QMenu();//((QWidget*)this);
28 // QAction *pActionAddPt = new QAction("添加顶点", pMenu);
29 // QAction *pActionDelPt = new QAction("删除顶点", pMenu);
30 // //1:添加多边形顶点 2:删除多边形顶点
31 // pActionAddPt->setData(1);
32 // pActionDelPt->setData(2);
33
34 // //把QAction对象添加到菜单上
35 // pMenu->addAction(pActionAddPt);
36 // pMenu->addAction(pActionDelPt);
37
38 // //连接鼠标右键点击信号
39 // connect(pActionAddPt, SIGNAL(triggered()), this, SLOT(onMenuEvent()));
40 // connect(pActionDelPt, SIGNAL(triggered()), this, SLOT(onMenuEvent()));
41 }
42 void mygraphicCaliperitem::onMenuEvent()
43 {
44 // QAction *pEven = qobject_cast<QAction *>(this->sender()); //this->sender()就是发信号者 QAction
45 // //获取发送信息类型 //1:添加多边形顶点 2:删除多边形顶点
46 // int iType = pEven->data().toInt();
47 // switch (iType)
48 // {
49 // case 1://添加多边形顶点
50 // m_oldPolygon.insert(m_MapDis2Line.value(m_MinDis)+1,m_startPos);
51 // break;
52 // case 2://删除多边形顶点
53 // if(m_oldPolygon.count()>3)
54 // {
55 // m_oldPolygon.remove(m_nPolyRemoveIndex);
56 // }
57 // break;
58 // default:
59 // break;
60 // }
61 // scene()->update();
62 }
63 QRectF mygraphicCaliperitem::boundingRect() const//用来控制本item绘制区域
64 {
65 QPainterPath path;
66 if(m_ShapeType == CALIPER_RECT)
67 {
68 path.setFillRule(Qt::WindingFill);
69 path.addPolygon(m_RECT_Pol);
70 path.addPolygon(m_RECT_Rotate_Pol);
71 path.addPolygon(m_RECT_TL_Pol);
72 path.addPolygon(m_RECT_TR_Pol);
73 path.addPolygon(m_RECT_BL_Pol);
74 path.addPolygon(m_RECT_BR_Pol);
75 path.addPolygon(m_RECT_Shadow_Dir_Pol);
76 path.addPolygon(m_RECT_Shear_Pol);
77 }
78 return path.boundingRect();
79 }
80
81 QPainterPath mygraphicCaliperitem::shape() const//用来控制检测碰撞collide和鼠标点击hit响应区域
82 {
83 QPainterPath path;
84 if(m_ShapeType == CALIPER_RECT)
85 {
86 path.setFillRule(Qt::WindingFill);
87 path.addPolygon(m_RECT_Pol);
88 path.addPolygon(m_RECT_Rotate_Pol);
89 path.addPolygon(m_RECT_TL_Pol);
90 path.addPolygon(m_RECT_TR_Pol);
91 path.addPolygon(m_RECT_BL_Pol);
92 path.addPolygon(m_RECT_BR_Pol);
93 path.addPolygon(m_RECT_Shadow_Dir_Pol);
94 path.addPolygon(m_RECT_Shear_Pol);
95 }
96 return path;
97 }
98
99 QPainterPath mygraphicCaliperitem::getCollideShape()
100 {
101 QPainterPath path;
102 if(m_ShapeType == CALIPER_RECT)
103 {
104 path.addPolygon(m_RECT_Pol);
105 }
106 return path;
107 }
108
109 QPainterPath mygraphicCaliperitem::getCollideShapeTopLeftAsOriginPoint()//返回左上角移动到item的(0,0)位置的collide区域
110 {
111 QPainterPath path;
112 if(m_ShapeType == CALIPER_RECT)
113 {
114 QTransform trans;
115 path.addPolygon(m_RECT_Pol);
116 trans.translate(-path.boundingRect().x(),-path.boundingRect().y());
117 path = trans.map(path);
118 }
119 return path;
120 }
121
122 mygraphicCaliperitem::~mygraphicCaliperitem()
123 {
124
125 }
126
127 void mygraphicCaliperitem::setRectSize(QRectF mrect, bool bResetRotateCenter)
128 {
129 m_RECT = mrect;
130 // if(m_newShearRECT.width() == 0)
131 // {
132 m_newShearRECT = m_RECT;
133 // }
134 if(bResetRotateCenter)
135 {
136 m_RotateCenter.setX(m_RECT.x()+m_RECT.width()/2);
137 m_RotateCenter.setY(m_RECT.y()+m_RECT.height()/2);
138 }
139 //test 扭曲
140 m_RECTShear = QPolygonF(m_RECT);
141 QTransform trans;
142 trans.translate(m_RECT.center().x(),m_RECT.center().y());
143 trans.shear(m_fShearX,0);
144 trans.translate(-m_RECT.center().x(),-m_RECT.center().y());
145 m_RECTShear = trans.map(m_RECTShear);//斜切之后的矩形
146 //test
147 m_RECT_Pol = getRotatePolygonFromPolygon(m_RotateCenter,m_RECTShear,m_RotateAngle);
148
149 //m_RECT_Inside = QRectF(m_RECTShear[0].x()+5,m_RECTShear[0].y()+5,m_RECT.width()-10,m_RECT.height()-10);
150 m_RECT_InsideShear.clear();
151 m_RECT_InsideShear.append(QPointF(m_RECTShear[0].x()+5,m_RECTShear[0].y()+5));
152 m_RECT_InsideShear.append(QPointF(m_RECTShear[1].x()-5,m_RECTShear[1].y()+5));
153 m_RECT_InsideShear.append(QPointF(m_RECTShear[2].x()-5,m_RECTShear[2].y()-5));
154 m_RECT_InsideShear.append(QPointF(m_RECTShear[3].x()+5,m_RECTShear[3].y()-5));
155 m_RECT_InsideShear.append(QPointF(m_RECTShear[0].x()+5,m_RECTShear[0].y()+5));
156 m_RECT_Inside_Pol = getRotatePolygonFromPolygon(m_RotateCenter,m_RECT_InsideShear,m_RotateAngle);
157
158 m_RECT_TL = QRectF(m_RECTShear[0].x()-5,m_RECTShear[0].y()-5,10,10);//左上角顶点
159 m_RECT_TL_Pol = getRotatePolygonFromRect(m_RotateCenter,m_RECT_TL,m_RotateAngle);
160
161 m_RECT_TR = QRectF(m_RECTShear[1].x()-5,m_RECTShear[1].y()-5,10,10);//右上角顶点
162 m_RECT_TR_Pol = getRotatePolygonFromRect(m_RotateCenter,m_RECT_TR,m_RotateAngle);
163
164 m_RECT_BL = QRectF(m_RECTShear[3].x()-5,m_RECTShear[3].y()-5,10,10);//左下角顶点
165 m_RECT_BL_Pol = getRotatePolygonFromRect(m_RotateCenter,m_RECT_BL,m_RotateAngle);
166
167 m_RECT_BR = QRectF(m_RECTShear[2].x()-5,m_RECTShear[2].y()-5,10,10);//右下角顶点
168 m_RECT_BR_Pol = getRotatePolygonFromRect(m_RotateCenter,m_RECT_BR,m_RotateAngle);
169
170 m_RECT_Rotate = QRectF((m_RECTShear[1].x()+m_RECTShear[2].x())/2-10,(m_RECTShear[1].y()+m_RECTShear[2].y())/2-10,20,20);//矩形右侧旋转标记矩形
171 m_RECT_Rotate_Pol = getRotatePolygonFromRect(m_RotateCenter,m_RECT_Rotate,m_RotateAngle);
172
173 m_RECT_Scan_Dir = QRectF((m_RECTShear[0].x()+m_RECTShear[1].x())/2-5,(m_RECTShear[0].y()+m_RECTShear[1].y())/2-5,10,10);
174 QPolygonF tempPol = getRotatePolygonFromRect(m_RotateCenter,m_RECT_Scan_Dir,m_RotateAngle);
175 QVector<QPointF> tempv;
176 tempv.append(QPointF(tempPol[0]));
177 tempv.append(QPointF((tempPol[1].x()+tempPol[2].x())/2,(tempPol[1].y()+tempPol[2].y())/2));
178 tempv.append(QPointF(tempPol[3]));
179 m_RECT_Scan_Dir_Pol = QPolygonF(tempv);//扫描方向的三角形
180
181 m_RECT_Shadow_Dir = QRectF(m_RECT.x()-5,m_RECT.bottomLeft().y()-15,10,10);//投影方向的三角形标记
182 QPolygonF tempShadow = QPolygonF(m_RECT_Shadow_Dir);
183 tempShadow = trans.map(tempShadow);
184 m_RECT_Shadow_Dir_Pol = getRotatePolygonFromPolygon(m_RotateCenter,tempShadow,m_RotateAngle);
185
186 m_RECT_Shear = QRectF((m_RECTShear[2].x()+m_RECTShear[3].x())/2-5,(m_RECTShear[2].y()+m_RECTShear[3].y())/2-5,10,10);
187 // tempPol = getRotatePolygonFromRect(m_RotateCenter,m_RECT_Shear,m_RotateAngle);
188 // tempv.clear();
189 // tempv.append(QPointF((tempPol[0].x()+tempPol[1].x())/2,(tempPol[0].y()+tempPol[1].y())/2));
190 // tempv.append(tempPol[1]);
191 // tempv.append(QPointF((tempPol[2].x()+tempPol[3].x())/2,(tempPol[2].y()+tempPol[3].y())/2));
192 // tempv.append(tempPol[3]);
193 // m_RECT_Shear_Pol = QPolygonF(tempv);//切变矩形标记
194 QPolygonF tempShear = QPolygonF(m_RECT_Shear);
195 QTransform transShear;
196 transShear.translate(m_RECT_Shear.center().x(),m_RECT_Shear.center().y());//先把中心移动到m_RECT_Shear中心
197 transShear.shear(1,0);
198 transShear.translate(-m_RECT_Shear.center().x(),-m_RECT_Shear.center().y());//先把中心移动到m_RECT_Shear中心
199 tempShear = transShear.map(tempShear);//斜切之后的矩形
200 m_RECT_Shear_Pol = getRotatePolygonFromPolygon(m_RotateCenter,tempShear,m_RotateAngle);
201
202 }
203
204 void mygraphicCaliperitem::setShearRectSize(QRectF mrect)
205 {
206 m_newShearRECT = mrect;
207 m_RotateCenter.setX(m_newShearRECT.x()+m_newShearRECT.width()/2);
208 m_RotateCenter.setY(m_newShearRECT.y()+m_newShearRECT.height()/2);
209 //test 扭曲
210 m_RECTShear = QPolygonF(m_newShearRECT);
211 QTransform trans;
212 trans.translate(m_newShearRECT.center().x(),m_newShearRECT.center().y());
213 trans.shear(m_fShearX,0);
214 trans.translate(-m_newShearRECT.center().x(),-m_newShearRECT.center().y());
215 m_RECTShear = trans.map(m_RECTShear);//斜切之后的矩形
216 //test
217 m_RECT_Pol = getRotatePolygonFromPolygon(m_RotateCenter,m_RECTShear,m_RotateAngle);
218
219 //m_RECT_Inside = QRectF(m_RECTShear[0].x()+5,m_RECTShear[0].y()+5,m_RECT.width()-10,m_RECT.height()-10);
220 m_RECT_InsideShear.clear();
221 m_RECT_InsideShear.append(QPointF(m_RECTShear[0].x()+5,m_RECTShear[0].y()+5));
222 m_RECT_InsideShear.append(QPointF(m_RECTShear[1].x()-5,m_RECTShear[1].y()+5));
223 m_RECT_InsideShear.append(QPointF(m_RECTShear[2].x()-5,m_RECTShear[2].y()-5));
224 m_RECT_InsideShear.append(QPointF(m_RECTShear[3].x()+5,m_RECTShear[3].y()-5));
225 m_RECT_InsideShear.append(QPointF(m_RECTShear[0].x()+5,m_RECTShear[0].y()+5));
226 m_RECT_Inside_Pol = getRotatePolygonFromPolygon(m_RotateCenter,m_RECT_InsideShear,m_RotateAngle);
227
228 m_RECT_TL = QRectF(m_RECTShear[0].x()-5,m_RECTShear[0].y()-5,10,10);//左上角顶点
229 m_RECT_TL_Pol = getRotatePolygonFromRect(m_RotateCenter,m_RECT_TL,m_RotateAngle);
230
231 m_RECT_TR = QRectF(m_RECTShear[1].x()-5,m_RECTShear[1].y()-5,10,10);//右上角顶点
232 m_RECT_TR_Pol = getRotatePolygonFromRect(m_RotateCenter,m_RECT_TR,m_RotateAngle);
233
234 m_RECT_BL = QRectF(m_RECTShear[3].x()-5,m_RECTShear[3].y()-5,10,10);//左下角顶点
235 m_RECT_BL_Pol = getRotatePolygonFromRect(m_RotateCenter,m_RECT_BL,m_RotateAngle);
236
237 m_RECT_BR = QRectF(m_RECTShear[2].x()-5,m_RECTShear[2].y()-5,10,10);//右下角顶点
238 m_RECT_BR_Pol = getRotatePolygonFromRect(m_RotateCenter,m_RECT_BR,m_RotateAngle);
239
240 m_RECT_Rotate = QRectF((m_RECTShear[1].x()+m_RECTShear[2].x())/2-10,(m_RECTShear[1].y()+m_RECTShear[2].y())/2-10,20,20);//矩形右侧旋转标记矩形
241 m_RECT_Rotate_Pol = getRotatePolygonFromRect(m_RotateCenter,m_RECT_Rotate,m_RotateAngle);
242
243 m_RECT_Scan_Dir = QRectF((m_RECTShear[0].x()+m_RECTShear[1].x())/2-5,(m_RECTShear[0].y()+m_RECTShear[1].y())/2-5,10,10);
244 QPolygonF tempPol = getRotatePolygonFromRect(m_RotateCenter,m_RECT_Scan_Dir,m_RotateAngle);
245 QVector<QPointF> tempv;
246 tempv.append(QPointF(tempPol[0]));
247 tempv.append(QPointF((tempPol[1].x()+tempPol[2].x())/2,(tempPol[1].y()+tempPol[2].y())/2));
248 tempv.append(QPointF(tempPol[3]));
249 m_RECT_Scan_Dir_Pol = QPolygonF(tempv);//扫描方向的三角形
250
251 m_RECT_Shadow_Dir = QRectF(m_newShearRECT.x()-5,m_newShearRECT.bottomLeft().y()-15,10,10);//投影方向的三角形标记
252 QPolygonF tempShadow = QPolygonF(m_RECT_Shadow_Dir);
253 tempShadow = trans.map(tempShadow);
254 m_RECT_Shadow_Dir_Pol = getRotatePolygonFromPolygon(m_RotateCenter,tempShadow,m_RotateAngle);
255
256 m_RECT_Shear = QRectF((m_RECTShear[2].x()+m_RECTShear[3].x())/2-5,(m_RECTShear[2].y()+m_RECTShear[3].y())/2-5,10,10);
257 QPolygonF tempShear = QPolygonF(m_RECT_Shear);
258 QTransform transShear;
259 transShear.translate(m_RECT_Shear.center().x(),m_RECT_Shear.center().y());//先把中心移动到m_RECT_Shear中心
260 transShear.shear(1,0);
261 transShear.translate(-m_RECT_Shear.center().x(),-m_RECT_Shear.center().y());//先把中心移动到m_RECT_Shear中心
262 tempShear = transShear.map(tempShear);//斜切之后的矩形
263 m_RECT_Shear_Pol = getRotatePolygonFromPolygon(m_RotateCenter,tempShear,m_RotateAngle);
264
265 }
266
267 void mygraphicCaliperitem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
268 {
269 QPen mPen;
270 mPen= QPen(Qt::yellow);
271 painter->setPen(mPen);
272 if(m_ShapeType == CALIPER_RECT)
273 {
274 //绘制旋转后的矩形
275 painter->drawPolygon(m_RECT_Pol);
276 //绘制旋转圆形
277 mPen.setWidth(2);
278 mPen.setColor(Qt::green);
279 painter->setPen(mPen);
280 QPointF pf = QPointF((m_RECT_Pol[1].x()+m_RECT_Pol[2].x())/2,(m_RECT_Pol[1].y()+m_RECT_Pol[2].y())/2);
281 QRectF rect = QRectF(pf.x()-10,pf.y()-10,20,20);
282 painter->drawEllipse(rect);//绘制圆形
283 painter->drawPoint(pf);//绘制点
284 //绘制4个顶点矩形
285 mPen.setWidth(1);
286 painter->setPen(mPen);
287 // painter->drawPolygon(m_RECT_TL_Pol);
288 // painter->drawPolygon(m_RECT_TR_Pol);
289 // painter->drawPolygon(m_RECT_BL_Pol);
290 painter->drawPolygon(m_RECT_BR_Pol);
291 //绘制投影标记
292 QPointF pt0 = m_RECT_Shadow_Dir_Pol[0];
293 QPointF pt1 = QPointF((m_RECT_Shadow_Dir_Pol[2].x()+m_RECT_Shadow_Dir_Pol[3].x())/2,(m_RECT_Shadow_Dir_Pol[2].y()+m_RECT_Shadow_Dir_Pol[3].y())/2);
294 QPointF pt2 = m_RECT_Shadow_Dir_Pol[1];
295 painter->drawLine(pt0,pt1);
296 painter->drawLine(pt2,pt1);
297 //绘制扫描方向标记
298 painter->drawPolygon(m_RECT_Scan_Dir_Pol);
299 //绘制切变矩形标记
300 painter->drawPolygon(m_RECT_Shear_Pol);
301
302 //painter->drawPolygon(m_RECT_Inside_Pol);
303 // mPen.setColor(Qt::red);
304 // mPen.setWidth(5);
305 // painter->setPen(mPen);
306 // painter->drawPoint(pCross1);
307 // painter->drawPoint(pCross2);
308 // painter->drawPoint(pCross3);
309 // painter->drawPoint(m_RECT.center());
310 }
311 }
312
313 double mygraphicCaliperitem::CalDis(const double x1, const double y1, const double x2, const double y2)
314 {
315 return sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
316 }
317
318 double mygraphicCaliperitem::CalDis(const double ptx, const double pty, const double x1, const double y1, const double x2, const double y2)
319 {
320 double f = (x2-x1)*(ptx-x1) + (y2-y1)*(pty-y1);
321 if (f<=0)
322 return CalDis(ptx, pty, x1, y1);
323 double d = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1);
324 if (f>d)
325 return CalDis(ptx, pty, x2, y2);
326 f = f/d;
327 double projX = (x1 + (x2 - x1)*f);
328 double projY = (y1 + (y2 - y1)*f);
329 return CalDis(ptx, pty, projX, projY);
330 }
331
332 double mygraphicCaliperitem::CalDisPoint2longLine(const double ptx, const double pty, const double x1, const double y1, const double x2, const double y2)
333 {
334 // double f = (x2-x1)*(ptx-x1) + (y2-y1)*(pty-y1);
335 if (f<=0)
336 return CalDis(ptx, pty, x1, y1);
337 // double d = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1);
338 if (f>d)
339 return CalDis(ptx, pty, x2, y2);
340 // f = f/d;
341 // double projX = (x1 + (x2 - x1)*f);
342 // double projY = (y1 + (y2 - y1)*f);
343 // return CalDis(ptx, pty, projX, projY);
344
345 //求点(ptx,pty)到直线(x1,y1)(x2,y2)的距离
346 //直线(x1,y1)(x2,y2)的方程为y=kx+b;
347 //过点(ptx,pty)的直线(x1,y1)(x2,y2)的中垂线方程为y=k2x+b2;两线交点为pCross(x0,y0)
348 qreal k,b,k2,b2,x0,y0;
349 if(x1==x2)
350 {
351 //直线方程为:x=x1
352 if(y1==y2)
353 {
354 //垂线方程为:x=ptx
355 //该情况异常,返回-1
356 return -1;
357 }
358 else
359 {
360 k2 = (x2-x1)/(y1-y2);
361 b2 = pty-k2*ptx;
362 x0=x1;
363 y0 = k2*x0+b2;
364 }
365 }
366 else
367 {
368 k = (y1-y2)/(x1-x2);
369 b = y1-k*x1;
370 if(y1==y2)
371 {
372 //垂线方程为:x=ptx
373 x0=ptx;
374 y0=k*x0+b;
375 }
376 else
377 {
378 k2 = (x2-x1)/(y1-y2);
379 b2 = pty-k2*ptx;
380 if(k==k2)
381 return -1;
382 else
383 {
384 x0=(b-b2)/(k2-k);
385 y0=k*x0+b;
386 }
387 }
388 }
389 return CalDis(x0,y0,ptx,pty);
390 }
391
392 bool mygraphicCaliperitem::get2CrossPt(QPointF p0, QPointF p1, QPointF p2, QPointF pc, QPointF pos, QPointF &pCross1, QPointF &pCross2)
393 {
394 qreal k1,k2,b1,b2;
395 //假设经过pc的平行于p0p1的直线方程为:y=k1*x+b1;
396 if(p1.x()!=p0.x())
397 {
398 k1 = (p1.y()-p0.y())/(p1.x()-p0.x());
399 b1 = pc.y()-k1*pc.x();
400 }
401 //假设经过pos的平行于p1p2的直线方程为:y=k2*x+b2;
402 if(p1.x()!=p2.x())
403 {
404 k2 = (p2.y()-p1.y())/(p2.x()-p1.x());
405 b2 = pos.y()-k2*pos.x();
406 }
407 //假设两线交点为(x,y)
408 qreal x,y;
409 if(p1.x()==p0.x())
410 {
411 //则k1不存在,直线1为x=pc.x()
412 if(p1.x()==p2.x())
413 {
414 //k2不存在,直线2为x=pos.x()
415 //则两线焦点不存在,直接return
416 return false;
417 }
418 else
419 {
420 x=pc.x();
421 y = k2*x+b2;
422 }
423 }
424 else
425 {
426 if(p1.x()==p2.x())
427 {
428 //k2不存在,直线2为x=pos.x()
429 x = pos.x();
430 y = k1*x+b1;
431 }
432 else
433 {
434 if(k1==k2)
435 return false;
436 x=(b1-b2)/(k2-k1);
437 y = k1*x+b1;
438 }
439 }
440 pCross1=QPointF(x,y);//经过pc的平行于p0p1的直线 与 经过Pos的平行于p1p2的直线 的焦点
441
442 //假设经过pos的平行于p0p1的直线方程为:y=k3*x+b3;
443 //假设两线交点为(x2,y2)
444 qreal k3,k4,b3,b4,x2,y2;
445 if(p1.x()!=p0.x())
446 {
447 k3 = (p1.y()-p0.y())/(p1.x()-p0.x());
448 b3 = pos.y()-k3*pos.x();
449 }
450 //假设经过pc的平行于p1p2的直线方程为:y=k4*x+b4;
451 if(p1.x()!=p2.x())
452 {
453 k4 = (p2.y()-p1.y())/(p2.x()-p1.x());
454 b4 = pc.y()-k4*pc.x();
455 }
456 if(p1.x()==p0.x())
457 {
458 //则k3不存在,直线1为x=pos.x()
459 if(p1.x()==p2.x())
460 {
461 //k4不存在,直线2为x=pc.x()
462 //则两线焦点不存在,直接return
463 return false;
464 }
465 else
466 {
467 x2=pos.x();
468 y2 = k4*x2+b4;
469 }
470 }
471 else
472 {
473 if(p1.x()==p2.x())
474 {
475 //k4不存在,直线2为x=pc.x()
476 x2=pc.x();
477 y2 = k3*x2+b3;
478 }
479 else
480 {
481 if(k3==k4)
482 return false;
483 x2=(b3-b4)/(k4-k3);
484 y2 = k3*x2+b3;
485 }
486 }
487 pCross2=QPointF(x2,y2);//经过pc的平行于p0p1的直线 与 经过Pos的平行于p1p2的直线 的焦点
488 return true;
489 }
490
491 void mygraphicCaliperitem::mousePressEvent(QGraphicsSceneMouseEvent *event)
492 {
493 if(event->button()== Qt::LeftButton)
494 {
495 //setSelected(true);
496 m_startPos = event->pos();//鼠标左击时,获取当前鼠标在图片中的坐标,
497 if(m_ShapeType == CALIPER_RECT)//矩形卡尺
498 {
499 if(m_RECT_Rotate_Pol.containsPoint(m_startPos,Qt::WindingFill))//旋转矩形
500 {
501 m_StateFlag = CALIPER_STATE_FLAG::CALI_RECT_ROTATE;
502 setCursor(Qt::PointingHandCursor);
503 }
504 // else if(m_RECT_TL_Pol.containsPoint(m_startPos,Qt::WindingFill))
505 // {
506 // m_StateFlag = CALI_RECT_TL;//标记当前为用户按下矩形的左上角顶点矩形区域
507 // setCursor(Qt::SizeAllCursor);
508 // //SetSideCursorByRotateAngle(m_RotateAngle);
509 // }
510 // else if(m_RECT_TR_Pol.containsPoint(m_startPos,Qt::WindingFill))
511 // {
512 // m_StateFlag = CALI_RECT_TR;//标记当前为用户按下矩形的右上角顶点矩形区域
513 // setCursor(Qt::SizeAllCursor);
514 // //SetSideCursorByRotateAngle(m_RotateAngle);
515 // }
516 else if(m_RECT_BR_Pol.containsPoint(m_startPos,Qt::WindingFill))
517 {
518 m_StateFlag = CALI_RECT_BR;//标记当前为用户按下矩形的右下角顶点矩形区域
519 setCursor(Qt::SizeAllCursor);
520 //SetSideCursorByRotateAngle(m_RotateAngle);
521 }
522 // else if(m_RECT_BL_Pol.containsPoint(m_startPos,Qt::WindingFill))
523 // {
524 // m_StateFlag = CALI_RECT_BL;//标记当前为用户按下矩形的左下角顶点矩形区域
525 // setCursor(Qt::SizeAllCursor);
526 // //SetSideCursorByRotateAngle(m_RotateAngle);
527 // }
528 else if(m_RECT_Shear_Pol.containsPoint(m_startPos,Qt::WindingFill))//在矩形内框区域时按下鼠标,则可拖动图片
529 {
530 m_StateFlag = CALIPER_STATE_FLAG::CALI_RECT_SHEAR;//标记当前为鼠标拖动图片移动状态
531 setCursor(Qt::PointingHandCursor); //改变光标形状,手指的形状
532 }
533 else if(m_RECT_Inside_Pol.containsPoint(m_startPos,Qt::WindingFill))//在矩形内框区域时按下鼠标,则可拖动图片
534 {
535 m_StateFlag = CALIPER_STATE_FLAG::CALI_RECT_MOVE;//标记当前为鼠标拖动图片移动状态
536 setCursor(Qt::ClosedHandCursor); //改变光标形状,手的形状
537 }
538 else
539 {
540 m_StateFlag = CALI_DEFAULT;
541 }
542 }
543 }
544 else if(event->button()== Qt::RightButton)
545 {
546 m_startPos = event->pos();
547 //pMenu->exec(event->screenPos());//弹出菜单
548 }
549 else
550 {
551 QGraphicsItem::mousePressEvent(event);
552 }
553 }
554
555 void mygraphicCaliperitem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
556 {
557 if(m_ShapeType == CALIPER_RECT)//矩形
558 {
559 if(m_StateFlag == CALI_RECT_ROTATE)
560 {
561 int nRotateAngle = atan2((event->pos().x()-m_RotateCenter.x()),(event->pos().y()-m_RotateCenter.y()))*180/M_PI;
562 SetRotate(90-nRotateAngle);
563 //qDebug()<<nRotateAngle;
564 }
565 else if(m_StateFlag == CALI_RECT_MOVE)
566 {
567 QPointF point = (event->pos() - m_startPos);
568 moveBy(point.x(), point.y());
569 scene()->update();
570 }
571 else if(m_StateFlag == CALI_RECT_SHEAR)//控制矩形斜切
572 {
573 QPointF pc,p0,p1,p2,p3;//,pCross1,pCross2;
574 pc = m_RotateCenter;
575 p0 = m_RECT_Pol[0];
576 p1 = m_RECT_Pol[1];
577 p2 = m_RECT_Pol[2];
578 p3 = m_RECT_Pol[3];
579 if(!get2CrossPt(p0,p1,p2,pc,event->pos(),pCross1,pCross2))
580 return;
581 //过pc做p2p3的垂线line3,line3方程为y=k3x+b3,line3与p2,p3交点为pCross3
582 qreal k3,b3,k4,b4;
583 qreal x3,y3;//pCross3(x3,y3),//y3=k3x3+b3,y3=k4x3+b4,求x3,y3
584 if(p3.y()==p2.y())
585 {
586 //k3不存在,lin3为x=pc.x()
587 //直线p2p3为y=k4x+b4
588 if(p3.x()==p2.x())
589 {
590 //k4不存在,直线p2p3为x=p2.x()
591 return;
592 }
593 else
594 {
595 k4=(p3.y()-p2.y())/(p3.x()-p2.x());
596 b4 = p2.y()-k4*p2.x();
597 //TODO:求(x3,y3)
598 x3 = pc.x();
599 y3 = k4*x3+b4;
600 }
601 }
602 else
603 {
604 k3 = (p2.x()-p3.x())/(p3.y()-p2.y());
605 b3=pc.y()-k3*pc.x();
606 //直线p2p3为y=k4x+b4
607 if(p3.x()==p2.x())
608 {
609 //k4不存在,直线p2p3为x=p2.x()
610 //TODO:求(x3,y3)
611 x3 = p2.x();
612 y3 = k3*x3+b3;
613 }
614 else
615 {
616 k4=(p3.y()-p2.y())/(p3.x()-p2.x());
617 b4 = p2.y()-k4*p2.x();
618 //TODO:求(x3,y3)
619 if(k3!=k4)
620 {
621 x3 = (b4-b3)/(k3-k4);
622 y3 = k3*x3+b3;
623 }
624 }
625 }
626 pCross3= QPointF(x3,y3);
627
628 //过pos做p2p3的垂线line5,line5方程为y=k5x+b5,line5与p2,p3交点为pCross5
629 qreal k5,b5;
630 qreal x5,y5;//pCross5(x5,y5),//y5=k5x5+b5,y5=k4x5+b4,求x5,y5
631 if(p3.y()==p2.y())
632 {
633 //k3不存在,lin5为x=event->pos().x()
634 //直线p2p3为y=k4x+b4
635 if(p3.x()==p2.x())
636 {
637 //k4不存在,直线p2p3为x=p2.x()
638 return;
639 }
640 else
641 {
642 k4=(p3.y()-p2.y())/(p3.x()-p2.x());
643 b4 = p2.y()-k4*p2.x();
644 //TODO:求(x5,y5)
645 x5 = event->pos().x();
646 y5 = k4*x5+b4;
647 }
648 }
649 else
650 {
651 k5 = (p2.x()-p3.x())/(p3.y()-p2.y());
652 b5=event->pos().y()-k5*event->pos().x();
653 //直线p2p3为y=k4x+b4
654 if(p3.x()==p2.x())
655 {
656 //k4不存在,直线p2p3为x=p2.x()
657 //TODO:求(x5,y5)
658 x5 = p2.x();
659 y5 = k5*x5+b5;
660 }
661 else
662 {
663 k4=(p3.y()-p2.y())/(p3.x()-p2.x());
664 b4 = p2.y()-k4*p2.x();
665 //TODO:求(x5,y5)
666 if(k5!=k4)
667 {
668 x5 = (b4-b5)/(k5-k4);
669 y5 = k5*x5+b5;
670 }
671 }
672 }
673 pCross5= QPointF(x5,y5);
674
675 //求pos到垂线line3的距离为disShear
676 double disShear = CalDisPoint2longLine(event->pos().x(),event->pos().y(),pc.x(),pc.y(),pCross3.x(),pCross3.y());
677 // double disp3pos = CalDis(p3.x(),p3.y(),event->pos().x(),event->pos().y());
678 // double disp2pos = CalDis(p2.x(),p2.y(),event->pos().x(),event->pos().y());
679 // double disp3pCross3 = CalDis(p3.x(),p3.y(),pCross3.x(),pCross3.y());
680 // double disp2pCross3 = CalDis(p2.x(),p2.y(),pCross3.x(),pCross3.y());
681 // double disVertical2RightLine = CalDisPoint2longLine(event->pos().x(),event->pos().y(),p1.x(),p1.y(),p2.x(),p2.y());
682 // double disVertical2LeftLine = CalDisPoint2longLine(event->pos().x(),event->pos().y(),p0.x(),p0.y(),p3.x(),p3.y());
683 double newHalfHeight;
684 if(m_bKeepShadowLength)
685 {
686 if(disShear>m_RECT.height()/2-1)
687 disShear = m_RECT.height()/2-1;
688 newHalfHeight = sqrt(qPow(m_RECT.height()/2,2)-disShear*disShear);
689 m_fShearX = disShear/newHalfHeight;
690 }
691 else
692 {
693 m_fShearX = disShear/(m_RECT.height()/2);
694 }
695 //确定往左斜切还是往右斜切
696 if(((-90<m_RotateAngle)&&(m_RotateAngle<90))||(m_RotateAngle>270 &&m_RotateAngle<360)||m_RotateAngle==360)
697 {
698 if(pCross5.x()<pCross3.x())
699 m_fShearX = -m_fShearX;
700 }
701 else if(m_RotateAngle == 90)
702 {
703 if(pCross5.y()<pCross3.y())
704 m_fShearX = -m_fShearX;
705 }
706 else if(m_RotateAngle>90&&m_RotateAngle<270)
707 {
708 if(pCross5.x()>pCross3.x())
709 m_fShearX = -m_fShearX;
710 }
711 else if(m_RotateAngle==270 ||m_RotateAngle == -90)
712 {
713 if(pCross5.y()>pCross3.y())
714 m_fShearX = -m_fShearX;
715 }
716 if(m_bKeepShadowLength)
717 {
718 setShearRectSize(QRectF(pc.x()-m_RECT.width()/2,pc.y()-newHalfHeight,m_newShearRECT.width(),newHalfHeight*2));//这个函数不会重置原始矩形的大小
719 }
720 else
721 {
722 setRectSize(m_RECT);
723 }
724 scene()->update();
725 // //如果是要保持投影长度不变,则矩形需要重新及计算切变前矩形的高度
726 // if(m_bKeepShadowLength)
727 // {
728 // double newHalfHeight = sqrt(qPow(m_RECT.height()/2,2)/(m_fShearX*m_fShearX+1));
729 // setShearRectSize(QRectF(pc.x()-m_RECT.width()/2,pc.y()-newHalfHeight,m_RECT.width(),newHalfHeight*2));//这个函数不会重置原始矩形的大小
730 // }
731 // else
732 // {
733 // setRectSize(m_RECT);
734 // }
735 }
736 else if(m_StateFlag == CALI_RECT_BR)//右下角顶点
737 {
738 QPointF pc,p0,p1,p2,p3;//,pCross1,pCross2;
739 pc = m_RotateCenter;
740 p0 = m_RECT_Pol[0];
741 p1 = m_RECT_Pol[1];
742 p2 = m_RECT_Pol[2];
743 p3 = m_RECT_Pol[3];
744 if(!get2CrossPt(p0,p1,p2,pc,event->pos(),pCross1,pCross2))
745 return;
746 // //该段代码可禁止矩形被反向拉伸!!!
747 // double disVertical2RightLine = CalDisPoint2longLine(event->pos().x(),event->pos().y(),p1.x(),p1.y(),p2.x(),p2.y());
748 // double disVertical2LeftLine = CalDisPoint2longLine(event->pos().x(),event->pos().y(),p0.x(),p0.y(),p3.x(),p3.y());
749 // if(disVertical2RightLine>disVertical2LeftLine)
750 // return;
751 // double disVertical2BottomLine = CalDisPoint2longLine(event->pos().x(),event->pos().y(),p2.x(),p2.y(),p3.x(),p3.y());
752 // double disVertical2TopLine = CalDisPoint2longLine(event->pos().x(),event->pos().y(),p0.x(),p0.y(),p1.x(),p1.y());
753 // if(disVertical2BottomLine>disVertical2TopLine)
754 // return;
755 // //该段代码可禁止矩形被反向拉伸!!!
756 if(m_bKeepShadowLength && m_fShearX!=0)//保证投影长度不变
757 {
758 double disp2pc = CalDis(m_RECTShear[2].x(),m_RECTShear[2].y(),pc.x(),pc.y());
759 double dispospc = CalDis(event->pos().x(),event->pos().y(),pc.x(),pc.y());
760 double newHeight = dispospc/disp2pc*m_newShearRECT.height();
761 double newWidth = dispospc/disp2pc*m_newShearRECT.width();
762 setShearRectSize(QRectF(pc.x()-newWidth/2,pc.y()-newHeight/2,newWidth,newHeight));
763 double newHeightOld = dispospc/disp2pc*m_RECT.height();
764 double newWidthOld = dispospc/disp2pc*m_RECT.width();
765 m_RECT = QRectF(pc.x()-newWidthOld/2,pc.y()-newHeightOld/2,newWidthOld,newHeightOld);
766 }
767 else//投影长度可变
768 {
769 //新矩形宽度一半:
770 double dispcpCross1 = CalDis(pc.x(),pc.y(),pCross1.x(),pCross1.y());
771 if(dispcpCross1<10)
772 return;//矩形宽度不能小于20
773 //新矩形高度一半:
774 double disVertical = CalDisPoint2longLine(event->pos().x(),event->pos().y(),pc.x(),pc.y(),pCross1.x(),pCross1.y());
775 if(disVertical<10)
776 return;//矩形高度不能小于20
777 setRectSize(QRectF(pc.x()-dispcpCross1,pc.y()-disVertical,dispcpCross1*2,disVertical*2));
778
779 }
780 scene()->update();
781 }
782 }
783 }
784
785 void mygraphicCaliperitem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
786 {
787 setCursor(Qt::ArrowCursor);
788 m_StateFlag = CALI_DEFAULT;
789 // if(m_StateFlag == CALI_RECT_MOVE)
790 // {
791 // m_StateFlag = CALI_DEFAULT;
792 // }
793 // else {
794 // QGraphicsItem::mouseReleaseEvent(event);
795 // }
796 QGraphicsItem::mouseReleaseEvent(event);
797 //setSelected(false);
798 }
799
800 int mygraphicCaliperitem::type() const
801 {
802 return UserType+1;//表示mygraphicCaliperitem
803 }
804
805 void mygraphicCaliperitem::SetRotate(qreal RotateAngle)
806 {
807 m_RotateAngle = RotateAngle;
808 if(m_bKeepShadowLength && m_newShearRECT.width() != 0)
809 {
810 setShearRectSize(m_newShearRECT);
811 }
812 else
813 {
814 setRectSize(m_RECT);
815 }
816 if(this->scene()!=nullptr)
817 this->scene()->update();
818 }
819
820 void mygraphicCaliperitem::SetSideCursorByRotateAngle(qreal RotateAngle)
821 {
822 if((RotateAngle>45&&RotateAngle<135) ||(RotateAngle>225&&RotateAngle<315))
823 {
824 if(m_StateFlag==CALI_RECT_TR ||m_StateFlag==CALI_RECT_BL)
825 {
826 setCursor(Qt::SizeFDiagCursor);
827 }
828 else if(m_StateFlag==CALI_RECT_TL ||m_StateFlag==CALI_RECT_BR)
829 {
830 setCursor(Qt::SizeBDiagCursor);
831 }
832 }
833 else
834 {
835 if(m_StateFlag==CALI_RECT_TR ||m_StateFlag==CALI_RECT_BL)
836 {
837 setCursor(Qt::SizeBDiagCursor);
838 }
839 else if(m_StateFlag==CALI_RECT_TL ||m_StateFlag==CALI_RECT_BR)
840 {
841 setCursor(Qt::SizeFDiagCursor);
842 }
843 }
844 }
845
846 QPointF mygraphicCaliperitem::getRotatePoint(QPointF ptCenter, QPointF ptIn, qreal angle)
847 {
848 double dx = ptCenter.x();
849 double dy = ptCenter.y();
850 double x = ptIn.x();
851 double y = ptIn.y();
852 double xx,yy;
853 xx = (x-dx)*cos(angle*M_PI/180)-(y-dy)*sin(angle*M_PI/180)+dx;
854 yy = (x-dx)*sin(angle*M_PI/180)+(y-dy)*cos(angle*M_PI/180)+dy;
855
856 return QPointF(xx,yy);
857 }
858
859 QList<QPointF> mygraphicCaliperitem::getRotatePoints(QPointF ptCenter, QList<QPointF> ptIns, qreal angle)
860 {
861 QList<QPointF> lstPt;
862 for(int i = 0;i<ptIns.count();i++)
863 {
864 lstPt.append(getRotatePoint(ptCenter,ptIns.at(i),angle));
865 }
866 return lstPt;
867 }
868
869 QPolygonF mygraphicCaliperitem::getRotatePolygonFromRect(QPointF ptCenter, QRectF rectIn, qreal angle)
870 {
871 QVector<QPointF> vpt;
872 QPointF pf = getRotatePoint(ptCenter,rectIn.topLeft(),angle);
873 vpt.append(pf);
874 pf = getRotatePoint(ptCenter,rectIn.topRight(),angle);
875 vpt.append(pf);
876 pf = getRotatePoint(ptCenter,rectIn.bottomRight(),angle);
877 vpt.append(pf);
878 pf = getRotatePoint(ptCenter,rectIn.bottomLeft(),angle);
879 vpt.append(pf);
880 pf = getRotatePoint(ptCenter,rectIn.topLeft(),angle);
881 vpt.append(pf);
882 return QPolygonF(vpt);
883 }
884
885 QPolygonF mygraphicCaliperitem::getRotatePolygonFromPolygon(QPointF ptCenter, QPolygonF polyIn, qreal angle)
886 {
887 QVector<QPointF> vpt;
888 for(int i = 0;i<polyIn.count();i++)
889 {
890 QPointF pf = getRotatePoint(ptCenter,polyIn[i],angle);
891 vpt.append(pf);
892 }
893 return QPolygonF(vpt);
894 }
895
896 QRectF mygraphicCaliperitem::getBoundedRectToSceen()
897 {
898 return QRectF(m_RECT_Pol.boundingRect().x()+pos().x(),m_RECT_Pol.boundingRect().y()+pos().y(),m_RECT_Pol.boundingRect().width(),m_RECT_Pol.boundingRect().height());
899 }
900
901 QPolygonF mygraphicCaliperitem::getCrtPolygonToScreen()
902 {
903 QVector<QPointF> vpt;
904 if(m_ShapeType == CALIPER_ELLIPSE)
905 {
906 for(int i = 0;i<m_RECT_Pol.length();i++)
907 {
908 vpt.append(QPointF(m_RECT_Pol[i].x()+pos().x(),m_RECT_Pol[i].y()+pos().y()));
909 }
910 }
911 return QPolygonF(vpt);
912 }
913 QRectF mygraphicCaliperitem::getSmallRotateRect(QPointF ptA,QPointF ptB)
914 {
915 QPointF pt = getSmallRotateRectCenter(ptA,ptB);
916 return QRectF(pt.x()-10,pt.y()-10,20,20);
917 }
918
919 QPointF mygraphicCaliperitem::getSmallRotateRectCenter(QPointF ptA,QPointF ptB)
920 {
921 QPointF ptCenter = QPointF((ptA.x()+ptB.x())/2,(ptA.y()+ptB.y())/2);//A,B点的中点C
922 //中垂线方程式为 y=x*k + b;
923 qreal x,y;//旋转图标矩形的中心
924 if(abs(ptB.y()-ptA.y())<0.1)
925 {
926 if(ptA.x()<ptB.x())//矩形左上角在上方
927 {
928 x = ptCenter.x();
929 y = ptCenter.y()-20;
930 }
931 else//矩形左上角在下方
932 {
933 x = ptCenter.x();
934 y = ptCenter.y()+20;
935 }
936 }
937 else if(ptB.y()>ptA.y())//顺时针旋转0-180
938 {
939 qreal k = (ptA.x()-ptB.x())/(ptB.y()-ptA.y());//中垂线斜率
940 qreal b = (ptA.y()+ptB.y())/2-k*(ptA.x()+ptB.x())/2;
941 //求AB线中垂线上离AB中点20个像素的点C的坐标
942 x = 20*cos(atan(k))+ptCenter.x();
943 y = k*x+b;
944 }
945 else if(ptB.y()<ptA.y())//顺时针旋转180-360
946 {
947 qreal k = (ptA.x()-ptB.x())/(ptB.y()-ptA.y());//中垂线斜率
948 qreal b = (ptA.y()+ptB.y())/2-k*(ptA.x()+ptB.x())/2;
949 //求AB线中垂线上离AB中点20个像素的点C的坐标
950 x = -20*cos(atan(k))+ptCenter.x();
951 y = k*x+b;
952 }
953 return QPointF(x,y);
954 }