/************************************************************************ ** ** @file ** @author Roman Telezhynskyi ** @date 1 10, 2016 ** ** @brief ** @copyright ** This source code is part of the Valentina project, a pattern making ** program, whose allow create and modeling patterns of clothing. ** Copyright (C) 2016 Valentina project ** All Rights Reserved. ** ** Valentina is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** Valentina is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with Valentina. If not, see . ** *************************************************************************/ #include "vistoolmove.h" #include #include #include #include #include #include #include #include #include #include #include "../ifc/xml/vdomdocument.h" #include "../vmisc/diagnostic.h" #include "../vgeometry/vabstractcurve.h" #include "../vgeometry/varc.h" #include "../vgeometry/vcubicbezier.h" #include "../vgeometry/vcubicbezierpath.h" #include "../vgeometry/vellipticalarc.h" #include "../vgeometry/vgeometrydef.h" #include "../vgeometry/vgobject.h" #include "../vgeometry/vpointf.h" #include "../vgeometry/vspline.h" #include "../vgeometry/vsplinepath.h" #include "../vgeometry/varc.h" #include "../vmisc/vabstractapplication.h" #include "../vpatterndb/vcontainer.h" #include "../vwidgets/vmaingraphicsscene.h" #include "visoperation.h" //--------------------------------------------------------------------------------------------------------------------- VisToolMove::VisToolMove(const VContainer *data, QGraphicsItem *parent) : VisOperation(data, parent), angle(0), rotationAngle(INT_MIN), length(0), pointOrigin(nullptr), pointFinish(nullptr), angleArc(nullptr), rotationLine(nullptr), xAxis(nullptr) { pointOrigin = InitPoint(supportColor2, this); pointFinish = InitPoint(supportColor, this); angleArc = InitItem(supportColor3, this); rotationLine = InitItem(supportColor3, this); xAxis = InitItem(supportColor3, this); } //--------------------------------------------------------------------------------------------------------------------- void VisToolMove::RefreshGeometry() { if (objects.isEmpty()) { return; } int iPoint = -1; int iCurve = -1; const QVector originObjects = CreateOriginObjects(iPoint, iCurve); const QPointF origin = GetOriginPoint(originObjects); DrawPoint(pointOrigin, origin, supportColor2); qreal tempAngle = 0; qreal tempLength = 0; qreal tempRoationAngle = 0; QLineF line; if (qFuzzyIsNull(length)) { if (QGuiApplication::keyboardModifiers() == Qt::ShiftModifier) { line = QLineF(origin, Visualization::scenePos); line.setAngle(CorrectAngle(line.angle())); } else { line = QLineF(origin, Visualization::scenePos); } tempAngle = line.angle(); tempLength = line.length(); } else { line = VGObject::BuildLine(origin, length, angle); tempAngle = angle; tempLength = length; QLineF rLine; if (VFuzzyComparePossibleNulls(rotationAngle, INT_MIN)) { rLine = QLineF(line.p2(), Visualization::scenePos); if (QGuiApplication::keyboardModifiers() == Qt::ShiftModifier) { rLine.setAngle(CorrectAngle(rLine.angle())); } qreal cursorLength = rLine.length(); rLine.setP2(Ray(line.p2(), rLine.angle())); //Radius of point circle, but little bigger. Need handle with hover sizes. qreal minL = ScaledRadius(SceneScale(qApp->getCurrentScene()))*1.5; if (cursorLength > minL) { tempRoationAngle = rLine.angle(); } else { rLine.setAngle(0); } } else { rLine = QLineF(line.p2(), Ray(line.p2(), rotationAngle)); tempRoationAngle = rotationAngle; } DrawLine(rotationLine, rLine, supportColor3, Qt::DashLine); DrawLine(xAxis, QLineF(line.p2(), Ray(line.p2(), 0)), supportColor3, Qt::DashLine); VArc arc(VPointF(line.p2()), ScaledRadius(SceneScale(qApp->getCurrentScene()))*2, 0, tempRoationAngle); DrawPath(angleArc, arc.GetPath(), supportColor3, Qt::SolidLine, Qt::RoundCap); } DrawLine(this, line, supportColor2, Qt::DashLine); DrawPoint(pointFinish, line.p2(), supportColor); static const QString prefix = UnitsToStr(qApp->patternUnit(), true); if (qFuzzyIsNull(length)) { Visualization::toolTip = tr("Length = %1%2, angle = %3°, Shift - sticking angle, " "Mouse click - finish selecting a position") .arg(qApp->TrVars()->FormulaToUser(QString::number(qApp->fromPixel(tempLength)), qApp->Settings()->GetOsSeparator())) .arg(prefix) .arg(tempAngle); } else { Visualization::toolTip = tr("Length = %1%2, angle = %3°, rotation angle = %4°, Shift - sticking angle, " "Mouse click - finish creating") .arg(qApp->TrVars()->FormulaToUser(QString::number(qApp->fromPixel(tempLength)), qApp->Settings()->GetOsSeparator())) .arg(prefix) .arg(tempAngle) .arg(tempRoationAngle); } CreateMovedRotatedObjects(iPoint, iCurve, tempLength, tempAngle, tempRoationAngle, line.p2()); } //--------------------------------------------------------------------------------------------------------------------- QString VisToolMove::Angle() const { return QString::number(line().angle()); } //--------------------------------------------------------------------------------------------------------------------- void VisToolMove::SetAngle(const QString &expression) { angle = FindValFromUser(expression, Visualization::data->DataVariables()); } //--------------------------------------------------------------------------------------------------------------------- QString VisToolMove::RotationAngle() const { return QString::number(rotationLine->line().angle()); } //--------------------------------------------------------------------------------------------------------------------- void VisToolMove::SetRotationAngle(const QString &expression) { rotationAngle = FindValFromUser(expression, Visualization::data->DataVariables()); } //--------------------------------------------------------------------------------------------------------------------- QString VisToolMove::Length() const { return QString::number(LengthValue()); } //--------------------------------------------------------------------------------------------------------------------- qreal VisToolMove::LengthValue() const { return qApp->fromPixel(line().length()); } //--------------------------------------------------------------------------------------------------------------------- void VisToolMove::SetLength(const QString &expression) { length = FindLengthFromUser(expression, Visualization::data->DataVariables()); } //--------------------------------------------------------------------------------------------------------------------- template QGraphicsPathItem *VisToolMove::AddOriginCurve(quint32 id, int &i) { const QSharedPointer curve = Visualization::data->template GeometricObject(id); ++i; VCurvePathItem *path = GetCurve(static_cast(i), supportColor2); DrawPath(path, curve->GetPath(), curve->DirectionArrows(), supportColor2, Qt::SolidLine, Qt::RoundCap); return path; } //--------------------------------------------------------------------------------------------------------------------- template int VisToolMove::AddMovedRotatedCurve(qreal angle, qreal length, quint32 id, int i, qreal rotationAngle, const QPointF &rotationOrigin) { const QSharedPointer curve = Visualization::data->template GeometricObject(id); ++i; VCurvePathItem *path = GetCurve(static_cast(i), supportColor); const Item moved = curve->Move(length, angle).Rotate(rotationOrigin, rotationAngle); DrawPath(path, moved.GetPath(), moved.DirectionArrows(), supportColor, Qt::SolidLine, Qt::RoundCap); return i; } //--------------------------------------------------------------------------------------------------------------------- QPointF VisToolMove::GetOriginPoint(const QVector &objects) { QRectF boundingRect; for (int i=0; i < objects.size(); ++i) { QGraphicsItem *object = objects.at(i); if (object) { QRectF childrenRect = object->childrenBoundingRect(); //map to scene coordinate. childrenRect.translate(object->scenePos()); QRectF itemRect = object->boundingRect(); //map to scene coordinate. itemRect.translate(object->scenePos()); boundingRect = boundingRect.united(itemRect); boundingRect = boundingRect.united(childrenRect); } } return boundingRect.center(); } //--------------------------------------------------------------------------------------------------------------------- QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wswitch-default") QVector VisToolMove::CreateOriginObjects(int &iPoint, int &iCurve) { QVector originObjects; for (int i = 0; i < objects.size(); ++i) { const quint32 id = objects.at(i); const QSharedPointer obj = Visualization::data->GetGObject(id); // This check helps to find missed objects in the switch Q_STATIC_ASSERT_X(static_cast(GOType::Unknown) == 8, "Not all objects were handled."); switch(static_cast(obj->getType())) { case GOType::Point: { const QSharedPointer p = Visualization::data->GeometricObject(id); ++iPoint; VScaledEllipse *point = GetPoint(static_cast(iPoint), supportColor2); DrawPoint(point, static_cast(*p), supportColor2); originObjects.append(point); break; } case GOType::Arc: originObjects.append(AddOriginCurve(id, iCurve)); break; case GOType::EllipticalArc: originObjects.append(AddOriginCurve(id, iCurve)); break; case GOType::Spline: originObjects.append(AddOriginCurve(id, iCurve)); break; case GOType::SplinePath: originObjects.append(AddOriginCurve(id, iCurve)); break; case GOType::CubicBezier: originObjects.append(AddOriginCurve(id, iCurve)); break; case GOType::CubicBezierPath: originObjects.append(AddOriginCurve(id, iCurve)); break; case GOType::Unknown: case GOType::PlaceLabel: Q_UNREACHABLE(); break; } } return originObjects; } QT_WARNING_POP //--------------------------------------------------------------------------------------------------------------------- QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wswitch-default") void VisToolMove::CreateMovedRotatedObjects(int &iPoint, int &iCurve, qreal length, qreal angle, qreal rotationAngle, const QPointF &rotationOrigin) { for (int i = 0; i < objects.size(); ++i) { const quint32 id = objects.at(i); const QSharedPointer obj = Visualization::data->GetGObject(id); // This check helps to find missed objects in the switch Q_STATIC_ASSERT_X(static_cast(GOType::Unknown) == 8, "Not all objects was handled."); switch(static_cast(obj->getType())) { case GOType::Point: { const QSharedPointer p = Visualization::data->GeometricObject(id); ++iPoint; VScaledEllipse *point = GetPoint(static_cast(iPoint), supportColor); DrawPoint(point, static_cast(p->Move(length, angle).Rotate(rotationOrigin, rotationAngle)), supportColor); break; } case GOType::Arc: iCurve = AddMovedRotatedCurve(angle, length, id, iCurve, rotationAngle, rotationOrigin); break; case GOType::EllipticalArc: iCurve = AddMovedRotatedCurve(angle, length, id, iCurve, rotationAngle, rotationOrigin); break; case GOType::Spline: iCurve = AddMovedRotatedCurve(angle, length, id, iCurve, rotationAngle, rotationOrigin); break; case GOType::SplinePath: iCurve = AddMovedRotatedCurve(angle, length, id, iCurve, rotationAngle, rotationOrigin); break; case GOType::CubicBezier: iCurve = AddMovedRotatedCurve(angle, length, id, iCurve, rotationAngle, rotationOrigin); break; case GOType::CubicBezierPath: iCurve = AddMovedRotatedCurve(angle, length, id, iCurve, rotationAngle, rotationOrigin); break; case GOType::Unknown: case GOType::PlaceLabel: Q_UNREACHABLE(); break; } } } QT_WARNING_POP