zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    使用SeaJS实现模块化JavaScript开发
    使用antixss防御xss
    AntiXSS
    FFmpeg 安装、日常使用及应用场景记录与总结。
    Cygwin 安装、设置及配置 FaTTY 多标签页(Tabs)
    Python 爬取B站(Bilibili.com)UP主的所有公开视频链接及信息
    windows10 彻底删除蓝牙设备,蓝牙设备删除失败解决方案
    VSCode 常用设置、快捷键及插件
    Python 文件IO:JSON 文件的读取与写入
    Python 文件IO:TXT 文件的读取与写入
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/13862397.html
Copyright © 2011-2022 走看看