diff --git a/src/libs/vgeometry/vabstractcubicbezier.cpp b/src/libs/vgeometry/vabstractcubicbezier.cpp index 02492bfcb..5c78bbbc4 100644 --- a/src/libs/vgeometry/vabstractcubicbezier.cpp +++ b/src/libs/vgeometry/vabstractcubicbezier.cpp @@ -401,7 +401,6 @@ auto VAbstractCubicBezier::CutSpline(qreal length, QPointF &spl1p2, QPointF &spl QPointF &spl2p3, const QString &pointName) const -> QPointF { //Always need return two splines, so we must correct wrong length. - const qreal minLength = ToPixel(1, Unit::Mm); const qreal fullLength = GetLength(); if (fullLength <= minLength) diff --git a/src/libs/vgeometry/vabstractcubicbezierpath.cpp b/src/libs/vgeometry/vabstractcubicbezierpath.cpp index a5e37ad44..a1b16691a 100644 --- a/src/libs/vgeometry/vabstractcubicbezierpath.cpp +++ b/src/libs/vgeometry/vabstractcubicbezierpath.cpp @@ -171,7 +171,6 @@ auto VAbstractCubicBezierPath::CutSplinePath(qreal length, qint32 &p1, qint32 &p } //Always need return two spline paths, so we must correct wrong length. - const qreal minLength = ToPixel(1, Unit::Mm); qreal fullLength = GetLength(); if (fullLength <= minLength) diff --git a/src/libs/vgeometry/vabstractcurve.cpp b/src/libs/vgeometry/vabstractcurve.cpp index fa83e2d57..02fe1a5a2 100644 --- a/src/libs/vgeometry/vabstractcurve.cpp +++ b/src/libs/vgeometry/vabstractcurve.cpp @@ -228,6 +228,50 @@ auto VAbstractCurve::ToEnd(const QVector &points, const QPointF &end, b return Reverse(reversed); } +//--------------------------------------------------------------------------------------------------------------------- +auto VAbstractCurve::ClosestPoint(QPointF scenePoint) const -> QPointF +{ + const QVector points = GetPoints(); + if (points.count() < 2) + { + return {}; + } + + if (VFuzzyComparePoints(ConstFirst(points), scenePoint)) + { + return ConstFirst(points); + } + + QPointF candidatePoint; + qreal bestDistance = INT_MAX; + bool found = false; + + for (qint32 i = 0; i < points.count()-1; ++i) + { + const QPointF cPoint = VGObject::ClosestPoint(QLineF(points.at(i), points.at(i+1)), scenePoint); + + if (IsPointOnLineSegment(cPoint, points.at(i), points.at(i+1))) + { + const qreal length = QLineF(scenePoint, cPoint).length(); + if (length < bestDistance) + { + candidatePoint = cPoint; + bestDistance = length; + found = true; + } + } + } + + if (found) + { + return candidatePoint; + } + else + { + return {}; + } +} + //--------------------------------------------------------------------------------------------------------------------- auto VAbstractCurve::GetPath() const -> QPainterPath { diff --git a/src/libs/vgeometry/vabstractcurve.h b/src/libs/vgeometry/vabstractcurve.h index 85cbefc1f..4c3c8a61c 100644 --- a/src/libs/vgeometry/vabstractcurve.h +++ b/src/libs/vgeometry/vabstractcurve.h @@ -81,6 +81,8 @@ public: static auto SubdividePath(const QVector &points, QPointF p, QVector &sub1, QVector &sub2) -> bool; + auto ClosestPoint(QPointF scenePoint) const -> QPointF; + virtual auto GetStartAngle () const -> qreal=0; virtual auto GetEndAngle () const -> qreal=0; @@ -109,6 +111,8 @@ public: static auto LengthCurveDirectionArrow() -> qreal; void SetAliasSuffix(const QString &aliasSuffix) override; + + static constexpr qreal minLength = ToPixel(1, Unit::Mm); protected: virtual void CreateName() =0; virtual void CreateAlias() =0; diff --git a/src/libs/vgeometry/varc.cpp b/src/libs/vgeometry/varc.cpp index e49241805..969e97381 100644 --- a/src/libs/vgeometry/varc.cpp +++ b/src/libs/vgeometry/varc.cpp @@ -460,8 +460,7 @@ auto VArc::CutPoint(qreal length, qreal fullLength, const QString &pointName) co length = fullLength + length; } - const qreal minLength = ToPixel(1, Unit::Mm); - const qreal maxLength = fullLength - ToPixel(1, Unit::Mm); + const qreal maxLength = fullLength - minLength; if (length < minLength) { @@ -512,10 +511,10 @@ auto VArc::CutPointFlipped(qreal length, qreal fullLength, const QString &pointN length = fullLength + length; } - const qreal minLength = fullLength + ToPixel(1, Unit::Mm); - const qreal maxLength = ToPixel(-1, Unit::Mm); + const qreal minLengthFlipped = fullLength + minLength; + const qreal maxLengthFlipped = -minLength; - if (length < minLength) + if (length < minLengthFlipped) { QString errorMsg; if (not pointName.isEmpty()) @@ -531,7 +530,7 @@ auto VArc::CutPointFlipped(qreal length, qreal fullLength, const QString &pointN VAbstractApplication::VApp()->IsPedantic() ? throw VException(errorMsg) : qWarning() << VAbstractApplication::warningMessageSignature + errorMsg; } - else if (length > maxLength) + else if (length > maxLengthFlipped) { QString errorMsg; if (not pointName.isEmpty()) @@ -548,7 +547,7 @@ auto VArc::CutPointFlipped(qreal length, qreal fullLength, const QString &pointN qWarning() << VAbstractApplication::warningMessageSignature + errorMsg; } - length = qBound(minLength, length, maxLength); + length = qBound(minLengthFlipped, length, maxLengthFlipped); QLineF line(static_cast(GetCenter()), GetP1()); line.setAngle(line.angle() - qRadiansToDegrees(qAbs(length)/d->radius)); diff --git a/src/libs/vgeometry/vellipticalarc.cpp b/src/libs/vgeometry/vellipticalarc.cpp index 7ec84790a..d41d2b1a3 100644 --- a/src/libs/vgeometry/vellipticalarc.cpp +++ b/src/libs/vgeometry/vellipticalarc.cpp @@ -353,7 +353,6 @@ auto VEllipticalArc::CutArc(const qreal &length, VEllipticalArc &arc1, VElliptic { //Always need return two arcs, so we must correct wrong length. qreal len = 0; - const qreal minLength = ToPixel(1, Unit::Mm); const qreal fullLength = GetLength(); if (fullLength <= minLength) diff --git a/src/libs/vtools/dialogs/tools/dialogcutspline.cpp b/src/libs/vtools/dialogs/tools/dialogcutspline.cpp index eaaf3c29e..8410edd64 100644 --- a/src/libs/vtools/dialogs/tools/dialogcutspline.cpp +++ b/src/libs/vtools/dialogs/tools/dialogcutspline.cpp @@ -47,6 +47,7 @@ #include "ui_dialogcutspline.h" #include "../vgeometry/vspline.h" #include "../qmuparser/qmudef.h" +#include "../vwidgets/vabstractmainwindow.h" //--------------------------------------------------------------------------------------------------------------------- /** @@ -180,8 +181,10 @@ void DialogCutSpline::ChosenObject(quint32 id, const SceneObject &type) 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); } } } @@ -310,7 +313,7 @@ auto DialogCutSpline::GetFormula() const -> QString * @brief getSplineId return id base point of line * @return id */ -quint32 DialogCutSpline::getSplineId() const +auto DialogCutSpline::getSplineId() const -> quint32 { return getCurrentObjectId(ui->comboBoxSpline); } @@ -354,3 +357,49 @@ auto DialogCutSpline::GetAliasSuffix2() const -> QString { return ui->lineEditAlias2->text(); } + +//--------------------------------------------------------------------------------------------------------------------- +void DialogCutSpline::ShowDialog(bool click) +{ + if (not prepare) + { + return; + } + + auto FinishCreating = [this]() + { + vis->SetMode(Mode::Show); + vis->RefreshGeometry(); + + emit ToolTip(QString()); + + setModal(true); + show(); + }; + + 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 spl = data->GeometricObject(getSplineId()); + QPointF p = spl->ClosestPoint(scene->getScenePos()); + qreal len = spl->GetLengthByPoint(p); + if (len > 0) + { + SetFormula(QString::number(FromPixel(len, *data->GetPatternUnit()))); + } + + FinishCreating(); + } + + FinishCreating(); +} diff --git a/src/libs/vtools/dialogs/tools/dialogcutspline.h b/src/libs/vtools/dialogs/tools/dialogcutspline.h index 419b3a2ae..c710f24c2 100644 --- a/src/libs/vtools/dialogs/tools/dialogcutspline.h +++ b/src/libs/vtools/dialogs/tools/dialogcutspline.h @@ -70,6 +70,8 @@ public: void SetAliasSuffix2(const QString &alias); auto GetAliasSuffix2() const -> QString; + + void ShowDialog(bool click) override; public slots: void ChosenObject(quint32 id, const SceneObject &type) override; /** @@ -112,6 +114,8 @@ private: QString m_originAliasSuffix1{}; QString m_originAliasSuffix2{}; + + bool m_firstRelease{false}; }; //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vtools/visualization/path/vistoolcutspline.cpp b/src/libs/vtools/visualization/path/vistoolcutspline.cpp index a39163d70..45589e2f1 100644 --- a/src/libs/vtools/visualization/path/vistoolcutspline.cpp +++ b/src/libs/vtools/visualization/path/vistoolcutspline.cpp @@ -44,6 +44,7 @@ #include "../visualization.h" #include "vispath.h" #include "../vwidgets/scalesceneitems.h" +#include "../vmisc/vmodifierkey.h" //--------------------------------------------------------------------------------------------------------------------- VisToolCutSpline::VisToolCutSpline(const VContainer *data, QGraphicsItem *parent) @@ -85,6 +86,19 @@ void VisToolCutSpline::RefreshGeometry() DrawPath(m_spl1, sp1.GetPath(), sp1.DirectionArrows(), Qt::darkGreen, lineStyle, Qt::RoundCap); DrawPath(m_spl2, sp2.GetPath(), sp2.DirectionArrows(), Qt::darkRed, lineStyle, Qt::RoundCap); } + else if (mode == Mode::Creation) + { + QPointF p = spl->ClosestPoint(Visualization::scenePos); + qreal length = spl->GetLengthByPoint(p); + + DrawPoint(m_point, p, mainColor); + + const QString prefix = UnitsToStr(VAbstractValApplication::VApp()->patternUnits(), true); + Visualization::toolTip = tr("Length = %1%2; " + "Mouse click - finish selecting the length, " + "%3 - skip") + .arg(NumberToUser(length), prefix, VModifierKey::EnterKey()); + } } }