From 2be911095541dcf673ba889b83410e99d2d56df2 Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Mon, 27 Feb 2017 11:59:08 +0200 Subject: [PATCH] Override method shape() to improve selection of grainline. --HG-- branch : feature --- src/libs/vwidgets/vgrainlineitem.cpp | 125 ++++++++++++++++++++------- src/libs/vwidgets/vgrainlineitem.h | 6 ++ 2 files changed, 102 insertions(+), 29 deletions(-) diff --git a/src/libs/vwidgets/vgrainlineitem.cpp b/src/libs/vwidgets/vgrainlineitem.cpp index 9190d5976..54574cdec 100644 --- a/src/libs/vwidgets/vgrainlineitem.cpp +++ b/src/libs/vwidgets/vgrainlineitem.cpp @@ -46,6 +46,7 @@ #define RESIZE_RECT_SIZE 10 #define ROTATE_CIRC_R 7 #define ACTIVE_Z 10 +#define LINE_PEN_WIDTH 3 //--------------------------------------------------------------------------------------------------------------------- /** @@ -81,6 +82,54 @@ VGrainlineItem::VGrainlineItem(QGraphicsItem* pParent) VGrainlineItem::~VGrainlineItem() {} +//--------------------------------------------------------------------------------------------------------------------- +QPainterPath VGrainlineItem::shape() const +{ + QPainterPath path; + + if (m_eMode == mNormal) + { + QPointF pt1; + QPointF pt2(pt1.x() + m_dLength * cos(m_dRotation), pt1.y() - m_dLength * sin(m_dRotation)); + + const QLineF mainLine = MainLine(); + QPainterPath linePath; + linePath.moveTo(mainLine.p1()); + linePath.lineTo(mainLine.p2()); + linePath.closeSubpath(); + + QPainterPathStroker stroker; + stroker.setWidth(LINE_PEN_WIDTH); + path.addPath((stroker.createStroke(linePath) + linePath).simplified()); + path.closeSubpath(); + + const qreal dArrLen = ARROW_LENGTH*GetScale(); + if (m_eArrowType != ArrowType::atRear) + { + // first arrow + QPainterPath polyPath; + polyPath.addPolygon(FirstArrow(dArrLen)); + path.addPath((stroker.createStroke(polyPath) + polyPath).simplified()); + path.closeSubpath(); + } + + if (m_eArrowType != ArrowType::atFront) + { + // second arrow + QPainterPath polyPath; + polyPath.addPolygon(SecondArrow(dArrLen)); + path.addPath((stroker.createStroke(polyPath) + polyPath).simplified()); + path.closeSubpath(); + } + } + else + { + path.addPolygon(m_polyBound); + } + + return path; +} + //--------------------------------------------------------------------------------------------------------------------- /** * @brief VGrainlineItem::paint paints the item content @@ -94,47 +143,26 @@ void VGrainlineItem::paint(QPainter* pP, const QStyleOptionGraphicsItem* pOption Q_UNUSED(pWidget) pP->save(); QColor clr = Qt::black; - pP->setPen(QPen(clr, 3)); - QPointF pt1(0, 0); - QPointF pt2; - - pt2.setX(pt1.x() + m_dLength * cos(m_dRotation)); - pt2.setY(pt1.y() - m_dLength * sin(m_dRotation)); + pP->setPen(QPen(clr, LINE_PEN_WIDTH, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); pP->setRenderHints(QPainter::Antialiasing); // line - pP->drawLine(pt1, pt2); + const QLineF mainLine = MainLine(); + pP->drawLine(mainLine.p1(), mainLine.p2()); pP->setBrush(clr); - QPolygonF poly; - QPointF ptA; m_dScale = GetScale(); qreal dArrLen = ARROW_LENGTH*m_dScale; if (m_eArrowType != ArrowType::atRear) { // first arrow - poly << pt1; - ptA.setX(pt1.x() + dArrLen*cos(m_dRotation + ARROW_ANGLE)); - ptA.setY(pt1.y() - dArrLen*sin(m_dRotation + ARROW_ANGLE)); - poly << ptA; - ptA.setX(pt1.x() + dArrLen*cos(m_dRotation - ARROW_ANGLE)); - ptA.setY(pt1.y() - dArrLen*sin(m_dRotation - ARROW_ANGLE)); - poly << ptA; - pP->drawPolygon(poly); + pP->drawPolygon(FirstArrow(dArrLen)); } if (m_eArrowType != ArrowType::atFront) { // second arrow - poly.clear(); - poly << pt2; - ptA.setX(pt2.x() + dArrLen*cos(M_PI + m_dRotation + ARROW_ANGLE)); - ptA.setY(pt2.y() - dArrLen*sin(M_PI + m_dRotation + ARROW_ANGLE)); - poly << ptA; - ptA.setX(pt2.x() + dArrLen*cos(M_PI + m_dRotation - ARROW_ANGLE)); - ptA.setY(pt2.y() - dArrLen*sin(M_PI + m_dRotation - ARROW_ANGLE)); - poly << ptA; - pP->drawPolygon(poly); + pP->drawPolygon(SecondArrow(dArrLen)); } if (m_eMode != mNormal) @@ -553,12 +581,51 @@ qreal VGrainlineItem::GetScale() const const QPoint p = pt - pt0; #if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) - const qreal dScale = qSqrt(QPoint::dotProduct(p, p)); + qreal dScale = qSqrt(QPoint::dotProduct(p, p)); #else - const qreal dScale = qSqrt(p.x() * p.x() + p.y() * p.y()); + qreal dScale = qSqrt(p.x() * p.x() + p.y() * p.y()); #endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) - return 100/dScale; + dScale = 100.0/dScale; + if (dScale < 1.0) + { + dScale = 1.0; + } + return dScale; } return 1.0; } + +//--------------------------------------------------------------------------------------------------------------------- +QLineF VGrainlineItem::MainLine() const +{ + QPointF pt1; + QPointF pt2(pt1.x() + m_dLength * cos(m_dRotation), pt1.y() - m_dLength * sin(m_dRotation)); + return QLineF(pt1, pt2); +} + +//--------------------------------------------------------------------------------------------------------------------- +QPolygonF VGrainlineItem::FirstArrow(qreal dArrLen) const +{ + const QPointF pt1 = MainLine().p1(); + QPolygonF poly; + poly << pt1; + poly << QPointF(pt1.x() + dArrLen*cos(m_dRotation + ARROW_ANGLE), + pt1.y() - dArrLen*sin(m_dRotation + ARROW_ANGLE)); + poly << QPointF(pt1.x() + dArrLen*cos(m_dRotation - ARROW_ANGLE), + pt1.y() - dArrLen*sin(m_dRotation - ARROW_ANGLE)); + return poly; +} + +//--------------------------------------------------------------------------------------------------------------------- +QPolygonF VGrainlineItem::SecondArrow(qreal dArrLen) const +{ + const QPointF pt2 = MainLine().p2(); + QPolygonF poly; + poly << pt2; + poly << QPointF(pt2.x() + dArrLen*cos(M_PI + m_dRotation + ARROW_ANGLE), + pt2.y() - dArrLen*sin(M_PI + m_dRotation + ARROW_ANGLE)); + poly << QPointF(pt2.x() + dArrLen*cos(M_PI + m_dRotation - ARROW_ANGLE), + pt2.y() - dArrLen*sin(M_PI + m_dRotation - ARROW_ANGLE)); + return poly; +} diff --git a/src/libs/vwidgets/vgrainlineitem.h b/src/libs/vwidgets/vgrainlineitem.h index bad83d687..cac4e1327 100644 --- a/src/libs/vwidgets/vgrainlineitem.h +++ b/src/libs/vwidgets/vgrainlineitem.h @@ -39,6 +39,8 @@ public: explicit VGrainlineItem(QGraphicsItem* pParent = nullptr); virtual ~VGrainlineItem(); + virtual QPainterPath shape() const Q_DECL_OVERRIDE; + virtual void paint(QPainter* pP, const QStyleOptionGraphicsItem* pOption, QWidget* pWidget) Q_DECL_OVERRIDE; void UpdateGeometry(const QPointF& ptPos, qreal dRotation, qreal dLength, ArrowType eAT); @@ -76,6 +78,10 @@ private: ArrowType m_eArrowType; qreal GetScale() const; + + QLineF MainLine() const; + QPolygonF FirstArrow(qreal dArrLen) const; + QPolygonF SecondArrow(qreal dArrLen) const; }; #endif // VGRAINLINEITEM_H