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.
- 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.

View File

@ -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();

View File

@ -1260,7 +1260,8 @@ bool MainWindowsNoGUI::ExportFMeasurementsToCSVData(const QString &fileName, boo
}
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)
{

View File

@ -532,7 +532,7 @@ void VPattern::LiteParseIncrements()
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::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<int>(VarType::Unknown) == 10, "Check that you used all types");
QVector<VarType> types({VarType::LineAngle,
Q_STATIC_ASSERT_X(static_cast<int>(VarType::Unknown) == 11, "Check that you used all types");
QVector<VarType> types{VarType::LineAngle,
VarType::LineLength,
VarType::CurveLength,
VarType::CurveCLength,
VarType::ArcRadius,
VarType::CurveAngle});
VarType::CurveAngle,
VarType::PieceArea};
if (parse == Document::FullLiteParse)
{
types.append(VarType::Increment);

View File

@ -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_
};

View File

@ -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;

View File

@ -744,6 +744,7 @@
<xs:attribute name="mx" type="xs:double"/>
<xs:attribute name="my" type="xs:double"/>
<xs:attribute name="name" type="xs:string"/>
<xs:attribute name="shortName" type="pieceShortName"/>
<xs:attribute name="uuid" type="uuid"/>
<xs:attribute name="gradationLabel" type="xs:string"/>
<xs:attribute name="bufferName" type="xs:string"/>
@ -820,7 +821,12 @@
</xs:element>
<xs:simpleType name="shortName">
<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:simpleType>
<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
// 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);
}

View File

@ -72,6 +72,8 @@ auto ConvertInternalPaths(const VPiece &piece, const VContainer *pattern) -> QVe
{
SCASSERT(pattern != nullptr)
piece.TestInternalPaths(pattern);
QVector<VLayoutPiecePath> paths;
const QVector<quint32> pathsId = piece.GetInternalPaths();
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,
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<typename T> constexpr inline auto PixelToMm(T pix) -> T { return (pix / PrintDPI) * 25.4; }
template<typename T> constexpr inline auto PixelToCm(T pix) -> T { return ((pix / PrintDPI) * 25.4) / 10.0; }
template<typename T> constexpr inline auto PixelToInch(T pix) -> T { return pix / PrintDPI; }
template<typename T> constexpr inline auto PixelToInch(T pix) -> T {return pix / PrintDPI;}
template<typename T> constexpr inline auto PixelToMm(T pix) -> T {return PixelToInch(pix) * 25.4;}
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
@ -421,6 +421,52 @@ Q_DECL_RELAXED_CONSTEXPR inline auto FromPixel(double pix, const Unit &unit) ->
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
{

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
// 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");
this->data->ClearVariables(QVector<VarType>({VarType::LineAngle,
Q_STATIC_ASSERT_X(static_cast<int>(VarType::Unknown) == 11, "Check that you used all types");
this->data->ClearVariables(QVector<VarType>{VarType::LineAngle,
VarType::LineLength,
VarType::CurveLength,
VarType::CurveCLength,
VarType::ArcRadius,
VarType::CurveAngle,
VarType::IncrementSeparator
}));
VarType::IncrementSeparator,
VarType::PieceArea});
}
VIncrementData(const VIncrementData &incr)

View File

@ -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
{

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/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<int>(VarType::Unknown) == 10, "Check that you used all types");
ClearVariables(QVector<VarType>({VarType::Increment,
Q_STATIC_ASSERT_X(static_cast<int>(VarType::Unknown) == 11, "Check that you used all types");
ClearVariables(QVector<VarType>{VarType::Increment,
VarType::IncrementSeparator,
VarType::LineAngle,
VarType::LineLength,
VarType::CurveLength,
VarType::CurveCLength,
VarType::ArcRadius,
VarType::CurveAngle}));
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<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
{
@ -650,6 +665,12 @@ const QMap<QString, QSharedPointer<VCurveAngle> > VContainer::DataAnglesCurves()
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
{

View File

@ -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<quint32, QSharedPointer<VGObject> > *CalculationGObjects() const;
const QHash<quint32, VPiece> *DataPieces() const;
const QHash<QString, QSharedPointer<VInternalVariable>> *DataVariables() const;
@ -209,6 +220,7 @@ public:
const QMap<QString, QSharedPointer<VLineAngle> > DataAngleLines() const;
const QMap<QString, QSharedPointer<VArcRadius> > DataRadiusesArcs() const;
const QMap<QString, QSharedPointer<VCurveAngle> > DataAnglesCurves() const;
const QMap<QString, QSharedPointer<VPieceArea> > DataPieceArea() const;
bool IsUnique(const QString &name) const;
static bool IsUnique(const QString &name, const QString &nspace);

View File

@ -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 \

View File

@ -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 <QSharedPointer>
#include <QDebug>
@ -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<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)
{
@ -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<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)

View File

@ -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<VPieceData> 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

View File

@ -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
};

View File

@ -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"));
}
//---------------------------------------------------------------------------------------------------------------------

View File

@ -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<VCurveAngle>(name)->GetValue(), specialUnits,
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())
{
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);
}

View File

@ -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;
};

View File

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

View File

@ -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<int>(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<uint>(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());

View File

@ -207,6 +207,19 @@
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<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">
<widget class="VLineEdit" name="lineEditName">
<property name="text">
@ -217,7 +230,7 @@
</property>
</widget>
</item>
<item row="1" column="0">
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Priority:</string>
@ -231,41 +244,28 @@
</property>
</widget>
</item>
<item row="1" column="1">
<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">
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Gradation label:</string>
</property>
</widget>
</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">
<item>
<widget class="QLineEdit" name="lineEditGradationLabel">
@ -286,6 +286,23 @@
</item>
</layout>
</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>
</item>
<item>

View File

@ -335,7 +335,7 @@ void VToolSeamAllowance::InsertNodes(const QVector<VPieceNode> &nodes, quint32 p
newDet.GetPath().Append(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);
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<QString>(domElement, AttrShortName, piece.GetShortName(),
[](const QString &name) noexcept {return name.isEmpty();});
doc->SetAttribute(domElement, AttrUUID, piece.GetUUID().toString());
doc->SetAttributeOrRemoveIf<QString>(domElement, AttrGradationLabel, piece.GetGradationLabel(),
[](const QString &label) noexcept {return label.isEmpty();});
@ -1365,7 +1367,9 @@ void VToolSeamAllowance::UpdateExcludeState()
//---------------------------------------------------------------------------------------------------------------------
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)
{
try

View File

@ -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());

View File

@ -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 <QPointF>
#include <QVector>
@ -379,6 +381,57 @@ void TST_VAbstractPiece::SumTrapezoids() const
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
{

View File

@ -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;