From 1c0885e766fc1c58d5e7893d8f9ea1b8e7ba0a3e Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Wed, 24 Aug 2022 18:53:25 +0300 Subject: [PATCH] Improve visualization for tool Elliptical Arc. --- src/libs/vtools/dialogs/tools/dialogarc.cpp | 2 +- .../dialogs/tools/dialogellipticalarc.cpp | 131 ++++++++++++++-- .../dialogs/tools/dialogellipticalarc.h | 6 + .../toolcurve/vtoolellipticalarc.cpp | 1 + .../vtools/visualization/path/vistoolarc.cpp | 12 -- .../vtools/visualization/path/vistoolarc.h | 1 - .../path/vistoolellipticalarc.cpp | 148 +++++++++++++++++- .../visualization/path/vistoolellipticalarc.h | 26 ++- .../vtools/visualization/visualization.cpp | 13 ++ src/libs/vtools/visualization/visualization.h | 1 + 10 files changed, 308 insertions(+), 33 deletions(-) diff --git a/src/libs/vtools/dialogs/tools/dialogarc.cpp b/src/libs/vtools/dialogs/tools/dialogarc.cpp index fd6f62de2..f80159b59 100644 --- a/src/libs/vtools/dialogs/tools/dialogarc.cpp +++ b/src/libs/vtools/dialogs/tools/dialogarc.cpp @@ -289,7 +289,7 @@ void DialogArc::ShowDialog(bool click) if (QGuiApplication::keyboardModifiers() == Qt::ShiftModifier) { QLineF correction = line; - correction.setAngle(VisToolArc::CorrectAngle(correction.angle())); + correction.setAngle(Visualization::CorrectAngle(correction.angle())); return correction.angle(); } diff --git a/src/libs/vtools/dialogs/tools/dialogellipticalarc.cpp b/src/libs/vtools/dialogs/tools/dialogellipticalarc.cpp index ab8160278..cb8fdeda2 100644 --- a/src/libs/vtools/dialogs/tools/dialogellipticalarc.cpp +++ b/src/libs/vtools/dialogs/tools/dialogellipticalarc.cpp @@ -48,6 +48,8 @@ #include "../vgeometry/vellipticalarc.h" #include "../qmuparser/qmudef.h" #include "../vpatterndb/vcontainer.h" +#include "../vwidgets/global.h" +#include "../vwidgets/vabstractmainwindow.h" //--------------------------------------------------------------------------------------------------------------------- /** @@ -542,6 +544,105 @@ void DialogEllipticalArc::DeployRotationAngleTextEdit() DeployFormula(this, ui->plainTextEditRotationAngle, ui->pushButtonGrowLengthRotationAngle,formulaBaseHeightRotationAngle); } +//--------------------------------------------------------------------------------------------------------------------- +void DialogEllipticalArc::ShowDialog(bool click) +{ + if (not prepare) + { + return; + } + + if (click) + { + // The check need to ignore first release of mouse button. + // User can select point by clicking on a label. + if (not m_firstRelease) + { + m_firstRelease = true; + return; + } + + auto *scene = qobject_cast(VAbstractValApplication::VApp()->getCurrentScene()); + SCASSERT(scene != nullptr) + + const QSharedPointer center = data->GeometricObject(GetCenter()); + QLineF line = QLineF(static_cast(*center), scene->getScenePos()); + + auto Angle = [line]() + { + if (QGuiApplication::keyboardModifiers() == Qt::ShiftModifier) + { + QLineF correction = line; + correction.setAngle(Visualization::CorrectAngle(correction.angle())); + return correction.angle(); + } + + return line.angle(); + }; + + if (m_stage == 0) // radius 1 + { + //Radius of point circle, but little bigger. Need to handle with hover sizes. + if (line.length() <= ScaledRadius(SceneScale(VAbstractValApplication::VApp()->getCurrentScene()))*1.5) + { + return; + } + + SetRadius1(QString::number(FromPixel(line.length(), *data->GetPatternUnit()))); + vis->RefreshGeometry(); + ++m_stage; + return; + } + + if (m_stage == 1) // radius 2 + { + QLineF radius2Line(center->x(), center->y(), center->x(), center->y() - 100); + QPointF p = VGObject::ClosestPoint(radius2Line, scene->getScenePos()); + line = QLineF(static_cast(*center), p); + + //Radius of point circle, but little bigger. Need to handle with hover sizes. + if (line.length() <= ScaledRadius(SceneScale(VAbstractValApplication::VApp()->getCurrentScene()))*1.5) + { + return; + } + + SetRadius2(QString::number(FromPixel(line.length(), *data->GetPatternUnit()))); + vis->RefreshGeometry(); + ++m_stage; + return; + } + + if (m_stage == 2) // f1 + { + SetF1(QString::number(Angle())); + vis->RefreshGeometry(); + ++m_stage; + return; + } + + if (m_stage == 3) // f2 + { + SetF2(QString::number(Angle())); + vis->RefreshGeometry(); + ++m_stage; + return; + } + + auto *path = qobject_cast(vis); + SCASSERT(path != nullptr) + + SetRotationAngle(QString::number(Angle() - path->StartingRotationAngle())); + } + + vis->SetMode(Mode::Show); + vis->RefreshGeometry(); + + emit ToolTip(QString()); + + setModal(true); + show(); +} + //--------------------------------------------------------------------------------------------------------------------- /** * @brief ChoosedObject gets id and type of selected object. Save right data and ignore wrong. @@ -550,21 +651,27 @@ void DialogEllipticalArc::DeployRotationAngleTextEdit() */ void DialogEllipticalArc::ChosenObject(quint32 id, const SceneObject &type) { - if (prepare == false)// After first choose we ignore all objects + if (prepare)// After first choose we ignore all objects { - if (type == SceneObject::Point) + return; + } + + if (type != SceneObject::Point) + { + return; + } + + if (SetObject(id, ui->comboBoxBasePoint, QString())) + { + if (vis != nullptr) { - if (SetObject(id, ui->comboBoxBasePoint, QString())) - { - if (vis != nullptr) - { - vis->VisualMode(id); - } - prepare = true; - this->setModal(true); - this->show(); - } + auto *window = qobject_cast(VAbstractValApplication::VApp()->getMainWindow()); + SCASSERT(window != nullptr) + connect(vis, &Visualization::ToolTip, window, &VAbstractMainWindow::ShowToolTip); + + vis->VisualMode(id); } + prepare = true; } } diff --git a/src/libs/vtools/dialogs/tools/dialogellipticalarc.h b/src/libs/vtools/dialogs/tools/dialogellipticalarc.h index 10cb5e7c3..e43eca10f 100644 --- a/src/libs/vtools/dialogs/tools/dialogellipticalarc.h +++ b/src/libs/vtools/dialogs/tools/dialogellipticalarc.h @@ -80,6 +80,8 @@ public: void SetAliasSuffix(const QString &alias); QString GetAliasSuffix() const; + void ShowDialog(bool click) override; + public slots: virtual void ChosenObject(quint32 id, const SceneObject &type) override; /** @@ -175,6 +177,10 @@ private: QString originAliasSuffix{}; + bool m_firstRelease{false}; + + int m_stage{0}; + void EvalRadiuses(); void EvalAngles(); }; diff --git a/src/libs/vtools/tools/drawTools/toolcurve/vtoolellipticalarc.cpp b/src/libs/vtools/tools/drawTools/toolcurve/vtoolellipticalarc.cpp index 8c3d2484e..a83cded12 100644 --- a/src/libs/vtools/tools/drawTools/toolcurve/vtoolellipticalarc.cpp +++ b/src/libs/vtools/tools/drawTools/toolcurve/vtoolellipticalarc.cpp @@ -430,6 +430,7 @@ void VToolEllipticalArc::SetVisualization() visual->SetF2(trVars->FormulaToUser(elArc->GetFormulaF2(), osSeparator)); visual->SetRotationAngle(trVars->FormulaToUser(elArc->GetFormulaRotationAngle(), osSeparator)); visual->SetLineStyle(LineStyleToPenStyle(elArc->GetPenStyle())); + visual->SetMode(Mode::Show); visual->RefreshGeometry(); } } diff --git a/src/libs/vtools/visualization/path/vistoolarc.cpp b/src/libs/vtools/visualization/path/vistoolarc.cpp index 66d008fce..bb9f53673 100644 --- a/src/libs/vtools/visualization/path/vistoolarc.cpp +++ b/src/libs/vtools/visualization/path/vistoolarc.cpp @@ -178,18 +178,6 @@ void VisToolArc::VisualMode(quint32 id) StartVisualMode(); } -//--------------------------------------------------------------------------------------------------------------------- -auto VisToolArc::CorrectAngle(qreal angle) -> qreal -{ - qreal ang = angle; - if (angle > 360) - { - ang = angle - 360.0 * qFloor(angle/360); - } - - return (qFloor(qAbs(ang)/5.)) * 5; -} - //--------------------------------------------------------------------------------------------------------------------- auto VisToolArc::StickyEnd(qreal angle) const -> qreal { diff --git a/src/libs/vtools/visualization/path/vistoolarc.h b/src/libs/vtools/visualization/path/vistoolarc.h index 9a40ba556..3ce230bb5 100644 --- a/src/libs/vtools/visualization/path/vistoolarc.h +++ b/src/libs/vtools/visualization/path/vistoolarc.h @@ -58,7 +58,6 @@ public: auto type() const -> int override {return Type;} enum {Type = UserType + static_cast(Vis::ToolArc)}; - static auto CorrectAngle(qreal angle) -> qreal; auto StickyEnd(qreal angle) const -> qreal; private: diff --git a/src/libs/vtools/visualization/path/vistoolellipticalarc.cpp b/src/libs/vtools/visualization/path/vistoolellipticalarc.cpp index ee12387ed..39b61c0e9 100644 --- a/src/libs/vtools/visualization/path/vistoolellipticalarc.cpp +++ b/src/libs/vtools/visualization/path/vistoolellipticalarc.cpp @@ -39,12 +39,31 @@ #include "../visualization.h" #include "../vwidgets/scalesceneitems.h" #include "vispath.h" +#include "../vmisc/vmodifierkey.h" + +namespace +{ +auto Angle(const QLineF &radius) -> qreal +{ + if (QGuiApplication::keyboardModifiers() == Qt::ShiftModifier) + { + QLineF correction = radius; + correction.setAngle(Visualization::CorrectAngle(correction.angle())); + return correction.angle(); + } + + return radius.angle(); +} +} // namespace //--------------------------------------------------------------------------------------------------------------------- VisToolEllipticalArc::VisToolEllipticalArc(const VContainer *data, QGraphicsItem *parent) :VisPath(data, parent) { m_arcCenter = InitPoint(Color(VColor::MainColor), this); + m_radius1Line = InitItem(Color(VColor::SupportColor), this); + m_radius2Line = InitItem(Color(VColor::SupportColor), this); + m_f1Point = InitPoint(Color(VColor::SupportColor), this); } //--------------------------------------------------------------------------------------------------------------------- @@ -55,11 +74,104 @@ void VisToolEllipticalArc::RefreshGeometry() const QSharedPointer first = GetData()->GeometricObject(m_centerId); DrawPoint(m_arcCenter, static_cast(*first), Color(VColor::SupportColor)); - if (not qFuzzyIsNull(m_radius1) && not qFuzzyIsNull(m_radius2) && m_f1 >= 0 && m_f2 >= 0 && m_rotationAngle >= 0) + static const QString prefix = UnitsToStr(VAbstractValApplication::VApp()->patternUnits(), true); + QLineF radius (static_cast(*first), ScenePos()); + auto center = static_cast(*first); + + if (GetMode() == Mode::Creation) { - VEllipticalArc elArc = VEllipticalArc(*first, m_radius1, m_radius2, m_f1, m_f2, m_rotationAngle); - DrawPath(this, elArc.GetPath(), elArc.DirectionArrows(), Color(VColor::MainColor), LineStyle(), - Qt::RoundCap); + if (qFuzzyIsNull(m_radius1)) + { + DrawRadius1Line(center, radius.length()); + + SetToolTip(tr("Elliptical arc: radius1 = %1%2; " + "Mouse click - finish selecting the first radius, " + "%3 - skip").arg(LengthToUser(radius.length()), prefix, VModifierKey::EnterKey())); + } + else if (qFuzzyIsNull(m_radius2)) + { + DrawRadius2Line(center, m_radius1); + + QLineF radius2Line(center.x(), center.y(), center.x(), center.y() - 100); + QPointF p = VGObject::ClosestPoint(radius2Line, ScenePos()); + radius = QLineF(static_cast(*first), p); + + DrawRadius2Line(center, radius.length()); + DrawElArc(*first, m_radius1, radius.length(), 0, 0); + + SetToolTip(tr("Elliptical arc: radius1 = %1%2, " + "radius2 = %3%2; " + "Mouse click - finish selecting the second radius, " + "%4 - skip") + .arg(LengthToUser(m_radius1), prefix, LengthToUser(radius.length()), + VModifierKey::EnterKey())); + } + else if (m_f1 < 0) + { + DrawRadius1Line(center, m_radius1); + DrawRadius2Line(center, m_radius2); + + qreal f1Angle = Angle(radius); + VEllipticalArc elArc = DrawElArc(*first, m_radius1, m_radius2, f1Angle, f1Angle); + + DrawPoint(m_f1Point, elArc.GetP1(), Color(VColor::SupportColor)); + + SetToolTip(tr("Elliptical arc: radius1 = %1%2, " + "radius2 = %3%2, angle1 = %4°; " + "Mouse click - finish selecting the second radius, " + "%5 - sticking angle, " + "%6 - skip") + .arg(LengthToUser(m_radius1), prefix, LengthToUser(m_radius2), + AngleToUser(f1Angle), VModifierKey::Shift(), VModifierKey::EnterKey())); + } + else if (m_f2 < 0) + { + DrawRadius1Line(center, m_radius1); + DrawRadius2Line(center, m_radius2); + + const qreal f2Angle = Angle(radius); + VEllipticalArc elArc = DrawElArc(*first, m_radius1, m_radius2, m_f1, f2Angle); + + DrawPoint(m_f1Point, elArc.GetP1(), Color(VColor::SupportColor)); + + SetToolTip(tr("Elliptical arc: radius1 = %1%2, " + "radius2 = %3%2, angle1 = %4°, angle2 = %5°; " + "Mouse click - finish selecting the second radius, " + "%6 - sticking angle, " + "%7 - skip") + .arg(LengthToUser(m_radius1), prefix, LengthToUser(m_radius2), + AngleToUser(m_f1), AngleToUser(f2Angle), VModifierKey::Shift(), + VModifierKey::EnterKey())); + } + else if (VFuzzyComparePossibleNulls(m_rotationAngle, INT_MAX)) + { + if (VFuzzyComparePossibleNulls(m_startingRotationAngle, INT_MAX)) + { + m_startingRotationAngle = radius.angle(); + } + + qreal rotationAngle = Angle(radius) - m_startingRotationAngle; + + DrawRadius1Line(center, m_radius1, rotationAngle); + DrawRadius2Line(center, m_radius2, rotationAngle); + VEllipticalArc elArc = DrawElArc(*first, m_radius1, m_radius2, m_f1, m_f2, rotationAngle); + + DrawPoint(m_f1Point, elArc.GetP1(), Color(VColor::SupportColor)); + + SetToolTip(tr("Elliptical arc: radius1 = %1%2, " + "radius2 = %3%2, angle1 = %4°, angle2 = %5°, rotation = %6°; " + "Mouse click - finish selecting the second radius, " + "%7 - sticking angle, " + "%8 - skip") + .arg(LengthToUser(m_radius1), prefix, LengthToUser(radius.length()), + AngleToUser(m_f1), AngleToUser(m_f2), AngleToUser(rotationAngle), + VModifierKey::Shift(), VModifierKey::EnterKey())); + } + } + else if (not qFuzzyIsNull(m_radius1) && not qFuzzyIsNull(m_radius2) && m_f1 >= 0 && m_f2 >= 0 && + not VFuzzyComparePossibleNulls(m_rotationAngle, INT_MAX)) + { + DrawElArc(*first, m_radius1, m_radius2, m_f1, m_f2, m_rotationAngle); } } } @@ -100,3 +212,31 @@ void VisToolEllipticalArc::SetRotationAngle(const QString &expression) { m_rotationAngle = FindValFromUser(expression, GetData()->DataVariables()); } + +//--------------------------------------------------------------------------------------------------------------------- +void VisToolEllipticalArc::DrawRadius1Line(const QPointF ¢er, qreal radius, qreal rotationAngle) +{ + QLineF radiusLine(center.x(), center.y(), center.x() + 100, center.y()); + radiusLine.setLength(radius); + radiusLine.setAngle(radiusLine.angle() + rotationAngle); + DrawLine(m_radius1Line, radiusLine, Color(VColor::SupportColor)); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VisToolEllipticalArc::DrawRadius2Line(const QPointF ¢er, qreal radius, qreal rotationAngle) +{ + QLineF radiusLine(center.x(), center.y(), center.x(), center.y() - 100); + radiusLine.setLength(radius); + radiusLine.setAngle(radiusLine.angle() + rotationAngle); + DrawLine(m_radius2Line, radiusLine, Color(VColor::SupportColor)); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VisToolEllipticalArc::DrawElArc(const VPointF ¢er, qreal radius1, qreal radius2, qreal f1, qreal f2, + qreal rotationAngle) -> VEllipticalArc +{ + VEllipticalArc elArc(center, radius1, radius2, f1, f2, rotationAngle); + DrawPath(this, elArc.GetPath(), elArc.DirectionArrows(), Color(VColor::MainColor), LineStyle(), Qt::RoundCap); + + return elArc; +} diff --git a/src/libs/vtools/visualization/path/vistoolellipticalarc.h b/src/libs/vtools/visualization/path/vistoolellipticalarc.h index ba6f27648..74e9027a0 100644 --- a/src/libs/vtools/visualization/path/vistoolellipticalarc.h +++ b/src/libs/vtools/visualization/path/vistoolellipticalarc.h @@ -38,6 +38,9 @@ #include "../vmisc/def.h" #include "vispath.h" +class VPointF; +class VEllipticalArc; + class VisToolEllipticalArc : public VisPath { Q_OBJECT // NOLINT @@ -55,17 +58,28 @@ public: void SetF2(const QString &expression); void SetRotationAngle(const QString &expression); + auto StartingRotationAngle() const -> qreal; + auto type() const -> int override {return Type;} enum {Type = UserType + static_cast(Vis::ToolEllipticalArc)}; private: Q_DISABLE_COPY_MOVE(VisToolEllipticalArc) // NOLINT VScaledEllipse *m_arcCenter{nullptr}; + VScaledLine *m_radius1Line{nullptr}; + VScaledLine *m_radius2Line{nullptr}; + VScaledEllipse *m_f1Point{nullptr}; qreal m_radius1{0}; qreal m_radius2{0}; - qreal m_f1{0}; - qreal m_f2{0}; - qreal m_rotationAngle{0}; + qreal m_f1{-1}; + qreal m_f2{-1}; + qreal m_startingRotationAngle{INT_MAX}; + qreal m_rotationAngle{INT_MAX}; quint32 m_centerId{NULL_ID}; + + void DrawRadius1Line(const QPointF ¢er, qreal radius, qreal rotationAngle = 0); + void DrawRadius2Line(const QPointF ¢er, qreal radius, qreal rotationAngle = 0); + auto DrawElArc(const VPointF ¢er, qreal radius1, qreal radius2, qreal f1, qreal f2, + qreal rotationAngle = 0) -> VEllipticalArc; }; //--------------------------------------------------------------------------------------------------------------------- @@ -74,4 +88,10 @@ inline void VisToolEllipticalArc::SetCenterId(quint32 newCenterId) m_centerId = newCenterId; } +//--------------------------------------------------------------------------------------------------------------------- +inline auto VisToolEllipticalArc::StartingRotationAngle() const -> qreal +{ + return m_startingRotationAngle; +} + #endif // VISTOOLELLIPTICALARC_H diff --git a/src/libs/vtools/visualization/visualization.cpp b/src/libs/vtools/visualization/visualization.cpp index c37c16d38..7a5a94601 100644 --- a/src/libs/vtools/visualization/visualization.cpp +++ b/src/libs/vtools/visualization/visualization.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include "../vpatterndb/calculator.h" #include "../vpatterndb/vtranslatevars.h" @@ -199,6 +200,18 @@ auto Visualization::FindValFromUser(const QString &expression, return val; } +//--------------------------------------------------------------------------------------------------------------------- +qreal Visualization::CorrectAngle(qreal angle) +{ + qreal ang = angle; + if (angle > 360) + { + ang = angle - 360.0 * qFloor(angle/360); + } + + return (qFloor(qAbs(ang)/5.)) * 5; +} + //--------------------------------------------------------------------------------------------------------------------- void Visualization::RefreshToolTip() const { diff --git a/src/libs/vtools/visualization/visualization.h b/src/libs/vtools/visualization/visualization.h index 1fb687db1..1f1846578 100644 --- a/src/libs/vtools/visualization/visualization.h +++ b/src/libs/vtools/visualization/visualization.h @@ -84,6 +84,7 @@ public: QSharedPointer > *vars, bool fromUser = true) -> qreal; static auto FindValFromUser(const QString &expression, const QHash > *vars, bool fromUser = true) -> qreal; + static auto CorrectAngle(qreal angle) -> qreal; auto CurrentToolTip() const -> QString;