Export area of piece in Final measurements.

This commit is contained in:
Roman Telezhynskyi 2022-11-10 11:30:08 +02:00
parent b4256fb500
commit d6e417b197
31 changed files with 817 additions and 99 deletions

View file

@ -7,6 +7,7 @@
- Fix option Hide labels. - Fix option Hide labels.
- Improve segmenting a curve for calculating a piece path. - Improve segmenting a curve for calculating a piece path.
- [smart-pattern/valentina#184] Fix incorrect seam allowance. - [smart-pattern/valentina#184] Fix incorrect seam allowance.
- Export area of piece in Final measurements.
# Valentina 0.7.52 September 12, 2022 # Valentina 0.7.52 September 12, 2022
- Fix crash when default locale is ru. - Fix crash when default locale is ru.

View file

@ -54,6 +54,8 @@ DialogFinalMeasurements::DialogFinalMeasurements(VPattern *doc, QWidget *parent)
setWindowFlags(Qt::Window); setWindowFlags(Qt::Window);
#endif #endif
m_data.FillPiecesAreas(VAbstractValApplication::VApp()->patternUnits());
ui->lineEditName->setClearButtonEnabled(true); ui->lineEditName->setClearButtonEnabled(true);
ui->lineEditFind->installEventFilter(this); ui->lineEditFind->installEventFilter(this);
@ -449,6 +451,7 @@ void DialogFinalMeasurements::Fx()
dialog->setWindowTitle(tr("Edit measurement")); dialog->setWindowTitle(tr("Edit measurement"));
dialog->SetFormula(VTranslateVars::TryFormulaFromUser(ui->plainTextEditFormula->toPlainText(), dialog->SetFormula(VTranslateVars::TryFormulaFromUser(ui->plainTextEditFormula->toPlainText(),
VAbstractApplication::VApp()->Settings()->GetOsSeparator())); VAbstractApplication::VApp()->Settings()->GetOsSeparator()));
dialog->ShowPieceArea(true);
const QString postfix = UnitsToStr(VAbstractValApplication::VApp()->patternUnits(), true); const QString postfix = UnitsToStr(VAbstractValApplication::VApp()->patternUnits(), true);
dialog->setPostfix(postfix);//Show unit in dialog lable (cm, mm or inch) dialog->setPostfix(postfix);//Show unit in dialog lable (cm, mm or inch)
@ -466,6 +469,7 @@ void DialogFinalMeasurements::Fx()
void DialogFinalMeasurements::FullUpdateFromFile() void DialogFinalMeasurements::FullUpdateFromFile()
{ {
m_data = m_doc->GetCompleteData(); m_data = m_doc->GetCompleteData();
m_data.FillPiecesAreas(VAbstractValApplication::VApp()->patternUnits());
m_measurements = m_doc->GetFinalMeasurements(); m_measurements = m_doc->GetFinalMeasurements();
FillFinalMeasurements(); FillFinalMeasurements();

View file

@ -1260,7 +1260,8 @@ bool MainWindowsNoGUI::ExportFMeasurementsToCSVData(const QString &fileName, boo
} }
const QVector<VFinalMeasurement> measurements = doc->GetFinalMeasurements(); const QVector<VFinalMeasurement> 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) for (int i=0; i < measurements.size(); ++i)
{ {

View file

@ -532,7 +532,7 @@ void VPattern::LiteParseIncrements()
data->ClearUniqueIncrementNames(); data->ClearUniqueIncrementNames();
Q_STATIC_ASSERT_X(static_cast<int>(VarType::Unknown) == 10, "Check that you used all types"); Q_STATIC_ASSERT_X(static_cast<int>(VarType::Unknown) == 11, "Check that you used all types");
data->ClearVariables(VarType::Increment); data->ClearVariables(VarType::Increment);
data->ClearVariables(VarType::IncrementSeparator); data->ClearVariables(VarType::IncrementSeparator);
@ -929,6 +929,7 @@ void VPattern::ParseDetailElement(QDomElement &domElement, const Document &parse
initData.id = GetParametrId(domElement); initData.id = GetParametrId(domElement);
initData.detail.SetName(GetParametrString(domElement, AttrName, tr("Detail"))); initData.detail.SetName(GetParametrString(domElement, AttrName, tr("Detail")));
initData.detail.SetUUID(GetParametrEmptyString(domElement, AttrUUID)); initData.detail.SetUUID(GetParametrEmptyString(domElement, AttrUUID));
initData.detail.SetShortName(GetParametrEmptyString(domElement, AttrShortName).left(25));
initData.detail.SetGradationLabel(GetParametrEmptyString(domElement, AttrGradationLabel)); initData.detail.SetGradationLabel(GetParametrEmptyString(domElement, AttrGradationLabel));
initData.detail.SetMx(VAbstractValApplication::VApp() initData.detail.SetMx(VAbstractValApplication::VApp()
->toPixel(GetParametrDouble(domElement, AttrMx, QStringLiteral("0.0")))); ->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) else if (parse == Document::LiteParse || parse == Document::FullLiteParse)
{ {
Q_STATIC_ASSERT_X(static_cast<int>(VarType::Unknown) == 10, "Check that you used all types"); Q_STATIC_ASSERT_X(static_cast<int>(VarType::Unknown) == 11, "Check that you used all types");
QVector<VarType> types({VarType::LineAngle, QVector<VarType> types{VarType::LineAngle,
VarType::LineLength, VarType::LineLength,
VarType::CurveLength, VarType::CurveLength,
VarType::CurveCLength, VarType::CurveCLength,
VarType::ArcRadius, VarType::ArcRadius,
VarType::CurveAngle}); VarType::CurveAngle,
VarType::PieceArea};
if (parse == Document::FullLiteParse) if (parse == Document::FullLiteParse)
{ {
types.append(VarType::Increment); types.append(VarType::Increment);

View file

@ -49,6 +49,7 @@ const QString AttrType = QStringLiteral("type");
const QString AttrMx = QStringLiteral("mx"); const QString AttrMx = QStringLiteral("mx");
const QString AttrMy = QStringLiteral("my"); const QString AttrMy = QStringLiteral("my");
const QString AttrName = QStringLiteral("name"); const QString AttrName = QStringLiteral("name");
const QString AttrShortName = QStringLiteral("shortName");
const QString AttrUUID = QStringLiteral("uuid"); const QString AttrUUID = QStringLiteral("uuid");
const QString AttrGradationLabel = QStringLiteral("gradationLabel"); const QString AttrGradationLabel = QStringLiteral("gradationLabel");
const QString AttrMx1 = QStringLiteral("mx1"); const QString AttrMx1 = QStringLiteral("mx1");
@ -316,31 +317,36 @@ const QString currentLength = QStringLiteral("CurrentLength");
const QString currentSeamAllowance = QStringLiteral("CurrentSeamAllowance"); const QString currentSeamAllowance = QStringLiteral("CurrentSeamAllowance");
const QString rotation_V = QStringLiteral("Rotation"); const QString rotation_V = QStringLiteral("Rotation");
const QString rotationElArc_ = rotation_V + elarc_; const QString rotationElArc_ = rotation_V + elarc_;
const QString pieceArea_ = QStringLiteral("PieceArea_");
const QStringList builInVariables = QStringList() << measurement_ const QStringList builInVariables
<< increment_ {
<< line_ measurement_,
<< angleLine_ increment_,
<< arc_ line_,
<< elarc_ angleLine_,
<< spl_ arc_,
<< splPath elarc_,
<< radiusArc_ spl_,
<< radius1ElArc_ splPath,
<< radius2ElArc_ radiusArc_,
<< angle1Arc_ radius1ElArc_,
<< angle2Arc_ radius2ElArc_,
<< angle1ElArc_ angle1Arc_,
<< angle2ElArc_ angle2Arc_,
<< angle1Spl_ angle1ElArc_,
<< angle2Spl_ angle2ElArc_,
<< angle1SplPath angle1Spl_,
<< angle2SplPath angle2Spl_,
<< seg_ angle1SplPath,
<< currentLength angle2SplPath,
<< currentSeamAllowance seg_,
<< c1LengthSpl_ currentLength,
<< c2LengthSpl_ currentSeamAllowance,
<< c1LengthSplPath c1LengthSpl_,
<< c2LengthSplPath c2LengthSpl_,
<< rotationElArc_; c1LengthSplPath,
c2LengthSplPath,
rotationElArc_,
pieceArea_
};

View file

@ -68,6 +68,7 @@ extern const QString AttrType;
extern const QString AttrMx; extern const QString AttrMx;
extern const QString AttrMy; extern const QString AttrMy;
extern const QString AttrName; extern const QString AttrName;
extern const QString AttrShortName;
extern const QString AttrUUID; extern const QString AttrUUID;
extern const QString AttrGradationLabel; extern const QString AttrGradationLabel;
extern const QString AttrMx1; extern const QString AttrMx1;
@ -241,6 +242,7 @@ extern const QString currentLength;
extern const QString currentSeamAllowance; extern const QString currentSeamAllowance;
extern const QString rotation_V; extern const QString rotation_V;
extern const QString rotationElArc_; extern const QString rotationElArc_;
extern const QString pieceArea_;
extern const QStringList builInVariables; extern const QStringList builInVariables;

View file

@ -744,6 +744,7 @@
<xs:attribute name="mx" type="xs:double"/> <xs:attribute name="mx" type="xs:double"/>
<xs:attribute name="my" type="xs:double"/> <xs:attribute name="my" type="xs:double"/>
<xs:attribute name="name" type="xs:string"/> <xs:attribute name="name" type="xs:string"/>
<xs:attribute name="shortName" type="pieceShortName"/>
<xs:attribute name="uuid" type="uuid"/> <xs:attribute name="uuid" type="uuid"/>
<xs:attribute name="gradationLabel" type="xs:string"/> <xs:attribute name="gradationLabel" type="xs:string"/>
<xs:attribute name="bufferName" type="xs:string"/> <xs:attribute name="bufferName" type="xs:string"/>
@ -820,7 +821,12 @@
</xs:element> </xs:element>
<xs:simpleType name="shortName"> <xs:simpleType name="shortName">
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:pattern value="([^\p{Nd}\p{Zs}*/&amp;|!&lt;&gt;^&#10;\()\-+.,٫, ٬.=?:;'\&quot;]){1,1}([^\p{Zs}*/&amp;|!&lt;&gt;^&#10;\()\-+.,٫, ٬.=?:;\&quot;]){0,}"/> <xs:pattern value="([^\p{Nd}\p{Zs}*\/&amp;|!&lt;&gt;^&#10;\()\-+.,٫, ٬.=?:;'\&quot;]){1,1}([^\p{Zs}*\/&amp;|!&lt;&gt;^&#10;\()\-+.,٫, ٬.=?:;\&quot;]){0,}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="pieceShortName">
<xs:restriction base="xs:string">
<xs:pattern value="([^\p{Zs}*\/&amp;|!&lt;&gt;^&#10;\()\-+.,٫, ٬.=?:;\&quot;]){0,}"/>
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
<xs:simpleType name="uuid"> <xs:simpleType name="uuid">

View file

@ -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 // 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 // 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. // line at the end of string use /z anchor.
regex = QString("\\A([^\\p{Nd}\\p{Zs}*/&|!<>^\\n\\()%1%2%3%4=?:;'\"]){1,1}" regex = QString("\\A([^\\p{Nd}\\p{Zs}*\\/&|!<>^\\n\\()%1%2%3%4=?:;'\"]){1,1}"
"([^\\p{Zs}*/&|!<>^\\n\\()%1%2%3%4=?:;\"]){0,}\\z") "([^\\p{Zs}*\\/&|!<>^\\n\\()%1%2%3%4=?:;\"]){0,}\\z")
.arg(negativeSigns, positiveSigns, decimalPoints, groupSeparators); .arg(negativeSigns, positiveSigns, decimalPoints, groupSeparators);
} }

View file

@ -72,6 +72,8 @@ auto ConvertInternalPaths(const VPiece &piece, const VContainer *pattern) -> QVe
{ {
SCASSERT(pattern != nullptr) SCASSERT(pattern != nullptr)
piece.TestInternalPaths(pattern);
QVector<VLayoutPiecePath> paths; QVector<VLayoutPiecePath> paths;
const QVector<quint32> pathsId = piece.GetInternalPaths(); const QVector<quint32> pathsId = piece.GetInternalPaths();
const QVector<QPointF> cuttingPath = piece.CuttingPathPoints(pattern); const QVector<QPointF> cuttingPath = piece.CuttingPathPoints(pattern);

View file

@ -275,7 +275,7 @@ enum class Vis : ToolVisHolderType
}; };
enum class VarType : qint8 { Measurement, MeasurementSeparator, Increment, IncrementSeparator, LineLength, CurveLength, 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 }; 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; return 0;
} }
template<typename T> constexpr inline auto PixelToMm(T pix) -> T { return (pix / PrintDPI) * 25.4; } template<typename T> constexpr inline auto PixelToInch(T pix) -> T {return pix / PrintDPI;}
template<typename T> constexpr inline auto PixelToCm(T pix) -> T { return ((pix / PrintDPI) * 25.4) / 10.0; } template<typename T> constexpr inline auto PixelToMm(T pix) -> T {return PixelToInch(pix) * 25.4;}
template<typename T> constexpr inline auto PixelToInch(T pix) -> T { return pix / PrintDPI; } template<typename T> 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 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; return 0;
} }
template<typename T> constexpr inline auto Inch2ToPixel2(T val) -> T {return val * (PrintDPI * PrintDPI);}
template<typename T> constexpr inline auto Mm2ToPixel2(T val) -> T {return Inch2ToPixel2(val * 0.001550031);}
template<typename T> 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<typename T> constexpr inline auto Pixel2ToInch2(T pix) -> T { return pix / (PrintDPI * PrintDPI);}
template<typename T> constexpr inline auto Pixel2ToMm2(T pix) -> T { return Pixel2ToInch2(pix) / 0.001550031;}
template<typename T> 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 Q_DECL_RELAXED_CONSTEXPR inline auto UnitConvertor(qreal value, const Unit &from, const Unit &to) -> qreal
{ {

View file

@ -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 // 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. // confuse a user. Increment should not know nothing about internal variables.
Q_STATIC_ASSERT_X(static_cast<int>(VarType::Unknown) == 10, "Check that you used all types"); Q_STATIC_ASSERT_X(static_cast<int>(VarType::Unknown) == 11, "Check that you used all types");
this->data->ClearVariables(QVector<VarType>({VarType::LineAngle, this->data->ClearVariables(QVector<VarType>{VarType::LineAngle,
VarType::LineLength, VarType::LineLength,
VarType::CurveLength, VarType::CurveLength,
VarType::CurveCLength, VarType::CurveCLength,
VarType::ArcRadius, VarType::ArcRadius,
VarType::CurveAngle, VarType::CurveAngle,
VarType::IncrementSeparator VarType::IncrementSeparator,
})); VarType::PieceArea});
} }
VIncrementData(const VIncrementData &incr) VIncrementData(const VIncrementData &incr)

View file

@ -78,12 +78,12 @@ VLineAngle &VLineAngle::operator=(const VLineAngle &var)
return *this; return *this;
} }
#ifdef Q_COMPILER_RVALUE_REFS
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VLineAngle::VLineAngle(VLineAngle &&var) Q_DECL_NOTHROW VLineAngle::VLineAngle(VLineAngle &&var) Q_DECL_NOTHROW
:VInternalVariable(std::move(var)), d(std::move(var.d)) :VInternalVariable(std::move(var)), d(std::move(var.d))
{} {}
#ifdef Q_COMPILER_RVALUE_REFS
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VLineAngle &VLineAngle::operator=(VLineAngle &&var) Q_DECL_NOTHROW VLineAngle &VLineAngle::operator=(VLineAngle &&var) Q_DECL_NOTHROW
{ {

View file

@ -0,0 +1,107 @@
/************************************************************************
**
** @file vpiecearea.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://gitlab.com/smart-pattern/valentina> 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 <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "vpiecearea.h"
#include "vpiecearea_p.h"
#include "../vpatterndb/vpiece.h"
#include "../vpatterndb/vcontainer.h"
#include <QRegularExpression>
//---------------------------------------------------------------------------------------------------------------------
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;
}

View file

@ -0,0 +1,60 @@
/************************************************************************
**
** @file vpiecearea.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://gitlab.com/smart-pattern/valentina> 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 <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#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<VPieceAreaData> d;
};
Q_DECLARE_TYPEINFO(VPieceArea, Q_MOVABLE_TYPE); // NOLINT
#endif // VPIECEAREA_H

View file

@ -0,0 +1,60 @@
/************************************************************************
**
** @file vpiecearea_p.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://gitlab.com/smart-pattern/valentina> 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 <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VPIECEAREA_P_H
#define VPIECEAREA_P_H
#include <QSharedData>
#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

View file

@ -52,6 +52,7 @@
#include "variables/vlineangle.h" #include "variables/vlineangle.h"
#include "variables/vlinelength.h" #include "variables/vlinelength.h"
#include "variables/vmeasurement.h" #include "variables/vmeasurement.h"
#include "variables/vpiecearea.h"
#include "vtranslatevars.h" #include "vtranslatevars.h"
QT_WARNING_PUSH QT_WARNING_PUSH
@ -391,15 +392,16 @@ void VContainer::ClearForFullParse()
d->pieces->clear(); d->pieces->clear();
d->piecePaths->clear(); d->piecePaths->clear();
Q_STATIC_ASSERT_X(static_cast<int>(VarType::Unknown) == 10, "Check that you used all types"); Q_STATIC_ASSERT_X(static_cast<int>(VarType::Unknown) == 11, "Check that you used all types");
ClearVariables(QVector<VarType>({VarType::Increment, ClearVariables(QVector<VarType>{VarType::Increment,
VarType::IncrementSeparator, VarType::IncrementSeparator,
VarType::LineAngle, VarType::LineAngle,
VarType::LineLength, VarType::LineLength,
VarType::CurveLength, VarType::CurveLength,
VarType::CurveCLength, VarType::CurveCLength,
VarType::ArcRadius, VarType::ArcRadius,
VarType::CurveAngle})); VarType::CurveAngle,
VarType::PieceArea});
ClearGObjects(); ClearGObjects();
ClearUniqueNames(); ClearUniqueNames();
} }
@ -570,6 +572,19 @@ void VContainer::RemoveIncrement(const QString &name)
d->variables.remove(name); d->variables.remove(name);
} }
//---------------------------------------------------------------------------------------------------------------------
void VContainer::FillPiecesAreas(Unit unit)
{
QHash<quint32, VPiece> *pieces = d->pieces.data();
auto i = pieces->constBegin();
while (i != pieces->constEnd())
{
AddVariable(QSharedPointer<VPieceArea>::create(i.key(), i.value(), this, unit));
++i;
}
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
const QMap<QString, QSharedPointer<VMeasurement> > VContainer::DataMeasurements() const const QMap<QString, QSharedPointer<VMeasurement> > VContainer::DataMeasurements() const
{ {
@ -650,6 +665,12 @@ const QMap<QString, QSharedPointer<VCurveAngle> > VContainer::DataAnglesCurves()
return DataVar<VCurveAngle>(VarType::CurveAngle); return DataVar<VCurveAngle>(VarType::CurveAngle);
} }
//---------------------------------------------------------------------------------------------------------------------
const QMap<QString, QSharedPointer<VPieceArea> > VContainer::DataPieceArea() const
{
return DataVar<VPieceArea>(VarType::PieceArea);
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool VContainer::IsUnique(const QString &name) const bool VContainer::IsUnique(const QString &name) const
{ {

View file

@ -58,6 +58,15 @@
#include "vtranslatevars.h" #include "vtranslatevars.h"
class VEllipticalArc; 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_PUSH
QT_WARNING_DISABLE_GCC("-Weffc++") QT_WARNING_DISABLE_GCC("-Weffc++")
@ -195,6 +204,8 @@ public:
void RemoveIncrement(const QString& name); void RemoveIncrement(const QString& name);
void FillPiecesAreas(Unit unit);
const QHash<quint32, QSharedPointer<VGObject> > *CalculationGObjects() const; const QHash<quint32, QSharedPointer<VGObject> > *CalculationGObjects() const;
const QHash<quint32, VPiece> *DataPieces() const; const QHash<quint32, VPiece> *DataPieces() const;
const QHash<QString, QSharedPointer<VInternalVariable>> *DataVariables() const; const QHash<QString, QSharedPointer<VInternalVariable>> *DataVariables() const;
@ -209,6 +220,7 @@ public:
const QMap<QString, QSharedPointer<VLineAngle> > DataAngleLines() const; const QMap<QString, QSharedPointer<VLineAngle> > DataAngleLines() const;
const QMap<QString, QSharedPointer<VArcRadius> > DataRadiusesArcs() const; const QMap<QString, QSharedPointer<VArcRadius> > DataRadiusesArcs() const;
const QMap<QString, QSharedPointer<VCurveAngle> > DataAnglesCurves() const; const QMap<QString, QSharedPointer<VCurveAngle> > DataAnglesCurves() const;
const QMap<QString, QSharedPointer<VPieceArea> > DataPieceArea() const;
bool IsUnique(const QString &name) const; bool IsUnique(const QString &name) const;
static bool IsUnique(const QString &name, const QString &nspace); static bool IsUnique(const QString &name, const QString &nspace);

View file

@ -3,6 +3,7 @@
SOURCES += \ SOURCES += \
$$PWD/testpassmark.cpp \ $$PWD/testpassmark.cpp \
$$PWD/variables/vpiecearea.cpp \
$$PWD/vcontainer.cpp \ $$PWD/vcontainer.cpp \
$$PWD/calculator.cpp \ $$PWD/calculator.cpp \
$$PWD/vnodedetail.cpp \ $$PWD/vnodedetail.cpp \
@ -34,6 +35,8 @@ SOURCES += \
HEADERS += \ HEADERS += \
$$PWD/testpassmark.h \ $$PWD/testpassmark.h \
$$PWD/variables/vpiecearea.h \
$$PWD/variables/vpiecearea_p.h \
$$PWD/vcontainer.h \ $$PWD/vcontainer.h \
$$PWD/stable.h \ $$PWD/stable.h \
$$PWD/calculator.h \ $$PWD/calculator.h \

View file

@ -37,8 +37,10 @@
#include "../vmisc/vabstractvalapplication.h" #include "../vmisc/vabstractvalapplication.h"
#include "../vmisc/compatibility.h" #include "../vmisc/compatibility.h"
#include "../ifc/exception/vexceptioninvalidnotch.h" #include "../ifc/exception/vexceptioninvalidnotch.h"
#include "../ifc/exception/vexceptionobjecterror.h"
#include "../vmisc/testpath.h" #include "../vmisc/testpath.h"
#include "../ifc/xml/vabstractpattern.h" #include "../ifc/xml/vabstractpattern.h"
#include "../vpatterndb/vpiecenode.h"
#include <QSharedPointer> #include <QSharedPointer>
#include <QDebug> #include <QDebug>
@ -390,6 +392,18 @@ void VPiece::SetUnited(bool united)
d->m_united = 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 QString VPiece::GetFormulaSAWidth() const
{ {
@ -1197,6 +1211,126 @@ auto VPiece::GlobalPassmarkLength(const VContainer *data) const -> qreal
return length; return length;
} }
//---------------------------------------------------------------------------------------------------------------------
void VPiece::TestInternalPathCuttingPathIntersection(const VContainer *data) const
{
SCASSERT(data != nullptr)
const QVector<QPointF> 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<quint32> 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<QPointF> 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<quint32> pathsId = GetInternalPaths();
if (pathsId.isEmpty())
{
return;
}
const QVector<QPointF> cuttingPoints = CuttingPathPoints(data);
// Internal pieces for cutting must not intersect
QSet<QPair<int, int>> 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<QPointF> 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<QPointF> 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) 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(); 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<QPointF> mainContour = CuttingPathPoints(data);
const qreal mainArea = qAbs(VAbstractPiece::SumTrapezoids(mainContour))/2.0;
qreal internalPathArea = 0;
const QVector<quint32> 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<QPointF> 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<QLocale> 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) #endif // !defined(V_NO_ASSERT)

View file

@ -92,6 +92,9 @@ public:
bool IsUnited() const; bool IsUnited() const;
void SetUnited(bool united); void SetUnited(bool united);
auto GetShortName() const -> QString;
void SetShortName(const QString &value);
QString GetFormulaSAWidth() const; QString GetFormulaSAWidth() const;
void SetFormulaSAWidth(const QString &formula, qreal value); void SetFormulaSAWidth(const QString &formula, qreal value);
@ -138,6 +141,11 @@ public:
auto GetGradationLabel() const -> QString; auto GetGradationLabel() const -> QString;
static void DumpPiece(const VPiece &piece, const VContainer *data, const QString &templateName=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: private:
QSharedDataPointer<VPieceData> d; QSharedDataPointer<VPieceData> d;
@ -163,6 +171,9 @@ private:
QJsonObject DBToJson(const VContainer *data) const; QJsonObject DBToJson(const VContainer *data) const;
qreal GlobalPassmarkLength(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 Q_DECLARE_TYPEINFO(VPiece, Q_MOVABLE_TYPE); // NOLINT

View file

@ -80,6 +80,8 @@ public:
QString m_gradationLabel{}; // NOLINT(misc-non-private-member-variables-in-classes) QString m_gradationLabel{}; // NOLINT(misc-non-private-member-variables-in-classes)
QString m_shortName{}; // NOLINT(misc-non-private-member-variables-in-classes)
private: private:
Q_DISABLE_ASSIGN_MOVE(VPieceData) // NOLINT Q_DISABLE_ASSIGN_MOVE(VPieceData) // NOLINT
}; };

View file

@ -393,6 +393,7 @@ void VTranslateVars::InitVariables()
variables.insert(c2LengthSplPath, translate("VTranslateVars", "C2LengthSplPath", variables.insert(c2LengthSplPath, translate("VTranslateVars", "C2LengthSplPath",
"Do not add symbol _ to the end of the name")); "Do not add symbol _ to the end of the name"));
variables.insert(rotationElArc_, translate("VTranslateVars", "RotationElArc_", "Left symbol _ in the name")); variables.insert(rotationElArc_, translate("VTranslateVars", "RotationElArc_", "Left symbol _ in the name"));
variables.insert(pieceArea_, translate("VTranslateVars", "PieceArea_", "Left symbol _ in the name"));
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------

View file

@ -63,6 +63,7 @@
#include "../vpatterndb/variables/vlineangle.h" #include "../vpatterndb/variables/vlineangle.h"
#include "../vpatterndb/variables/vlinelength.h" #include "../vpatterndb/variables/vlinelength.h"
#include "../vpatterndb/variables/vmeasurement.h" #include "../vpatterndb/variables/vmeasurement.h"
#include "../vpatterndb/variables/vpiecearea.h"
#include "../vmisc/def.h" #include "../vmisc/def.h"
#include "../vmisc/vabstractapplication.h" #include "../vmisc/vabstractapplication.h"
#include "../vmisc/vcommonsettings.h" #include "../vmisc/vcommonsettings.h"
@ -85,6 +86,8 @@ DialogEditWrongFormula::DialogEditWrongFormula(const VContainer *data, quint32 t
ui->setupUi(this); ui->setupUi(this);
ui->radioButtonPieceArea->setVisible(false);
timerFormula->setSingleShot(true); timerFormula->setSingleShot(true);
connect(timerFormula, &QTimer::timeout, this, &DialogEditWrongFormula::EvalFormula); connect(timerFormula, &QTimer::timeout, this, &DialogEditWrongFormula::EvalFormula);
@ -233,6 +236,34 @@ void DialogEditWrongFormula::ValChanged(int row)
SetDescription(item->text(), *m_data->GetVariable<VCurveAngle>(name)->GetValue(), specialUnits, SetDescription(item->text(), *m_data->GetVariable<VCurveAngle>(name)->GetValue(), specialUnits,
tr("Curve angle")); tr("Curve angle"));
} }
else if (ui->radioButtonCLength->isChecked())
{
const bool specialUnits = false;
SetDescription(item->text(), *m_data->GetVariable<VCurveCLength>(name)->GetValue(), specialUnits,
tr("Length to control point"));
}
else if (ui->radioButtonPieceArea->isChecked())
{
const bool specialUnits = false;
const QSharedPointer<VPieceArea> var = m_data->GetVariable<VPieceArea>(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()) else if (ui->radioButtonFunctions->isChecked())
{ {
ui->labelDescription->setText(item->toolTip()); ui->labelDescription->setText(item->toolTip());
@ -356,6 +387,13 @@ void DialogEditWrongFormula::PreviewCalculations()
ShowIncrementsInPreviewCalculation(true); ShowIncrementsInPreviewCalculation(true);
} }
//---------------------------------------------------------------------------------------------------------------------
void DialogEditWrongFormula::PieceArea()
{
ui->checkBoxHideEmpty->setEnabled(false);
ShowVariable(m_data->DataPieceArea());
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
/** /**
* @brief Functions show in list functions * @brief Functions show in list functions
@ -479,6 +517,12 @@ void DialogEditWrongFormula::SetPreviewCalculationsMode()
ui->radioButtonCLength->setDisabled(true); ui->radioButtonCLength->setDisabled(true);
} }
//---------------------------------------------------------------------------------------------------------------------
void DialogEditWrongFormula::ShowPieceArea(bool show) const
{
ui->radioButtonPieceArea->setVisible(show);
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
auto DialogEditWrongFormula::GetFormula() const -> QString 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, &DialogEditWrongFormula::CurvesCLength);
connect(ui->radioButtonCLength, &QRadioButton::clicked, this, ClearFilterFormulaInputs); 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, &DialogEditWrongFormula::Functions);
connect(ui->radioButtonFunctions, &QRadioButton::clicked, this, ClearFilterFormulaInputs); connect(ui->radioButtonFunctions, &QRadioButton::clicked, this, ClearFilterFormulaInputs);
@ -531,9 +578,15 @@ void DialogEditWrongFormula::InitVariables()
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void DialogEditWrongFormula::SetDescription(const QString &name, qreal value, bool specialUnits, 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); const QString desc = QStringLiteral("%1(%2%3) - %4").arg(name).arg(value).arg(unit, description);
ui->labelDescription->setText(desc); ui->labelDescription->setText(desc);
} }

View file

@ -72,6 +72,7 @@ public:
void SetMeasurementsMode(); void SetMeasurementsMode();
void SetIncrementsMode(); void SetIncrementsMode();
void SetPreviewCalculationsMode(); void SetPreviewCalculationsMode();
void ShowPieceArea(bool show) const;
public slots: public slots:
virtual void DialogAccepted(); virtual void DialogAccepted();
virtual void DialogRejected(); virtual void DialogRejected();
@ -90,6 +91,7 @@ public slots:
void AngleLines(); void AngleLines();
void Increments(); void Increments();
void PreviewCalculations(); void PreviewCalculations();
void PieceArea();
void Functions(); void Functions();
signals: signals:
/** /**
@ -144,7 +146,8 @@ private:
void ShowFunctions(); void ShowFunctions();
void ShowIncrementsInPreviewCalculation(bool show); 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; auto Eval(const FormulaData &formulaData, bool &flag) -> qreal;
}; };

View file

@ -10,7 +10,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>542</width> <width>542</width>
<height>481</height> <height>483</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -171,7 +171,7 @@
<bool>true</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
<widget class="QWidget" name=""> <widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="3,1"> <layout class="QVBoxLayout" name="verticalLayout_4" stretch="3,1">
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_3">
@ -309,6 +309,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QRadioButton" name="radioButtonPieceArea">
<property name="text">
<string>Pieces areas</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QRadioButton" name="radioButtonFunctions"> <widget class="QRadioButton" name="radioButtonFunctions">
<property name="sizePolicy"> <property name="sizePolicy">

View file

@ -357,6 +357,7 @@ void DialogSeamAllowance::SetPiece(const VPiece &piece)
uiTabPaths->checkBoxBuiltIn->setChecked(piece.IsSeamAllowanceBuiltIn()); uiTabPaths->checkBoxBuiltIn->setChecked(piece.IsSeamAllowanceBuiltIn());
uiTabPaths->lineEditName->setText(piece.GetName()); uiTabPaths->lineEditName->setText(piece.GetName());
uiTabPaths->lineEditUUID->setText(piece.GetUUID().toString()); uiTabPaths->lineEditUUID->setText(piece.GetUUID().toString());
uiTabPaths->lineEditShortName->setText(piece.GetShortName());
uiTabPaths->lineEditGradationLabel->setText(piece.GetGradationLabel()); uiTabPaths->lineEditGradationLabel->setText(piece.GetGradationLabel());
uiTabPaths->spinBoxPriority->setValue(static_cast<int>(piece.GetPriority())); uiTabPaths->spinBoxPriority->setValue(static_cast<int>(piece.GetPriority()));
@ -2600,6 +2601,7 @@ VPiece DialogSeamAllowance::CreatePiece() const
piece.SetHideMainPath(uiTabPaths->checkBoxHideMainPath->isChecked()); piece.SetHideMainPath(uiTabPaths->checkBoxHideMainPath->isChecked());
piece.SetName(uiTabPaths->lineEditName->text()); piece.SetName(uiTabPaths->lineEditName->text());
piece.SetUUID(uiTabPaths->lineEditUUID->text()); piece.SetUUID(uiTabPaths->lineEditUUID->text());
piece.SetShortName(uiTabPaths->lineEditShortName->text());
piece.SetGradationLabel(uiTabPaths->lineEditGradationLabel->text()); piece.SetGradationLabel(uiTabPaths->lineEditGradationLabel->text());
piece.SetPriority(static_cast<uint>(uiTabPaths->spinBoxPriority->value())); piece.SetPriority(static_cast<uint>(uiTabPaths->spinBoxPriority->value()));
piece.SetFormulaSAWidth(GetFormulaFromUser(uiTabPaths->plainTextEditFormulaWidth), m_saWidth); piece.SetFormulaSAWidth(GetFormulaFromUser(uiTabPaths->plainTextEditFormulaWidth), m_saWidth);
@ -3026,6 +3028,9 @@ void DialogSeamAllowance::InitPieceTab()
{ {
connect(uiTabPaths->lineEditName, &QLineEdit::textChanged, this, &DialogSeamAllowance::NameDetailChanged); connect(uiTabPaths->lineEditName, &QLineEdit::textChanged, this, &DialogSeamAllowance::NameDetailChanged);
uiTabPaths->lineEditShortName->setValidator(
new QRegularExpressionValidator(QRegularExpression(VPiece::ShortNameRegExp()), this));
uiTabPaths->lineEditName->setClearButtonEnabled(true); uiTabPaths->lineEditName->setClearButtonEnabled(true);
uiTabPaths->lineEditName->setText(GetDefaultPieceName()); uiTabPaths->lineEditName->setText(GetDefaultPieceName());

View file

@ -207,6 +207,19 @@
<layout class="QVBoxLayout" name="verticalLayout_9"> <layout class="QVBoxLayout" name="verticalLayout_9">
<item> <item>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="3" column="1">
<widget class="QLineEdit" name="lineEditUUID">
<property name="toolTip">
<string>Universally Unique IDentifier of piece. Used to identifier piece while updating manual layout. Left empty to generate new value.</string>
</property>
<property name="placeholderText">
<string notr="true">{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}</string>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="VLineEdit" name="lineEditName"> <widget class="VLineEdit" name="lineEditName">
<property name="text"> <property name="text">
@ -217,7 +230,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="2" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>Priority:</string> <string>Priority:</string>
@ -231,41 +244,28 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="4" column="0">
<widget class="QSpinBox" name="spinBoxPriority">
<property name="toolTip">
<string>Controls priority in layout. 0 - no priority.</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="lineEditUUID">
<property name="toolTip">
<string>Universally Unique IDentifier of piece. Used to identifier piece while updating manual layout. Left empty to generate new value.</string>
</property>
<property name="placeholderText">
<string notr="true">{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}</string>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelEditUUID">
<property name="text">
<string notr="true">UUID:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_5"> <widget class="QLabel" name="label_5">
<property name="text"> <property name="text">
<string>Gradation label:</string> <string>Gradation label:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="3" column="0">
<widget class="QLabel" name="labelEditUUID">
<property name="text">
<string notr="true">UUID:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="spinBoxPriority">
<property name="toolTip">
<string>Controls priority in layout. 0 - no priority.</string>
</property>
</widget>
</item>
<item row="4" column="1">
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
<widget class="QLineEdit" name="lineEditGradationLabel"> <widget class="QLineEdit" name="lineEditGradationLabel">
@ -286,6 +286,23 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="1" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Short name:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="lineEditShortName">
<property name="toolTip">
<string>Name used to generate a variable</string>
</property>
<property name="maxLength">
<number>25</number>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>

View file

@ -335,7 +335,7 @@ void VToolSeamAllowance::InsertNodes(const QVector<VPieceNode> &nodes, quint32 p
newDet.GetPath().Append(node); newDet.GetPath().Append(node);
// Seam allowance tool already initializated and can't init the node // Seam allowance tool already initializated and can't init the node
VToolSeamAllowance *saTool = qobject_cast<VToolSeamAllowance*>(VAbstractPattern::getTool(pieceId)); auto *saTool = qobject_cast<VToolSeamAllowance*>(VAbstractPattern::getTool(pieceId));
SCASSERT(saTool != nullptr); SCASSERT(saTool != nullptr);
InitNode(node, scene, saTool); InitNode(node, scene, saTool);
@ -352,6 +352,8 @@ void VToolSeamAllowance::AddAttributes(VAbstractPattern *doc, QDomElement &domEl
doc->SetAttribute(domElement, VDomDocument::AttrId, id); doc->SetAttribute(domElement, VDomDocument::AttrId, id);
doc->SetAttribute(domElement, AttrName, piece.GetName()); doc->SetAttribute(domElement, AttrName, piece.GetName());
doc->SetAttributeOrRemoveIf<QString>(domElement, AttrShortName, piece.GetShortName(),
[](const QString &name) noexcept {return name.isEmpty();});
doc->SetAttribute(domElement, AttrUUID, piece.GetUUID().toString()); doc->SetAttribute(domElement, AttrUUID, piece.GetUUID().toString());
doc->SetAttributeOrRemoveIf<QString>(domElement, AttrGradationLabel, piece.GetGradationLabel(), doc->SetAttributeOrRemoveIf<QString>(domElement, AttrGradationLabel, piece.GetGradationLabel(),
[](const QString &label) noexcept {return label.isEmpty();}); [](const QString &label) noexcept {return label.isEmpty();});
@ -1365,7 +1367,9 @@ void VToolSeamAllowance::UpdateExcludeState()
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VToolSeamAllowance::UpdateInternalPaths() void VToolSeamAllowance::UpdateInternalPaths()
{ {
const QVector<quint32> paths = VAbstractTool::data.GetPiece(m_id).GetInternalPaths(); VPiece piece = VAbstractTool::data.GetPiece(m_id);
piece.TestInternalPaths(&(VAbstractTool::data));
const QVector<quint32> paths = piece.GetInternalPaths();
for (auto path : paths) for (auto path : paths)
{ {
try try

View file

@ -170,6 +170,7 @@ void TST_BuitInRegExp::TestCheckUnderlineExists_data()
data.insert(c1LengthSplPath, false); data.insert(c1LengthSplPath, false);
data.insert(c2LengthSplPath, false); data.insert(c2LengthSplPath, false);
data.insert(rotationElArc_, true); data.insert(rotationElArc_, true);
data.insert(pieceArea_, true);
//Catch case when new internal variable appears. //Catch case when new internal variable appears.
QCOMPARE(data.size(), builInVariables.size()); QCOMPARE(data.size(), builInVariables.size());

View file

@ -29,6 +29,8 @@
#include "tst_vabstractpiece.h" #include "tst_vabstractpiece.h"
#include "../vlayout/vabstractpiece.h" #include "../vlayout/vabstractpiece.h"
#include "../vlayout/vrawsapoint.h" #include "../vlayout/vrawsapoint.h"
#include "../vgeometry/varc.h"
#include "../vgeometry/vpointf.h"
#include <QPointF> #include <QPointF>
#include <QVector> #include <QVector>
@ -379,6 +381,57 @@ void TST_VAbstractPiece::SumTrapezoids() const
Case5(); Case5();
} }
//---------------------------------------------------------------------------------------------------------------------
void TST_VAbstractPiece::TestAreaCalculation_data()
{
QTest::addColumn<QVector<QPointF>>("path");
QTest::addColumn<qreal>("excpectedArea");
{
QVector<QPointF> 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<QPointF> 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<QPointF> 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<QPointF>, 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 void TST_VAbstractPiece::RawPathRemoveLoop_data() const
{ {

View file

@ -45,6 +45,8 @@ private slots:
void LayoutAllowanceRemoveLoop_data(); void LayoutAllowanceRemoveLoop_data();
void LayoutAllowanceRemoveLoop() const; void LayoutAllowanceRemoveLoop() const;
void SumTrapezoids() const; void SumTrapezoids() const;
void TestAreaCalculation_data();
void TestAreaCalculation() const;
void RawPathRemoveLoop_data() const; void RawPathRemoveLoop_data() const;
void RawPathRemoveLoop() const; void RawPathRemoveLoop() const;
void PathRemoveLoop_data() const; void PathRemoveLoop_data() const;