Qt 重写QGraphicItem实现拖动缩放旋转斜切矩形,即VisionPro中的卡尺的功能


在这里插入图片描述

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

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM