From ff7fc0146f6e3b74c8e606f9bbf170e651efb0aa Mon Sep 17 00:00:00 2001 From: wandererfan Date: Sat, 23 Nov 2024 10:06:52 -0500 Subject: [PATCH] [TD]allow weld symbol on rotated leader --- src/Mod/TechDraw/App/DrawLeaderLine.cpp | 40 ++++- src/Mod/TechDraw/App/DrawLeaderLine.h | 4 + src/Mod/TechDraw/Gui/QGILeaderLine.cpp | 62 +++++-- src/Mod/TechDraw/Gui/QGILeaderLine.h | 1 + src/Mod/TechDraw/Gui/QGITile.cpp | 166 ++++++++++-------- src/Mod/TechDraw/Gui/QGITile.h | 53 +++--- src/Mod/TechDraw/Gui/QGIWeldSymbol.cpp | 221 ++++++++++++++++-------- src/Mod/TechDraw/Gui/QGIWeldSymbol.h | 17 +- 8 files changed, 357 insertions(+), 207 deletions(-) diff --git a/src/Mod/TechDraw/App/DrawLeaderLine.cpp b/src/Mod/TechDraw/App/DrawLeaderLine.cpp index 99b8213825..fad7be8e3e 100644 --- a/src/Mod/TechDraw/App/DrawLeaderLine.cpp +++ b/src/Mod/TechDraw/App/DrawLeaderLine.cpp @@ -226,45 +226,71 @@ std::vector DrawLeaderLine::horizLastSegment(const std::vector DrawLeaderLine::getTransformedWayPoints() const +{ + auto doScale = Scalable.getValue(); + auto doRotate = RotatesWithParent.getValue(); + auto vPoints = getScaledAndRotatedPoints(doScale, doRotate); + if (AutoHorizontal.getValue()) { + vPoints = DrawLeaderLine::horizLastSegment(vPoints, getBaseView()->Rotation.getValue()); + } + + return vPoints; +} + //! returns the mid point of last segment. used by leader decorators like weld symbol. //! the returned point is unscaled and unrotated. Base::Vector3d DrawLeaderLine::getTileOrigin() const { - std::vector wp = WayPoints.getValues(); + std::vector wp = getTransformedWayPoints(); if (wp.size() > 1) { Base::Vector3d last = wp.rbegin()[0]; Base::Vector3d second = wp.rbegin()[1]; - return (last + second) / 2.0; + return (last + second) / 2; } - Base::Console().Warning("DLL::getTileOrigin - no waypoints\n"); return Base::Vector3d(); } //! returns start of last line segment Base::Vector3d DrawLeaderLine::getKinkPoint() const { - std::vector wp = WayPoints.getValues(); + std::vector wp = getTransformedWayPoints(); if (wp.size() > 1) { return wp.rbegin()[1]; // second point from end } - Base::Console().Warning("DLL::getKinkPoint - no waypoints\n"); return Base::Vector3d(); } //end of last line segment Base::Vector3d DrawLeaderLine::getTailPoint() const { - std::vector wp = WayPoints.getValues(); + std::vector wp = getTransformedWayPoints(); if (!wp.empty()) { return wp.rbegin()[0]; // Last } - Base::Console().Warning("DLL::getTailPoint - no waypoints\n"); return Base::Vector3d(); } +//! returns the (transformed) direction of the last segment of the leader line +Base::Vector3d DrawLeaderLine::lastSegmentDirection() const +{ + std::vector wp = getTransformedWayPoints(); + if (wp.empty()) { + return Base::Vector3d(1,0,0); + } + // this direction is in conventional coords? Y+ up? + // vertical segment will be small negative Y - large negative Y -> a positive Y but we want a negative Y + auto tailPoint = DU::invertY(wp.rbegin()[0]); + auto kinkPoint = DU::invertY(wp.rbegin()[1]); + auto direction = kinkPoint - tailPoint; // from kink to tail + direction = DU::invertY(direction); + direction.Normalize(); + return direction; +} //! create a new leader feature from parameters. Used by python method makeLeader. //! pagePoints are in mm from bottom left of page. diff --git a/src/Mod/TechDraw/App/DrawLeaderLine.h b/src/Mod/TechDraw/App/DrawLeaderLine.h index 427e07c759..0e1bb33258 100644 --- a/src/Mod/TechDraw/App/DrawLeaderLine.h +++ b/src/Mod/TechDraw/App/DrawLeaderLine.h @@ -89,6 +89,10 @@ public: void dumpWaypoints(const std::vector& points, const std::string& label); + std::vector getTransformedWayPoints() const; + + Base::Vector3d lastSegmentDirection() const; + private: diff --git a/src/Mod/TechDraw/Gui/QGILeaderLine.cpp b/src/Mod/TechDraw/Gui/QGILeaderLine.cpp index e7c4ce2fb5..0e87207234 100644 --- a/src/Mod/TechDraw/Gui/QGILeaderLine.cpp +++ b/src/Mod/TechDraw/Gui/QGILeaderLine.cpp @@ -258,8 +258,8 @@ void QGILeaderLine::onLineEditFinished(QPointF tipDisplace, std::vector std::vector pageDeltas; for (auto& pt : scenePoints) { QPointF distFromP0 = pt - scenePoints.front(); - // convert deltas to mm and conventional Y axis from scene coords - Base::Vector3d deltaInPageCoords = DGU::fromSceneCoords(DU::toVector3d(distFromP0)); + // convert deltas to mm + Base::Vector3d deltaInPageCoords = Rez::appX(DU::toVector3d(distFromP0)); pageDeltas.push_back(deltaInPageCoords); } pageDeltas.at(0) = Base::Vector3d(0.0, 0.0, 0.0); @@ -287,7 +287,14 @@ void QGILeaderLine::startPathEdit() m_editPath->setScale(scale); m_editPath->inEdit(true); m_editPath->show(); - m_editPath->startPathEdit(getWayPointsFromFeature()); + // m_editPath->startPathEdit(getWayPointsFromFeature()); + auto vPoints = featLeader->getTransformedWayPoints(); + std::vector qPoints; + qPoints.reserve(vPoints.size()); + for (auto& point : vPoints) { + qPoints.emplace_back(Rez::guiX(DU::toQPointF(point))); + } + m_editPath->startPathEdit(qPoints); } void QGILeaderLine::saveState() @@ -334,7 +341,6 @@ void QGILeaderLine::updateView(bool update) void QGILeaderLine::draw() { - // Base::Console().Message("QGILL::draw()- %s\n", getViewObject()->getNameInDocument()); if (m_blockDraw) { return; } @@ -370,22 +376,13 @@ void QGILeaderLine::draw() // set the leader's Qt position from feature's X,Y and scale. // the feature's x,y is unscaled, unrotated and conventional Y - // line style is standing in for line number here? - m_lineStyle = static_cast(vp->LineStyle.getValue()); - double baseScale = featLeader->getBaseScale(); - double xPos = Rez::guiX(featLeader->X.getValue()); - double yPos = Rez::guiX(featLeader->Y.getValue()); - Base::Vector3d vAttachPoint{xPos, yPos}; - vAttachPoint = vAttachPoint * baseScale; - double rotationRad = parent->Rotation.getValue() * M_PI / DegreesHalfCircle; - if (rotationRad != 0.0) { - vAttachPoint.RotateZ(rotationRad); - } - vAttachPoint = DU::invertY(vAttachPoint); - QPointF qPoint = DU::toQPointF(vAttachPoint); + QPointF qPoint = DU::toQPointF(getAttachPoint()); // ???? why does the attach point not need Rez applied? setPos(qPoint); + // line style is standing in for line number here? + m_lineStyle = static_cast(vp->LineStyle.getValue()); + m_line->setFillStyle(Qt::NoBrush); m_line->setStyle(m_lineStyle); m_line->setWidth(getLineWidth()); @@ -570,6 +567,33 @@ void QGILeaderLine::drawBorder() // QGIView::drawBorder(); //good for debugging } + +//! return the position of the tip of the leader's arrow +Base::Vector3d QGILeaderLine::getAttachPoint() +{ + TechDraw::DrawLeaderLine* featLeader = getLeaderFeature(); + if (!featLeader) { + return Base::Vector3d(0, 0, 0); + } + TechDraw::DrawView* parent = featLeader->getBaseView(); + + if (!parent) { + return Base::Vector3d(0, 0, 0); + } + + double baseScale = featLeader->getBaseScale(); + double xPos = Rez::guiX(featLeader->X.getValue()); + double yPos = Rez::guiX(featLeader->Y.getValue()); + Base::Vector3d vAttachPoint{xPos, yPos}; + vAttachPoint = vAttachPoint * baseScale; + double rotationRad = parent->Rotation.getValue() * M_PI / DegreesHalfCircle; + if (rotationRad != 0.0) { + vAttachPoint.RotateZ(rotationRad); + } + vAttachPoint = DU::invertY(vAttachPoint); + return vAttachPoint; +} + //****************************************************************************** @@ -624,8 +648,8 @@ void QGILeaderLine::paint(QPainter* painter, const QStyleOptionGraphicsItem* opt QStyleOptionGraphicsItem myOption(*option); myOption.state &= ~QStyle::State_Selected; - painter->setPen(Qt::blue); - painter->drawRect(boundingRect()); //good for debugging + // painter->setPen(Qt::blue); + // painter->drawRect(boundingRect()); //good for debugging QGIView::paint(painter, &myOption, widget); } diff --git a/src/Mod/TechDraw/Gui/QGILeaderLine.h b/src/Mod/TechDraw/Gui/QGILeaderLine.h index 916e3f76e6..7fd7e046df 100644 --- a/src/Mod/TechDraw/Gui/QGILeaderLine.h +++ b/src/Mod/TechDraw/Gui/QGILeaderLine.h @@ -99,6 +99,7 @@ public: void setLeaderFeature(TechDraw::DrawLeaderLine* feat); bool useOldCoords() const; + Base::Vector3d getAttachPoint(); public Q_SLOTS: diff --git a/src/Mod/TechDraw/Gui/QGITile.cpp b/src/Mod/TechDraw/Gui/QGITile.cpp index 4f150b8e41..d20db38396 100644 --- a/src/Mod/TechDraw/Gui/QGITile.cpp +++ b/src/Mod/TechDraw/Gui/QGITile.cpp @@ -32,6 +32,7 @@ #include #include +#include #include "QGITile.h" #include "PreferencesGui.h" @@ -41,6 +42,7 @@ using namespace TechDrawGui; using namespace TechDraw; +using DU = DrawUtil; QGITile::QGITile(TechDraw::DrawTileWeld* dtw) : m_textL(QString::fromUtf8(" ")), @@ -69,10 +71,7 @@ QGITile::QGITile(TechDraw::DrawTileWeld* dtw) : m_wide = getSymbolWidth(); m_high = getSymbolHeight(); -// m_high = prefFontSize(); - m_textL = QString(); - m_textR = QString(); - m_textC = QString(); + m_fontName = prefTextFont(); m_font = QFont(m_fontName); @@ -88,55 +87,19 @@ QGITile::QGITile(TechDraw::DrawTileWeld* dtw) : m_colCurrent = m_colNormal; } -QGITile::~QGITile() -{ - -} void QGITile::draw() { -// Base::Console().Message("QGIT::draw()\n"); - prepareGeometryChange(); m_wide = getSymbolWidth(); m_high = getSymbolHeight(); makeText(); makeSymbol(); - - double textWidthL = m_qgTextL->boundingRect().width(); - double textWidthR = m_qgTextR->boundingRect().width(); - double totalWidth = m_wide + textWidthL + textWidthR; - if (m_row == 0) { //arrowSide - double x = m_origin.x(); - double y = m_origin.y() - (m_high * 0.5); //inverted y!! - setPos(x, y); - } else if (m_row == -1) { //otherSide - if (getAltWeld()) { - if (isTailRight()) { - double x = m_origin.x() + (0.5 * totalWidth); //move to right 1/2 tile width - double y = m_origin.y() + (m_high * 0.5); //inverted y!! - setPos(x, y); - } else { - double x = m_origin.x() - (0.5 * totalWidth); //move to left 1/2 tile width - double y = m_origin.y() + (m_high * 0.5); //inverted y!! - setPos(x, y); - } - } else { - double x = m_origin.x(); - double y = m_origin.y() + (m_high * 0.5); //inverted y!! - setPos(x, y); - } - } else { - double x = m_origin.x() + m_col * totalWidth; - double y = m_origin.y() - (m_row * m_high) - (m_high * 0.5); //inverted y!! - setPos(x, y); - } } void QGITile::makeSymbol() { -// Base::Console().Message("QGIT::makeSymbol()\n"); // m_effect->setColor(m_colCurrent); // m_qgSvg->setGraphicsEffect(m_effect); @@ -155,12 +118,9 @@ void QGITile::makeSymbol() void QGITile::makeText() { -// Base::Console().Message("QGIT::makeText()\n"); prepareGeometryChange(); -// m_font.setPixelSize(prefFontSize()); double verticalFudge = 0.10; - //(0, 0) is 1/2 up symbol (above line symbol)! m_qgTextL->setFont(m_font); m_qgTextL->setPlainText(m_textL); m_qgTextL->setColor(m_colCurrent); @@ -193,7 +153,7 @@ void QGITile::makeText() charWidth = textWidth / m_textR.size(); hMargin = 1; if (!m_textR.isEmpty()) { - hMargin = (m_wide / 2.0) + (charWidth); + hMargin = (m_wide / 2) + (charWidth); } double textHeightR = m_qgTextR->boundingRect().height(); if (m_row < 0) { // below line @@ -216,7 +176,7 @@ void QGITile::makeText() } //read whole text file into std::string -std::string QGITile::getStringFromFile(std::string inSpec) +std::string QGITile::getStringFromFile(const std::string& inSpec) { Base::FileInfo fi(inSpec); Base::ifstream f(fi); @@ -237,41 +197,40 @@ void QGITile::setTileScale(double s) m_scale = s; } -void QGITile::setTileTextLeft(std::string s) +void QGITile::setTileTextLeft(const std::string& text) { - m_textL = QString::fromUtf8(s.c_str()); + m_textL = QString::fromUtf8(text.c_str()); } -void QGITile::setTileTextRight(std::string s) +void QGITile::setTileTextRight(const std::string& text) { - m_textR = QString::fromUtf8(s.c_str()); + m_textR = QString::fromUtf8(text.c_str()); } -void QGITile::setTileTextCenter(std::string s) +void QGITile::setTileTextCenter(const std::string& text) { - m_textC = QString::fromUtf8(s.c_str()); + m_textC = QString::fromUtf8(text.c_str()); } -void QGITile::setFont(QFont f, double fSizePx) +void QGITile::setFont(const QFont& font, double fSizePx) { -// Base::Console().Message("QGIT::setFont(%s, %.3f)\n", qPrintable(f.family()), fSizePx); - m_font = f; + m_font = font; m_font.setPixelSize(fSizePx); } -void QGITile::setFont(std::string fName, double fSizePx) + +void QGITile::setFont(const std::string &fName, double fSizePx) { QString qFName = QString::fromStdString(fName); - QFont f(qFName); - setFont(f, fSizePx); + QFont font(qFName); + setFont(font, fSizePx); } -void QGITile::setSymbolFile(std::string s) +void QGITile::setSymbolFile(const std::string &fileSpec) { -// Base::Console().Message("QGIT::setSymbolFile(%s)\n", s.c_str()); - if (!s.empty()) { - m_svgPath = QString::fromUtf8(s.c_str()); + if (!fileSpec.empty()) { + m_svgPath = QString::fromUtf8(fileSpec.c_str()); } } @@ -308,12 +267,12 @@ void QGITile::setPrettySel() { draw(); } -bool QGITile::isTailRight() +bool QGITile::isTailRight() const { return m_tailRight; } -bool QGITile::getAltWeld() +bool QGITile::getAltWeld() const { return m_altWeld; } @@ -327,24 +286,22 @@ QColor QGITile::getTileColor() const double QGITile::getSymbolWidth() const { - double w = Preferences::getPreferenceGroup("Dimensions")->GetFloat("SymbolSize", 64); + double symbolWidth = Preferences::getPreferenceGroup("Dimensions")->GetFloat("SymbolSize", 64); // symbols are only nominally 64x64. they actually have a "border" of 4 - 0.5*stroke(0.5) // so we'll say effectively 62x62? 60 x 60 -// double w = 64.0; - double fudge = 4.0; //allowance for tile border - w = w - fudge; - w = w * getSymbolFactor(); - return w; + constexpr double borderAllow = 4.0; //allowance for tile border + symbolWidth = symbolWidth - borderAllow; + symbolWidth = symbolWidth * getSymbolFactor(); + return symbolWidth; } double QGITile::getSymbolHeight() const { - double h = Preferences::getPreferenceGroup("Dimensions")->GetFloat("SymbolSize", 64); - double fudge = 4.0; - h = h - fudge; -// double h = 60.0; - h = h * getSymbolFactor(); - return h; + double height = Preferences::getPreferenceGroup("Dimensions")->GetFloat("SymbolSize", 64); + double borderAllow = 4.0; + height = height - borderAllow; + height = height * getSymbolFactor(); + return height; } //make symbols larger or smaller than standard @@ -355,7 +312,6 @@ double QGITile::getSymbolFactor() const double QGITile::prefFontSize() const { -// Base::Reference hGrp = Preferences::getPreferenceGroup("Dimensions"); return Preferences::dimFontSizeMM(); } @@ -369,3 +325,61 @@ QRectF QGITile::boundingRect() const return childrenBoundingRect(); } + +//! determine where to position the tile based on which fields are used. +QPointF QGITile::calcTilePosition() +{ + constexpr double OneHalf{0.5}; + auto xDir = m_leaderXDirection; // "right" + auto yDir = m_leaderYDirection; // "up" + Base::Vector3d stdX{1, 0, 0}; + auto dot = stdX.Dot(xDir); + if (dot < 0) { + // our leader points left, so yDir should be +Y, but we need -Y up + yDir = -yDir; + } + + double textWidthL = m_qgTextL->boundingRect().width(); + double textWidthR = m_qgTextR->boundingRect().width(); + double totalWidth = m_wide + textWidthL + textWidthR; + + if (m_row == 0) { //arrowSide + double offsetDistanceY = getSymbolHeight() * OneHalf; + auto vOffset = yDir * offsetDistanceY; + auto netPosition = m_origin + DU::toQPointF(vOffset); + return netPosition; + } + + if (m_row == -1) { //otherSide + if (getAltWeld()) { + if (isTailRight()) { + auto hOffset = DU::toQPointF(xDir * (OneHalf * totalWidth)); //move to right 1/2 tile width + auto vOffset = DU::toQPointF(yDir * (getSymbolHeight() * OneHalf)); // move down 1/2 tile height + auto netPosition = m_origin + hOffset - vOffset; + return netPosition; + } + auto hOffset = DU::toQPointF(xDir * (OneHalf * totalWidth)); + auto vOffset = DU::toQPointF(yDir * (OneHalf * getSymbolHeight())); + auto netPosition = m_origin - hOffset - vOffset; // left and down + return netPosition; + } + + auto vOffset = DU::toQPointF(yDir * (OneHalf * getSymbolHeight())); // down 1/2 tile height + auto netPosition = m_origin - vOffset; + return netPosition; + } + + auto hOffset = DU::toQPointF(xDir * (m_col * totalWidth)); + auto vOffset = DU::toQPointF(yDir * ((m_row * m_high) + (m_high * OneHalf))); + auto netPosition = m_origin + hOffset - vOffset; + + return netPosition; +} + +void QGITile::setLocalAxes(Base::Vector3d xdir, Base::Vector3d ydir) +{ + m_leaderXDirection = xdir; + m_leaderYDirection = ydir; +} + + diff --git a/src/Mod/TechDraw/Gui/QGITile.h b/src/Mod/TechDraw/Gui/QGITile.h index a9eb95d321..a9f349c531 100644 --- a/src/Mod/TechDraw/Gui/QGITile.h +++ b/src/Mod/TechDraw/Gui/QGITile.h @@ -47,45 +47,49 @@ class TechDrawGuiExport QGITile : public QGIDecoration { public: explicit QGITile(TechDraw::DrawTileWeld*); - ~QGITile() override; + ~QGITile() override = default; enum {Type = QGraphicsItem::UserType + 325}; - int type(void) const override { return Type;} + int type() const override { return Type;} QRectF boundingRect() const override; - void setTileTextLeft(std::string s); - void setTileTextRight(std::string s); - void setTileTextCenter(std::string s); - void setFont(QFont f, double fSizePx); - void setFont(std::string fName, double fSizePx); - void setSymbolFile(std::string s); - void setTilePosition(QPointF org, int r, int c); - void setTileScale(double s); - void setTailRight(bool b) { m_tailRight = b; } - void setAltWeld(bool b) { m_altWeld = b; } - bool isTailRight(); + void setTileTextLeft(const std::string& text); + void setTileTextRight(const std::string& text); + void setTileTextCenter(const std::string& text); + void setFont(const QFont& font, double fSizePx); + void setFont(const std::string& fName, double fSizePx); + void setSymbolFile(const std::string& fileSpec); + void setTilePosition(QPointF org, int row, int col); + void setTileScale(double scale); + void setTailRight(bool state) { m_tailRight = state; } + void setAltWeld(bool state) { m_altWeld = state; } + bool isTailRight() const; void draw() override; + void setLocalAxes(Base::Vector3d xdir, Base::Vector3d ydir); + QPointF mapPointToRotation(Base::Vector3d pointIn); + QPointF calcTilePosition(); + protected: - QColor getTileColor(void) const; + QColor getTileColor() const; void setPrettyNormal(); void setPrettyPre(); void setPrettySel(); - double getSymbolWidth(void) const; - double getSymbolHeight(void) const; - double getSymbolFactor(void) const; + double getSymbolWidth() const; + double getSymbolHeight() const; + double getSymbolFactor() const; QByteArray getSvgString(QString svgPath); - QString prefTextFont(void) const; - double prefFontSize(void) const; - void makeSymbol(void); - void makeText(void); + QString prefTextFont() const; + double prefFontSize() const; + void makeSymbol(); + void makeText(); - bool getAltWeld(void); + bool getAltWeld() const; bool isReadable(QString filePath); - std::string getStringFromFile(std::string inSpec); + std::string getStringFromFile(const std::string &inSpec); private: @@ -109,6 +113,9 @@ private: bool m_tailRight; bool m_altWeld; TechDraw::DrawTileWeld* m_tileFeat; + + Base::Vector3d m_leaderXDirection; + Base::Vector3d m_leaderYDirection; }; } diff --git a/src/Mod/TechDraw/Gui/QGIWeldSymbol.cpp b/src/Mod/TechDraw/Gui/QGIWeldSymbol.cpp index 929af6dd22..e20398e3d1 100644 --- a/src/Mod/TechDraw/Gui/QGIWeldSymbol.cpp +++ b/src/Mod/TechDraw/Gui/QGIWeldSymbol.cpp @@ -29,6 +29,7 @@ #endif #include +#include #include #include @@ -58,25 +59,23 @@ using DU = DrawUtil; QGIWeldSymbol::QGIWeldSymbol() : m_arrowFeat(nullptr), m_otherFeat(nullptr), - m_tailText(nullptr), - m_fieldFlag(nullptr), - m_allAround(nullptr), + m_tailText(new QGCustomText()), + m_fieldFlag(new QGIPrimPath()), + m_allAround(new QGIVertex(-1)), m_blockDraw(false) { - setFiltersChildEvents(true); //qt5 + setFiltersChildEvents(true); setFlag(QGraphicsItem::ItemIsMovable, false); setCacheMode(QGraphicsItem::NoCache); setZValue(ZVALUE::DIMENSION); - m_tailText = new QGCustomText(); m_tailText->setPlainText( QString::fromUtf8(" ")); addToGroup(m_tailText); m_tailText->hide(); m_tailText->setPos(0.0, 0.0); //avoid bRect issues - m_allAround = new QGIVertex(-1); addToGroup(m_allAround); m_allAround->setPos(0.0, 0.0); m_allAround->setAcceptHoverEvents(false); @@ -86,7 +85,6 @@ QGIWeldSymbol::QGIWeldSymbol() : m_allAround->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); m_allAround->setFlag(QGraphicsItem::ItemStacksBehindParent, true); - m_fieldFlag = new QGIPrimPath(); addToGroup(m_fieldFlag); m_fieldFlag->setPos(0.0, 0.0); m_fieldFlag->setAcceptHoverEvents(false); @@ -95,9 +93,10 @@ QGIWeldSymbol::QGIWeldSymbol() : m_fieldFlag->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, false); m_fieldFlag->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); m_fieldFlag->setFlag(QGraphicsItem::ItemStacksBehindParent, true); - m_fieldFlag->setFill(prefNormalColor(), Qt::SolidPattern); + m_fieldFlag->setFill(prefNormalColor(), Qt::SolidPattern); setNormalColor(prefNormalColor()); + setCurrentColor(getNormalColor()); setSettingColor(getNormalColor()); @@ -106,7 +105,6 @@ QGIWeldSymbol::QGIWeldSymbol() : QVariant QGIWeldSymbol::itemChange(GraphicsItemChange change, const QVariant &value) { -// Base::Console().Message("QGIWS::itemChange(%d)\n", change); if (change == ItemSelectedHasChanged && scene()) { if(isSelected()) { setPrettySel(); @@ -121,7 +119,6 @@ QVariant QGIWeldSymbol::itemChange(GraphicsItemChange change, const QVariant &va void QGIWeldSymbol::updateView(bool update) { -// Base::Console().Message("QGIWS::updateView()\n"); Q_UNUSED(update); TechDraw::DrawWeldSymbol *feature = getFeature(); @@ -139,7 +136,6 @@ void QGIWeldSymbol::updateView(bool update) void QGIWeldSymbol::draw() { -// Base::Console().Message("QGIWS::draw()- %s\n", getFeature()->getNameInDocument()); if (!isVisible()) { return; } @@ -164,18 +160,20 @@ void QGIWeldSymbol::draw() void QGIWeldSymbol::drawTile(TechDraw::DrawTileWeld* tileFeat) { -// Base::Console().Message("QGIWS::drawTile() - tileFeat: %X\n", tileFeat); if (!tileFeat) { Base::Console().Message("QGIWS::drawTile - tile is null\n"); return; } - const auto sym = getFeature(); - if (!sym) + const auto symbol = getFeature(); + if (!symbol) { return; - auto vp = dynamic_cast(getViewProvider(sym)); - if (!vp) + } + auto vp = dynamic_cast(getViewProvider(symbol)); + if (!vp) { return; + } + std::string fontName = vp->Font.getValue(); int fontSize = QGIView::exactFontSize(vp->Font.getValue(), vp->TileFontSize.getValue()); @@ -185,11 +183,10 @@ void QGIWeldSymbol::drawTile(TechDraw::DrawTileWeld* tileFeat) std::string tileTextL = tileFeat->LeftText.getValue(); std::string tileTextR = tileFeat->RightText.getValue(); std::string tileTextC = tileFeat->CenterText.getValue(); -// std::string symbolFile = tileFeat->SymbolFile.getValue(); - int row = tileFeat->TileRow.getValue(); - int col = tileFeat->TileColumn.getValue(); + int row = (int)tileFeat->TileRow.getValue(); + int col = (int)tileFeat->TileColumn.getValue(); - QGITile* tile = new QGITile(tileFeat); + auto tile = new QGITile(tileFeat); addToGroup(tile); QPointF org = getTileOrigin(); @@ -199,18 +196,32 @@ void QGIWeldSymbol::drawTile(TechDraw::DrawTileWeld* tileFeat) tile->setTileTextLeft(tileTextL); tile->setTileTextRight(tileTextR); tile->setTileTextCenter(tileTextC); -// tile->setSymbolFile(symbolFile); tile->setZValue(ZVALUE::DIMENSION); tile->setTileScale(featScale); tile->setTailRight(getFeature()->isTailRightSide()); tile->setAltWeld(getFeature()->AlternatingWeld.getValue()); + auto localAxes = getLocalAxes(); + tile->setLocalAxes(localAxes.first, localAxes.second); + auto tilePos = tile->calcTilePosition(); // this is not the center! pos is left and up from center + + auto rotationDeg = getLastSegAngle(); + Base::Vector3d stdX{1, 0, 0}; + auto xdir = localAxes.first; + auto dot = stdX.Dot(xdir); + constexpr double DegreesHalfCircle{180.0}; + if (dot < 0) { + rotationDeg -= DegreesHalfCircle; + } + tile->setRotation(rotationDeg); // Qt angles are clockwise + tile->draw(); + tile->setPos(tilePos); + } void QGIWeldSymbol::drawAllAround() { -// Base::Console().Message("QGIWS::drawAllAround()\n"); QPointF allAroundPos = getKinkPoint(); m_allAround->setPos(allAroundPos); @@ -225,7 +236,6 @@ void QGIWeldSymbol::drawAllAround() m_allAround->setNormalColor(getCurrentColor()); m_allAround->setFill(Qt::NoBrush); -// m_allAround->setRadius(calculateFontPixelSize(getDimFontSize())); m_allAround->setRadius(PreferencesGui::dimFontSizePX()); auto qgiLead = dynamic_cast(getQGIVByName(getLeader()->getNameInDocument())); @@ -237,26 +247,32 @@ void QGIWeldSymbol::drawAllAround() void QGIWeldSymbol::drawTailText() { -// Base::Console().Message("QGIWS::drawTailText()\n"); + constexpr double DegreesHalfCircle{180.0}; + constexpr double verticalBRectAdjustFactor{1.2}; // text bounding rect is bigger than font size and text is not + // vertically aligned with brect midline, so we artificially + // bump the text size so the middle aligns with the leader + QPointF textPos = getTailPoint(); m_tailText->setPos(textPos); //avoid messing up brect with empty item at 0, 0 !!! std::string tText = getFeature()->TailText.getValue(); if (tText.empty()) { m_tailText->hide(); return; - } else { - m_tailText->show(); } - const auto sym = getFeature(); - if (!sym) + + m_tailText->show(); + + const auto symbol = getFeature(); + if (!symbol) { return; - auto vp = dynamic_cast(getViewProvider(sym)); + } + auto vp = dynamic_cast(getViewProvider(symbol)); if (!vp) { return; } QString qFontName = QString::fromStdString(vp->Font.getValue()); int fontSize = QGIView::exactFontSize(vp->Font.getValue(), - vp->FontSize.getValue()); + vp->FontSize.getValue()); // this is different from the size used in the tiles m_font.setFamily(qFontName); m_font.setPixelSize(fontSize); @@ -267,23 +283,42 @@ void QGIWeldSymbol::drawTailText() m_tailText->setColor(getCurrentColor()); m_tailText->setZValue(ZVALUE::DIMENSION); - double textWidth = m_tailText->boundingRect().width(); - double charWidth = textWidth / tText.size(); - double hMargin = charWidth + prefArrowSize(); + auto brWidth = m_tailText->boundingRect().width(); + auto brHeight = m_tailText->boundingRect().height(); + auto brCharWidth = brWidth / tText.length(); - double textHeight = m_tailText->boundingRect().width(); - double vFudge = textHeight * 0.1; + double hMargin = brCharWidth + prefArrowSize(); // leave a gap from the graphic + auto angleDeg = getLastSegAngle(); - if (getFeature()->isTailRightSide()) { - m_tailText->justifyLeftAt(textPos.x() + hMargin, textPos.y() - vFudge, true); - } else { - m_tailText->justifyRightAt(textPos.x() - hMargin, textPos.y() - vFudge, true); + auto localAxes = getLocalAxes(); + auto xdir = localAxes.first; + auto ydir = localAxes.second; + Base::Vector3d stdX{1, 0, 0}; + auto xdirStartOffset = DU::toQPointF(xdir * brWidth) * -1; // start of text in xDir when leader points left + auto dot = stdX.Dot(xdir); + if (dot < 0) { + angleDeg -= DegreesHalfCircle; + xdirStartOffset = QPointF(0, 0); + ydir = -ydir; } + + auto xAdjust = DU::toQPointF(xdir * hMargin); + auto yAdjust = DU::toQPointF(ydir * (brHeight * verticalBRectAdjustFactor) / 2); + + // QGCustomText doesn't know about rotation so we can't use the justify methods + QPointF justPoint = textPos - xAdjust + yAdjust; // original + justPoint += xdirStartOffset; + + m_tailText->setPos(justPoint); + + auto kink = getLeader()->getKinkPoint(); + m_tailText->setTransformOriginPoint(DU::toQPointF(kink)); + + m_tailText->setRotation(angleDeg); } void QGIWeldSymbol::drawFieldFlag() { -// Base::Console().Message("QGIWS::drawFieldFlag()\n"); QPointF fieldFlagPos = getKinkPoint(); m_fieldFlag->setPos(fieldFlagPos); @@ -293,19 +328,33 @@ void QGIWeldSymbol::drawFieldFlag() m_fieldFlag->hide(); return; } + + auto localAxes = getLocalAxes(); + auto xdir = localAxes.first; + auto ydir = localAxes.second; + + // TODO: similar code used here and in QGITiled to handle leader points left. different actions, though. + // used here and QGITile. + Base::Vector3d stdX{1, 0, 0}; + auto dot = stdX.Dot(xdir); + if (dot < 0) { + // our leader points left, so yDir should be +Y, but we need -Y up + ydir = -ydir; + } + +// NOLINTBEGIN readability-magic-numbers std::vector flagPoints = { QPointF(0.0, 0.0), - QPointF(0.0, -3.0), - QPointF(-2.0, -2.5), - QPointF(0.0, -2.0) }; - //flag sb about 2x text? -// double scale = calculateFontPixelSize(getDimFontSize()) / 2.0; - double scale = PreferencesGui::dimFontSizePX() / 2.0; + DU::toQPointF(ydir * 3.0), + DU::toQPointF(xdir * -2.0 + ydir * 2.5), + DU::toQPointF(ydir * 2.0) }; +// NOLINTEND readability-magic-numbers + + double scale = (float)PreferencesGui::dimFontSizePX() / 2; QPainterPath path; path.moveTo(flagPoints.at(0) * scale); - int i = 1; - int stop = flagPoints.size(); - for ( ; i < stop; i++) { - path.lineTo(flagPoints.at(i) * scale); + size_t iSeg = 1; + for ( ; iSeg < flagPoints.size(); iSeg++) { + path.lineTo(flagPoints.at(iSeg) * scale); } auto qgiLead = dynamic_cast(getQGIVByName(getLeader()->getNameInDocument())); @@ -343,17 +392,17 @@ void QGIWeldSymbol::getTileFeats() void QGIWeldSymbol::removeQGITiles() { - std::vector tiles = getQGITiles(); - for (auto t: tiles) { - QList tChildren = t->childItems(); + std::vector tilesAll = getQGITiles(); + for (auto tile: tilesAll) { + QList tChildren = tile->childItems(); for (auto tc: tChildren) { - t->removeFromGroup(tc); + tile->removeFromGroup(tc); scene()->removeItem(tc); //tc gets deleted when QGIWS gets deleted } - removeFromGroup(t); - scene()->removeItem(t); - delete t; + removeFromGroup(tile); + scene()->removeItem(tile); + delete tile; } } @@ -361,8 +410,8 @@ std::vector QGIWeldSymbol::getQGITiles() const { std::vector result; QList children = childItems(); - for (auto& c:children) { - QGITile* tile = dynamic_cast(c); + for (auto& child:children) { + auto tile = dynamic_cast(child); if (tile) { result.push_back(tile); } @@ -404,10 +453,10 @@ void QGIWeldSymbol::drawBorder() void QGIWeldSymbol::setPrettyNormal() { - std::vector tiles = getQGITiles(); - for (auto t: tiles) { - t->setColor(getNormalColor()); - t->draw(); + std::vector tilesAll = getQGITiles(); + for (auto tile: tilesAll) { + tile->setColor(getNormalColor()); + tile->draw(); } setCurrentColor(getNormalColor()); m_fieldFlag->setNormalColor(getNormalColor()); @@ -420,10 +469,10 @@ void QGIWeldSymbol::setPrettyNormal() void QGIWeldSymbol::setPrettyPre() { - std::vector tiles = getQGITiles(); - for (auto t: tiles) { - t->setColor(getPreColor()); - t->draw(); + std::vector tilesAll = getQGITiles(); + for (auto tile: tilesAll) { + tile->setColor(getPreColor()); + tile->draw(); } setCurrentColor(getPreColor()); @@ -437,10 +486,10 @@ void QGIWeldSymbol::setPrettyPre() void QGIWeldSymbol::setPrettySel() { - std::vector tiles = getQGITiles(); - for (auto t: tiles) { - t->setColor(getSelectColor()); - t->draw(); + std::vector tilesAll = getQGITiles(); + for (auto tile: tilesAll) { + tile->setColor(getSelectColor()); + tile->draw(); } setCurrentColor(getSelectColor()); @@ -488,6 +537,25 @@ TechDraw::DrawLeaderLine *QGIWeldSymbol::getLeader() return dynamic_cast(feature->Leader.getValue()); } +//! get the angle for the transformed last segment +double QGIWeldSymbol::getLastSegAngle() +{ + auto lastSegDirection = getLeader()->lastSegmentDirection(); + auto lastSegAngleRad = DU::angleWithX(lastSegDirection); + return Base::toDegrees(lastSegAngleRad); +} + +std::pair QGIWeldSymbol::getLocalAxes() +{ + auto localX = getLeader()->lastSegmentDirection(); + auto localY = DU::invertY(localX); + localY.RotateZ(M_PI_2); + localY.Normalize(); + localY = DU::invertY(localY); + return {localX, localY}; +} + + //preference QColor QGIWeldSymbol::prefNormalColor() { @@ -495,7 +563,7 @@ QColor QGIWeldSymbol::prefNormalColor() return getNormalColor(); } -double QGIWeldSymbol::prefArrowSize() +double QGIWeldSymbol::prefArrowSize() const { return PreferencesGui::dimArrowSize(); } @@ -530,8 +598,8 @@ QRectF QGIWeldSymbol::customBoundingRect() const } std::vector qgTiles = getQGITiles(); - for (auto& t: qgTiles) { - QRectF childRect = mapFromItem(t, t->boundingRect()).boundingRect(); + for (auto& tile: qgTiles) { + QRectF childRect = mapFromItem(tile, tile->boundingRect()).boundingRect(); result = result.united(childRect); } return result; @@ -547,10 +615,11 @@ void QGIWeldSymbol::paint ( QPainter * painter, const QStyleOptionGraphicsItem * QStyleOptionGraphicsItem myOption(*option); myOption.state &= ~QStyle::State_Selected; - painter->setPen(Qt::red); - painter->drawRect(boundingRect()); //good for debugging + // painter->setPen(Qt::red); + // painter->drawRect(boundingRect()); //good for debugging QGIView::paint (painter, &myOption, widget); } + #include diff --git a/src/Mod/TechDraw/Gui/QGIWeldSymbol.h b/src/Mod/TechDraw/Gui/QGIWeldSymbol.h index 416dce3849..7370d3cec8 100644 --- a/src/Mod/TechDraw/Gui/QGIWeldSymbol.h +++ b/src/Mod/TechDraw/Gui/QGIWeldSymbol.h @@ -84,11 +84,14 @@ public: QPointF getKinkPoint(); QPointF getTailPoint(); - virtual void setPrettyNormal(); - virtual void setPrettySel(); - virtual void setPrettyPre(); + void setPrettyNormal(); + void setPrettySel(); + void setPrettyPre(); void getTileFeats(); + void makeLines(); + double getLastSegAngle(); + std::pair getLocalAxes(); protected: QVariant itemChange( GraphicsItemChange change, @@ -106,10 +109,13 @@ protected: void removeQGITiles(); std::vector getQGITiles() const; - virtual QColor prefNormalColor(); - double prefArrowSize(); + QColor prefNormalColor(); + double prefArrowSize() const; double prefFontSize() const; + virtual QRectF customBoundingRect() const; + +private: TechDraw::DrawTileWeld* m_arrowFeat; TechDraw::DrawTileWeld* m_otherFeat; std::string m_arrowName; @@ -123,7 +129,6 @@ protected: bool m_blockDraw; //prevent redraws while updating. - virtual QRectF customBoundingRect() const; };