如上图所示,绘制矩形之后,可以按住中间缩放、然后按住右侧中间进行旋转,按住右下角进行缩放,按住下方中间进行斜切矩形。
整体都是仿照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 }