直线卡尺:

圆形卡尺:

源码下载连接:https://download.csdn.net/download/weixin_43935474/75226350

我主要是重写了QGraphicsItem类
头文件如下:

#ifndef MYGRAPHICCALIPERITEM_H
#define MYGRAPHICCALIPERITEM_H
#include <QObject>
#include <QWidget>
#include <QMouseEvent>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QGraphicsSceneMouseEvent>
#include <QRect>
#include <QPainter>
#include <QPolygon>
#include <QList>
#include <QTransform>
#include <QMap>
enum CALIPER_STATE_FLAG{CALI_DEFAULT=0,CALI_RECT_TL,//标记当前为用户按下矩形的左上角CALI_RECT_TR,//标记当前为用户按下矩形的右上角CALI_RECT_BL,//左下角CALI_RECT_BR,//右下角CALI_RECT_SHEAR,//标记当前为用户按下矩形的下边中点的切变矩形CALI_RECT_MOVE,//标记当前为鼠标拖动矩形移动状态CALI_RECT_ROTATE,//标记当前为旋转状态CALIMOV_POLYGON_POINT,//移动多边形的某个点CALI_LINE_MOVE,//标记当前为直线卡尺的拖动CALI_LINE_PT1_MOVE,//标记当前为直线顶点1的拖动CALI_LINE_PT2_MOVE,//标记当前为直线顶点2的拖动CALI_CIRCLE_MOVE,//标记圆形卡尺被拖动CALI_CIRCLE_PT1_MOVE,//标记圆形卡尺点1被拖动CALI_CIRCLE_PT2_MOVE,//标记圆形卡尺点2被拖动CALI_CIRCLE_PT3_MOVE,//标记圆形卡尺点3被拖动CALI_CIRCLE_FillP1,//标记圆形卡尺点1附近双向箭头被拖动,用来补全圆CALI_CIRCLE_FillP3
};
enum CALIPER_SHAPE_TYPE{CALIPER_RECT,//矩形CALIPER_LINE,CALIPER_CIRCLE,CALIPER_ELLIPSE
};
struct CALI_RECT
{//CALIPER_RECT矩形卡尺使用qreal       m_RotateAngle;QPointF     m_RotateCenter;bool        m_bKeepShadowLength;//保持投影长度不变QRectF      m_RECT;QRectF      m_newShearRECT;QPolygonF   m_RECTShear;//矩形斜切后QPolygonF   m_RECT_Pol;//矩形旋转后QPolygonF   m_RECT_TL_Pol;//左上角顶点旋转后QRectF      m_RECT_TL;//左上角顶点QPolygonF   m_RECT_TR_Pol;//右上角顶点旋转后QRectF      m_RECT_TR;//右上角顶点QPolygonF   m_RECT_BL_Pol;//左下角顶点旋转后QRectF      m_RECT_BL;//左下角顶点QPolygonF   m_RECT_BR_Pol;//右下角顶点旋转后QRectF      m_RECT_BR;//右下角顶点QPolygonF   m_RECT_Inside_Pol;//内部区域旋转后QPolygonF   m_RECT_InsideShear;//内部区域斜切后QRectF      m_RECT_Inside;//内部区域QPolygonF   m_RECT_Scan_Dir_Pol;//扫描方向标记旋转后QRectF      m_RECT_Scan_Dir;//扫描方向标记QPolygonF   m_RECT_Shadow_Dir_Pol;//投影方向标记旋转后QRectF      m_RECT_Shadow_Dir;//投影方向标记qreal       m_fShadowLength;//投影长度QPolygonF   m_RECT_Rotate_Pol;//旋转的标记的矩形旋转后形成的多边形QRectF      m_RECT_Rotate;//旋转的标记的矩形QPolygonF   m_RECT_Shear_Pol;//切变矩形标记旋转后QRectF      m_RECT_Shear;//切变矩形标记qreal       m_fShearX;//切变矩形x方向参数
};class mygraphicCaliperitem:public QObject,public QGraphicsItem
{Q_OBJECT
public:CALIPER_SHAPE_TYPE m_ShapeType;mygraphicCaliperitem(QGraphicsItem *parent = nullptr);~mygraphicCaliperitem();//mygraphicCaliperitem(QRectF m_OriginRect = QRectF(0,0,100,100));QRectF          boundingRect() const;QPainterPath    shape() const;QPainterPath    getCollideShape();QPainterPath    getCollideShapeTopLeftAsOriginPoint();//直线卡尺(直线起点pt1,终点pt2,卡尺数量nCalipNum,搜索长度searchLength,投影长度shadowLength,矩形自身旋转角度fRectRotateAngle,切变系数fShearX,切变时是否保持投影长度不变bKeepShadowLength)void            InitLineCalip(QPointF pt1=QPointF(0,0),QPointF pt2=QPointF(200,0),int nCalipNum=4,qreal searchLength=50,qreal shadowLength=80,qreal fRectRotateAngle=0,qreal fShearX=0,bool bKeepShadowLength=false);//圆形卡尺(圆形卡尺起点pt1,终点pt2,卡尺数量nCalipNum,搜索长度searchLength,投影长度shadowLength,                               搜索方向SearchDir(1向内,0向外))void            InitCircleCalip(QPointF pt1=QPointF(0,0),QPointF pt2=QPointF(100,-100),QPointF pt3=QPointF(200,0),int nCalipNum=4,qreal searchLength=40,qreal shadowLength=80,int SearchDir=1);void            setCalipNum(int nCalipNum=4);//设置卡尺中矩形个数void            setRectSize(QRectF mrect,CALI_RECT &caliRect);//矩形卡尺用void            setRectSize(QRectF mrect);//矩形卡尺用void            setShearRectSize(QRectF mrect);void            setShearRectSize(QRectF mrect,CALI_RECT &circleRect);void            setKeepShadowLength(bool bkeeplength);//在斜切的时候,保持投影长度不变(即保持斜切后4条边的长度不变)void            paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);void            mousePressEvent(QGraphicsSceneMouseEvent *event);void            mouseMoveEvent(QGraphicsSceneMouseEvent *event);void            mouseReleaseEvent(QGraphicsSceneMouseEvent *event);int             type() const;void            SetRotate(qreal RotateAngle);void            SetRotate(qreal RotateAngle,CALI_RECT &circleRect);void            SetSideCursorByRotateAngle(qreal RotateAngle);//计算两点距离double          CalDis(const double x1, const double y1,const double x2, const double y2);//计算点(ptx,pty)到线段(x1y1,x2y2)的距离(如果垂线和本线段交点不在线段上,则距离为点到线段较近的那一点的距离double          CalDis(const double ptx, const double pty,const double x1, const double y1,const double x2, const double y2);//计算点(ptx,pty)到线段(x1y1,x2y2)的距离double          CalDisPoint2longLine(const double ptx, const double pty,const double x1, const double y1,const double x2, const double y2);//计算斜切后分别经过中心点和鼠标所在点的两平行线的2个焦点bool            get2CrossPt(QPointF p0, QPointF p1, QPointF p2, QPointF pc, QPointF pos, QPointF &pCross1, QPointF &pCross2);QPointF pCross1,pCross2,pCross3,pCross5;QPointF         getRotatePoint(QPointF ptCenter, QPointF ptIn, qreal angle);//获取旋转后的点QList<QPointF>  getRotatePoints(QPointF ptCenter,QList<QPointF> ptIns,qreal angle);//获取多个旋转后的点QPolygonF       getRotatePolygonFromRect(QPointF ptCenter,QRectF rectIn,qreal angle);//将矩形旋转之后返回多边形QPolygonF       getRotatePolygonFromPolygon(QPointF ptCenter,QPolygonF polyIn,qreal angle);//将多边形旋转之后返回多边形QRectF          getBoundedRectToSceen();QPolygonF       getCrtPolygonToScreen();QPointF         getVeritacalLinePoint(QPointF ptA,QPointF ptB,qreal offset=20);//获取旋转时候矩形正上方的旋转标记矩形QRectF          getSmallRotateRect(QPointF ptA,QPointF ptB);bool            getCenterFrom3Pt(QPointF p1,QPointF p2,QPointF p3,QPointF &pc);//过3点求圆心
private://CALIPER_RECT矩形卡尺使用CALI_RECT           m_tCaliRect;int                 m_nCalipNum;//卡尺中矩形的个数,给直线卡尺和圆形卡尺使用QList<CALI_RECT>    m_tCaliRectLst;//卡尺中的矩形,给直线卡尺和圆形卡尺使用qreal               m_searchLength;//卡尺中矩形宽度,给直线卡尺和圆形卡尺使用qreal               m_shadowLength;//卡尺中矩形高度,给直线卡尺和圆形卡尺使用//CALIPER_LINE直线卡尺使用:QLineF              m_CaliLine;QPolygonF           m_LineBodyPol;//直线上下各10像素范围内的矩形区域,用多边形表示QRectF              m_LineP1;QRectF              m_LineP2;QPolygonF           m_LineP1Pol;QPolygonF           m_LineP2Pol;qreal               m_RectRotateAngle;//直线卡尺中矩形相对于直线方向的旋转角度qreal               m_pt2pt1Angle;//直线相对于x正方向角度bool                m_bsetRectSize;void                setLineCalip(QPointF pt1=QPointF(0,0),QPointF pt2=QPointF(200,0),int nCalipNum=4,qreal searchLength=50,qreal shadowLength=80,qreal fRectRotateAngle=0,qreal fShearX=0,bool bKeepShadowLength=false);//CALIPER_CIRCLE圆形卡尺使用:QPointF             m_CircleP1;//圆弧的点1QPolygonF           m_CircleP1Pol;//圆弧的点1接收鼠标响应区域QRectF              m_FillCircleP1Rect;//P1附近补全圆使用的鼠标响应区域中心QPointF             m_CircleP2;//圆弧的点2QPolygonF           m_CircleP2Pol;//圆弧的点2接收鼠标响应区域QPointF             m_CircleP3;//圆弧的点3QPolygonF           m_CircleP3Pol;//圆弧的点3接收鼠标响应区域QRectF              m_FillCircleP3Rect;//P3附近补全圆使用的鼠标响应区域QPointF             m_CircleCenter;//圆心qreal               m_radius;//半径QRectF              m_CircleRect;//圆形外接矩形int                 m_nSearchDir;//卡尺搜索方向,0:从内向外//p1移动后求中点p2void                CalMidPosByMoveP1(QPointF p1, QPointF p2, QPointF p3, QPointF moveEdn, QPointF &outp2);//p1,p3移动后求中点p2//p3移动后求中点p2void                CalMidPosByMoveP3(QPointF p1, QPointF p2, QPointF p3, QPointF moveEdn, QPointF &outp2);//p1,p3移动后求中点p2//p2移动后求中点p2void                CalMidPos(QPointF start,QPointF end,QPointF moveEdn,QPointF &moveMid);//圆形卡尺(圆形卡尺起点pt1,终点pt2,卡尺数量nCalipNum,搜索长度searchLength,投影长度shadowLength,                               搜索方向SearchDir(1向内,0向外))void                setCircleCalip(QPointF pt1=QPointF(0,0),QPointF pt2=QPointF(100,-100),QPointF pt3=QPointF(200,0), int nCalipNum=4, qreal searchLength=50, qreal shadowLength=80, int nSearchDir=1);//获取圆上一点向圆心移动offset距离的点QPointF             getFillCirclePt(QPointF circlePt, QPointF centerPt,qreal radius, qreal roffset=10);//通过FillCirclePt反推圆上那一点QPointF             getCirclePtByFillCirclePt(QPointF fillCirclePt, QPointF centerPt, qreal radius, qreal roffset=10);//通过鼠标点与圆心点的线段与圆的交点QPointF             getCirclePtByMousePos(QPointF mousePt, QPointF centerPt,qreal radius);//通过m_CircleP1,m_CircleP3,m_CircleCenter求m_CircleP2QPointF             getP2ByP1P3PCenter(QPointF P1,QPointF P3,QPointF PCenter);//过一点p1,求垂直于线段p1p2并距离线段10像素的两个点void                getVeritacalLinePoint(QPointF pt1,QPointF pt2,qreal offset,QPointF &ptout1,QPointF &ptout2);//获取双向箭头标记QPainterPath        getFillCircleArrow(QPointF circlePt, QPointF centerPt,qreal radius, qreal roffset=10);QPointF             m_startPos;CALIPER_STATE_FLAG  m_StateFlag;bool                m_bResize;
};#endif // MYGRAPHICCALIPERITEM_H

源文件如下:

