diff --git a/ChangeLog.txt b/ChangeLog.txt index cc04ef6a6..ce7443c99 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -7,6 +7,7 @@ - Fix option Hide labels. - Improve segmenting a curve for calculating a piece path. - [smart-pattern/valentina#184] Fix incorrect seam allowance. +- Export area of piece in Final measurements. # Valentina 0.7.52 September 12, 2022 - Fix crash when default locale is ru. diff --git a/src/app/valentina/dialogs/dialogfinalmeasurements.cpp b/src/app/valentina/dialogs/dialogfinalmeasurements.cpp index 56b4b5c07..adcc8a596 100644 --- a/src/app/valentina/dialogs/dialogfinalmeasurements.cpp +++ b/src/app/valentina/dialogs/dialogfinalmeasurements.cpp @@ -54,6 +54,8 @@ DialogFinalMeasurements::DialogFinalMeasurements(VPattern *doc, QWidget *parent) setWindowFlags(Qt::Window); #endif + m_data.FillPiecesAreas(VAbstractValApplication::VApp()->patternUnits()); + ui->lineEditName->setClearButtonEnabled(true); ui->lineEditFind->installEventFilter(this); @@ -449,6 +451,7 @@ void DialogFinalMeasurements::Fx() dialog->setWindowTitle(tr("Edit measurement")); dialog->SetFormula(VTranslateVars::TryFormulaFromUser(ui->plainTextEditFormula->toPlainText(), VAbstractApplication::VApp()->Settings()->GetOsSeparator())); + dialog->ShowPieceArea(true); const QString postfix = UnitsToStr(VAbstractValApplication::VApp()->patternUnits(), true); dialog->setPostfix(postfix);//Show unit in dialog lable (cm, mm or inch) @@ -466,6 +469,7 @@ void DialogFinalMeasurements::Fx() void DialogFinalMeasurements::FullUpdateFromFile() { m_data = m_doc->GetCompleteData(); + m_data.FillPiecesAreas(VAbstractValApplication::VApp()->patternUnits()); m_measurements = m_doc->GetFinalMeasurements(); FillFinalMeasurements(); diff --git a/src/app/valentina/mainwindowsnogui.cpp b/src/app/valentina/mainwindowsnogui.cpp index 2f9491df1..403566b4c 100644 --- a/src/app/valentina/mainwindowsnogui.cpp +++ b/src/app/valentina/mainwindowsnogui.cpp @@ -1260,7 +1260,8 @@ bool MainWindowsNoGUI::ExportFMeasurementsToCSVData(const QString &fileName, boo } const QVector measurements = doc->GetFinalMeasurements(); - const VContainer completeData = doc->GetCompleteData(); + VContainer completeData = doc->GetCompleteData(); + completeData.FillPiecesAreas(VAbstractValApplication::VApp()->patternUnits()); for (int i=0; i < measurements.size(); ++i) { diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp index 90d54a0ae..dbf66a35e 100644 --- a/src/app/valentina/xml/vpattern.cpp +++ b/src/app/valentina/xml/vpattern.cpp @@ -532,7 +532,7 @@ void VPattern::LiteParseIncrements() data->ClearUniqueIncrementNames(); - Q_STATIC_ASSERT_X(static_cast(VarType::Unknown) == 10, "Check that you used all types"); + Q_STATIC_ASSERT_X(static_cast(VarType::Unknown) == 11, "Check that you used all types"); data->ClearVariables(VarType::Increment); data->ClearVariables(VarType::IncrementSeparator); @@ -929,6 +929,7 @@ void VPattern::ParseDetailElement(QDomElement &domElement, const Document &parse initData.id = GetParametrId(domElement); initData.detail.SetName(GetParametrString(domElement, AttrName, tr("Detail"))); initData.detail.SetUUID(GetParametrEmptyString(domElement, AttrUUID)); + initData.detail.SetShortName(GetParametrEmptyString(domElement, AttrShortName).left(25)); initData.detail.SetGradationLabel(GetParametrEmptyString(domElement, AttrGradationLabel)); initData.detail.SetMx(VAbstractValApplication::VApp() ->toPixel(GetParametrDouble(domElement, AttrMx, QStringLiteral("0.0")))); @@ -4446,13 +4447,14 @@ void VPattern::PrepareForParse(const Document &parse) } else if (parse == Document::LiteParse || parse == Document::FullLiteParse) { - Q_STATIC_ASSERT_X(static_cast(VarType::Unknown) == 10, "Check that you used all types"); - QVector types({VarType::LineAngle, - VarType::LineLength, - VarType::CurveLength, - VarType::CurveCLength, - VarType::ArcRadius, - VarType::CurveAngle}); + Q_STATIC_ASSERT_X(static_cast(VarType::Unknown) == 11, "Check that you used all types"); + QVector types{VarType::LineAngle, + VarType::LineLength, + VarType::CurveLength, + VarType::CurveCLength, + VarType::ArcRadius, + VarType::CurveAngle, + VarType::PieceArea}; if (parse == Document::FullLiteParse) { types.append(VarType::Increment); diff --git a/src/libs/ifc/ifcdef.cpp b/src/libs/ifc/ifcdef.cpp index 0050d8cdf..3494d0e5f 100644 --- a/src/libs/ifc/ifcdef.cpp +++ b/src/libs/ifc/ifcdef.cpp @@ -49,6 +49,7 @@ const QString AttrType = QStringLiteral("type"); const QString AttrMx = QStringLiteral("mx"); const QString AttrMy = QStringLiteral("my"); const QString AttrName = QStringLiteral("name"); +const QString AttrShortName = QStringLiteral("shortName"); const QString AttrUUID = QStringLiteral("uuid"); const QString AttrGradationLabel = QStringLiteral("gradationLabel"); const QString AttrMx1 = QStringLiteral("mx1"); @@ -316,31 +317,36 @@ const QString currentLength = QStringLiteral("CurrentLength"); const QString currentSeamAllowance = QStringLiteral("CurrentSeamAllowance"); const QString rotation_V = QStringLiteral("Rotation"); const QString rotationElArc_ = rotation_V + elarc_; +const QString pieceArea_ = QStringLiteral("PieceArea_"); -const QStringList builInVariables = QStringList() << measurement_ - << increment_ - << line_ - << angleLine_ - << arc_ - << elarc_ - << spl_ - << splPath - << radiusArc_ - << radius1ElArc_ - << radius2ElArc_ - << angle1Arc_ - << angle2Arc_ - << angle1ElArc_ - << angle2ElArc_ - << angle1Spl_ - << angle2Spl_ - << angle1SplPath - << angle2SplPath - << seg_ - << currentLength - << currentSeamAllowance - << c1LengthSpl_ - << c2LengthSpl_ - << c1LengthSplPath - << c2LengthSplPath - << rotationElArc_; +const QStringList builInVariables +{ + measurement_, + increment_, + line_, + angleLine_, + arc_, + elarc_, + spl_, + splPath, + radiusArc_, + radius1ElArc_, + radius2ElArc_, + angle1Arc_, + angle2Arc_, + angle1ElArc_, + angle2ElArc_, + angle1Spl_, + angle2Spl_, + angle1SplPath, + angle2SplPath, + seg_, + currentLength, + currentSeamAllowance, + c1LengthSpl_, + c2LengthSpl_, + c1LengthSplPath, + c2LengthSplPath, + rotationElArc_, + pieceArea_ +}; diff --git a/src/libs/ifc/ifcdef.h b/src/libs/ifc/ifcdef.h index 65f3be0ad..3ef04aa29 100644 --- a/src/libs/ifc/ifcdef.h +++ b/src/libs/ifc/ifcdef.h @@ -68,6 +68,7 @@ extern const QString AttrType; extern const QString AttrMx; extern const QString AttrMy; extern const QString AttrName; +extern const QString AttrShortName; extern const QString AttrUUID; extern const QString AttrGradationLabel; extern const QString AttrMx1; @@ -241,6 +242,7 @@ extern const QString currentLength; extern const QString currentSeamAllowance; extern const QString rotation_V; extern const QString rotationElArc_; +extern const QString pieceArea_; extern const QStringList builInVariables; diff --git a/src/libs/ifc/schema/pattern/v0.9.2.xsd b/src/libs/ifc/schema/pattern/v0.9.2.xsd index ef82ce847..1dbc44128 100644 --- a/src/libs/ifc/schema/pattern/v0.9.2.xsd +++ b/src/libs/ifc/schema/pattern/v0.9.2.xsd @@ -744,6 +744,7 @@ + @@ -820,7 +821,12 @@ - + + + + + + diff --git a/src/libs/qmuparser/qmudef.cpp b/src/libs/qmuparser/qmudef.cpp index 3bdd565c2..7bc8a9f6c 100644 --- a/src/libs/qmuparser/qmudef.cpp +++ b/src/libs/qmuparser/qmudef.cpp @@ -326,8 +326,8 @@ QString NameRegExp() // Here we use permanent start of string and end of string anchors \A and \z to match whole pattern as one // string. In some cases, a user may pass multiline or line that ends with a new line. To cover case with a new // line at the end of string use /z anchor. - regex = QString("\\A([^\\p{Nd}\\p{Zs}*/&|!<>^\\n\\()%1%2%3%4=?:;'\"]){1,1}" - "([^\\p{Zs}*/&|!<>^\\n\\()%1%2%3%4=?:;\"]){0,}\\z") + regex = QString("\\A([^\\p{Nd}\\p{Zs}*\\/&|!<>^\\n\\()%1%2%3%4=?:;'\"]){1,1}" + "([^\\p{Zs}*\\/&|!<>^\\n\\()%1%2%3%4=?:;\"]){0,}\\z") .arg(negativeSigns, positiveSigns, decimalPoints, groupSeparators); } diff --git a/src/libs/vlayout/vlayoutpiece.cpp b/src/libs/vlayout/vlayoutpiece.cpp index f5210b937..d8557c21b 100644 --- a/src/libs/vlayout/vlayoutpiece.cpp +++ b/src/libs/vlayout/vlayoutpiece.cpp @@ -72,6 +72,8 @@ auto ConvertInternalPaths(const VPiece &piece, const VContainer *pattern) -> QVe { SCASSERT(pattern != nullptr) + piece.TestInternalPaths(pattern); + QVector paths; const QVector pathsId = piece.GetInternalPaths(); const QVector cuttingPath = piece.CuttingPathPoints(pattern); diff --git a/src/libs/vmisc/def.h b/src/libs/vmisc/def.h index 76bef0e78..ad48cb5b3 100644 --- a/src/libs/vmisc/def.h +++ b/src/libs/vmisc/def.h @@ -275,7 +275,7 @@ enum class Vis : ToolVisHolderType }; enum class VarType : qint8 { Measurement, MeasurementSeparator, Increment, IncrementSeparator, LineLength, CurveLength, - CurveCLength, LineAngle, CurveAngle, ArcRadius, Unknown }; + CurveCLength, LineAngle, CurveAngle, ArcRadius, PieceArea, Unknown }; enum class IncrementType : qint8 { Increment, Separator }; @@ -398,9 +398,9 @@ Q_DECL_RELAXED_CONSTEXPR inline auto ToPixel(double val, const Unit &unit) -> do return 0; } -template constexpr inline auto PixelToMm(T pix) -> T { return (pix / PrintDPI) * 25.4; } -template constexpr inline auto PixelToCm(T pix) -> T { return ((pix / PrintDPI) * 25.4) / 10.0; } -template constexpr inline auto PixelToInch(T pix) -> T { return pix / PrintDPI; } +template constexpr inline auto PixelToInch(T pix) -> T {return pix / PrintDPI;} +template constexpr inline auto PixelToMm(T pix) -> T {return PixelToInch(pix) * 25.4;} +template constexpr inline auto PixelToCm(T pix) -> T {return PixelToInch(pix) * 2.54;} //--------------------------------------------------------------------------------------------------------------------- Q_DECL_RELAXED_CONSTEXPR inline auto FromPixel(double pix, const Unit &unit) -> double @@ -421,6 +421,52 @@ Q_DECL_RELAXED_CONSTEXPR inline auto FromPixel(double pix, const Unit &unit) -> return 0; } +template constexpr inline auto Inch2ToPixel2(T val) -> T {return val * (PrintDPI * PrintDPI);} +template constexpr inline auto Mm2ToPixel2(T val) -> T {return Inch2ToPixel2(val * 0.001550031);} +template constexpr inline auto Cm2ToPixel2(T val) -> T {return Inch2ToPixel2(val * 0.15500031);} + +//--------------------------------------------------------------------------------------------------------------------- +Q_DECL_RELAXED_CONSTEXPR inline auto ToPixel2(double val, const Unit &unit) -> double +{ + switch (unit) + { + case Unit::Mm: + return Mm2ToPixel2(val); + case Unit::Cm: + return Cm2ToPixel2(val); + case Unit::Inch: + return Inch2ToPixel2(val); + case Unit::Px: + return val; + default: + break; + } + return 0; +} + +template constexpr inline auto Pixel2ToInch2(T pix) -> T { return pix / (PrintDPI * PrintDPI);} +template constexpr inline auto Pixel2ToMm2(T pix) -> T { return Pixel2ToInch2(pix) / 0.001550031;} +template constexpr inline auto Pixel2ToCm2(T pix) -> T { return Pixel2ToInch2(pix) / 0.15500031;} + +//--------------------------------------------------------------------------------------------------------------------- +Q_DECL_RELAXED_CONSTEXPR inline auto FromPixel2(double pix, const Unit &unit) -> double +{ + switch (unit) + { + case Unit::Mm: + return Pixel2ToMm2(pix); + case Unit::Cm: + return Pixel2ToCm2(pix); + case Unit::Inch: + return Pixel2ToInch2(pix); + case Unit::Px: + return pix; + default: + break; + } + return 0; +} + //--------------------------------------------------------------------------------------------------------------------- Q_DECL_RELAXED_CONSTEXPR inline auto UnitConvertor(qreal value, const Unit &from, const Unit &to) -> qreal { diff --git a/src/libs/vpatterndb/variables/vincrement_p.h b/src/libs/vpatterndb/variables/vincrement_p.h index 9a67413e4..b57746eb1 100644 --- a/src/libs/vpatterndb/variables/vincrement_p.h +++ b/src/libs/vpatterndb/variables/vincrement_p.h @@ -54,15 +54,15 @@ public: { // When we create an increment in the dialog it will get neccesary data. Such data must be removed because will // confuse a user. Increment should not know nothing about internal variables. - Q_STATIC_ASSERT_X(static_cast(VarType::Unknown) == 10, "Check that you used all types"); - this->data->ClearVariables(QVector({VarType::LineAngle, - VarType::LineLength, - VarType::CurveLength, - VarType::CurveCLength, - VarType::ArcRadius, - VarType::CurveAngle, - VarType::IncrementSeparator - })); + Q_STATIC_ASSERT_X(static_cast(VarType::Unknown) == 11, "Check that you used all types"); + this->data->ClearVariables(QVector{VarType::LineAngle, + VarType::LineLength, + VarType::CurveLength, + VarType::CurveCLength, + VarType::ArcRadius, + VarType::CurveAngle, + VarType::IncrementSeparator, + VarType::PieceArea}); } VIncrementData(const VIncrementData &incr) diff --git a/src/libs/vpatterndb/variables/vlineangle.cpp b/src/libs/vpatterndb/variables/vlineangle.cpp index 27084d177..4f67802ff 100644 --- a/src/libs/vpatterndb/variables/vlineangle.cpp +++ b/src/libs/vpatterndb/variables/vlineangle.cpp @@ -78,12 +78,12 @@ VLineAngle &VLineAngle::operator=(const VLineAngle &var) return *this; } +#ifdef Q_COMPILER_RVALUE_REFS //--------------------------------------------------------------------------------------------------------------------- VLineAngle::VLineAngle(VLineAngle &&var) Q_DECL_NOTHROW :VInternalVariable(std::move(var)), d(std::move(var.d)) {} -#ifdef Q_COMPILER_RVALUE_REFS //--------------------------------------------------------------------------------------------------------------------- VLineAngle &VLineAngle::operator=(VLineAngle &&var) Q_DECL_NOTHROW { diff --git a/src/libs/vpatterndb/variables/vpiecearea.cpp b/src/libs/vpatterndb/variables/vpiecearea.cpp new file mode 100644 index 000000000..75a7a1866 --- /dev/null +++ b/src/libs/vpatterndb/variables/vpiecearea.cpp @@ -0,0 +1,107 @@ +/************************************************************************ + ** + ** @file vpiecearea.cpp + ** @author Roman Telezhynskyi + ** @date 8 11, 2022 + ** + ** @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) 2022 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 "vpiecearea.h" +#include "vpiecearea_p.h" +#include "../vpatterndb/vpiece.h" +#include "../vpatterndb/vcontainer.h" + +#include + +//--------------------------------------------------------------------------------------------------------------------- +VPieceArea::VPieceArea() + :d(new VPieceAreaData) +{ + SetType(VarType::PieceArea); +} + +//--------------------------------------------------------------------------------------------------------------------- +VPieceArea::VPieceArea(quint32 pieceId, const VPiece &piece, const VContainer *data, Unit unit) + :d(new VPieceAreaData(pieceId)) +{ + // cppcheck-suppress unknownMacro + SCASSERT(data != nullptr) + + SetType(VarType::PieceArea); + + QString shortName = piece.GetShortName(); + if (shortName.isEmpty()) + { + shortName = piece.GetName().replace(QChar(QChar::Space), '_').left(25); + if (shortName.isEmpty() || not QRegularExpression(VPiece::ShortNameRegExp()).match(shortName).hasMatch()) + { + shortName = QObject::tr("Unknown"); + } + } + SetName(pieceArea_ + shortName); + VInternalVariable::SetValue(FromPixel2(piece.Area(data), unit)); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPieceArea::operator=(const VPieceArea &var) -> VPieceArea & +{ + if ( &var == this ) + { + return *this; + } + VInternalVariable::operator=(var); + d = var.d; + return *this; +} + +#ifdef Q_COMPILER_RVALUE_REFS +//--------------------------------------------------------------------------------------------------------------------- +VPieceArea::VPieceArea(VPieceArea &&var) Q_DECL_NOTHROW + :VInternalVariable(std::move(var)), d(std::move(var.d)) +{} + +//--------------------------------------------------------------------------------------------------------------------- +VPieceArea::~VPieceArea() // NOLINT(modernize-use-equals-default) +{} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPieceArea::operator=(VPieceArea &&var) Q_DECL_NOTHROW -> VPieceArea & +{ + VInternalVariable::operator=(var); + std::swap(d, var.d); + return *this; +} +#endif + +//--------------------------------------------------------------------------------------------------------------------- +void VPieceArea::SetValue(quint32 pieceId, const VPiece &piece, const VContainer *data, Unit unit) +{ + SCASSERT(data != nullptr) + d->m_pieceId = pieceId; + VInternalVariable::SetValue(FromPixel(piece.Area(data), unit)); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPieceArea::GetPieceId() const -> quint32 +{ + return d->m_pieceId; +} diff --git a/src/libs/vpatterndb/variables/vpiecearea.h b/src/libs/vpatterndb/variables/vpiecearea.h new file mode 100644 index 000000000..d0bf0a97d --- /dev/null +++ b/src/libs/vpatterndb/variables/vpiecearea.h @@ -0,0 +1,60 @@ +/************************************************************************ + ** + ** @file vpiecearea.h + ** @author Roman Telezhynskyi + ** @date 8 11, 2022 + ** + ** @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) 2022 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 . + ** + *************************************************************************/ +#ifndef VPIECEAREA_H +#define VPIECEAREA_H + +#include "vinternalvariable.h" + +class VPiece; +class VContainer; +class VPieceAreaData; + +class VPieceArea final :public VInternalVariable +{ +public: + VPieceArea(); + explicit VPieceArea(quint32 pieceId, const VPiece &piece, const VContainer *data, Unit unit); + VPieceArea(const VPieceArea &var) = default; + ~VPieceArea() override; + + auto operator=(const VPieceArea &var) -> VPieceArea &; +#ifdef Q_COMPILER_RVALUE_REFS + VPieceArea(VPieceArea &&var) Q_DECL_NOTHROW; + auto operator=(VPieceArea &&var) Q_DECL_NOTHROW -> VPieceArea &; +#endif + + void SetValue(quint32 pieceId, const VPiece &piece, const VContainer *data, Unit unit); + + auto GetPieceId() const -> quint32; +private: + QSharedDataPointer d; +}; + +Q_DECLARE_TYPEINFO(VPieceArea, Q_MOVABLE_TYPE); // NOLINT + +#endif // VPIECEAREA_H diff --git a/src/libs/vpatterndb/variables/vpiecearea_p.h b/src/libs/vpatterndb/variables/vpiecearea_p.h new file mode 100644 index 000000000..f2c9a933a --- /dev/null +++ b/src/libs/vpatterndb/variables/vpiecearea_p.h @@ -0,0 +1,60 @@ +/************************************************************************ + ** + ** @file vpiecearea_p.h + ** @author Roman Telezhynskyi + ** @date 9 11, 2022 + ** + ** @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) 2022 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 . + ** + *************************************************************************/ +#ifndef VPIECEAREA_P_H +#define VPIECEAREA_P_H + +#include + +#include "../vmisc/defglobal.h" +#include "../vmisc/typedef.h" + +QT_WARNING_PUSH +QT_WARNING_DISABLE_GCC("-Weffc++") +QT_WARNING_DISABLE_GCC("-Wnon-virtual-dtor") + +class VPieceAreaData final : public QSharedData +{ +public: + VPieceAreaData() = default; + + explicit VPieceAreaData(quint32 pieceId) + : m_pieceId(pieceId) + {} + + VPieceAreaData(const VPieceAreaData &var) = default; + ~VPieceAreaData() = default; + + quint32 m_pieceId{NULL_ID}; // NOLINT(misc-non-private-member-variables-in-classes) + +private: + Q_DISABLE_ASSIGN_MOVE(VPieceAreaData) // NOLINT +}; + +QT_WARNING_POP + +#endif // VPIECEAREA_P_H diff --git a/src/libs/vpatterndb/vcontainer.cpp b/src/libs/vpatterndb/vcontainer.cpp index 84b89e8c6..1a9851cc4 100644 --- a/src/libs/vpatterndb/vcontainer.cpp +++ b/src/libs/vpatterndb/vcontainer.cpp @@ -52,6 +52,7 @@ #include "variables/vlineangle.h" #include "variables/vlinelength.h" #include "variables/vmeasurement.h" +#include "variables/vpiecearea.h" #include "vtranslatevars.h" QT_WARNING_PUSH @@ -391,15 +392,16 @@ void VContainer::ClearForFullParse() d->pieces->clear(); d->piecePaths->clear(); - Q_STATIC_ASSERT_X(static_cast(VarType::Unknown) == 10, "Check that you used all types"); - ClearVariables(QVector({VarType::Increment, - VarType::IncrementSeparator, - VarType::LineAngle, - VarType::LineLength, - VarType::CurveLength, - VarType::CurveCLength, - VarType::ArcRadius, - VarType::CurveAngle})); + Q_STATIC_ASSERT_X(static_cast(VarType::Unknown) == 11, "Check that you used all types"); + ClearVariables(QVector{VarType::Increment, + VarType::IncrementSeparator, + VarType::LineAngle, + VarType::LineLength, + VarType::CurveLength, + VarType::CurveCLength, + VarType::ArcRadius, + VarType::CurveAngle, + VarType::PieceArea}); ClearGObjects(); ClearUniqueNames(); } @@ -570,6 +572,19 @@ void VContainer::RemoveIncrement(const QString &name) d->variables.remove(name); } +//--------------------------------------------------------------------------------------------------------------------- +void VContainer::FillPiecesAreas(Unit unit) +{ + QHash *pieces = d->pieces.data(); + + auto i = pieces->constBegin(); + while (i != pieces->constEnd()) + { + AddVariable(QSharedPointer::create(i.key(), i.value(), this, unit)); + ++i; + } +} + //--------------------------------------------------------------------------------------------------------------------- const QMap > VContainer::DataMeasurements() const { @@ -650,6 +665,12 @@ const QMap > VContainer::DataAnglesCurves() return DataVar(VarType::CurveAngle); } +//--------------------------------------------------------------------------------------------------------------------- +const QMap > VContainer::DataPieceArea() const +{ + return DataVar(VarType::PieceArea); +} + //--------------------------------------------------------------------------------------------------------------------- bool VContainer::IsUnique(const QString &name) const { diff --git a/src/libs/vpatterndb/vcontainer.h b/src/libs/vpatterndb/vcontainer.h index 772eb2247..d445a8320 100644 --- a/src/libs/vpatterndb/vcontainer.h +++ b/src/libs/vpatterndb/vcontainer.h @@ -58,6 +58,15 @@ #include "vtranslatevars.h" class VEllipticalArc; +class VMeasurement; +class VIncrement; +class VLengthLine; +class VCurveLength; +class VCurveCLength; +class VLineAngle; +class VArcRadius; +class VCurveAngle; +class VPieceArea; QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Weffc++") @@ -195,6 +204,8 @@ public: void RemoveIncrement(const QString& name); + void FillPiecesAreas(Unit unit); + const QHash > *CalculationGObjects() const; const QHash *DataPieces() const; const QHash> *DataVariables() const; @@ -209,6 +220,7 @@ public: const QMap > DataAngleLines() const; const QMap > DataRadiusesArcs() const; const QMap > DataAnglesCurves() const; + const QMap > DataPieceArea() const; bool IsUnique(const QString &name) const; static bool IsUnique(const QString &name, const QString &nspace); diff --git a/src/libs/vpatterndb/vpatterndb.pri b/src/libs/vpatterndb/vpatterndb.pri index 801b974a2..2c4d8391c 100644 --- a/src/libs/vpatterndb/vpatterndb.pri +++ b/src/libs/vpatterndb/vpatterndb.pri @@ -3,6 +3,7 @@ SOURCES += \ $$PWD/testpassmark.cpp \ + $$PWD/variables/vpiecearea.cpp \ $$PWD/vcontainer.cpp \ $$PWD/calculator.cpp \ $$PWD/vnodedetail.cpp \ @@ -34,6 +35,8 @@ SOURCES += \ HEADERS += \ $$PWD/testpassmark.h \ + $$PWD/variables/vpiecearea.h \ + $$PWD/variables/vpiecearea_p.h \ $$PWD/vcontainer.h \ $$PWD/stable.h \ $$PWD/calculator.h \ diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp index 69e270b17..3b61905ef 100644 --- a/src/libs/vpatterndb/vpiece.cpp +++ b/src/libs/vpatterndb/vpiece.cpp @@ -37,8 +37,10 @@ #include "../vmisc/vabstractvalapplication.h" #include "../vmisc/compatibility.h" #include "../ifc/exception/vexceptioninvalidnotch.h" +#include "../ifc/exception/vexceptionobjecterror.h" #include "../vmisc/testpath.h" #include "../ifc/xml/vabstractpattern.h" +#include "../vpatterndb/vpiecenode.h" #include #include @@ -390,6 +392,18 @@ void VPiece::SetUnited(bool united) d->m_united = united; } +//--------------------------------------------------------------------------------------------------------------------- +auto VPiece::GetShortName() const -> QString +{ + return d->m_shortName; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPiece::SetShortName(const QString &value) +{ + d->m_shortName = value; +} + //--------------------------------------------------------------------------------------------------------------------- QString VPiece::GetFormulaSAWidth() const { @@ -1197,6 +1211,126 @@ auto VPiece::GlobalPassmarkLength(const VContainer *data) const -> qreal return length; } +//--------------------------------------------------------------------------------------------------------------------- +void VPiece::TestInternalPathCuttingPathIntersection(const VContainer *data) const +{ + SCASSERT(data != nullptr) + + const QVector cuttingPoints = CuttingPathPoints(data); + const QPainterPath contourPath = VAbstractPiece::PainterPath(cuttingPoints); + + // Internal path for cutting must not intersect cutting contour and be inside of it. + const QVector pathsId = GetInternalPaths(); + for (auto id : pathsId) + { + const VPiecePath path = data->GetPiecePath(id); + if (path.GetType() != PiecePathType::InternalPath || not path.IsVisible(data->DataVariables()) || + not path.IsCutPath()) + { + continue; + } + + QVector points; + CastTo(path.PathPoints(data, cuttingPoints), points); + if (points.isEmpty() || not VFuzzyComparePoints(ConstFirst(points), ConstLast(points))) + { + continue; + } + + const QPainterPath internalPath = VAbstractPiece::PainterPath(points); + + if (internalPath.intersects(contourPath)) + { + const QString errorMsg = QObject::tr("Piece '%1'. Internal path '%2' intersects with cutting " + "countour.").arg(GetName(), path.GetName()); + VAbstractApplication::VApp()->IsPedantic() ? throw VExceptionObjectError(errorMsg) : + qWarning() << VAbstractValApplication::warningMessageSignature + errorMsg; + continue; + } + + if (not contourPath.contains(internalPath)) + { + const QString errorMsg = QObject::tr("Piece '%1'. Internal path '%2' not inside of cutting " + "countour.").arg(GetName(), path.GetName()); + VAbstractApplication::VApp()->IsPedantic() ? throw VExceptionObjectError(errorMsg) : + qWarning() << VAbstractValApplication::warningMessageSignature + errorMsg; + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPiece::TestInternalPathsIntersections(const VContainer *data) const +{ + SCASSERT(data != nullptr) + + const QVector pathsId = GetInternalPaths(); + + if (pathsId.isEmpty()) + { + return; + } + + const QVector cuttingPoints = CuttingPathPoints(data); + + // Internal pieces for cutting must not intersect + QSet> pairs; + for (int k=0; k < pathsId.size(); ++k) + { + const VPiecePath path1 = data->GetPiecePath(pathsId.at(k)); + + if (path1.GetType() != PiecePathType::InternalPath || not path1.IsVisible(data->DataVariables()) || + not path1.IsCutPath()) + { + continue; + } + + QVector pointsPath1; + CastTo(path1.PathPoints(data, cuttingPoints), pointsPath1); + if (pointsPath1.isEmpty() || not VFuzzyComparePoints(ConstFirst(pointsPath1), ConstLast(pointsPath1))) + { + continue; + } + + const QPainterPath painterPath1 = VAbstractPiece::PainterPath(pointsPath1); + + for (int i=0; i < pathsId.size(); ++i) + { + if (k == i || pairs.contains(qMakePair(k, i)) || pairs.contains(qMakePair(i, k))) + { + continue; + } + + const VPiecePath path2 = data->GetPiecePath(pathsId.at(i)); + + if (path2.GetType() != PiecePathType::InternalPath || not path2.IsVisible(data->DataVariables()) || + not path2.IsCutPath()) + { + continue; + } + + QVector pointsPath2; + CastTo(path2.PathPoints(data, cuttingPoints), pointsPath2); + if (pointsPath2.isEmpty() || not VFuzzyComparePoints(ConstFirst(pointsPath2), ConstLast(pointsPath2))) + { + continue; + } + + const QPainterPath painterPath2 = VAbstractPiece::PainterPath(pointsPath2); + + pairs.insert(qMakePair(k, i)); + pairs.insert(qMakePair(i, k)); + + if (painterPath1.intersects(painterPath2)) + { + const QString errorMsg = QObject::tr("Piece '%1'. Internal path '%2' intersects with internal path " + "'%3'.").arg(GetName(), path1.GetName(), path2.GetName()); + VAbstractApplication::VApp()->IsPedantic() ? throw VExceptionObjectError(errorMsg) : + qWarning() << VAbstractValApplication::warningMessageSignature + errorMsg; + } + } + } +} + //--------------------------------------------------------------------------------------------------------------------- void VPiece::DumpPiece(const VPiece &piece, const VContainer *data, const QString &templateName) { @@ -1239,4 +1373,96 @@ void VPiece::DumpPiece(const VPiece &piece, const VContainer *data, const QStrin out.flush(); } } + +//--------------------------------------------------------------------------------------------------------------------- +void VPiece::TestInternalPaths(const VContainer *data) const +{ + TestInternalPathCuttingPathIntersection(data); + TestInternalPathsIntersections(data); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPiece::Area(const VContainer *data) const -> qreal +{ + SCASSERT(data != nullptr) + + const QVector mainContour = CuttingPathPoints(data); + const qreal mainArea = qAbs(VAbstractPiece::SumTrapezoids(mainContour))/2.0; + + qreal internalPathArea = 0; + const QVector pathsId = GetInternalPaths(); + for (auto id : pathsId) + { + const VPiecePath path = data->GetPiecePath(id); + if (path.GetType() != PiecePathType::InternalPath || not path.IsVisible(data->DataVariables()) || + not path.IsCutPath()) + { + continue; + } + + QVector points; + CastTo(path.PathPoints(data, mainContour), points); + if (points.isEmpty() || not VFuzzyComparePoints(ConstFirst(points), ConstLast(points))) + { + continue; + } + + internalPathArea += qAbs(VAbstractPiece::SumTrapezoids(points))/2.0; + } + + return mainArea - internalPathArea; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPiece::ShortNameRegExp() -> QString +{ + static QString regex; + + if (regex.isEmpty()) + { + const QList allLocales = + QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry); + + QString positiveSigns; + QString negativeSigns; + QString decimalPoints; + QString groupSeparators; + + for(const auto &locale : allLocales) + { + if (not positiveSigns.contains(locale.positiveSign())) + { + positiveSigns.append(locale.positiveSign()); + } + + if (not negativeSigns.contains(locale.negativeSign())) + { + negativeSigns.append(locale.negativeSign()); + } + + if (not decimalPoints.contains(locale.decimalPoint())) + { + decimalPoints.append(locale.decimalPoint()); + } + + if (not groupSeparators.contains(locale.groupSeparator())) + { + groupSeparators.append(locale.groupSeparator()); + } + } + + negativeSigns.replace('-', QLatin1String("\\-")); + groupSeparators.remove('\''); + + //Same regexp in pattern.xsd shema file. Don't forget to synchronize. + // \p{Zs} - \p{Space_Separator} + // Here we use permanent start of string and end of string anchors \A and \z to match whole pattern as one + // string. In some cases, a user may pass multiline or line that ends with a new line. To cover case with a new + // line at the end of string use /z anchor. + regex = QStringLiteral("\\A([^\\p{Zs}*\\/&|!<>^\\n\\()%1%2%3%4=?:;\"]){0,}\\z") + .arg(negativeSigns, positiveSigns, decimalPoints, groupSeparators); + } + + return regex; +} #endif // !defined(V_NO_ASSERT) diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h index 72ed7a6aa..1fafabe79 100644 --- a/src/libs/vpatterndb/vpiece.h +++ b/src/libs/vpatterndb/vpiece.h @@ -92,6 +92,9 @@ public: bool IsUnited() const; void SetUnited(bool united); + auto GetShortName() const -> QString; + void SetShortName(const QString &value); + QString GetFormulaSAWidth() const; void SetFormulaSAWidth(const QString &formula, qreal value); @@ -138,6 +141,11 @@ public: auto GetGradationLabel() const -> QString; static void DumpPiece(const VPiece &piece, const VContainer *data, const QString &templateName=QString()); + + void TestInternalPaths(const VContainer *data) const; + + static auto ShortNameRegExp() -> QString; + auto Area(const VContainer *data) const -> qreal; private: QSharedDataPointer d; @@ -163,6 +171,9 @@ private: QJsonObject DBToJson(const VContainer *data) const; qreal GlobalPassmarkLength(const VContainer *data) const; + + void TestInternalPathCuttingPathIntersection(const VContainer *data) const; + void TestInternalPathsIntersections(const VContainer *data) const; }; Q_DECLARE_TYPEINFO(VPiece, Q_MOVABLE_TYPE); // NOLINT diff --git a/src/libs/vpatterndb/vpiece_p.h b/src/libs/vpatterndb/vpiece_p.h index ee855fe69..ed58e47c8 100644 --- a/src/libs/vpatterndb/vpiece_p.h +++ b/src/libs/vpatterndb/vpiece_p.h @@ -80,6 +80,8 @@ public: QString m_gradationLabel{}; // NOLINT(misc-non-private-member-variables-in-classes) + QString m_shortName{}; // NOLINT(misc-non-private-member-variables-in-classes) + private: Q_DISABLE_ASSIGN_MOVE(VPieceData) // NOLINT }; diff --git a/src/libs/vpatterndb/vtranslatevars.cpp b/src/libs/vpatterndb/vtranslatevars.cpp index 713b7e586..fa700106e 100644 --- a/src/libs/vpatterndb/vtranslatevars.cpp +++ b/src/libs/vpatterndb/vtranslatevars.cpp @@ -393,6 +393,7 @@ void VTranslateVars::InitVariables() variables.insert(c2LengthSplPath, translate("VTranslateVars", "C2LengthSplPath", "Do not add symbol _ to the end of the name")); variables.insert(rotationElArc_, translate("VTranslateVars", "RotationElArc_", "Left symbol _ in the name")); + variables.insert(pieceArea_, translate("VTranslateVars", "PieceArea_", "Left symbol _ in the name")); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vtools/dialogs/support/dialogeditwrongformula.cpp b/src/libs/vtools/dialogs/support/dialogeditwrongformula.cpp index 7d8eca39d..426173cc7 100644 --- a/src/libs/vtools/dialogs/support/dialogeditwrongformula.cpp +++ b/src/libs/vtools/dialogs/support/dialogeditwrongformula.cpp @@ -63,6 +63,7 @@ #include "../vpatterndb/variables/vlineangle.h" #include "../vpatterndb/variables/vlinelength.h" #include "../vpatterndb/variables/vmeasurement.h" +#include "../vpatterndb/variables/vpiecearea.h" #include "../vmisc/def.h" #include "../vmisc/vabstractapplication.h" #include "../vmisc/vcommonsettings.h" @@ -85,6 +86,8 @@ DialogEditWrongFormula::DialogEditWrongFormula(const VContainer *data, quint32 t ui->setupUi(this); + ui->radioButtonPieceArea->setVisible(false); + timerFormula->setSingleShot(true); connect(timerFormula, &QTimer::timeout, this, &DialogEditWrongFormula::EvalFormula); @@ -233,6 +236,34 @@ void DialogEditWrongFormula::ValChanged(int row) SetDescription(item->text(), *m_data->GetVariable(name)->GetValue(), specialUnits, tr("Curve angle")); } + else if (ui->radioButtonCLength->isChecked()) + { + const bool specialUnits = false; + SetDescription(item->text(), *m_data->GetVariable(name)->GetValue(), specialUnits, + tr("Length to control point")); + } + else if (ui->radioButtonPieceArea->isChecked()) + { + const bool specialUnits = false; + const QSharedPointer var = m_data->GetVariable(name); + QString description = tr("Area of piece"); + + try + { + VPiece piece = m_data->GetPiece(var->GetPieceId()); + QString name = piece.GetName(); + if (not name.isEmpty()) + { + description += QStringLiteral(" '%1'").arg(piece.GetName()); + } + } + catch (const VExceptionBadId &) + { + // do nothing + } + + SetDescription(item->text(), *var->GetValue(), specialUnits, description, true); + } else if (ui->radioButtonFunctions->isChecked()) { ui->labelDescription->setText(item->toolTip()); @@ -356,6 +387,13 @@ void DialogEditWrongFormula::PreviewCalculations() ShowIncrementsInPreviewCalculation(true); } +//--------------------------------------------------------------------------------------------------------------------- +void DialogEditWrongFormula::PieceArea() +{ + ui->checkBoxHideEmpty->setEnabled(false); + ShowVariable(m_data->DataPieceArea()); +} + //--------------------------------------------------------------------------------------------------------------------- /** * @brief Functions show in list functions @@ -479,6 +517,12 @@ void DialogEditWrongFormula::SetPreviewCalculationsMode() ui->radioButtonCLength->setDisabled(true); } +//--------------------------------------------------------------------------------------------------------------------- +void DialogEditWrongFormula::ShowPieceArea(bool show) const +{ + ui->radioButtonPieceArea->setVisible(show); +} + //--------------------------------------------------------------------------------------------------------------------- auto DialogEditWrongFormula::GetFormula() const -> QString { @@ -523,6 +567,9 @@ void DialogEditWrongFormula::InitVariables() connect(ui->radioButtonCLength, &QRadioButton::clicked, this, &DialogEditWrongFormula::CurvesCLength); connect(ui->radioButtonCLength, &QRadioButton::clicked, this, ClearFilterFormulaInputs); + connect(ui->radioButtonPieceArea, &QRadioButton::clicked, this, &DialogEditWrongFormula::PieceArea); + connect(ui->radioButtonPieceArea, &QRadioButton::clicked, this, ClearFilterFormulaInputs); + connect(ui->radioButtonFunctions, &QRadioButton::clicked, this, &DialogEditWrongFormula::Functions); connect(ui->radioButtonFunctions, &QRadioButton::clicked, this, ClearFilterFormulaInputs); @@ -531,9 +578,15 @@ void DialogEditWrongFormula::InitVariables() //--------------------------------------------------------------------------------------------------------------------- void DialogEditWrongFormula::SetDescription(const QString &name, qreal value, bool specialUnits, - const QString &description) + const QString &description, bool square) { - const QString unit = specialUnits ? degreeSymbol : ' ' + postfix; + QString unitName = postfix; + if (not specialUnits && square) + { + unitName += QStringLiteral("²"); + } + + const QString unit = specialUnits ? degreeSymbol : ' ' + unitName; const QString desc = QStringLiteral("%1(%2%3) - %4").arg(name).arg(value).arg(unit, description); ui->labelDescription->setText(desc); } diff --git a/src/libs/vtools/dialogs/support/dialogeditwrongformula.h b/src/libs/vtools/dialogs/support/dialogeditwrongformula.h index 52635c1ed..39ede8918 100644 --- a/src/libs/vtools/dialogs/support/dialogeditwrongformula.h +++ b/src/libs/vtools/dialogs/support/dialogeditwrongformula.h @@ -72,6 +72,7 @@ public: void SetMeasurementsMode(); void SetIncrementsMode(); void SetPreviewCalculationsMode(); + void ShowPieceArea(bool show) const; public slots: virtual void DialogAccepted(); virtual void DialogRejected(); @@ -90,6 +91,7 @@ public slots: void AngleLines(); void Increments(); void PreviewCalculations(); + void PieceArea(); void Functions(); signals: /** @@ -144,7 +146,8 @@ private: void ShowFunctions(); void ShowIncrementsInPreviewCalculation(bool show); - void SetDescription(const QString &name, qreal value, bool specialUnits, const QString &description); + void SetDescription(const QString &name, qreal value, bool specialUnits, const QString &description, + bool square = false); auto Eval(const FormulaData &formulaData, bool &flag) -> qreal; }; diff --git a/src/libs/vtools/dialogs/support/dialogeditwrongformula.ui b/src/libs/vtools/dialogs/support/dialogeditwrongformula.ui index fa9c4c89a..d1c282ddc 100644 --- a/src/libs/vtools/dialogs/support/dialogeditwrongformula.ui +++ b/src/libs/vtools/dialogs/support/dialogeditwrongformula.ui @@ -10,7 +10,7 @@ 0 0 542 - 481 + 483 @@ -171,7 +171,7 @@ true - + @@ -309,6 +309,13 @@ + + + + Pieces areas + + + diff --git a/src/libs/vtools/dialogs/tools/piece/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/piece/dialogseamallowance.cpp index ffa5bc600..83c303299 100644 --- a/src/libs/vtools/dialogs/tools/piece/dialogseamallowance.cpp +++ b/src/libs/vtools/dialogs/tools/piece/dialogseamallowance.cpp @@ -357,6 +357,7 @@ void DialogSeamAllowance::SetPiece(const VPiece &piece) uiTabPaths->checkBoxBuiltIn->setChecked(piece.IsSeamAllowanceBuiltIn()); uiTabPaths->lineEditName->setText(piece.GetName()); uiTabPaths->lineEditUUID->setText(piece.GetUUID().toString()); + uiTabPaths->lineEditShortName->setText(piece.GetShortName()); uiTabPaths->lineEditGradationLabel->setText(piece.GetGradationLabel()); uiTabPaths->spinBoxPriority->setValue(static_cast(piece.GetPriority())); @@ -2600,6 +2601,7 @@ VPiece DialogSeamAllowance::CreatePiece() const piece.SetHideMainPath(uiTabPaths->checkBoxHideMainPath->isChecked()); piece.SetName(uiTabPaths->lineEditName->text()); piece.SetUUID(uiTabPaths->lineEditUUID->text()); + piece.SetShortName(uiTabPaths->lineEditShortName->text()); piece.SetGradationLabel(uiTabPaths->lineEditGradationLabel->text()); piece.SetPriority(static_cast(uiTabPaths->spinBoxPriority->value())); piece.SetFormulaSAWidth(GetFormulaFromUser(uiTabPaths->plainTextEditFormulaWidth), m_saWidth); @@ -3026,6 +3028,9 @@ void DialogSeamAllowance::InitPieceTab() { connect(uiTabPaths->lineEditName, &QLineEdit::textChanged, this, &DialogSeamAllowance::NameDetailChanged); + uiTabPaths->lineEditShortName->setValidator( + new QRegularExpressionValidator(QRegularExpression(VPiece::ShortNameRegExp()), this)); + uiTabPaths->lineEditName->setClearButtonEnabled(true); uiTabPaths->lineEditName->setText(GetDefaultPieceName()); diff --git a/src/libs/vtools/dialogs/tools/piece/tabs/tabpaths.ui b/src/libs/vtools/dialogs/tools/piece/tabs/tabpaths.ui index 39848c017..c38c17caa 100644 --- a/src/libs/vtools/dialogs/tools/piece/tabs/tabpaths.ui +++ b/src/libs/vtools/dialogs/tools/piece/tabs/tabpaths.ui @@ -207,6 +207,19 @@ + + + + Universally Unique IDentifier of piece. Used to identifier piece while updating manual layout. Left empty to generate new value. + + + {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} + + + true + + + @@ -217,7 +230,7 @@ - + Priority: @@ -231,41 +244,28 @@ - - - - Controls priority in layout. 0 - no priority. - - - - - - - Universally Unique IDentifier of piece. Used to identifier piece while updating manual layout. Left empty to generate new value. - - - {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} - - - true - - - - - - - UUID: - - - - + Gradation label: - + + + + UUID: + + + + + + + Controls priority in layout. 0 - no priority. + + + + @@ -286,6 +286,23 @@ + + + + Short name: + + + + + + + Name used to generate a variable + + + 25 + + + diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp index 59f38f651..75da7eaf8 100644 --- a/src/libs/vtools/tools/vtoolseamallowance.cpp +++ b/src/libs/vtools/tools/vtoolseamallowance.cpp @@ -335,7 +335,7 @@ void VToolSeamAllowance::InsertNodes(const QVector &nodes, quint32 p newDet.GetPath().Append(node); // Seam allowance tool already initializated and can't init the node - VToolSeamAllowance *saTool = qobject_cast(VAbstractPattern::getTool(pieceId)); + auto *saTool = qobject_cast(VAbstractPattern::getTool(pieceId)); SCASSERT(saTool != nullptr); InitNode(node, scene, saTool); @@ -352,6 +352,8 @@ void VToolSeamAllowance::AddAttributes(VAbstractPattern *doc, QDomElement &domEl doc->SetAttribute(domElement, VDomDocument::AttrId, id); doc->SetAttribute(domElement, AttrName, piece.GetName()); + doc->SetAttributeOrRemoveIf(domElement, AttrShortName, piece.GetShortName(), + [](const QString &name) noexcept {return name.isEmpty();}); doc->SetAttribute(domElement, AttrUUID, piece.GetUUID().toString()); doc->SetAttributeOrRemoveIf(domElement, AttrGradationLabel, piece.GetGradationLabel(), [](const QString &label) noexcept {return label.isEmpty();}); @@ -1365,7 +1367,9 @@ void VToolSeamAllowance::UpdateExcludeState() //--------------------------------------------------------------------------------------------------------------------- void VToolSeamAllowance::UpdateInternalPaths() { - const QVector paths = VAbstractTool::data.GetPiece(m_id).GetInternalPaths(); + VPiece piece = VAbstractTool::data.GetPiece(m_id); + piece.TestInternalPaths(&(VAbstractTool::data)); + const QVector paths = piece.GetInternalPaths(); for (auto path : paths) { try diff --git a/src/test/TranslationsTest/tst_buitinregexp.cpp b/src/test/TranslationsTest/tst_buitinregexp.cpp index a24030283..f3d9a3bd6 100644 --- a/src/test/TranslationsTest/tst_buitinregexp.cpp +++ b/src/test/TranslationsTest/tst_buitinregexp.cpp @@ -170,6 +170,7 @@ void TST_BuitInRegExp::TestCheckUnderlineExists_data() data.insert(c1LengthSplPath, false); data.insert(c2LengthSplPath, false); data.insert(rotationElArc_, true); + data.insert(pieceArea_, true); //Catch case when new internal variable appears. QCOMPARE(data.size(), builInVariables.size()); diff --git a/src/test/ValentinaTest/tst_vabstractpiece.cpp b/src/test/ValentinaTest/tst_vabstractpiece.cpp index ec87c2c0b..37d7c48da 100644 --- a/src/test/ValentinaTest/tst_vabstractpiece.cpp +++ b/src/test/ValentinaTest/tst_vabstractpiece.cpp @@ -29,6 +29,8 @@ #include "tst_vabstractpiece.h" #include "../vlayout/vabstractpiece.h" #include "../vlayout/vrawsapoint.h" +#include "../vgeometry/varc.h" +#include "../vgeometry/vpointf.h" #include #include @@ -379,6 +381,57 @@ void TST_VAbstractPiece::SumTrapezoids() const Case5(); } +//--------------------------------------------------------------------------------------------------------------------- +void TST_VAbstractPiece::TestAreaCalculation_data() +{ + QTest::addColumn>("path"); + QTest::addColumn("excpectedArea"); + + { + QVector rect + { + QPointF(), + QPointF(100, 0), + QPointF(100, 50), + QPointF(0, 50), + QPointF() + }; + + QTest::newRow("Rectangle 100 x 50") << rect << 100.0 * 50.0; + } + + { + VArc circle(VPointF(100, 100, QChar('C'), 0, 0), 100, 35, 35); + circle.SetApproximationScale(maxCurveApproximationScale); + QVector circlePath = circle.GetPoints(); + if (not circlePath.isEmpty() && not VFuzzyComparePoints(ConstFirst(circlePath), ConstLast(circlePath))) + { + circlePath.append(ConstFirst(circlePath)); + } + QTest::newRow("Circle radis 100") << circlePath << M_PI * pow(100, 2); + } + + { + VPointF sectorCenter(100, 100, QChar('C'), 0, 0); + VArc sector(sectorCenter, 100, 15, 45); + sector.SetApproximationScale(maxCurveApproximationScale); + QVector sectorPath = sector.GetPoints(); + sectorPath.append(sectorCenter.toQPointF()); + sectorPath.append(ConstFirst(sectorPath)); + QTest::newRow("Sector radius 100, 30 degree") << sectorPath << (M_PI * pow(100, 2) * 30.0) / 360.0; + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void TST_VAbstractPiece::TestAreaCalculation() const +{ + QFETCH(QVector, path); + QFETCH(qreal, excpectedArea); + + const qreal result = qAbs(VAbstractPiece::SumTrapezoids(path)/2.0); + QVERIFY(qAbs(result - excpectedArea) < MmToPixel(1.0)); +} + //--------------------------------------------------------------------------------------------------------------------- void TST_VAbstractPiece::RawPathRemoveLoop_data() const { diff --git a/src/test/ValentinaTest/tst_vabstractpiece.h b/src/test/ValentinaTest/tst_vabstractpiece.h index 78a8c822c..17f1d6aeb 100644 --- a/src/test/ValentinaTest/tst_vabstractpiece.h +++ b/src/test/ValentinaTest/tst_vabstractpiece.h @@ -45,6 +45,8 @@ private slots: void LayoutAllowanceRemoveLoop_data(); void LayoutAllowanceRemoveLoop() const; void SumTrapezoids() const; + void TestAreaCalculation_data(); + void TestAreaCalculation() const; void RawPathRemoveLoop_data() const; void RawPathRemoveLoop() const; void PathRemoveLoop_data() const;