#include "myGraphicCaliperItem.h"
#include <QtMath>
#include <QDebug>
#include <QMenu>#pragma execution_character_set("utf-8")//让能够正常显示中文字符串
#define ROTATE_AND_SHEAR//允许斜切和旋转矩形
mygraphicCaliperitem::mygraphicCaliperitem(QGraphicsItem *parent):m_ShapeType(CALIPER_RECT),m_bResize(false),m_StateFlag(CALI_DEFAULT)
{m_tCaliRect.m_newShearRECT.setWidth(0);m_tCaliRect.m_RECT=QRectF(-100,-200,200,400);m_tCaliRect.m_RotateAngle =0;m_tCaliRect.m_bKeepShadowLength = false;//斜切时保持投影长度不变m_tCaliRect.m_fShearX = 0;//斜切参数m_pt2pt1Angle = 0;//直线与x正方向角度m_bsetRectSize = false;//setRectSize(m_tCaliRect.m_RECT);//setToolTip("Click and drag me!");  //提示setCursor(Qt::ArrowCursor);   //改变光标形状,手的形状setFlag(QGraphicsItem::ItemIsMovable);setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable);
}
QRectF mygraphicCaliperitem::boundingRect() const//用来控制本item绘制区域
{QPainterPath path;if(m_ShapeType == CALIPER_RECT)//矩形卡尺{path.setFillRule(Qt::WindingFill);path.addPolygon(m_tCaliRect.m_RECT_Pol);path.addPolygon(m_tCaliRect.m_RECT_Rotate_Pol);path.addPolygon(m_tCaliRect.m_RECT_TL_Pol);path.addPolygon(m_tCaliRect.m_RECT_TR_Pol);path.addPolygon(m_tCaliRect.m_RECT_BL_Pol);path.addPolygon(m_tCaliRect.m_RECT_BR_Pol);path.addPolygon(m_tCaliRect.m_RECT_Shadow_Dir_Pol);path.addPolygon(m_tCaliRect.m_RECT_Shear_Pol);}else if(m_ShapeType == CALIPER_LINE)//直线卡尺{path.setFillRule(Qt::WindingFill);path.addPolygon(m_LineBodyPol);path.addPolygon(m_LineP1);path.addPolygon(m_LineP2);int nCount = m_tCaliRectLst.count();for(int i=0;i<nCount;i++){if((nCount+1)/2-1==i)//让中间那个矩形控制所有矩形的变换{path.addPolygon(m_tCaliRectLst[i].m_RECT_Pol);path.addPolygon(m_tCaliRectLst[i].m_RECT_BR_Pol);path.addPolygon(m_tCaliRectLst[i].m_RECT_Rotate_Pol);path.addPolygon(m_tCaliRectLst[i].m_RECT_Shear_Pol);}}}else if(m_ShapeType == CALIPER_CIRCLE)//圆形卡尺{path.setFillRule(Qt::WindingFill);path.addEllipse(m_CircleRect);path.addPolygon(m_CircleP1Pol);path.addPolygon(m_CircleP2Pol);path.addPolygon(m_CircleP3Pol);int nCount = m_tCaliRectLst.count();for(int i=0;i<nCount;i++){path.addPolygon(m_tCaliRectLst[i].m_RECT_Pol);path.addPolygon(m_tCaliRectLst[i].m_RECT_BR_Pol);path.addPolygon(m_tCaliRectLst[i].m_RECT_Rotate_Pol);path.addPolygon(m_tCaliRectLst[i].m_RECT_Shear_Pol);}}shape();//添加这个主要是为了防止本图形在移动或者缩放之后无法接收鼠标点击事件return path.boundingRect();
}QPainterPath mygraphicCaliperitem::shape() const//用来控制检测碰撞collide和鼠标点击hit响应区域
{QPainterPath path;if(m_ShapeType == CALIPER_RECT)//矩形卡尺{path.setFillRule(Qt::WindingFill);path.addPolygon(m_tCaliRect.m_RECT_Pol);path.addPolygon(m_tCaliRect.m_RECT_Rotate_Pol);path.addPolygon(m_tCaliRect.m_RECT_TL_Pol);path.addPolygon(m_tCaliRect.m_RECT_TR_Pol);path.addPolygon(m_tCaliRect.m_RECT_BL_Pol);path.addPolygon(m_tCaliRect.m_RECT_BR_Pol);path.addPolygon(m_tCaliRect.m_RECT_Shadow_Dir_Pol);path.addPolygon(m_tCaliRect.m_RECT_Shear_Pol);}else if(m_ShapeType == CALIPER_LINE)//直线卡尺{path.setFillRule(Qt::WindingFill);path.addPolygon(m_LineBodyPol);path.addPolygon(m_LineP1);path.addPolygon(m_LineP2);int nCount = m_tCaliRectLst.count();for(int i=0;i<nCount;i++){if((nCount+1)/2-1==i)//让中间那个矩形控制所有矩形的变换{path.addPolygon(m_tCaliRectLst[i].m_RECT_Pol);path.addPolygon(m_tCaliRectLst[i].m_RECT_BR_Pol);path.addPolygon(m_tCaliRectLst[i].m_RECT_Rotate_Pol);path.addPolygon(m_tCaliRectLst[i].m_RECT_Shear_Pol);}}}else if(m_ShapeType == CALIPER_CIRCLE)//圆形卡尺{path.setFillRule(Qt::WindingFill);path.addEllipse(m_CircleRect);path.addPolygon(m_CircleP1Pol);path.addPolygon(m_CircleP2Pol);path.addPolygon(m_CircleP3Pol);int nCount = m_tCaliRectLst.count();for(int i=0;i<nCount;i++){path.addPolygon(m_tCaliRectLst[i].m_RECT_Pol);path.addPolygon(m_tCaliRectLst[i].m_RECT_BR_Pol);path.addPolygon(m_tCaliRectLst[i].m_RECT_Rotate_Pol);path.addPolygon(m_tCaliRectLst[i].m_RECT_Shear_Pol);}}return path;
}QPainterPath mygraphicCaliperitem::getCollideShape()//获取撞击区域
{QPainterPath path;if(m_ShapeType == CALIPER_RECT)//矩形卡尺{path.addPolygon(m_tCaliRect.m_RECT_Pol);}else if(m_ShapeType == CALIPER_LINE)//直线卡尺{path.moveTo(m_CaliLine.p1());path.lineTo(m_CaliLine.p2());}return path;
}QPainterPath mygraphicCaliperitem::getCollideShapeTopLeftAsOriginPoint()//返回左上角移动到item的(0,0)位置的collide区域
{QPainterPath path;if(m_ShapeType == CALIPER_RECT){QTransform trans;path.addPolygon(m_tCaliRect.m_RECT_Pol);trans.translate(-path.boundingRect().x(),-path.boundingRect().y());path = trans.map(path);}return path;
}void mygraphicCaliperitem::InitLineCalip(QPointF pt1, QPointF pt2, int nCalipNum, qreal searchLength, qreal shadowLength, qreal fRectRotateAngle, qreal fShearX, bool bKeepShadowLength)
{m_bsetRectSize = true;setLineCalip(pt1,pt2,nCalipNum,searchLength,shadowLength,fRectRotateAngle,fShearX,bKeepShadowLength);m_bsetRectSize = false;
}void mygraphicCaliperitem::InitCircleCalip(QPointF pt1, QPointF pt2, QPointF pt3, int nCalipNum, qreal searchLength, qreal shadowLength, int SearchDir)
{setCircleCalip(pt1, pt2, pt3, nCalipNum, searchLength, shadowLength, SearchDir);
}void mygraphicCaliperitem::setCalipNum(int nCalipNum)
{if(m_ShapeType==CALIPER_LINE)setLineCalip(m_CaliLine.p1(),m_CaliLine.p2(),nCalipNum,m_searchLength,m_shadowLength,m_tCaliRectLst[0].m_RotateAngle-m_pt2pt1Angle,m_tCaliRectLst[0].m_fShearX,m_tCaliRectLst[0].m_bKeepShadowLength);else if(m_ShapeType == CALIPER_CIRCLE)setCircleCalip(m_CircleP1,m_CircleP2,m_CircleP3,nCalipNum,m_searchLength,m_shadowLength,m_nSearchDir);
}mygraphicCaliperitem::~mygraphicCaliperitem()
{}void mygraphicCaliperitem::setLineCalip(QPointF pt1, QPointF pt2, int nCalipNum, qreal searchLength, qreal shadowLength, qreal fRectRotateAngle, qreal fShearX, bool bKeepShadowLength)
{//pt1,pt2长度rLenPt1Pt2m_CaliLine = QLineF(pt1,pt2);m_nCalipNum = nCalipNum;m_searchLength = searchLength;//搜索长度(矩形宽度)m_shadowLength = shadowLength;//投影长度m_RectRotateAngle = fRectRotateAngle;m_pt2pt1Angle = 90-atan2(pt2.x()-pt1.x(),pt2.y()-pt1.y())*180/M_PI;qreal rLenPt1Pt2 = sqrt(qPow((pt1.x()-pt2.x()),2)+qPow((pt1.y()-pt2.y()),2));//确定直线上下10像素范围内的区域,便于拖动QPointF p1=getVeritacalLinePoint(pt1,QPointF((20+20)/rLenPt1Pt2*(pt2.x()-pt1.x())+pt1.x(),(20+20)/rLenPt1Pt2*(pt2.y()-pt1.y())+pt1.y()),10);QPointF p2=getVeritacalLinePoint(QPointF((rLenPt1Pt2-40)/rLenPt1Pt2*(pt2.x()-pt1.x())+pt1.x(),(rLenPt1Pt2-40)/rLenPt1Pt2*(pt2.y()-pt1.y())+pt1.y()),pt2,10);QPointF p3=getVeritacalLinePoint(pt2,QPointF((rLenPt1Pt2-40)/rLenPt1Pt2*(pt2.x()-pt1.x())+pt1.x(),(rLenPt1Pt2-40)/rLenPt1Pt2*(pt2.y()-pt1.y())+pt1.y()),10);QPointF p4=getVeritacalLinePoint(QPointF((20+20)/rLenPt1Pt2*(pt2.x()-pt1.x())+pt1.x(),(20+20)/rLenPt1Pt2*(pt2.y()-pt1.y())+pt1.y()),pt1,10);m_LineBodyPol.clear();m_LineBodyPol.append(p1);m_LineBodyPol.append(p2);m_LineBodyPol.append(p3);m_LineBodyPol.append(p4);m_LineP1 = QRectF(pt1.x()-5,pt1.y()-5,10,10);m_LineP1Pol = QPolygonF(m_LineP1);m_LineP2 = QRectF(pt2.x()-5,pt2.y()-5,10,10);m_LineP2Pol = QPolygonF(m_LineP2);//卡尺中相邻两个矩形中西的距离rOffsetqreal rOffset = rLenPt1Pt2/nCalipNum;if(m_tCaliRectLst.count()==nCalipNum){for(int i = 0;i<nCalipNum;i++)//一共要绘制nCalipNum个矩形{qreal x = (rOffset/2+rOffset*i)/rLenPt1Pt2*(pt2.x()-pt1.x())+pt1.x();qreal y = (rOffset/2+rOffset*i)/rLenPt1Pt2*(pt2.y()-pt1.y())+pt1.y();QRectF rect = QRectF(x-searchLength/2,y-shadowLength/2,searchLength,shadowLength);m_tCaliRectLst[i].m_RotateAngle = m_pt2pt1Angle+m_RectRotateAngle;//90-atan2(pt2.x()-pt1.x(),pt2.y()-pt1.y())*180/M_PI;m_tCaliRectLst[i].m_fShearX=fShearX;m_tCaliRectLst[i].m_bKeepShadowLength = bKeepShadowLength;if(m_tCaliRectLst[i].m_bKeepShadowLength){if(m_bsetRectSize){setRectSize(rect,m_tCaliRectLst[i]);}else{setShearRectSize(rect,m_tCaliRectLst[i]);//这个函数不会重置原始矩形的大小}}else{setRectSize(rect,m_tCaliRectLst[i]);}}}else{m_tCaliRectLst.clear();for(int i = 0;i<nCalipNum;i++)//一共要绘制nCalipNum个矩形{CALI_RECT caliRect;qreal x = (rOffset/2+rOffset*i)/rLenPt1Pt2*(pt2.x()-pt1.x())+pt1.x();qreal y = (rOffset/2+rOffset*i)/rLenPt1Pt2*(pt2.y()-pt1.y())+pt1.y();QRectF rect = QRectF(x-searchLength/2,y-shadowLength/2,searchLength,shadowLength);caliRect.m_RotateAngle = m_pt2pt1Angle+m_RectRotateAngle;//90-atan2(pt2.x()-pt1.x(),pt2.y()-pt1.y())*180/M_PI;caliRect.m_fShearX=fShearX;caliRect.m_bKeepShadowLength = bKeepShadowLength;if(caliRect.m_bKeepShadowLength){if(m_bsetRectSize){setRectSize(rect,caliRect);}else{setShearRectSize(rect,caliRect);//这个函数不会重置原始矩形的大小}}else{setRectSize(rect,caliRect);}m_tCaliRectLst.append(caliRect);}}}void mygraphicCaliperitem::CalMidPosByMoveP1(QPointF p1, QPointF p2, QPointF p3, QPointF moveEdn, QPointF &outp2)
{//旧的p1p3的中心点qreal midp1p3_x = (p1.x() + p3.x()) / 2;qreal midp1p3_y = (p1.y() + p3.y()) / 2;//旧的p1p3的中心点到p2的距离qreal dis = sqrt((p2.x() - midp1p3_x) * (p2.x() - midp1p3_x) + (p2.y() - midp1p3_y) * (p2.y() - midp1p3_y));//假设三维空间中点p3到p1为向量a=(p1.x() - p3.x(),p1.y() - p3.y(),0)//假设三维空间中点p3到p2为向量b=(p2.x() - p3.x(),p2.y() - p3.y(),0)//                  i ,j ,k//则向量a和b的外积a×b=x1,y1,z1 =((y1z2-y2z1)i,(x2z1-x1z2)j,(x1y2-x2y1)k)//                  x2,y2,z2//因为i,j,k为单位长度,则他们都为1//因为向量a和b都在x,y坐标轴的平面内,所以z1=0,z2=0//所以a×b=(0,0,x1y2-x2y1)=(0,0,(p1.x() - p3.x())*(p2.y() - p3.y())-(p2.x() - p3.x())*(p1.y() - p3.y()))qreal sOld= (p1.x() - p3.x()) * (p2.y() - p3.y()) - (p2.x() - p3.x())*(p1.y() - p3.y());//向量a和b的外积在几何上垂直于向量a和b所形成的平面//根据右手定则,四指指向a,向b弯曲,则大拇指的方向为外积的方向,所以//如果sOld为正数,则点p2在向量a的左侧;//如果sOld为负数,则点p2在向量a的右侧;//如果sOld为0,则点p2在直线p1p3上。//圆弧拉伸规则:移动p1,p3的时候,要保持旧的圆弧中点p2到p1p3的距离dis=新的圆弧中点outp2到p1p3的距离//而在点moveEdn和点p1的中垂线上,距离中点距离为dis的点一共有两个,假设这两点为(x1,x2)  (y1,y2)qreal x1, y1;qreal x2, y2;if (p3.y() - moveEdn.y() == 0){x1 = (p3.x() + moveEdn.x()) / 2;y1 = (p3.y() + moveEdn.y()) / 2 + dis;x2 = (p3.x() + moveEdn.x()) / 2;y2 = (p3.y() + moveEdn.y()) / 2 - dis;}else{midp1p3_x = (p3.x() + moveEdn.x()) / 2;midp1p3_y = (p3.y() + moveEdn.y()) / 2;qreal k = (p3.x() - moveEdn.x()) / (p3.y() - moveEdn.y());x1 = midp1p3_x + dis /sqrt(1 + k * k);y1 = midp1p3_y - k * (x1 - midp1p3_x);x2 = midp1p3_x - dis / sqrt(1 + k * k);y2 = midp1p3_y - k * (x2 - midp1p3_x);}qreal sNew = (moveEdn.x() - p3.x()) * (y1 - p3.y()) - (moveEdn.y() - p3.y()) * (x1 - p3.x());if (sOld * sNew > 0)//表示计算得到的点和原P2在向量a的同一方向{outp2.setX(x1);outp2.setY(y1);}else//表示计算得到的点和原P2在向量a的不同方向{outp2.setX(x2);outp2.setY(y2);}
}//p3移动后求圆弧中点p2
void mygraphicCaliperitem::CalMidPosByMoveP3(QPointF p1, QPointF p2, QPointF p3, QPointF moveEdn, QPointF &outp2)
{//旧的p1p3的中心点qreal midp1p3_x = (p1.x() + p3.x()) / 2;qreal midp1p3_y = (p1.y() + p3.y()) / 2;//旧的p1p3的中心点到p2的距离qreal dis = sqrt((p2.x() - midp1p3_x) * (p2.x() - midp1p3_x) + (p2.y() - midp1p3_y) * (p2.y() - midp1p3_y));//假设三维空间中点p3到p1为向量a=(p1.x() - p3.x(),p1.y() - p3.y(),0)//假设三维空间中点p3到p2为向量b=(p2.x() - p3.x(),p2.y() - p3.y(),0)//                  i ,j ,k//则向量a和b的外积a×b=x1,y1,z1 =((y1z2-y2z1)i,(x2z1-x1z2)j,(x1y2-x2y1)k)//                  x2,y2,z2//因为i,j,k为单位长度,则他们都为1//因为向量a和b都在x,y坐标轴的平面内,所以z1=0,z2=0//所以a×b=(0,0,x1y2-x2y1)=(0,0,(p1.x() - p3.x())*(p2.y() - p3.y())-(p2.x() - p3.x())*(p1.y() - p3.y()))qreal sOld= (p1.x() - p3.x()) * (p2.y() - p3.y()) - (p2.x() - p3.x())*(p1.y() - p3.y());//向量a和b的外积在几何上垂直于向量a和b所形成的平面//根据右手定则,四指指向a,向b弯曲,则大拇指的方向为外积的方向,所以//如果sOld为正数,则点p2在向量a的左侧;//如果sOld为负数,则点p2在向量a的右侧;//如果sOld为0,则点p2在直线p1p3上。//圆弧拉伸规则:移动p1,p3的时候,要保持旧的圆弧中点p2到p1p3的距离dis=新的圆弧中点outp2到p1p3的距离//而在点moveEdn和点p1的中垂线上,距离中点距离为dis的点一共有两个,假设这两点为(x1,x2)  (y1,y2)qreal x1, y1;qreal x2, y2;if (p1.y() - moveEdn.y() == 0){x1 = (p1.x() + moveEdn.x()) / 2;y1 = (p1.y() + moveEdn.y()) / 2 + dis;x2 = (p1.x() + moveEdn.x()) / 2;y2 = (p1.y() + moveEdn.y()) / 2 - dis;}else{midp1p3_x = (p1.x() + moveEdn.x()) / 2;midp1p3_y = (p1.y() + moveEdn.y()) / 2;qreal k = (p1.x() - moveEdn.x()) / (p1.y() - moveEdn.y());x1 = midp1p3_x + dis /sqrt(1 + k * k);y1 = midp1p3_y - k * (x1 - midp1p3_x);x2 = midp1p3_x - dis / sqrt(1 + k * k);y2 = midp1p3_y - k * (x2 - midp1p3_x);}qreal sNew = (p1.x() - p3.x()) * (y1 - p3.y()) - (p1.y() - p3.y()) * (x1 - p3.x());if (sOld * sNew > 0)//表示计算得到的点和原P2在向量a的同一方向{outp2.setX(x1);outp2.setY(y1);}else//表示计算得到的点和原P2在向量a的不同方向{outp2.setX(x2);outp2.setY(y2);}
}
//p2移动后求中点p2
void mygraphicCaliperitem::CalMidPos(QPointF start, QPointF end, QPointF moveEdn, QPointF &moveMid)
{qreal mid13_x = (start.x()+end.x())/2;qreal mid13_y = (start.y()+end.y())/2;if(start.y() == end.y()){moveMid.setY(moveEdn.y());moveMid.setX(mid13_x);}else{//斜率qreal k = (start.x() - end.x()) / (start.y() - end.y());moveMid.setY((k * k * moveEdn.y() - k * moveEdn.x() + k * mid13_x + mid13_y) / (1 + k * k));moveMid.setX(k * (moveMid.y() - moveEdn.y()) + moveEdn.x());}
}void mygraphicCaliperitem::setCircleCalip(QPointF pt1, QPointF pt2, QPointF pt3, int nCalipNum, qreal searchLength, qreal shadowLength, int nSearchDir)
{m_CircleP1 = pt1;m_CircleP1Pol =QPolygonF(QRectF(pt1.x()-5,pt1.y()-5,10,10));m_CircleP2 = pt2;m_CircleP2Pol = QPolygonF(QRectF(pt2.x()-5,pt2.y()-5,10,10));m_CircleP3 = pt3;m_CircleP3Pol = QPolygonF(QRectF(pt3.x()-5,pt3.y()-5,10,10));m_nCalipNum = nCalipNum;m_searchLength = searchLength;m_shadowLength = shadowLength;m_nSearchDir = nSearchDir;getCenterFrom3Pt(pt1,pt2,pt3,m_CircleCenter);m_radius = CalDis(m_CircleCenter.x(),m_CircleCenter.y(),pt1.x(),pt1.y());m_CircleRect = QRectF(m_CircleCenter.x()-m_radius,m_CircleCenter.y()-m_radius,m_radius*2,m_radius*2);QPainterPath path = getFillCircleArrow(m_CircleP1,m_CircleCenter,m_radius,10);m_FillCircleP1Rect = path.boundingRect();path = getFillCircleArrow(m_CircleP3,m_CircleCenter,m_radius,10);m_FillCircleP3Rect = path.boundingRect();if(m_tCaliRectLst.count()==m_nCalipNum){for(int i=0;i<m_nCalipNum;i++){qreal qAngle1 = 180-atan2((pt1.x()-m_CircleCenter.x()),(pt1.y()-m_CircleCenter.y()))*180/M_PI;qreal qAngle3 = 180-atan2((pt3.x()-m_CircleCenter.x()),(pt3.y()-m_CircleCenter.y()))*180/M_PI;qreal qAngle2;qreal s= (m_CircleP1.x() - m_CircleP3.x()) * (m_CircleP2.y() - m_CircleP3.y()) - (m_CircleP2.x() - m_CircleP3.x())*(m_CircleP1.y() - m_CircleP3.y());//向量p3p1和p3p2的叉积if(s>0)//叉积方向决定了弧形是内弧还是外弧{if(qAngle3<qAngle1)qAngle3 +=360;qAngle2 = qAngle1+(qAngle3-qAngle1)/(m_nCalipNum)/2+(qAngle3-qAngle1)/(m_nCalipNum)*(i);//将弧分成m_nCalipNum份,qAngle2表示第i个矩形的中心和圆心的夹角,注意y轴负方向为0度if(qAngle2>360)qAngle2 -= 360;}else{if(qAngle1<qAngle3)qAngle1 +=360;qAngle2 = qAngle1+(qAngle3-qAngle1)/(m_nCalipNum)/2+(qAngle3-qAngle1)/(m_nCalipNum)*(i);//将弧分成m_nCalipNum份,qAngle2表示第i个矩形的中心和圆心的夹角,注意y轴负方向为0度if(qAngle2>360)qAngle2 -= 360;}QPointF ptTop = QPointF(m_CircleCenter.x(),m_CircleCenter.y()-m_radius);QPointF rectCenter = getRotatePoint(m_CircleCenter,ptTop,qAngle2);QRectF rect = QRectF(rectCenter.x()-searchLength/2,rectCenter.y()-shadowLength/2,searchLength,shadowLength);if(nSearchDir == 0)//向外{qAngle2 = qAngle2+180;if(qAngle2>360)qAngle2 = qAngle2-360;}m_tCaliRectLst[i].m_RotateAngle = qAngle2;m_tCaliRectLst[i].m_fShearX=0;m_tCaliRectLst[i].m_bKeepShadowLength = false;setRectSize(rect,m_tCaliRectLst[i]);}}else{m_tCaliRectLst.clear();for(int i=0;i<m_nCalipNum;i++){CALI_RECT caliRect;qreal qAngle1 = 180-atan2((pt1.x()-m_CircleCenter.x()),(pt1.y()-m_CircleCenter.y()))*180/M_PI;qreal qAngle3 = 180-atan2((pt3.x()-m_CircleCenter.x()),(pt3.y()-m_CircleCenter.y()))*180/M_PI;qreal qAngle2;qreal s= (m_CircleP1.x() - m_CircleP3.x()) * (m_CircleP2.y() - m_CircleP3.y()) - (m_CircleP2.x() - m_CircleP3.x())*(m_CircleP1.y() - m_CircleP3.y());//向量p3p1和p3p2的叉积if(s>0)//叉积方向决定了弧形是内弧还是外弧{if(qAngle3<qAngle1)qAngle3 +=360;qAngle2 = qAngle1+(qAngle3-qAngle1)/(m_nCalipNum)/2+(qAngle3-qAngle1)/(m_nCalipNum)*(i);//将弧分成m_nCalipNum份,qAngle2表示第i个矩形的中心和圆心的夹角,注意y轴负方向为0度if(qAngle2>360)qAngle2 -= 360;}else{if(qAngle1<qAngle3)qAngle1 +=360;qAngle2 = qAngle1+(qAngle3-qAngle1)/(m_nCalipNum)/2+(qAngle3-qAngle1)/(m_nCalipNum)*(i);//将弧分成m_nCalipNum份,qAngle2表示第i个矩形的中心和圆心的夹角,注意y轴负方向为0度if(qAngle2>360)qAngle2 -= 360;}QPointF ptTop = QPointF(m_CircleCenter.x(),m_CircleCenter.y()-m_radius);QPointF rectCenter = getRotatePoint(m_CircleCenter,ptTop,qAngle2);QRectF rect = QRectF(rectCenter.x()-searchLength/2,rectCenter.y()-shadowLength/2,searchLength,shadowLength);if(nSearchDir == 0)//向外{qAngle2 = qAngle2+180;if(qAngle2>360)qAngle2 = qAngle2-360;}caliRect.m_RotateAngle = qAngle2;caliRect.m_fShearX=0;caliRect.m_bKeepShadowLength = false;setRectSize(rect,caliRect);m_tCaliRectLst.append(caliRect);}}
}QPointF mygraphicCaliperitem::getFillCirclePt(QPointF circlePt, QPointF centerPt, qreal radius, qreal roffset)
{qreal x = roffset/radius*(centerPt.x()-circlePt.x())+circlePt.x();qreal y = roffset/radius*(centerPt.y()-circlePt.y())+circlePt.y();return QPointF(x,y);
}QPointF mygraphicCaliperitem::getCirclePtByFillCirclePt(QPointF fillCirclePt, QPointF centerPt, qreal radius, qreal roffset)
{qreal x = roffset/radius*(fillCirclePt.x()-centerPt.x())+fillCirclePt.x();qreal y = roffset/radius*(fillCirclePt.y()-centerPt.y())+fillCirclePt.y();return QPointF(x,y);
}QPointF mygraphicCaliperitem::getCirclePtByMousePos(QPointF mousePt, QPointF centerPt, qreal radius)
{//鼠标点在qreal qAngle = 90-atan2((mousePt.x()-centerPt.x()),(mousePt.y()-centerPt.y()))*180/M_PI;//QPointF ptRight = QPointF(centerPt.x()+radius,centerPt.y());return getRotatePoint(centerPt,ptRight,qAngle);
}QPointF mygraphicCaliperitem::getP2ByP1P3PCenter(QPointF P1, QPointF P3, QPointF PCenter)
{qreal qAngle1 = 180-atan2((P1.x()-PCenter.x()),(P1.y()-PCenter.y()))*180/M_PI;qreal qAngle3 = 180-atan2((P3.x()-PCenter.x()),(P3.y()-PCenter.y()))*180/M_PI;if(qAngle1<qAngle3)qAngle1 +=360;qreal qAngle2 = qAngle3+(qAngle1-qAngle3)/2;if(qAngle2>360)qAngle2 -= 360;qreal s= (m_CircleP1.x() - m_CircleP3.x()) * (m_CircleP2.y() - m_CircleP3.y()) - (m_CircleP2.x() - m_CircleP3.x())*(m_CircleP1.y() - m_CircleP3.y());//向量p3p1和p3p2的叉积if(s>0)//叉积方向决定了弧形是内弧还是外弧{if(qAngle2>180)qAngle2-=180;elseqAngle2+=180;}QPointF ptTop = QPointF(PCenter.x(),PCenter.y()-m_radius);return getRotatePoint(PCenter,ptTop,qAngle2);
}
//过一点p1,求垂直于线段p1p2并距离线段10像素的两个点,ptout1为p1指向pt2向量的左手边
void mygraphicCaliperitem::getVeritacalLinePoint(QPointF pt1, QPointF pt2, qreal offset, QPointF &ptout1, QPointF &ptout2)
{//中垂线方程式为 y=x*k + b;qreal x1,y1,x2,y2;//两点与pt1距离都为offset,得到方程sqrt((x-ptx.x)*(x-ptx.x)+(y-ptx.y)*(y-ptx.y))=offsetif(pt1.y()==pt2.y()){//垂线方程为 x = pt1.x()x1 = pt1.x();y1 = pt1.y()+offset;x2 = pt1.x();y2 = pt1.y()-offset;}else{qreal k = (pt2.x()-pt1.x())/(pt1.y()-pt2.y());qreal b = pt1.y()-k*pt1.x();x1 = pt1.x()+sqrt(offset*offset/(1+k*k));y1 = k*x1+b;x2 = pt1.x()-sqrt(offset*offset/(1+k*k));y2 = k*x2+b;}//根据pt1pt2向量叉积公式和右手定则得到qreal sNew = (pt1.x() - pt2.x()) * (y1 - pt2.y()) - (pt1.y() - pt2.y()) * (x1 - pt2.x());if(sNew>0){ptout1.setX(x1);ptout1.setY(y1);ptout2.setX(x2);ptout2.setY(y2);}else{ptout1.setX(x2);ptout1.setY(y2);ptout2.setX(x1);ptout2.setY(y1);}
}QPainterPath mygraphicCaliperitem::getFillCircleArrow(QPointF circlePt, QPointF centerPt, qreal radius, qreal roffset)
{QPainterPath path;QPointF ptCenter = getFillCirclePt(circlePt,centerPt,radius,roffset);QPointF ptCenterleft = getFillCirclePt(circlePt,centerPt,radius,roffset-2);QPointF ptCenterright = getFillCirclePt(circlePt,centerPt,radius,roffset+2);QPointF ptCenter1,ptCenter2,ptleft1,ptleft2,ptright1,ptright2;getVeritacalLinePoint(ptCenter,circlePt,5,ptCenter1,ptCenter2);getVeritacalLinePoint(ptCenterleft,circlePt,2,ptleft1,ptleft2);getVeritacalLinePoint(ptCenterright,circlePt,2,ptright1,ptright2);path.moveTo(ptleft1);path.lineTo(ptCenter1);path.lineTo(ptright1);path.moveTo(ptleft2);path.lineTo(ptCenter2);path.lineTo(ptright2);return path;
}void mygraphicCaliperitem::setRectSize(QRectF mrect, CALI_RECT &caliRect)
{caliRect.m_RECT = mrect;caliRect.m_newShearRECT = mrect;caliRect.m_RotateCenter.setX(caliRect.m_RECT.x()+caliRect.m_RECT.width()/2);caliRect.m_RotateCenter.setY(caliRect.m_RECT.y()+caliRect.m_RECT.height()/2);//test 扭曲caliRect.m_RECTShear = QPolygonF(caliRect.m_RECT);QTransform trans;trans.translate(caliRect.m_RECT.center().x(),caliRect.m_RECT.center().y());trans.shear(caliRect.m_fShearX,0);trans.translate(-caliRect.m_RECT.center().x(),-caliRect.m_RECT.center().y());caliRect.m_RECTShear = trans.map(caliRect.m_RECTShear);//斜切之后的矩形//testcaliRect.m_RECT_Pol = getRotatePolygonFromPolygon(caliRect.m_RotateCenter,caliRect.m_RECTShear,caliRect.m_RotateAngle);//m_RECT_Inside = QRectF(m_RECTShear[0].x()+5,m_RECTShear[0].y()+5,m_RECT.width()-10,m_RECT.height()-10);caliRect.m_RECT_InsideShear.clear();caliRect.m_RECT_InsideShear.append(QPointF(caliRect.m_RECTShear[0].x()+5,caliRect.m_RECTShear[0].y()+5));caliRect.m_RECT_InsideShear.append(QPointF(caliRect.m_RECTShear[1].x()-5,caliRect.m_RECTShear[1].y()+5));caliRect.m_RECT_InsideShear.append(QPointF(caliRect.m_RECTShear[2].x()-5,caliRect.m_RECTShear[2].y()-5));caliRect.m_RECT_InsideShear.append(QPointF(caliRect.m_RECTShear[3].x()+5,caliRect.m_RECTShear[3].y()-5));caliRect.m_RECT_InsideShear.append(QPointF(caliRect.m_RECTShear[0].x()+5,caliRect.m_RECTShear[0].y()+5));caliRect.m_RECT_Inside_Pol = getRotatePolygonFromPolygon(caliRect.m_RotateCenter,caliRect.m_RECT_InsideShear,caliRect.m_RotateAngle);caliRect.m_RECT_TL = QRectF(caliRect.m_RECTShear[0].x()-5,caliRect.m_RECTShear[0].y()-5,10,10);//左上角顶点caliRect.m_RECT_TL_Pol = getRotatePolygonFromRect(caliRect.m_RotateCenter,caliRect.m_RECT_TL,caliRect.m_RotateAngle);caliRect.m_RECT_TR = QRectF(caliRect.m_RECTShear[1].x()-5,caliRect.m_RECTShear[1].y()-5,10,10);//右上角顶点caliRect.m_RECT_TR_Pol = getRotatePolygonFromRect(caliRect.m_RotateCenter,caliRect.m_RECT_TR,caliRect.m_RotateAngle);caliRect.m_RECT_BL = QRectF(caliRect.m_RECTShear[3].x()-5,caliRect.m_RECTShear[3].y()-5,10,10);//左下角顶点caliRect.m_RECT_BL_Pol = getRotatePolygonFromRect(caliRect.m_RotateCenter,caliRect.m_RECT_BL,caliRect.m_RotateAngle);caliRect.m_RECT_BR = QRectF(caliRect.m_RECTShear[2].x()-5,caliRect.m_RECTShear[2].y()-5,10,10);//右下角顶点caliRect.m_RECT_BR_Pol = getRotatePolygonFromRect(caliRect.m_RotateCenter,caliRect.m_RECT_BR,caliRect.m_RotateAngle);caliRect.m_RECT_Rotate = QRectF((caliRect.m_RECTShear[1].x()+caliRect.m_RECTShear[2].x())/2-10,(caliRect.m_RECTShear[1].y()+caliRect.m_RECTShear[2].y())/2-10,20,20);//矩形右侧旋转标记矩形caliRect.m_RECT_Rotate_Pol = getRotatePolygonFromRect(caliRect.m_RotateCenter,caliRect.m_RECT_Rotate,caliRect.m_RotateAngle);caliRect.m_RECT_Scan_Dir = QRectF((caliRect.m_RECTShear[0].x()+caliRect.m_RECTShear[1].x())/2-5,(caliRect.m_RECTShear[0].y()+caliRect.m_RECTShear[1].y())/2-5,10,10);QPolygonF tempPol = getRotatePolygonFromRect(caliRect.m_RotateCenter,caliRect.m_RECT_Scan_Dir,caliRect.m_RotateAngle);QVector<QPointF> tempv;tempv.append(QPointF(tempPol[0]));tempv.append(QPointF((tempPol[1].x()+tempPol[2].x())/2,(tempPol[1].y()+tempPol[2].y())/2));tempv.append(QPointF(tempPol[3]));caliRect.m_RECT_Scan_Dir_Pol = QPolygonF(tempv);//扫描方向的三角形caliRect.m_RECT_Shadow_Dir = QRectF(caliRect.m_RECT.x()-5,caliRect.m_RECT.bottomLeft().y()-15,10,10);//投影方向的三角形标记QPolygonF tempShadow = QPolygonF(caliRect.m_RECT_Shadow_Dir);tempShadow = trans.map(tempShadow);caliRect.m_RECT_Shadow_Dir_Pol = getRotatePolygonFromPolygon(caliRect.m_RotateCenter,tempShadow,caliRect.m_RotateAngle);caliRect.m_RECT_Shear = QRectF((caliRect.m_RECTShear[2].x()+caliRect.m_RECTShear[3].x())/2-5,(caliRect.m_RECTShear[2].y()+caliRect.m_RECTShear[3].y())/2-5,10,10);QPolygonF tempShear = QPolygonF(caliRect.m_RECT_Shear);QTransform transShear;transShear.translate(caliRect.m_RECT_Shear.center().x(),caliRect.m_RECT_Shear.center().y());//先把中心移动到m_RECT_Shear中心transShear.shear(1,0);transShear.translate(-caliRect.m_RECT_Shear.center().x(),-caliRect.m_RECT_Shear.center().y());//先把中心移动到m_RECT_Shear中心tempShear = transShear.map(tempShear);//斜切之后的矩形caliRect.m_RECT_Shear_Pol = getRotatePolygonFromPolygon(caliRect.m_RotateCenter,tempShear,caliRect.m_RotateAngle);
}void mygraphicCaliperitem::setRectSize(QRectF mrect)
{m_tCaliRect.m_RECT = mrect;m_tCaliRect.m_newShearRECT = mrect;m_tCaliRect.m_RotateCenter.setX(m_tCaliRect.m_RECT.x()+m_tCaliRect.m_RECT.width()/2);m_tCaliRect.m_RotateCenter.setY(m_tCaliRect.m_RECT.y()+m_tCaliRect.m_RECT.height()/2);//test 扭曲m_tCaliRect.m_RECTShear = QPolygonF(m_tCaliRect.m_RECT);QTransform trans;trans.translate(m_tCaliRect.m_RECT.center().x(),m_tCaliRect.m_RECT.center().y());trans.shear(m_tCaliRect.m_fShearX,0);trans.translate(-m_tCaliRect.m_RECT.center().x(),-m_tCaliRect.m_RECT.center().y());m_tCaliRect.m_RECTShear = trans.map(m_tCaliRect.m_RECTShear);//斜切之后的矩形//testm_tCaliRect.m_RECT_Pol = getRotatePolygonFromPolygon(m_tCaliRect.m_RotateCenter,m_tCaliRect.m_RECTShear,m_tCaliRect.m_RotateAngle);//m_RECT_Inside = QRectF(m_RECTShear[0].x()+5,m_RECTShear[0].y()+5,m_RECT.width()-10,m_RECT.height()-10);m_tCaliRect.m_RECT_InsideShear.clear();m_tCaliRect.m_RECT_InsideShear.append(QPointF(m_tCaliRect.m_RECTShear[0].x()+5,m_tCaliRect.m_RECTShear[0].y()+5));m_tCaliRect.m_RECT_InsideShear.append(QPointF(m_tCaliRect.m_RECTShear[1].x()-5,m_tCaliRect.m_RECTShear[1].y()+5));m_tCaliRect.m_RECT_InsideShear.append(QPointF(m_tCaliRect.m_RECTShear[2].x()-5,m_tCaliRect.m_RECTShear[2].y()-5));m_tCaliRect.m_RECT_InsideShear.append(QPointF(m_tCaliRect.m_RECTShear[3].x()+5,m_tCaliRect.m_RECTShear[3].y()-5));m_tCaliRect.m_RECT_InsideShear.append(QPointF(m_tCaliRect.m_RECTShear[0].x()+5,m_tCaliRect.m_RECTShear[0].y()+5));m_tCaliRect.m_RECT_Inside_Pol = getRotatePolygonFromPolygon(m_tCaliRect.m_RotateCenter,m_tCaliRect.m_RECT_InsideShear,m_tCaliRect.m_RotateAngle);m_tCaliRect.m_RECT_TL = QRectF(m_tCaliRect.m_RECTShear[0].x()-5,m_tCaliRect.m_RECTShear[0].y()-5,10,10);//左上角顶点m_tCaliRect.m_RECT_TL_Pol = getRotatePolygonFromRect(m_tCaliRect.m_RotateCenter,m_tCaliRect.m_RECT_TL,m_tCaliRect.m_RotateAngle);m_tCaliRect.m_RECT_TR = QRectF(m_tCaliRect.m_RECTShear[1].x()-5,m_tCaliRect.m_RECTShear[1].y()-5,10,10);//右上角顶点m_tCaliRect.m_RECT_TR_Pol = getRotatePolygonFromRect(m_tCaliRect.m_RotateCenter,m_tCaliRect.m_RECT_TR,m_tCaliRect.m_RotateAngle);m_tCaliRect.m_RECT_BL = QRectF(m_tCaliRect.m_RECTShear[3].x()-5,m_tCaliRect.m_RECTShear[3].y()-5,10,10);//左下角顶点m_tCaliRect.m_RECT_BL_Pol = getRotatePolygonFromRect(m_tCaliRect.m_RotateCenter,m_tCaliRect.m_RECT_BL,m_tCaliRect.m_RotateAngle);m_tCaliRect.m_RECT_BR = QRectF(m_tCaliRect.m_RECTShear[2].x()-5,m_tCaliRect.m_RECTShear[2].y()-5,10,10);//右下角顶点m_tCaliRect.m_RECT_BR_Pol = getRotatePolygonFromRect(m_tCaliRect.m_RotateCenter,m_tCaliRect.m_RECT_BR,m_tCaliRect.m_RotateAngle);m_tCaliRect.m_RECT_Rotate = QRectF((m_tCaliRect.m_RECTShear[1].x()+m_tCaliRect.m_RECTShear[2].x())/2-10,(m_tCaliRect.m_RECTShear[1].y()+m_tCaliRect.m_RECTShear[2].y())/2-10,20,20);//矩形右侧旋转标记矩形m_tCaliRect.m_RECT_Rotate_Pol = getRotatePolygonFromRect(m_tCaliRect.m_RotateCenter,m_tCaliRect.m_RECT_Rotate,m_tCaliRect.m_RotateAngle);m_tCaliRect.m_RECT_Scan_Dir = QRectF((m_tCaliRect.m_RECTShear[0].x()+m_tCaliRect.m_RECTShear[1].x())/2-5,(m_tCaliRect.m_RECTShear[0].y()+m_tCaliRect.m_RECTShear[1].y())/2-5,10,10);QPolygonF tempPol = getRotatePolygonFromRect(m_tCaliRect.m_RotateCenter,m_tCaliRect.m_RECT_Scan_Dir,m_tCaliRect.m_RotateAngle);QVector<QPointF> tempv;tempv.append(QPointF(tempPol[0]));tempv.append(QPointF((tempPol[1].x()+tempPol[2].x())/2,(tempPol[1].y()+tempPol[2].y())/2));tempv.append(QPointF(tempPol[3]));m_tCaliRect.m_RECT_Scan_Dir_Pol = QPolygonF(tempv);//扫描方向的三角形m_tCaliRect.m_RECT_Shadow_Dir = QRectF(m_tCaliRect.m_RECT.x()-5,m_tCaliRect.m_RECT.bottomLeft().y()-15,10,10);//投影方向的三角形标记QPolygonF tempShadow = QPolygonF(m_tCaliRect.m_RECT_Shadow_Dir);tempShadow = trans.map(tempShadow);m_tCaliRect.m_RECT_Shadow_Dir_Pol = getRotatePolygonFromPolygon(m_tCaliRect.m_RotateCenter,tempShadow,m_tCaliRect.m_RotateAngle);m_tCaliRect.m_RECT_Shear = QRectF((m_tCaliRect.m_RECTShear[2].x()+m_tCaliRect.m_RECTShear[3].x())/2-5,(m_tCaliRect.m_RECTShear[2].y()+m_tCaliRect.m_RECTShear[3].y())/2-5,10,10);QPolygonF tempShear = QPolygonF(m_tCaliRect.m_RECT_Shear);QTransform transShear;transShear.translate(m_tCaliRect.m_RECT_Shear.center().x(),m_tCaliRect.m_RECT_Shear.center().y());//先把中心移动到m_RECT_Shear中心transShear.shear(1,0);transShear.translate(-m_tCaliRect.m_RECT_Shear.center().x(),-m_tCaliRect.m_RECT_Shear.center().y());//先把中心移动到m_RECT_Shear中心tempShear = transShear.map(tempShear);//斜切之后的矩形m_tCaliRect.m_RECT_Shear_Pol = getRotatePolygonFromPolygon(m_tCaliRect.m_RotateCenter,tempShear,m_tCaliRect.m_RotateAngle);}void mygraphicCaliperitem::setShearRectSize(QRectF mrect)
{m_tCaliRect.m_newShearRECT = mrect;m_tCaliRect.m_RotateCenter.setX(m_tCaliRect.m_newShearRECT.x()+m_tCaliRect.m_newShearRECT.width()/2);m_tCaliRect.m_RotateCenter.setY(m_tCaliRect.m_newShearRECT.y()+m_tCaliRect.m_newShearRECT.height()/2);//test 扭曲m_tCaliRect.m_RECTShear = QPolygonF(m_tCaliRect.m_newShearRECT);QTransform trans;trans.translate(m_tCaliRect.m_newShearRECT.center().x(),m_tCaliRect.m_newShearRECT.center().y());trans.shear(m_tCaliRect.m_fShearX,0);trans.translate(-m_tCaliRect.m_newShearRECT.center().x(),-m_tCaliRect.m_newShearRECT.center().y());m_tCaliRect.m_RECTShear = trans.map(m_tCaliRect.m_RECTShear);//斜切之后的矩形//testm_tCaliRect.m_RECT_Pol = getRotatePolygonFromPolygon(m_tCaliRect.m_RotateCenter,m_tCaliRect.m_RECTShear,m_tCaliRect.m_RotateAngle);//m_RECT_Inside = QRectF(m_RECTShear[0].x()+5,m_RECTShear[0].y()+5,m_RECT.width()-10,m_RECT.height()-10);m_tCaliRect.m_RECT_InsideShear.clear();m_tCaliRect.m_RECT_InsideShear.append(QPointF(m_tCaliRect.m_RECTShear[0].x()+5,m_tCaliRect.m_RECTShear[0].y()+5));m_tCaliRect.m_RECT_InsideShear.append(QPointF(m_tCaliRect.m_RECTShear[1].x()-5,m_tCaliRect.m_RECTShear[1].y()+5));m_tCaliRect.m_RECT_InsideShear.append(QPointF(m_tCaliRect.m_RECTShear[2].x()-5,m_tCaliRect.m_RECTShear[2].y()-5));m_tCaliRect.m_RECT_InsideShear.append(QPointF(m_tCaliRect.m_RECTShear[3].x()+5,m_tCaliRect.m_RECTShear[3].y()-5));m_tCaliRect.m_RECT_InsideShear.append(QPointF(m_tCaliRect.m_RECTShear[0].x()+5,m_tCaliRect.m_RECTShear[0].y()+5));m_tCaliRect.m_RECT_Inside_Pol = getRotatePolygonFromPolygon(m_tCaliRect.m_RotateCenter,m_tCaliRect.m_RECT_InsideShear,m_tCaliRect.m_RotateAngle);m_tCaliRect.m_RECT_TL = QRectF(m_tCaliRect.m_RECTShear[0].x()-5,m_tCaliRect.m_RECTShear[0].y()-5,10,10);//左上角顶点m_tCaliRect.m_RECT_TL_Pol = getRotatePolygonFromRect(m_tCaliRect.m_RotateCenter,m_tCaliRect.m_RECT_TL,m_tCaliRect.m_RotateAngle);m_tCaliRect.m_RECT_TR = QRectF(m_tCaliRect.m_RECTShear[1].x()-5,m_tCaliRect.m_RECTShear[1].y()-5,10,10);//右上角顶点m_tCaliRect.m_RECT_TR_Pol = getRotatePolygonFromRect(m_tCaliRect.m_RotateCenter,m_tCaliRect.m_RECT_TR,m_tCaliRect.m_RotateAngle);m_tCaliRect.m_RECT_BL = QRectF(m_tCaliRect.m_RECTShear[3].x()-5,m_tCaliRect.m_RECTShear[3].y()-5,10,10);//左下角顶点m_tCaliRect.m_RECT_BL_Pol = getRotatePolygonFromRect(m_tCaliRect.m_RotateCenter,m_tCaliRect.m_RECT_BL,m_tCaliRect.m_RotateAngle);m_tCaliRect.m_RECT_BR = QRectF(m_tCaliRect.m_RECTShear[2].x()-5,m_tCaliRect.m_RECTShear[2].y()-5,10,10);//右下角顶点m_tCaliRect.m_RECT_BR_Pol = getRotatePolygonFromRect(m_tCaliRect.m_RotateCenter,m_tCaliRect.m_RECT_BR,m_tCaliRect.m_RotateAngle);m_tCaliRect.m_RECT_Rotate = QRectF((m_tCaliRect.m_RECTShear[1].x()+m_tCaliRect.m_RECTShear[2].x())/2-10,(m_tCaliRect.m_RECTShear[1].y()+m_tCaliRect.m_RECTShear[2].y())/2-10,20,20);//矩形右侧旋转标记矩形m_tCaliRect.m_RECT_Rotate_Pol = getRotatePolygonFromRect(m_tCaliRect.m_RotateCenter,m_tCaliRect.m_RECT_Rotate,m_tCaliRect.m_RotateAngle);m_tCaliRect.m_RECT_Scan_Dir = QRectF((m_tCaliRect.m_RECTShear[0].x()+m_tCaliRect.m_RECTShear[1].x())/2-5,(m_tCaliRect.m_RECTShear[0].y()+m_tCaliRect.m_RECTShear[1].y())/2-5,10,10);QPolygonF tempPol = getRotatePolygonFromRect(m_tCaliRect.m_RotateCenter,m_tCaliRect.m_RECT_Scan_Dir,m_tCaliRect.m_RotateAngle);QVector<QPointF> tempv;tempv.append(QPointF(tempPol[0]));tempv.append(QPointF((tempPol[1].x()+tempPol[2].x())/2,(tempPol[1].y()+tempPol[2].y())/2));tempv.append(QPointF(tempPol[3]));m_tCaliRect.m_RECT_Scan_Dir_Pol = QPolygonF(tempv);//扫描方向的三角形m_tCaliRect.m_RECT_Shadow_Dir = QRectF(m_tCaliRect.m_newShearRECT.x()-5,m_tCaliRect.m_newShearRECT.bottomLeft().y()-15,10,10);//投影方向的三角形标记QPolygonF tempShadow = QPolygonF(m_tCaliRect.m_RECT_Shadow_Dir);tempShadow = trans.map(tempShadow);m_tCaliRect.m_RECT_Shadow_Dir_Pol = getRotatePolygonFromPolygon(m_tCaliRect.m_RotateCenter,tempShadow,m_tCaliRect.m_RotateAngle);m_tCaliRect.m_RECT_Shear = QRectF((m_tCaliRect.m_RECTShear[2].x()+m_tCaliRect.m_RECTShear[3].x())/2-5,(m_tCaliRect.m_RECTShear[2].y()+m_tCaliRect.m_RECTShear[3].y())/2-5,10,10);QPolygonF tempShear = QPolygonF(m_tCaliRect.m_RECT_Shear);QTransform transShear;transShear.translate(m_tCaliRect.m_RECT_Shear.center().x(),m_tCaliRect.m_RECT_Shear.center().y());//先把中心移动到m_RECT_Shear中心transShear.shear(1,0);transShear.translate(-m_tCaliRect.m_RECT_Shear.center().x(),-m_tCaliRect.m_RECT_Shear.center().y());//先把中心移动到m_RECT_Shear中心tempShear = transShear.map(tempShear);//斜切之后的矩形m_tCaliRect.m_RECT_Shear_Pol = getRotatePolygonFromPolygon(m_tCaliRect.m_RotateCenter,tempShear,m_tCaliRect.m_RotateAngle);}void mygraphicCaliperitem::setShearRectSize(QRectF mrect, CALI_RECT &circleRect)
{circleRect.m_newShearRECT = mrect;circleRect.m_RotateCenter.setX(circleRect.m_newShearRECT.x()+circleRect.m_newShearRECT.width()/2);circleRect.m_RotateCenter.setY(circleRect.m_newShearRECT.y()+circleRect.m_newShearRECT.height()/2);//test 扭曲circleRect.m_RECTShear = QPolygonF(circleRect.m_newShearRECT);QTransform trans;trans.translate(circleRect.m_newShearRECT.center().x(),circleRect.m_newShearRECT.center().y());trans.shear(circleRect.m_fShearX,0);trans.translate(-circleRect.m_newShearRECT.center().x(),-circleRect.m_newShearRECT.center().y());circleRect.m_RECTShear = trans.map(circleRect.m_RECTShear);//斜切之后的矩形//testcircleRect.m_RECT_Pol = getRotatePolygonFromPolygon(circleRect.m_RotateCenter,circleRect.m_RECTShear,circleRect.m_RotateAngle);//m_RECT_Inside = QRectF(m_RECTShear[0].x()+5,m_RECTShear[0].y()+5,m_RECT.width()-10,m_RECT.height()-10);circleRect.m_RECT_InsideShear.clear();circleRect.m_RECT_InsideShear.append(QPointF(circleRect.m_RECTShear[0].x()+5,circleRect.m_RECTShear[0].y()+5));circleRect.m_RECT_InsideShear.append(QPointF(circleRect.m_RECTShear[1].x()-5,circleRect.m_RECTShear[1].y()+5));circleRect.m_RECT_InsideShear.append(QPointF(circleRect.m_RECTShear[2].x()-5,circleRect.m_RECTShear[2].y()-5));circleRect.m_RECT_InsideShear.append(QPointF(circleRect.m_RECTShear[3].x()+5,circleRect.m_RECTShear[3].y()-5));circleRect.m_RECT_InsideShear.append(QPointF(circleRect.m_RECTShear[0].x()+5,circleRect.m_RECTShear[0].y()+5));circleRect.m_RECT_Inside_Pol = getRotatePolygonFromPolygon(circleRect.m_RotateCenter,circleRect.m_RECT_InsideShear,circleRect.m_RotateAngle);circleRect.m_RECT_TL = QRectF(circleRect.m_RECTShear[0].x()-5,circleRect.m_RECTShear[0].y()-5,10,10);//左上角顶点circleRect.m_RECT_TL_Pol = getRotatePolygonFromRect(circleRect.m_RotateCenter,circleRect.m_RECT_TL,circleRect.m_RotateAngle);circleRect.m_RECT_TR = QRectF(circleRect.m_RECTShear[1].x()-5,circleRect.m_RECTShear[1].y()-5,10,10);//右上角顶点circleRect.m_RECT_TR_Pol = getRotatePolygonFromRect(circleRect.m_RotateCenter,circleRect.m_RECT_TR,circleRect.m_RotateAngle);circleRect.m_RECT_BL = QRectF(circleRect.m_RECTShear[3].x()-5,circleRect.m_RECTShear[3].y()-5,10,10);//左下角顶点circleRect.m_RECT_BL_Pol = getRotatePolygonFromRect(circleRect.m_RotateCenter,circleRect.m_RECT_BL,circleRect.m_RotateAngle);circleRect.m_RECT_BR = QRectF(circleRect.m_RECTShear[2].x()-5,circleRect.m_RECTShear[2].y()-5,10,10);//右下角顶点circleRect.m_RECT_BR_Pol = getRotatePolygonFromRect(circleRect.m_RotateCenter,circleRect.m_RECT_BR,circleRect.m_RotateAngle);circleRect.m_RECT_Rotate = QRectF((circleRect.m_RECTShear[1].x()+circleRect.m_RECTShear[2].x())/2-10,(circleRect.m_RECTShear[1].y()+circleRect.m_RECTShear[2].y())/2-10,20,20);//矩形右侧旋转标记矩形circleRect.m_RECT_Rotate_Pol = getRotatePolygonFromRect(circleRect.m_RotateCenter,circleRect.m_RECT_Rotate,circleRect.m_RotateAngle);circleRect.m_RECT_Scan_Dir = QRectF((circleRect.m_RECTShear[0].x()+circleRect.m_RECTShear[1].x())/2-5,(circleRect.m_RECTShear[0].y()+circleRect.m_RECTShear[1].y())/2-5,10,10);QPolygonF tempPol = getRotatePolygonFromRect(circleRect.m_RotateCenter,circleRect.m_RECT_Scan_Dir,circleRect.m_RotateAngle);QVector<QPointF> tempv;tempv.append(QPointF(tempPol[0]));tempv.append(QPointF((tempPol[1].x()+tempPol[2].x())/2,(tempPol[1].y()+tempPol[2].y())/2));tempv.append(QPointF(tempPol[3]));circleRect.m_RECT_Scan_Dir_Pol = QPolygonF(tempv);//扫描方向的三角形circleRect.m_RECT_Shadow_Dir = QRectF(circleRect.m_newShearRECT.x()-5,circleRect.m_newShearRECT.bottomLeft().y()-15,10,10);//投影方向的三角形标记QPolygonF tempShadow = QPolygonF(circleRect.m_RECT_Shadow_Dir);tempShadow = trans.map(tempShadow);circleRect.m_RECT_Shadow_Dir_Pol = getRotatePolygonFromPolygon(circleRect.m_RotateCenter,tempShadow,circleRect.m_RotateAngle);circleRect.m_RECT_Shear = QRectF((circleRect.m_RECTShear[2].x()+circleRect.m_RECTShear[3].x())/2-5,(circleRect.m_RECTShear[2].y()+circleRect.m_RECTShear[3].y())/2-5,10,10);QPolygonF tempShear = QPolygonF(circleRect.m_RECT_Shear);QTransform transShear;transShear.translate(circleRect.m_RECT_Shear.center().x(),circleRect.m_RECT_Shear.center().y());//先把中心移动到m_RECT_Shear中心transShear.shear(1,0);transShear.translate(-circleRect.m_RECT_Shear.center().x(),-circleRect.m_RECT_Shear.center().y());//先把中心移动到m_RECT_Shear中心tempShear = transShear.map(tempShear);//斜切之后的矩形circleRect.m_RECT_Shear_Pol = getRotatePolygonFromPolygon(circleRect.m_RotateCenter,tempShear,circleRect.m_RotateAngle);}void mygraphicCaliperitem::setKeepShadowLength(bool bkeeplength)
{if(m_ShapeType==CALIPER_RECT)m_tCaliRect.m_bKeepShadowLength = bkeeplength;else if(m_ShapeType==CALIPER_LINE){//TODO:}
}void mygraphicCaliperitem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{QPen mPen;mPen= QPen(Qt::yellow);painter->setPen(mPen);if(m_ShapeType == CALIPER_RECT)//{        //绘制旋转后的矩形painter->drawPolygon(m_tCaliRect.m_RECT_Pol);mPen.setColor(Qt::green);//绘制右下角顶点矩形mPen.setWidth(1);painter->setPen(mPen);//绘制右下角顶点矩形QPainterPath path;path.moveTo(QPointF((m_tCaliRect.m_RECT_BR_Pol[0].x()+m_tCaliRect.m_RECT_BR_Pol[1].x())/2,(m_tCaliRect.m_RECT_BR_Pol[0].y()+m_tCaliRect.m_RECT_BR_Pol[1].y())/2));path.lineTo(QPointF((m_tCaliRect.m_RECT_BR_Pol[2].x()+m_tCaliRect.m_RECT_BR_Pol[3].x())/2,(m_tCaliRect.m_RECT_BR_Pol[2].y()+m_tCaliRect.m_RECT_BR_Pol[3].y())/2));path.moveTo(QPointF((m_tCaliRect.m_RECT_BR_Pol[0].x()+m_tCaliRect.m_RECT_BR_Pol[3].x())/2,(m_tCaliRect.m_RECT_BR_Pol[0].y()+m_tCaliRect.m_RECT_BR_Pol[3].y())/2));path.lineTo(QPointF((m_tCaliRect.m_RECT_BR_Pol[2].x()+m_tCaliRect.m_RECT_BR_Pol[1].x())/2,(m_tCaliRect.m_RECT_BR_Pol[2].y()+m_tCaliRect.m_RECT_BR_Pol[1].y())/2));painter->setPen(QPen(Qt::yellow,2));painter->drawPath(path);//绘制投影标记QPointF pt0 = m_tCaliRect.m_RECT_Shadow_Dir_Pol[0];QPointF pt1 = QPointF((m_tCaliRect.m_RECT_Shadow_Dir_Pol[2].x()+m_tCaliRect.m_RECT_Shadow_Dir_Pol[3].x())/2,(m_tCaliRect.m_RECT_Shadow_Dir_Pol[2].y()+m_tCaliRect.m_RECT_Shadow_Dir_Pol[3].y())/2);QPointF pt2 = m_tCaliRect.m_RECT_Shadow_Dir_Pol[1];painter->drawLine(pt0,pt1);painter->drawLine(pt2,pt1);//绘制扫描方向标记painter->drawPolygon(m_tCaliRect.m_RECT_Scan_Dir_Pol);//绘制旋转圆形mPen.setWidth(2);painter->setPen(mPen);QPointF pf = QPointF((m_tCaliRect.m_RECT_Pol[1].x()+m_tCaliRect.m_RECT_Pol[2].x())/2,(m_tCaliRect.m_RECT_Pol[1].y()+m_tCaliRect.m_RECT_Pol[2].y())/2);QRectF rect = QRectF(pf.x()-10,pf.y()-10,20,20);painter->drawEllipse(rect);//绘制圆形painter->drawPoint(pf);//绘制点//绘制切变矩形标记painter->drawPolygon(m_tCaliRect.m_RECT_Shear_Pol);//painter->drawPolygon(m_RECT_Inside_Pol);
//        mPen.setColor(Qt::red);
//        mPen.setWidth(5);
//        painter->setPen(mPen);
//        painter->drawPoint(pCross1);
//        painter->drawPoint(pCross2);
//        painter->drawPoint(pCross3);
//        painter->drawPoint(m_RECT.center());}else if(m_ShapeType == CALIPER_LINE)//直线卡尺{mPen.setColor(Qt::yellow);mPen.setWidth(2);painter->drawLine(m_CaliLine);mPen.setWidth(1);int nCount = m_tCaliRectLst.count();for(int i = 0;i<nCount;i++){painter->setPen(QPen(Qt::green,1));//绘制旋转后的矩形painter->drawPolygon(m_tCaliRectLst[i].m_RECT_Pol);if((nCount+1)/2-1==i){//绘制右下角顶点矩形QPainterPath path;path.moveTo(QPointF((m_tCaliRectLst[i].m_RECT_BR_Pol[0].x()+m_tCaliRectLst[i].m_RECT_BR_Pol[1].x())/2,(m_tCaliRectLst[i].m_RECT_BR_Pol[0].y()+m_tCaliRectLst[i].m_RECT_BR_Pol[1].y())/2));path.lineTo(QPointF((m_tCaliRectLst[i].m_RECT_BR_Pol[2].x()+m_tCaliRectLst[i].m_RECT_BR_Pol[3].x())/2,(m_tCaliRectLst[i].m_RECT_BR_Pol[2].y()+m_tCaliRectLst[i].m_RECT_BR_Pol[3].y())/2));path.moveTo(QPointF((m_tCaliRectLst[i].m_RECT_BR_Pol[0].x()+m_tCaliRectLst[i].m_RECT_BR_Pol[3].x())/2,(m_tCaliRectLst[i].m_RECT_BR_Pol[0].y()+m_tCaliRectLst[i].m_RECT_BR_Pol[3].y())/2));path.lineTo(QPointF((m_tCaliRectLst[i].m_RECT_BR_Pol[2].x()+m_tCaliRectLst[i].m_RECT_BR_Pol[1].x())/2,(m_tCaliRectLst[i].m_RECT_BR_Pol[2].y()+m_tCaliRectLst[i].m_RECT_BR_Pol[1].y())/2));painter->setPen(QPen(Qt::yellow,2));painter->drawPath(path);//绘制投影标记painter->setPen(QPen(Qt::yellow,1));QPointF pt0 = m_tCaliRectLst[i].m_RECT_Shadow_Dir_Pol[0];QPointF pt1 = QPointF((m_tCaliRectLst[i].m_RECT_Shadow_Dir_Pol[2].x()+m_tCaliRectLst[i].m_RECT_Shadow_Dir_Pol[3].x())/2,(m_tCaliRectLst[i].m_RECT_Shadow_Dir_Pol[2].y()+m_tCaliRectLst[i].m_RECT_Shadow_Dir_Pol[3].y())/2);QPointF pt2 = m_tCaliRectLst[i].m_RECT_Shadow_Dir_Pol[1];painter->drawLine(pt0,pt1);painter->drawLine(pt2,pt1);//绘制扫描方向标记painter->drawPolygon(m_tCaliRectLst[i].m_RECT_Scan_Dir_Pol);
#ifdef ROTATE_AND_SHEAR//绘制旋转圆形painter->setPen(QPen(Qt::yellow,2));QPointF pf = QPointF((m_tCaliRectLst[i].m_RECT_Pol[1].x()+m_tCaliRectLst[i].m_RECT_Pol[2].x())/2,(m_tCaliRectLst[i].m_RECT_Pol[1].y()+m_tCaliRectLst[i].m_RECT_Pol[2].y())/2);QRectF rect = QRectF(pf.x()-10,pf.y()-10,20,20);painter->drawEllipse(rect);//绘制圆形painter->drawPoint(pf);//绘制点//绘制切变矩形标记painter->drawPolygon(m_tCaliRectLst[i].m_RECT_Shear_Pol);
#endif}}mPen= QPen(Qt::red);mPen.setWidth(4);painter->setPen(mPen);painter->drawPoint(m_CaliLine.p1());painter->drawPoint(m_CaliLine.p2());
//        painter->drawPolygon(m_LineBodyPol);//直线上下各10像素范围内的矩形区域
//        painter->drawEllipse(m_LineP1);
//        painter->drawEllipse(m_LineP2);}else if(m_ShapeType == CALIPER_CIRCLE)//圆形卡尺{int nCount = m_tCaliRectLst.count();for(int i = 0;i<nCount;i++){//绘制旋转后的矩形painter->setPen(QPen(Qt::green,1));painter->drawPolygon(m_tCaliRectLst[i].m_RECT_Pol);//绘制右下角顶点矩形十字if((nCount+1)/2-1==i){QPainterPath path;path.moveTo(QPointF((m_tCaliRectLst[i].m_RECT_BR_Pol[0].x()+m_tCaliRectLst[i].m_RECT_BR_Pol[1].x())/2,(m_tCaliRectLst[i].m_RECT_BR_Pol[0].y()+m_tCaliRectLst[i].m_RECT_BR_Pol[1].y())/2));path.lineTo(QPointF((m_tCaliRectLst[i].m_RECT_BR_Pol[2].x()+m_tCaliRectLst[i].m_RECT_BR_Pol[3].x())/2,(m_tCaliRectLst[i].m_RECT_BR_Pol[2].y()+m_tCaliRectLst[i].m_RECT_BR_Pol[3].y())/2));path.moveTo(QPointF((m_tCaliRectLst[i].m_RECT_BR_Pol[0].x()+m_tCaliRectLst[i].m_RECT_BR_Pol[3].x())/2,(m_tCaliRectLst[i].m_RECT_BR_Pol[0].y()+m_tCaliRectLst[i].m_RECT_BR_Pol[3].y())/2));path.lineTo(QPointF((m_tCaliRectLst[i].m_RECT_BR_Pol[2].x()+m_tCaliRectLst[i].m_RECT_BR_Pol[1].x())/2,(m_tCaliRectLst[i].m_RECT_BR_Pol[2].y()+m_tCaliRectLst[i].m_RECT_BR_Pol[1].y())/2));painter->setPen(QPen(Qt::yellow,2));painter->drawPath(path);//绘制扫描方向标记painter->setPen(QPen(Qt::yellow,1));painter->drawPolygon(m_tCaliRectLst[i].m_RECT_Scan_Dir_Pol);}}//painter->drawEllipse(QRectF(m_CircleCenter.x()-m_radius,m_CircleCenter.y()-m_radius,m_radius*2,m_radius*2));painter->setPen(QPen(Qt::red,4));painter->drawPoint(m_CircleP1);painter->drawPoint(m_CircleP2);painter->drawPoint(m_CircleP3);qreal angle1 = atan2(m_CircleP1.x()-m_CircleCenter.x(),m_CircleP1.y()-m_CircleCenter.y())*180/M_PI-90;//qDebug()<<"angle1:"<<angle1<<endl;if(angle1<0)angle1 = 360+angle1;if(angle1>360)angle1 = angle1-360;qreal angle3 = atan2(m_CircleP3.x()-m_CircleCenter.x(),m_CircleP3.y()-m_CircleCenter.y())*180/M_PI-90;//qDebug()<<"angle3:"<<angle3<<endl;if(angle3<0)angle3 = 360+angle3;if(angle3>360)angle3 = angle3-360;qreal angle0 = angle3-angle1;if(angle0<0)angle0 = 360+angle0;if(angle0>360)angle0 = angle0-360;painter->setPen(QPen(Qt::yellow,1));qreal s= (m_CircleP1.x() - m_CircleP3.x()) * (m_CircleP2.y() - m_CircleP3.y()) - (m_CircleP2.x() - m_CircleP3.x())*(m_CircleP1.y() - m_CircleP3.y());//向量p3p1和p3p2的叉积if(s>0)//叉积方向决定了弧形是内弧还是外弧{painter->drawArc(m_CircleRect,(int)angle3*16,(int)(360-angle0)*16);}else{painter->drawArc(m_CircleRect,(int)angle1*16,(int)angle0*16);}//qDebug()<<"angle1:"<<angle1<<"angle3:"<<angle3<<"angle0:"<<angle0<<"s:"<<s;//绘制补全圆使用的双向箭头QPainterPath path = getFillCircleArrow(m_CircleP1,m_CircleCenter,m_radius,10);painter->setPen(QPen(Qt::green,1));painter->drawPath(path);path = getFillCircleArrow(m_CircleP3,m_CircleCenter,m_radius,10);painter->drawPath(path);}
}double mygraphicCaliperitem::CalDis(const double x1, const double y1, const double x2, const double y2)
{return sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
}double mygraphicCaliperitem::CalDis(const double ptx, const double pty, const double x1, const double y1, const double x2, const double y2)
{double f = (x2-x1)*(ptx-x1) + (y2-y1)*(pty-y1);if (f<=0)return CalDis(ptx, pty, x1, y1);double d = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1);if (f>d)return CalDis(ptx, pty, x2, y2);f = f/d;double projX = (x1 + (x2 - x1)*f);double projY = (y1 + (y2 - y1)*f);return CalDis(ptx, pty, projX, projY);
}double mygraphicCaliperitem::CalDisPoint2longLine(const double ptx, const double pty, const double x1, const double y1, const double x2, const double y2)
{//    double f = (x2-x1)*(ptx-x1) + (y2-y1)*(pty-y1);
    if (f<=0)
        return CalDis(ptx, pty, x1, y1);
//    double d = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1);
    if (f>d)
        return CalDis(ptx, pty, x2, y2);
//    f = f/d;
//    double projX = (x1 + (x2 - x1)*f);
//    double projY = (y1 + (y2 - y1)*f);
//    return CalDis(ptx, pty, projX, projY);//求点(ptx,pty)到直线(x1,y1)(x2,y2)的距离//直线(x1,y1)(x2,y2)的方程为y=kx+b;//过点(ptx,pty)的直线(x1,y1)(x2,y2)的中垂线方程为y=k2x+b2;两线交点为pCross(x0,y0)qreal k,b,k2,b2,x0,y0;if(x1==x2){//直线方程为:x=x1if(y1==y2){//垂线方程为:x=ptx//该情况异常,返回-1return -1;}else{k2 = (x2-x1)/(y1-y2);b2 = pty-k2*ptx;x0=x1;y0 = k2*x0+b2;}}else{k = (y1-y2)/(x1-x2);b = y1-k*x1;if(y1==y2){//垂线方程为:x=ptxx0=ptx;y0=k*x0+b;}else{k2 = (x2-x1)/(y1-y2);b2 = pty-k2*ptx;if(k==k2)return -1;else{x0=(b-b2)/(k2-k);y0=k*x0+b;}}}return CalDis(x0,y0,ptx,pty);
}bool mygraphicCaliperitem::get2CrossPt(QPointF p0, QPointF p1, QPointF p2, QPointF pc, QPointF pos, QPointF &pCross1, QPointF &pCross2)
{qreal k1,k2,b1,b2;//假设经过pc的平行于p0p1的直线方程为:y=k1*x+b1;if(p1.x()!=p0.x()){k1 = (p1.y()-p0.y())/(p1.x()-p0.x());b1 = pc.y()-k1*pc.x();}//假设经过pos的平行于p1p2的直线方程为:y=k2*x+b2;if(p1.x()!=p2.x()){k2 = (p2.y()-p1.y())/(p2.x()-p1.x());b2 = pos.y()-k2*pos.x();}//假设两线交点为(x,y)qreal x,y;if(p1.x()==p0.x()){//则k1不存在,直线1为x=pc.x()if(p1.x()==p2.x()){//k2不存在,直线2为x=pos.x()//则两线焦点不存在,直接returnreturn false;}else{x=pc.x();y = k2*x+b2;}}else{if(p1.x()==p2.x()){//k2不存在,直线2为x=pos.x()x = pos.x();y = k1*x+b1;}else{if(k1==k2)return false;x=(b1-b2)/(k2-k1);y = k1*x+b1;}}pCross1=QPointF(x,y);//经过pc的平行于p0p1的直线 与 经过Pos的平行于p1p2的直线 的焦点//假设经过pos的平行于p0p1的直线方程为:y=k3*x+b3;//假设两线交点为(x2,y2)qreal k3,k4,b3,b4,x2,y2;if(p1.x()!=p0.x()){k3 = (p1.y()-p0.y())/(p1.x()-p0.x());b3 = pos.y()-k3*pos.x();}//假设经过pc的平行于p1p2的直线方程为:y=k4*x+b4;if(p1.x()!=p2.x()){k4 = (p2.y()-p1.y())/(p2.x()-p1.x());b4 = pc.y()-k4*pc.x();}if(p1.x()==p0.x()){//则k3不存在,直线1为x=pos.x()if(p1.x()==p2.x()){//k4不存在,直线2为x=pc.x()//则两线焦点不存在,直接returnreturn false;}else{x2=pos.x();y2 = k4*x2+b4;}}else{if(p1.x()==p2.x()){//k4不存在,直线2为x=pc.x()x2=pc.x();y2 = k3*x2+b3;}else{if(k3==k4)return false;x2=(b3-b4)/(k4-k3);y2 = k3*x2+b3;}}pCross2=QPointF(x2,y2);//经过pc的平行于p0p1的直线 与 经过Pos的平行于p1p2的直线 的焦点return true;
}void mygraphicCaliperitem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{if(event->button()== Qt::LeftButton){//setSelected(true);m_startPos = event->pos();//鼠标左击时,获取当前鼠标在图片中的坐标,if(m_ShapeType == CALIPER_RECT)//矩形卡尺{if(m_tCaliRect.m_RECT_Rotate_Pol.containsPoint(m_startPos,Qt::WindingFill))//旋转矩形{m_StateFlag = CALIPER_STATE_FLAG::CALI_RECT_ROTATE;setCursor(Qt::PointingHandCursor);}else if(m_tCaliRect.m_RECT_BR_Pol.containsPoint(m_startPos,Qt::WindingFill)){m_StateFlag = CALI_RECT_BR;//标记当前为用户按下矩形的右下角顶点矩形区域setCursor(Qt::SizeAllCursor);}else if(m_tCaliRect.m_RECT_Shear_Pol.containsPoint(m_startPos,Qt::WindingFill))//在矩形内框区域时按下鼠标,则可拖动图片{m_StateFlag = CALIPER_STATE_FLAG::CALI_RECT_SHEAR;//标记当前为鼠标拖动图片移动状态setCursor(Qt::PointingHandCursor);   //改变光标形状,手指的形状}else if(m_tCaliRect.m_RECT_Inside_Pol.containsPoint(m_startPos,Qt::WindingFill))//在矩形内框区域时按下鼠标,则可拖动图片{m_StateFlag = CALIPER_STATE_FLAG::CALI_RECT_MOVE;//标记当前为鼠标拖动图片移动状态setCursor(Qt::ClosedHandCursor);   //改变光标形状,手的形状}else{m_StateFlag = CALI_DEFAULT;}}else if(m_ShapeType == CALIPER_LINE)//直线{int nCount = m_tCaliRectLst.count();for(int i=0;i<nCount;i++){if((nCount+1)/2-1==i)//让中间那个矩形控制所有矩形的变换{if(m_tCaliRectLst[i].m_RECT_Rotate_Pol.containsPoint(m_startPos,Qt::WindingFill))//旋转矩形{m_StateFlag = CALIPER_STATE_FLAG::CALI_RECT_ROTATE;setCursor(Qt::PointingHandCursor);return;}else if(m_tCaliRectLst[i].m_RECT_BR_Pol.containsPoint(m_startPos,Qt::WindingFill)){m_StateFlag = CALI_RECT_BR;//标记当前为用户按下矩形的右下角顶点矩形区域setCursor(Qt::SizeAllCursor);return;}else if(m_tCaliRectLst[i].m_RECT_Shear_Pol.containsPoint(m_startPos,Qt::WindingFill))//在矩形内框区域时按下鼠标,则可拖动图片{m_StateFlag = CALIPER_STATE_FLAG::CALI_RECT_SHEAR;//标记当前为切变状态setCursor(Qt::PointingHandCursor);   //改变光标形状,手指的形状return;}
//                    else if(m_tCaliRectLst[i].m_RECT_Inside_Pol.containsPoint(m_startPos,Qt::WindingFill))//在矩形内框区域时按下鼠标,则可拖动图片
//                    {//                        m_StateFlag = CALIPER_STATE_FLAG::CALI_RECT_MOVE;//标记当前为鼠标拖动图片移动状态
//                        setCursor(Qt::ClosedHandCursor);   //改变光标形状,手的形状
//                        return;
//                    }}}if(m_LineBodyPol.containsPoint(m_startPos,Qt::WindingFill))//拖动直线{m_StateFlag = CALI_LINE_MOVE;//标记当前为直线卡尺的拖动setCursor(Qt::ClosedHandCursor);   //改变光标形状,手的形状}else if(m_LineP1Pol.containsPoint(m_startPos,Qt::WindingFill))//移动直线顶点1{m_StateFlag =CALI_LINE_PT1_MOVE;setCursor(Qt::SizeAllCursor);//变换鼠标形状}else if(m_LineP2Pol.containsPoint(m_startPos,Qt::WindingFill))//移动直线顶点1{m_StateFlag =CALI_LINE_PT2_MOVE;setCursor(Qt::SizeAllCursor);//变换鼠标形状}}else if(m_ShapeType == CALIPER_CIRCLE){QPolygonF CirclePoly = QPolygonF(m_CircleRect);QPolygonF FillCircleP1Poly = QPolygonF(m_FillCircleP1Rect);QPolygonF FillCircleP3Poly = QPolygonF(m_FillCircleP3Rect);int nCount = m_tCaliRectLst.count();for(int i=0;i<nCount;i++){if((nCount+1)/2-1==i)//让中间那个矩形控制所有矩形的变换{if(m_tCaliRectLst[i].m_RECT_BR_Pol.containsPoint(m_startPos,Qt::WindingFill)){m_StateFlag = CALI_RECT_BR;//标记当前为用户按下矩形的右下角顶点矩形区域setCursor(Qt::SizeAllCursor);return;}}}if(m_CircleP1Pol.containsPoint(m_startPos,Qt::WindingFill)){m_StateFlag = CALI_CIRCLE_PT1_MOVE;setCursor(Qt::SizeAllCursor);//变换鼠标形状return;}else if(m_CircleP2Pol.containsPoint(m_startPos,Qt::WindingFill)){m_StateFlag = CALI_CIRCLE_PT2_MOVE;setCursor(Qt::SizeAllCursor);//变换鼠标形状return;}else if(m_CircleP3Pol.containsPoint(m_startPos,Qt::WindingFill)){m_StateFlag = CALI_CIRCLE_PT3_MOVE;setCursor(Qt::SizeAllCursor);//变换鼠标形状return;}else if(FillCircleP1Poly.containsPoint(m_startPos,Qt::WindingFill)){m_StateFlag = CALI_CIRCLE_FillP1;setCursor(Qt::PointingHandCursor);//变成手指形状return;}else if(FillCircleP3Poly.containsPoint(m_startPos,Qt::WindingFill)){m_StateFlag = CALI_CIRCLE_FillP3;setCursor(Qt::PointingHandCursor);//变成手指形状return;}else if(CirclePoly.containsPoint(m_startPos,Qt::WindingFill)){m_StateFlag = CALI_CIRCLE_MOVE;setCursor(Qt::ClosedHandCursor);//变换鼠标形状return;}for(int i=0;i<nCount;i++){if(m_tCaliRectLst[i].m_RECT_Inside_Pol.containsPoint(m_startPos,Qt::WindingFill)){m_StateFlag = CALI_CIRCLE_MOVE;//移动圆形卡尺setCursor(Qt::ClosedHandCursor);return;}}}}else if(event->button()== Qt::RightButton){m_startPos = event->pos();//pMenu->exec(event->screenPos());//弹出菜单}else{QGraphicsItem::mousePressEvent(event);}
}void mygraphicCaliperitem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{prepareGeometryChange();if(m_ShapeType == CALIPER_RECT)//矩形{if(m_StateFlag == CALI_RECT_ROTATE){qreal nRotateAngle = atan2((event->pos().x()-m_tCaliRect.m_RotateCenter.x()),(event->pos().y()-m_tCaliRect.m_RotateCenter.y()))*180/M_PI;SetRotate(90-nRotateAngle);//qDebug()<<nRotateAngle;}else if(m_StateFlag == CALI_RECT_MOVE){QPointF point = (event->pos() - m_startPos);moveBy(point.x(), point.y());scene()->update();}else if(m_StateFlag == CALI_RECT_SHEAR)//控制矩形斜切{QPointF pc,p0,p1,p2,p3;//,pCross1,pCross2;pc = m_tCaliRect.m_RotateCenter;p0 = m_tCaliRect.m_RECT_Pol[0];p1 = m_tCaliRect.m_RECT_Pol[1];p2 = m_tCaliRect.m_RECT_Pol[2];p3 = m_tCaliRect.m_RECT_Pol[3];if(!get2CrossPt(p0,p1,p2,pc,event->pos(),pCross1,pCross2))return;//过pc做p2p3的垂线line3,line3方程为y=k3x+b3,line3与p2,p3交点为pCross3qreal k3,b3,k4,b4;qreal x3,y3;//pCross3(x3,y3),//y3=k3x3+b3,y3=k4x3+b4,求x3,y3if(p3.y()==p2.y()){//k3不存在,lin3为x=pc.x()//直线p2p3为y=k4x+b4if(p3.x()==p2.x()){//k4不存在,直线p2p3为x=p2.x()return;}else{k4=(p3.y()-p2.y())/(p3.x()-p2.x());b4 = p2.y()-k4*p2.x();//TODO:求(x3,y3)x3 = pc.x();y3 = k4*x3+b4;}}else{k3 = (p2.x()-p3.x())/(p3.y()-p2.y());b3=pc.y()-k3*pc.x();//直线p2p3为y=k4x+b4if(p3.x()==p2.x()){//k4不存在,直线p2p3为x=p2.x()//TODO:求(x3,y3)x3 = p2.x();y3 = k3*x3+b3;}else{k4=(p3.y()-p2.y())/(p3.x()-p2.x());b4 = p2.y()-k4*p2.x();//TODO:求(x3,y3)if(k3!=k4){x3 = (b4-b3)/(k3-k4);y3 = k3*x3+b3;}}}pCross3= QPointF(x3,y3);//过pos做p2p3的垂线line5,line5方程为y=k5x+b5,line5与p2,p3交点为pCross5qreal k5,b5;qreal x5,y5;//pCross5(x5,y5),//y5=k5x5+b5,y5=k4x5+b4,求x5,y5if(p3.y()==p2.y()){//k3不存在,lin5为x=event->pos().x()//直线p2p3为y=k4x+b4if(p3.x()==p2.x()){//k4不存在,直线p2p3为x=p2.x()return;}else{k4=(p3.y()-p2.y())/(p3.x()-p2.x());b4 = p2.y()-k4*p2.x();//TODO:求(x5,y5)x5 = event->pos().x();y5 = k4*x5+b4;}}else{k5 = (p2.x()-p3.x())/(p3.y()-p2.y());b5=event->pos().y()-k5*event->pos().x();//直线p2p3为y=k4x+b4if(p3.x()==p2.x()){//k4不存在,直线p2p3为x=p2.x()//TODO:求(x5,y5)x5 = p2.x();y5 = k5*x5+b5;}else{k4=(p3.y()-p2.y())/(p3.x()-p2.x());b4 = p2.y()-k4*p2.x();//TODO:求(x5,y5)if(k5!=k4){x5 = (b4-b5)/(k5-k4);y5 = k5*x5+b5;}}}pCross5= QPointF(x5,y5);//求pos到垂线line3的距离为disSheardouble disShear = CalDisPoint2longLine(event->pos().x(),event->pos().y(),pc.x(),pc.y(),pCross3.x(),pCross3.y());double newHalfHeight;if(m_tCaliRect.m_bKeepShadowLength){if(disShear>m_tCaliRect.m_RECT.height()/2-1)disShear = m_tCaliRect.m_RECT.height()/2-1;newHalfHeight = sqrt(qPow(m_tCaliRect.m_RECT.height()/2,2)-disShear*disShear);m_tCaliRect.m_fShearX = disShear/newHalfHeight;}else{m_tCaliRect.m_fShearX = disShear/(m_tCaliRect.m_RECT.height()/2);}//确定往左斜切还是往右斜切if(((-90<m_tCaliRect.m_RotateAngle)&&(m_tCaliRect.m_RotateAngle<90))||(m_tCaliRect.m_RotateAngle>270 &&m_tCaliRect.m_RotateAngle<360)||m_tCaliRect.m_RotateAngle==360){if(pCross5.x()<pCross3.x())m_tCaliRect.m_fShearX = -m_tCaliRect.m_fShearX;}else if(m_tCaliRect.m_RotateAngle == 90){if(pCross5.y()<pCross3.y())m_tCaliRect.m_fShearX = -m_tCaliRect.m_fShearX;}else if(m_tCaliRect.m_RotateAngle>90&&m_tCaliRect.m_RotateAngle<270){if(pCross5.x()>pCross3.x())m_tCaliRect.m_fShearX = -m_tCaliRect.m_fShearX;}else if(m_tCaliRect.m_RotateAngle==270 ||m_tCaliRect.m_RotateAngle == -90){if(pCross5.y()>pCross3.y())m_tCaliRect.m_fShearX = -m_tCaliRect.m_fShearX;}if(m_tCaliRect.m_bKeepShadowLength){setShearRectSize(QRectF(pc.x()-m_tCaliRect.m_RECT.width()/2,pc.y()-newHalfHeight,m_tCaliRect.m_newShearRECT.width(),newHalfHeight*2));//这个函数不会重置原始矩形的大小}else{setRectSize(m_tCaliRect.m_RECT);}scene()->update();}else if(m_StateFlag == CALI_RECT_BR)//右下角顶点{QPointF pc,p0,p1,p2,p3;//,pCross1,pCross2;pc = m_tCaliRect.m_RotateCenter;p0 = m_tCaliRect.m_RECT_Pol[0];p1 = m_tCaliRect.m_RECT_Pol[1];p2 = m_tCaliRect.m_RECT_Pol[2];p3 = m_tCaliRect.m_RECT_Pol[3];if(!get2CrossPt(p0,p1,p2,pc,event->pos(),pCross1,pCross2))return;
//            //该段代码可禁止矩形被反向拉伸!!!
//            double disVertical2RightLine = CalDisPoint2longLine(event->pos().x(),event->pos().y(),p1.x(),p1.y(),p2.x(),p2.y());
//            double disVertical2LeftLine = CalDisPoint2longLine(event->pos().x(),event->pos().y(),p0.x(),p0.y(),p3.x(),p3.y());
//            if(disVertical2RightLine>disVertical2LeftLine)
//                return;
//            double disVertical2BottomLine = CalDisPoint2longLine(event->pos().x(),event->pos().y(),p2.x(),p2.y(),p3.x(),p3.y());
//            double disVertical2TopLine = CalDisPoint2longLine(event->pos().x(),event->pos().y(),p0.x(),p0.y(),p1.x(),p1.y());
//            if(disVertical2BottomLine>disVertical2TopLine)
//                return;
//            //该段代码可禁止矩形被反向拉伸!!!if(m_tCaliRect.m_bKeepShadowLength && m_tCaliRect.m_fShearX!=0)//保证投影长度不变{double disp2pc = CalDis(m_tCaliRect.m_RECTShear[2].x(),m_tCaliRect.m_RECTShear[2].y(),pc.x(),pc.y());double dispospc = CalDis(event->pos().x(),event->pos().y(),pc.x(),pc.y());double newHeight = dispospc/disp2pc*m_tCaliRect.m_newShearRECT.height();double newWidth = dispospc/disp2pc*m_tCaliRect.m_newShearRECT.width();setShearRectSize(QRectF(pc.x()-newWidth/2,pc.y()-newHeight/2,newWidth,newHeight));double newHeightOld = dispospc/disp2pc*m_tCaliRect.m_RECT.height();double newWidthOld = dispospc/disp2pc*m_tCaliRect.m_RECT.width();m_tCaliRect.m_RECT = QRectF(pc.x()-newWidthOld/2,pc.y()-newHeightOld/2,newWidthOld,newHeightOld);}else//投影长度可变{//新矩形宽度一半:double dispcpCross1 = CalDis(pc.x(),pc.y(),pCross1.x(),pCross1.y());if(dispcpCross1<10)return;//矩形宽度不能小于20//新矩形高度一半:double disVertical = CalDisPoint2longLine(event->pos().x(),event->pos().y(),pc.x(),pc.y(),pCross1.x(),pCross1.y());if(disVertical<10)return;//矩形高度不能小于20setRectSize(QRectF(pc.x()-dispcpCross1,pc.y()-disVertical,dispcpCross1*2,disVertical*2));}scene()->update();}}else if(m_ShapeType == CALIPER_LINE)//直线{int nCount = m_tCaliRectLst.count();for(int i=0;i<nCount;i++){if((nCount+1)/2-1==i)//让中间那个矩形控制所有矩形的变换{if(m_StateFlag == CALI_RECT_BR)//右下角顶点{QPointF pc,p0,p1,p2,p3;//,pCross1,pCross2;pc = m_tCaliRectLst[i].m_RotateCenter;p0 = m_tCaliRectLst[i].m_RECT_Pol[0];p1 = m_tCaliRectLst[i].m_RECT_Pol[1];p2 = m_tCaliRectLst[i].m_RECT_Pol[2];p3 = m_tCaliRectLst[i].m_RECT_Pol[3];if(!get2CrossPt(p0,p1,p2,pc,event->pos(),pCross1,pCross2))return;if(m_tCaliRectLst[i].m_bKeepShadowLength && m_tCaliRectLst[i].m_fShearX!=0)//保证投影长度不变{double disp2pc = CalDis(m_tCaliRectLst[i].m_RECTShear[2].x(),m_tCaliRectLst[i].m_RECTShear[2].y(),pc.x(),pc.y());double dispospc = CalDis(event->pos().x(),event->pos().y(),pc.x(),pc.y());double newHeight = dispospc/disp2pc*m_tCaliRectLst[i].m_newShearRECT.height();double newWidth = dispospc/disp2pc*m_tCaliRectLst[i].m_newShearRECT.width();setLineCalip(m_CaliLine.p1(),m_CaliLine.p2(),m_nCalipNum,newWidth,newHeight,m_tCaliRectLst[i].m_RotateAngle-m_pt2pt1Angle,m_tCaliRectLst[i].m_fShearX,m_tCaliRectLst[i].m_bKeepShadowLength);//setShearRectSize(QRectF(pc.x()-newWidth/2,pc.y()-newHeight/2,newWidth,newHeight),m_tCaliRectLst[i]);double newHeightOld = dispospc/disp2pc*m_tCaliRectLst[i].m_RECT.height();double newWidthOld = dispospc/disp2pc*m_tCaliRectLst[i].m_RECT.width();for(int j=0;j<nCount;j++){m_tCaliRectLst[j].m_RECT = QRectF(m_tCaliRectLst[j].m_RECT.x()-newWidthOld/2,m_tCaliRectLst[j].m_RECT.y()-newHeightOld/2,newWidthOld,newHeightOld);}}else//投影长度可变{//新矩形宽度一半:double dispcpCross1 = CalDis(pc.x(),pc.y(),pCross1.x(),pCross1.y());if(dispcpCross1<5)return;//矩形宽度不能小于10//新矩形高度一半:double disVertical = CalDisPoint2longLine(event->pos().x(),event->pos().y(),pc.x(),pc.y(),pCross1.x(),pCross1.y());if(disVertical<5)return;//矩形高度不能小于10m_bsetRectSize = true;setLineCalip(m_CaliLine.p1(),m_CaliLine.p2(),m_nCalipNum,dispcpCross1*2,disVertical*2,m_tCaliRectLst[i].m_RotateAngle-m_pt2pt1Angle,m_tCaliRectLst[i].m_fShearX,m_tCaliRectLst[i].m_bKeepShadowLength);m_bsetRectSize = false;}scene()->update();return;}
#ifdef ROTATE_AND_SHEARelse if(m_StateFlag == CALI_RECT_ROTATE)//旋转{int nRotateAngle = atan2((event->pos().x()-m_tCaliRectLst[i].m_RotateCenter.x()),(event->pos().y()-m_tCaliRectLst[i].m_RotateCenter.y()))*180/M_PI;for(int j = 0;j<nCount;j++){SetRotate(90-nRotateAngle,m_tCaliRectLst[j]);}scene()->update();return;}else if(m_StateFlag == CALI_RECT_SHEAR)//切变{QPointF pc,p0,p1,p2,p3;//,pCross1,pCross2;pc = m_tCaliRectLst[i].m_RotateCenter;p0 = m_tCaliRectLst[i].m_RECT_Pol[0];p1 = m_tCaliRectLst[i].m_RECT_Pol[1];p2 = m_tCaliRectLst[i].m_RECT_Pol[2];p3 = m_tCaliRectLst[i].m_RECT_Pol[3];if(!get2CrossPt(p0,p1,p2,pc,event->pos(),pCross1,pCross2))return;//过pc做p2p3的垂线line3,line3方程为y=k3x+b3,line3与p2,p3交点为pCross3qreal k3,b3,k4,b4;qreal x3,y3;//pCross3(x3,y3),//y3=k3x3+b3,y3=k4x3+b4,求x3,y3if(p3.y()==p2.y()){//k3不存在,lin3为x=pc.x()//直线p2p3为y=k4x+b4if(p3.x()==p2.x()){//k4不存在,直线p2p3为x=p2.x()return;}else{k4=(p3.y()-p2.y())/(p3.x()-p2.x());b4 = p2.y()-k4*p2.x();//TODO:求(x3,y3)x3 = pc.x();y3 = k4*x3+b4;}}else{k3 = (p2.x()-p3.x())/(p3.y()-p2.y());b3=pc.y()-k3*pc.x();//直线p2p3为y=k4x+b4if(p3.x()==p2.x()){//k4不存在,直线p2p3为x=p2.x()//TODO:求(x3,y3)x3 = p2.x();y3 = k3*x3+b3;}else{k4=(p3.y()-p2.y())/(p3.x()-p2.x());b4 = p2.y()-k4*p2.x();//TODO:求(x3,y3)if(k3!=k4){x3 = (b4-b3)/(k3-k4);y3 = k3*x3+b3;}}}pCross3= QPointF(x3,y3);//过pos做p2p3的垂线line5,line5方程为y=k5x+b5,line5与p2,p3交点为pCross5qreal k5,b5;qreal x5,y5;//pCross5(x5,y5),//y5=k5x5+b5,y5=k4x5+b4,求x5,y5if(p3.y()==p2.y()){//k3不存在,lin5为x=event->pos().x()//直线p2p3为y=k4x+b4if(p3.x()==p2.x()){//k4不存在,直线p2p3为x=p2.x()return;}else{k4=(p3.y()-p2.y())/(p3.x()-p2.x());b4 = p2.y()-k4*p2.x();//TODO:求(x5,y5)x5 = event->pos().x();y5 = k4*x5+b4;}}else{k5 = (p2.x()-p3.x())/(p3.y()-p2.y());b5=event->pos().y()-k5*event->pos().x();//直线p2p3为y=k4x+b4if(p3.x()==p2.x()){//k4不存在,直线p2p3为x=p2.x()//TODO:求(x5,y5)x5 = p2.x();y5 = k5*x5+b5;}else{k4=(p3.y()-p2.y())/(p3.x()-p2.x());b4 = p2.y()-k4*p2.x();//TODO:求(x5,y5)if(k5!=k4){x5 = (b4-b5)/(k5-k4);y5 = k5*x5+b5;}}}pCross5= QPointF(x5,y5);//求pos到垂线line3的距离为disSheardouble disShear = CalDisPoint2longLine(event->pos().x(),event->pos().y(),pc.x(),pc.y(),pCross3.x(),pCross3.y());double newHalfHeight;if(m_tCaliRectLst[i].m_bKeepShadowLength){if(disShear>m_tCaliRectLst[i].m_RECT.height()/2-1)disShear = m_tCaliRectLst[i].m_RECT.height()/2-1;newHalfHeight = sqrt(qPow(m_tCaliRectLst[i].m_RECT.height()/2,2)-disShear*disShear);m_tCaliRectLst[i].m_fShearX = disShear/newHalfHeight;}else{m_tCaliRectLst[i].m_fShearX = disShear/(m_tCaliRectLst[i].m_RECT.height()/2);}//确定往左斜切还是往右斜切if(((-90<m_tCaliRectLst[i].m_RotateAngle)&&(m_tCaliRectLst[i].m_RotateAngle<90))||(m_tCaliRectLst[i].m_RotateAngle>270 &&m_tCaliRectLst[i].m_RotateAngle<360)||m_tCaliRectLst[i].m_RotateAngle==360){if(pCross5.x()<pCross3.x())m_tCaliRectLst[i].m_fShearX = -m_tCaliRectLst[i].m_fShearX;}else if(m_tCaliRectLst[i].m_RotateAngle == 90){if(pCross5.y()<pCross3.y())m_tCaliRectLst[i].m_fShearX = -m_tCaliRectLst[i].m_fShearX;}else if(m_tCaliRectLst[i].m_RotateAngle>90&&m_tCaliRectLst[i].m_RotateAngle<270){if(pCross5.x()>pCross3.x())m_tCaliRectLst[i].m_fShearX = -m_tCaliRectLst[i].m_fShearX;}else if(m_tCaliRectLst[i].m_RotateAngle==270 ||m_tCaliRectLst[i].m_RotateAngle == -90){if(pCross5.y()>pCross3.y())m_tCaliRectLst[i].m_fShearX = -m_tCaliRectLst[i].m_fShearX;}if(m_tCaliRectLst[i].m_bKeepShadowLength){setLineCalip(m_CaliLine.p1(),m_CaliLine.p2(),m_nCalipNum,m_tCaliRectLst[i].m_RECT.width(),newHalfHeight*2,m_tCaliRectLst[i].m_RotateAngle-m_pt2pt1Angle,m_tCaliRectLst[i].m_fShearX,m_tCaliRectLst[i].m_bKeepShadowLength);//setShearRectSize(QRectF(pc.x()-m_tCaliRectLst[i].m_RECT.width()/2,pc.y()-newHalfHeight,m_tCaliRect.m_newShearRECT.width(),newHalfHeight*2));//这个函数不会重置原始矩形的大小}else{setLineCalip(m_CaliLine.p1(),m_CaliLine.p2(),m_nCalipNum,m_tCaliRectLst[i].m_RECT.width(),m_tCaliRectLst[i].m_RECT.height(),m_tCaliRectLst[i].m_RotateAngle-m_pt2pt1Angle,m_tCaliRectLst[i].m_fShearX,m_tCaliRectLst[i].m_bKeepShadowLength);//setRectSize(m_tCaliRectLst[i].m_RECT,m_tCaliRectLst[i]);}scene()->update();}
#endif}}if(m_StateFlag == CALI_LINE_MOVE){QPointF point = (event->pos() - m_startPos);moveBy(point.x(), point.y());scene()->update();}else if(m_StateFlag == CALI_LINE_PT1_MOVE){m_CaliLine.setP1(event->pos());qreal rLenPt1Pt2 = sqrt(qPow((m_CaliLine.p1().x()-m_CaliLine.p2().x()),2)+qPow((m_CaliLine.p1().y()-m_CaliLine.p2().y()),2));if(rLenPt1Pt2<80)return;setLineCalip(m_CaliLine.p1(),m_CaliLine.p2(),m_nCalipNum,m_searchLength,m_shadowLength,m_tCaliRectLst[0].m_RotateAngle-m_pt2pt1Angle,m_tCaliRectLst[0].m_fShearX,m_tCaliRectLst[0].m_bKeepShadowLength);scene()->update();}else if(m_StateFlag == CALI_LINE_PT2_MOVE){m_CaliLine.setP2(event->pos());qreal rLenPt1Pt2 = sqrt(qPow((m_CaliLine.p1().x()-m_CaliLine.p2().x()),2)+qPow((m_CaliLine.p1().y()-m_CaliLine.p2().y()),2));if(rLenPt1Pt2<80)return;setLineCalip(m_CaliLine.p1(),m_CaliLine.p2(),m_nCalipNum,m_searchLength,m_shadowLength,m_tCaliRectLst[0].m_RotateAngle-m_pt2pt1Angle,m_tCaliRectLst[0].m_fShearX,m_tCaliRectLst[0].m_bKeepShadowLength);scene()->update();}}else if(m_ShapeType == CALIPER_CIRCLE)//圆形卡尺{int nCount = m_tCaliRectLst.count();for(int i=0;i<nCount;i++){if((nCount+1)/2-1==i)//让中间那个矩形控制所有矩形的变换{if(m_StateFlag == CALI_RECT_BR)//右下角顶点{QPointF pc,p0,p1,p2,p3;//,pCross1,pCross2;pc = m_tCaliRectLst[i].m_RotateCenter;p0 = m_tCaliRectLst[i].m_RECT_Pol[0];p1 = m_tCaliRectLst[i].m_RECT_Pol[1];p2 = m_tCaliRectLst[i].m_RECT_Pol[2];p3 = m_tCaliRectLst[i].m_RECT_Pol[3];if(!get2CrossPt(p0,p1,p2,pc,event->pos(),pCross1,pCross2))return;{//新矩形宽度一半:double dispcpCross1 = CalDis(pc.x(),pc.y(),pCross1.x(),pCross1.y());if(dispcpCross1<5)return;//矩形宽度不能小于10//新矩形高度一半:double disVertical = CalDisPoint2longLine(event->pos().x(),event->pos().y(),pc.x(),pc.y(),pCross1.x(),pCross1.y());if(disVertical<5)return;//矩形高度不能小于10setCircleCalip(m_CircleP1,m_CircleP2,m_CircleP3,m_nCalipNum,dispcpCross1*2,disVertical*2,m_nSearchDir);
//                        m_bsetRectSize = true;
//                        setLineCalip(m_CaliLine.p1(),m_CaliLine.p2(),m_nCalipNum,dispcpCross1*2,disVertical*2,m_tCaliRectLst[i].m_RotateAngle-m_pt2pt1Angle,m_tCaliRectLst[i].m_fShearX,m_tCaliRectLst[i].m_bKeepShadowLength);
//                        m_bsetRectSize = false;}scene()->update();return;}}}if(m_StateFlag == CALI_CIRCLE_PT1_MOVE){QPointF pt2;CalMidPosByMoveP1(m_CircleP1,m_CircleP2,m_CircleP3,event->pos(),pt2);//得到新的P2点m_CircleP2 = pt2;setCircleCalip(event->pos(),m_CircleP2,m_CircleP3,m_nCalipNum,m_searchLength,m_shadowLength,m_nSearchDir);scene()->update();}else if(m_StateFlag == CALI_CIRCLE_PT2_MOVE){QPointF pt2;CalMidPos(m_CircleP1,m_CircleP3,event->pos(),pt2);//得到新的P2点m_CircleP2 = pt2;setCircleCalip(m_CircleP1,m_CircleP2,m_CircleP3,m_nCalipNum,m_searchLength,m_shadowLength,m_nSearchDir);scene()->update();}else if(m_StateFlag == CALI_CIRCLE_PT3_MOVE){QPointF pt2;CalMidPosByMoveP3(m_CircleP1,m_CircleP2,m_CircleP3,event->pos(),pt2);//得到新的P2点m_CircleP2 = pt2;setCircleCalip(m_CircleP1,m_CircleP2,event->pos(),m_nCalipNum,m_searchLength,m_shadowLength,m_nSearchDir);scene()->update();}else if(m_StateFlag ==CALI_CIRCLE_FillP1){m_CircleP1= getCirclePtByMousePos(event->pos(),m_CircleCenter,m_radius);m_CircleP2 = getP2ByP1P3PCenter(m_CircleP1,m_CircleP3,m_CircleCenter);setCircleCalip(m_CircleP1,m_CircleP2,m_CircleP3,m_nCalipNum,m_searchLength,m_shadowLength,m_nSearchDir);scene()->update();}else if(m_StateFlag ==CALI_CIRCLE_FillP3){m_CircleP3= getCirclePtByMousePos(event->pos(),m_CircleCenter,m_radius);m_CircleP2 = getP2ByP1P3PCenter(m_CircleP1,m_CircleP3,m_CircleCenter);setCircleCalip(m_CircleP1,m_CircleP2,m_CircleP3,m_nCalipNum,m_searchLength,m_shadowLength,m_nSearchDir);scene()->update();}else if(m_StateFlag == CALI_CIRCLE_MOVE){QPointF point = (event->pos() - m_startPos);moveBy(point.x(), point.y());scene()->update();}}
}void mygraphicCaliperitem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{setCursor(Qt::ArrowCursor);m_StateFlag = CALI_DEFAULT;QGraphicsItem::mouseReleaseEvent(event);//setSelected(false);
}int mygraphicCaliperitem::type() const
{return UserType+1;//表示mygraphicCaliperitem
}void mygraphicCaliperitem::SetRotate(qreal RotateAngle)
{m_tCaliRect.m_RotateAngle = RotateAngle;if(m_tCaliRect.m_bKeepShadowLength && m_tCaliRect.m_newShearRECT.width() != 0){setShearRectSize(m_tCaliRect.m_newShearRECT);}else{setRectSize(m_tCaliRect.m_RECT);}if(this->scene()!=nullptr)this->scene()->update();
}void mygraphicCaliperitem::SetRotate(qreal RotateAngle, CALI_RECT &circleRect)
{circleRect.m_RotateAngle = RotateAngle;if(circleRect.m_bKeepShadowLength && circleRect.m_newShearRECT.width() != 0){setShearRectSize(circleRect.m_newShearRECT,circleRect);}else{setRectSize(circleRect.m_RECT,circleRect);}
}void mygraphicCaliperitem::SetSideCursorByRotateAngle(qreal RotateAngle)
{if((RotateAngle>45&&RotateAngle<135) ||(RotateAngle>225&&RotateAngle<315)){if(m_StateFlag==CALI_RECT_TR ||m_StateFlag==CALI_RECT_BL){setCursor(Qt::SizeFDiagCursor);}else if(m_StateFlag==CALI_RECT_TL ||m_StateFlag==CALI_RECT_BR){setCursor(Qt::SizeBDiagCursor);}}else{if(m_StateFlag==CALI_RECT_TR ||m_StateFlag==CALI_RECT_BL){setCursor(Qt::SizeBDiagCursor);}else if(m_StateFlag==CALI_RECT_TL ||m_StateFlag==CALI_RECT_BR){setCursor(Qt::SizeFDiagCursor);}}
}QPointF mygraphicCaliperitem::getRotatePoint(QPointF ptCenter, QPointF ptIn, qreal angle)
{double dx = ptCenter.x();double dy = ptCenter.y();double x = ptIn.x();double y = ptIn.y();double xx,yy;xx = (x-dx)*cos(angle*M_PI/180)-(y-dy)*sin(angle*M_PI/180)+dx;yy = (x-dx)*sin(angle*M_PI/180)+(y-dy)*cos(angle*M_PI/180)+dy;return QPointF(xx,yy);
}QList<QPointF> mygraphicCaliperitem::getRotatePoints(QPointF ptCenter, QList<QPointF> ptIns, qreal angle)
{QList<QPointF> lstPt;for(int i = 0;i<ptIns.count();i++){lstPt.append(getRotatePoint(ptCenter,ptIns.at(i),angle));}return lstPt;
}QPolygonF mygraphicCaliperitem::getRotatePolygonFromRect(QPointF ptCenter, QRectF rectIn, qreal angle)
{QVector<QPointF> vpt;QPointF pf = getRotatePoint(ptCenter,rectIn.topLeft(),angle);vpt.append(pf);pf = getRotatePoint(ptCenter,rectIn.topRight(),angle);vpt.append(pf);pf = getRotatePoint(ptCenter,rectIn.bottomRight(),angle);vpt.append(pf);pf = getRotatePoint(ptCenter,rectIn.bottomLeft(),angle);vpt.append(pf);pf = getRotatePoint(ptCenter,rectIn.topLeft(),angle);vpt.append(pf);return QPolygonF(vpt);
}QPolygonF mygraphicCaliperitem::getRotatePolygonFromPolygon(QPointF ptCenter, QPolygonF polyIn, qreal angle)
{QVector<QPointF> vpt;for(int i = 0;i<polyIn.count();i++){QPointF pf = getRotatePoint(ptCenter,polyIn[i],angle);vpt.append(pf);}return QPolygonF(vpt);
}QRectF mygraphicCaliperitem::getBoundedRectToSceen()
{return QRectF(m_tCaliRect.m_RECT_Pol.boundingRect().x()+pos().x(),m_tCaliRect.m_RECT_Pol.boundingRect().y()+pos().y(),m_tCaliRect.m_RECT_Pol.boundingRect().width(),m_tCaliRect.m_RECT_Pol.boundingRect().height());
}QPolygonF mygraphicCaliperitem::getCrtPolygonToScreen()
{QVector<QPointF> vpt;if(m_ShapeType == CALIPER_ELLIPSE){for(int i = 0;i<m_tCaliRect.m_RECT_Pol.length();i++){vpt.append(QPointF(m_tCaliRect.m_RECT_Pol[i].x()+pos().x(),m_tCaliRect.m_RECT_Pol[i].y()+pos().y()));}}return QPolygonF(vpt);
}
QRectF mygraphicCaliperitem::getSmallRotateRect(QPointF ptA,QPointF ptB)
{QPointF pt = getVeritacalLinePoint(ptA,ptB);return QRectF(pt.x()-10,pt.y()-10,20,20);
}bool mygraphicCaliperitem::getCenterFrom3Pt(QPointF p1, QPointF p2, QPointF p3, QPointF &pc)//过3点求圆心
{qreal x,y,k1,b1,k2,b2;//中心点为x,y//p1p2中垂线方程为:y=k1x+b1;p2p3中垂线方程为y=k2x+b2if(p2.y()==p1.y())//则p1p2中垂线方程为:x=(p1.X()+p2.X())/2{if(p2.y()==p3.y())return false;else{k2 = (p3.x()-p2.x())/(p2.y()-p3.y());//中垂线斜率b2 = (p3.y()+p2.y())/2-k2*(p3.x()+p2.x())/2;//TODO:x = (p1.x()+p2.x())/2;y = k2*x+b2;}}else{k1 = (p1.x()-p2.x())/(p2.y()-p1.y());//中垂线斜率b1 = (p1.y()+p2.y())/2-k1*(p1.x()+p2.x())/2;if(p2.y()==p3.y())//则p2p3中垂线方程为:x=(p2.X()+p3.X())/2{x=(p2.x()+p3.x())/2;y = k1*x+b1;}else{k2 = (p3.x()-p2.x())/(p2.y()-p3.y());//中垂线斜率b2 = (p3.y()+p2.y())/2-k2*(p3.x()+p2.x())/2;if(k2==k1)//两线斜率相同,则中垂线没有交点return false;x = (b2-b1)/(k1-k2);y = k1*x+b1;}}pc = QPointF(x,y);return true;
}QPointF mygraphicCaliperitem::getVeritacalLinePoint(QPointF ptA, QPointF ptB, qreal offset)
{QPointF ptCenter = QPointF((ptA.x()+ptB.x())/2,(ptA.y()+ptB.y())/2);//A,B点的中点C//中垂线方程式为 y=x*k + b;qreal x,y;//旋转图标矩形的中心if(abs(ptB.y()-ptA.y())<0.1){if(ptA.x()<ptB.x())//矩形左上角在上方{x = ptCenter.x();y = ptCenter.y()-offset;}else//矩形左上角在下方{x = ptCenter.x();y = ptCenter.y()+offset;}}else if(ptB.y()>ptA.y())//顺时针旋转0-180{qreal k = (ptA.x()-ptB.x())/(ptB.y()-ptA.y());//中垂线斜率qreal b = (ptA.y()+ptB.y())/2-k*(ptA.x()+ptB.x())/2;//求AB线中垂线上离AB中点offset个像素的点C的坐标x = offset*cos(atan(k))+ptCenter.x();y = k*x+b;}else if(ptB.y()<ptA.y())//顺时针旋转180-360{qreal k = (ptA.x()-ptB.x())/(ptB.y()-ptA.y());//中垂线斜率qreal b = (ptA.y()+ptB.y())/2-k*(ptA.x()+ptB.x())/2;//求AB线中垂线上离AB中点offset个像素的点C的坐标x = -offset*cos(atan(k))+ptCenter.x();y = k*x+b;}return QPointF(x,y);
}

用法参见我前面的博客

qt实现visionpro的直线和圆形卡尺工具控件相关推荐

  1. 使用GDI+实现圆形进度条控件的平滑效果

    DownLoad Src 传统的GDI绘制图形时的一个致命缺点是图像存在锯齿毛糙, 使用GDI+能绘制漂亮的渐变图像并有光滑图像的功能.利用GDI+对圆形进度条控件进行修改,效果如下:

  2. VC用MFC开发的圆形进度条控件

    DownLoad Src VC用MFC开发的圆形进度条控件 visualsan@yahoo.cn NUAA zss 在NBA2007游戏里,还有很多科幻电影里,经常可以看到圆形进度条.有的用来显示导弹 ...

  3. QT实现Qt Quick和three.js渲染和实现QML3D控件

    QT实现Qt Quick和three.js渲染和实现QML3D控件 项目简介 项目技术 项目展示 主要源码片段解析 获取完整项目源码传送门 项目简介 结合Qt Quick和three.js渲染. 演示 ...

  4. 【QT开发笔记-基础篇】| 第二章 常用控件 | 2.12 表格控件 QTableWidget

    本节对应的视频讲解:B_站_链_接 QTableWidget 是 Qt 中的表格控件,可以行列的形式来展示数据 1. 属性和方法 QTableWidget 有很多属性和方法,完整的可查看帮助文档. 在 ...

  5. qt设置圆形按钮_Qt开源作品25-电池电量控件

    一.前言 现在这个时代,智能手机不要太流行,满大街都是,甚至连爷爷奶奶级别的人都会用智能手机,本次要写的控件就是智能手机中的电池电量表示控件,采用纯painter绘制,其实也可以采用贴图,我估计大部分 ...

  6. qt 进度条_Qt开源作品12-硬盘容量控件

    一.前言 磁盘容量统计控件,说白了,就是用来统计本地盘符占用的容量,包括但不限于已用空间.剩余空间.总大小.已用百分比等,其中对应的百分比采用进度条显示,该进度条的前景色和背景色及文字颜色可以设置,在 ...

  7. QT信号与槽-启动系统程序以及相关控件介绍

    1.1 创建一个继承至QWidget的项目. 1.2 设计界面,分析界面采用的布局方式. 首先,每行控件采用水平布局方式,第三行为了使控件靠右,前面添加一个占位控件. 三行采用垂直平局: 选中控件,通 ...

  8. Qt图形界面编程入门(基本窗口及控件)

    基本窗口类QWidget QWidget是所有窗体部件的基类,例如对话框类,主窗体类,以及其他诸如按钮,编辑框,标签等等都是由QWidget派生得到,QWidget拥有的方法往往都可以在其他子类中使用 ...

  9. Qt解决资源文件中添加图片,对应控件不显示图片的问题

    //资源文件--为控件添加图标//:/new/prefix1/image/mr.jpgQPixmap pic; //定义一个图片对象pic.load(":/new/prefix1/a.jpg ...

最新文章

  1. linux 与 window 对比式理解与应用
  2. 国二c语言改错题答案,c语言国二考试编程题答案
  3. 启明云端分享|ESP32摄像头应用方案常遇到的问题
  4. linux怎么设置tomcat自动启动,linux添加tomcat服务并设置开机启动
  5. javascript 西瓜一期 01.什么是编程 什么是编程语言
  6. ireport怎么套打_方向盘套你选对了吗?老司机告诉你该这样做|酷斯特玩车
  7. 如何添加评论_如何运用运镜+转场让视频更酷炫
  8. JavaScript文档对象模型DOM节点操作之父节点和子节点(2)
  9. scp实现mac与linux服务器之间文件传输
  10. Unity编辑器控件的使用(—)
  11. 用VBA实现OUTLOOK接收新邮件后的自动转发
  12. IOS-播放器开发(1)-视频基本原理
  13. vs2017官方下载路径
  14. 计算机上安装了更新ie版本,电脑ie浏览器版本过低怎么升级方法
  15. 怎么做到对mac电脑的监控呢?
  16. am调制解调仿真matlab,AM调制与解调仿真matlab
  17. 2点直线方程 + 3点平面方程
  18. 2021-2025年中国电源管理IC(PMIC)行业市场供需与战略研究报告
  19. 高德地图基础使用教程(附demo)
  20. 一起学java!java环境搭建

热门文章

  1. 中兴路由器查看时间_中兴路由器简单命令
  2. TB6600最简单的驱动程序
  3. 桁架工业机器人编程_桁架机器人规划设计,工业软件开发
  4. 将GeoJson面域转换成PPT可编辑的多段线
  5. java数组元素序号,Java在数组中查找指定元素
  6. VR/AR迷失元宇宙“硝烟”
  7. 损失函数笔记(2)--对比损失
  8. 【Matlab】模拟退火+最低水平线解决物流上的二维装箱问题
  9. 最全的MySQL分库分表方案总结
  10. word滑动时出现花屏/黑线